MDM5. Doing filesystem cURL ups (WIP DRAFT)
Published:Tags: mdm-story breaking-and-entering
1030 words
5 min read
In the last part we got a root shell access to the modem, but it’s still not good enough! The modem has some utilities installed on it, but it’s still rather limiting to poke around files on. It’d really hit the sweet spot if we could dump the filesystem off of the modem onto my hard drive.
We’ve got root access, so exfiltrating files isn’t going to be a problem. Worst case scenario is that we’ll have to encode the files to text and make a little script to encode file contents as text and read it into files over telnet, but I don’t feel like writing that unless I really have to.
We don’t have netcat nor scp, which is rather expected for a modem.
~ # busybox nc
nc: applet not found
~ # nc
-sh: nc: not found
~ # scp
-sh: scp: not found
Listing all of the functions that this build of busybox was compiled with gives us a couple of utilities we could use — tftp
and wget
(POST out data). Also there’s our old friend traceroute
, and for some reason we also have cal
!
Currently defined functions:
[, [[, arp, arping, ash, awk, basename, brctl, cal, cat, catv, chmod,
chown, cp, cut, date, dd, df, dhcprelay, dirname, dnsdomainname, du,
dumpleases, echo, egrep, env, expr, false, fgrep, find, free, fsync,
grep, groups, gunzip, halt, head, hostid, hostname, id, ifconfig, init,
insmod, install, kill, killall, ln, login, logread, ls, lsmod, md5sum,
mdev, mkdir, mkfifo, mknod, mkswap, mount, mv, netstat, ping, ping6,
poweroff, ps, pwd, reboot, rm, rmdir, rmmod, route, sed, sh, sleep,
sort, stat, swapoff, swapon, sync, sysctl, syslogd, tac, tail, telnetd,
test, tftp, top, touch, tr, traceroute, traceroute6, true, tty, udhcpc,
udhcpd, umount, uname, uniq, unzip, users, wc, wget, zcat
Listing out the arguments supported by the busybox wget implementation it doesn’t look like it supports POSTing files, so that’s no good.
There is tftp
.
During poking around the system I noticed that there’s a (seemingly) full curl
binary on it.
A fact that’s not well known (or at least I hope it’s not, otherwise I’m the one not in the know writing that statement ;)) is that cURL doesn’t only support HTTP, but in fact supports 26 protocols!
Among those 26 protocols are a couple of that are of interest to us: SCP and {S,T}FTP (we have tftp
available on the system, but if we didn’t then cURL could also use that).
tftp
pros are probably looking confused as they’re wondering “why not just use tftp?” and there’s a good reason for it: I’ve never used tftp.
So if it’s possible to use something that I’m familiar with then I’ll try going that route.
~ # curl sftp://192.168.0.100/test
curl: (1) Protocol "sftp" not supported or disabled in libcurl
~ # curl scp://192.168.0.100/test
curl: (1) Protocol "scp" not supported or disabled in libcurl
~ # curl ftp://192.168.0.100/test
curl: (7) Failed to connect to 192.168.0.100 port 21: Connection refused
Damn, still back to using TFTP or FTP.
FTP it is, as I’ve used a similar method once before.
I’m using pyftpdlib
to create a FTP server that allows for uploads to the working directory of the script.
The script creates a single user a:a
with write permissions, as I had problems figuring out how to give anonymous users mkdir permissions.
In a sudden moment of creativity I named the script ftpd.py
.
#!/bin/python3
from pyftpdlib.authorizers import DummyAuthorizer
from pyftpdlib.handlers import FTPHandler
from pyftpdlib.servers import FTPServer
import os
authorizer = DummyAuthorizer()
authorizer.add_user("a", "a", ".", perm="elradfmw")
authorizer.add_anonymous(os.getcwd())
handler = FTPHandler
handler.authorizer = authorizer
address = ('',5000)
server = FTPServer((address), handler)
server.serve_forever()
Now all that’s left is to send every file over FTP using cURL. I’ll also want to send over all symlinked files for completeness. It’s a bit wasteful of disk space, but if that becomes a problem then writing a little script that re-creates all symlinks won’t be too complicated.
To send each file we’ll first need a way to find all regular files and symlinks in the filesystem. We’ll use the utility find
, which is present on the modem.
The maxdepth
argument is rather useful when following symlinks, since there may be recursive symlinks (there were in this case).
For the first test lets produce a complete filesystem listing with file sizes and yank it out of the modem to verify that our exfiltration procedure would work.
Since I want to redirect stdout
to file then I’ll have to be in a writeable directory, I chose /cache
(symlinked to /mnt/userdata/cache
) for that purpose.
On the desktop computer:
➜ mkdir fs-dump && cd fs-dump
➜ python3 ../ftpd.py
On the modem:
/mnt/userdata/cache # find / -type f -follow -maxdepth 10 -exec echo {} \; > file-list
/mnt/userdata/cache # curl -T file-list ftp://192.168.0.100:5000/dir/file-list --user a:a --ftp-create-dirs
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 3610 0 0 100 3610 0 14744 --:--:-- --:--:-- --:--:-- 14855
Cool! We got the file off of the modem and onto our disk.
The write was into a nonexistent subdirectory (dir/
) to verify that the folder creation works as expected.
Let’s verify that the files completely match (better safe than sorry ;)).
➜ md5sum dir/file-list
8a42f8a0f216cf77eff8721fc8ab3cde dir/file-list
/mnt/userdata/cache # md5sum file-list
8a42f8a0f216cf77eff8721fc8ab3cde file-list
Now we can go ahead with the complete filesystem dump.
Since the USB upload rates (modem to PC) are really slow with this modem then this is the right moment to switch over to WiFi.
This takes a while, especially since we’re also dumping the /sys/
directory.
~ # find / -type f -follow -maxdepth 10 -exec curl -T {} ftp://192.168.0.100:5000/{} --user a:a --ftp-create-dirs \;
PS. For the transfer over WiFi I plugged it into one of those USB power meters. According to the meter (of unverified accuracy) the idle current is around 10 mA and average current when dumping files over WiFi is around 80 mA. Keep in mind that the LTE network was not connected. 5 V input voltage, like all USB devices ;). Saw peaks at around 200 mA, which would result in a power dissipation around 1 W. Guess that itty bitty heatsink makes some sense.