Enable Telnet Shell
WARNING: Operations shown here can potentially brick your device if not followed correctly, proceed at your own risk!
We've already got a shell by using the U-boot bootargs
trick. However the shell we have access to is not under the runtime environment of a C200 which booted normally.
When
analyzing a device, some information can be extremely helpful. For example :
- What processes are running? What's the options passed to a binary when it was executed? These can be answered by
ps
. - What network ports are open? What processes are listening to them? What connections are made? These can be answered by
netstat
. - What drivers/modules are loaded?
lsmod
can tell us. - Are there any data or keys generated only on boot?
- .........
The list goes on and on, and different devices will have different questions to be asked.
However, the system state when we get a shell through U-boot greatly restricted the information we can gather, and what we can do on the
device [*].
So, having access to a shell during runtime (and remotely) is the best thing a
pentester can wish for.
Hunt for Vulnerability
We can easily find that there is telnetd
in the firmware, so the only thing we need to do is find a vulnerability to execute it.
Luckily there is a command injection vulnerability we identified in /bin/tp_manage
. The guilty function is located at address 0x40a4c8
:
Here, the program first decompressed a file
called isp_config.bin
, then tries to read product_id
from /tmp/base-files/etc/config.ini
If
it successfully reads a product id, it will finally call system()
(FUN_0040c240) and execute command uci set device_info.info.product_id=%s
with
product id passed to the format string without sanitizing or checks.
So, if we can manipulate product_id
passed to the format string, then in theory
we should be able to run any command we want!
Where Is Isp_config.bin ?
We now know product_id
is read from /tmp/base-files/etc/config.ini
, and this file is decompressed
from isp_config.bin
.
However we can't find this isp_config.bin
anywhere in the firmware
file or flash dump!
This indicates that isp_config.bin
is created at runtime. Now our priority is to find how it was created.
It turns out Ghidra
decompiler is making things look more complicated than they really are. Right in the same function, there is the following code:
First
it reads 0x100
(256) bytes from flash address 0x20000
and stores the data in
lvar4
.
Then there's a while loop, reading 0x10000
(65536) bytes from flash at each iteration, starting at address 0x20100
.
Finally,
after checking some md5 value, the data is written to /tmp/isp_config.bin
.
Analyze "art" Partition
What deduction can be drawn from the code above ?
- Address
0x20000
of flash isart
partition, according to the bootlog - First
0x100
bytes ofart
may be some kind of header or meta data. - The meta data contains md5 hash, which is used to verify md5 hash of the data read starting from flash address
0x20100
.
Having the above deduction in mind, we can start by dumping art
partition to a file:
Using
binwalk
to analyze art.bin
we just dumped, we can see there's actually a gzip
compressed
file locating at offset 0x100
:
base-files/etc/config.ini
can then be found after we extract the compressed data :
Edit and Repack
Now we've found our place to put the command we want to execute, let's do that right now:
By
adding ;telnetd -l /bin/sh
after the original product id, a telnetd
without login
prompt will be launched when this modified string is read by /bin/tp_manage
and passed to command uci set device_info.info.product_id=%s
.
What's left for us to do might sound as simple as reverse what we did till now - compress these files and write it back to flash.
However let's not forget there is a md5 check for the compress data.
And by adding our command in product_id
, the md5 sum of our compressed data won't be the same with what's originally in art
partition
meta data!
Just writing this into flash chip recklessly may result in bricking our C200, nobody wants this to happen.
We will first have to figure out where the md5 hash resides in the 0x100
bytes
of meta data/header.
Let's take a look at the meta data in hex dump :
At
first sight, it surely looks like a mess. The only easy things that can be spotted are the product name C200_1.0
and the firmware version
1.0.10 Build 200520 Rel.45325n
.
However some deeper inspection allows us to identify two important information in this mess [*]:
We
can confirm this by using dd
to extract 0x0001eab7
(125,623) bytes starting
from offset 0x100
, and check its md5sum:
Amazing,
right ? 😉
Edit and Repack - Part 2
The important meta data are identified, now let's make our customized art.bin
partition data.
We'll
need to re-compress all the data with our telnetd payload inside, then calculate its md5sum
and file size :
Repacking
is a little more complicated, but hang in there with us:
Click here far larger image
Here
we used dd
to extract data portion from the beginning to offset 0x4c
as part1, and data
portion from
offset 0x4c
to offset 0x100
as part2.
After that, we can
use cat
and echo
to append part1, file size ( 0x001eb62
),
md5 value and part2 together. This will complete the modification of partition meta data.
Next, append the whole backdoored gzip file to arttelnetd.bin
:
After making sure our gzip file (with file
signature 0x1f8b08
) landed at the correct offset, we see that arttelnetd.bin
is now
126,050
bytes large.
However art
partition has to be exactly 0x20000
(131,072)
bytes large, as defined in C200's flash partition table [*], so the last thing we need to do is put some padding of 0xff
at the end of arttelnetd.bin
and
make it exactly 131,072
bytes large.
In
our case we need to put 5022 bytes of padding, so our command will be as follows:dd if=/dev/zero bs=1 count=5022 | tr "\000" "\377" >> arttelnetd.bin
(Edit: Command is updated to one with better performance, so it will be different from the picture above.)
Check
the file size of arttelnetd.bin
one last time. If it's 131,072
, then we finally
made our customized version of art
partition! 🥳🥳
Writing Our Customized Data Into Flash
WARNING: Operations shown here can potentially brick your device if not followed correctly, proceed at your own risk!
Our backdoored art
partition is ready, only thing left is to write it into the flash chip.
There's a binary called mtd
conveniently
built in C200 that serves exactly this purpose:
mtd
only deal with mtdX
virtual devices, not mtdblockX
. So we'll have
to use mknod
to create a node for art
partition, which is /dev/mtd2
.
Here we also checked the head and tail
of /dev/mtd2
, just to make sure it really is accessing the part of flash chip we wish to modify.
If everything went well, let's put our customized
arttelnetd.bin
into SD card and insert it into C200:
arttelnetd.bin
- check ✅/dev/mtd2
- check ✅
Finally, it's time to really write our backdoored partition into flash:
Just like that, our backdoored
partition is written into flash.
Now, reboot your C200 and hope for the best enjoy your runtime telnet root shell!