CTF Una-Al-Mes La casa de papel 1ª parte. Write-up Una al Mes Mision 004: Write-Up » Transform your Hak5 Packet Squirrel into an automatic TOR annonymizer Preamble I’ve been testing some Hak5 devices recently. I have to admit that they are all incredible, easy to use and well-designed. The Packet Squirrel is an incredible small MIPS device, based on OpenWRT, full of possibilities. Although its main goal is to perform advanced MitM attacks, it can be used for the common good as well. Being a MIPS device, some of the most used and well-known utilities and programs are included, but of course some others are not. TOR, for instance, it’s not installed out-of-the-box. That’s not a problem, of course, because you can always get its sources and cross-compile it. So I thought that using the Packet Squirrel for routing all the TCP traffic from a “TARGET” computer would be nice. Instead of using the device to perform MitM attacks, this would showcase its possibilities in quite another way. Get to know the device Before trying to cross-compile TOR, we need to know which libraries and hardware the device runs on. So we connect the device to our computer using the “ETH IN” device, we power it on and we connect to it using an SSH session. Then we perform the usual commands to get the standard C library used, its Kernel version, OpenSSL version, system architecture, and so on: uname -a

Linux squirrel 3.18.45 #13 Mon Oct 30 21:24:27 UTC 2017 mips GNU/Linux cat /proc/cpuinfo |grep model

cpu model : MIPS 24Kc V7.4 ls -l libc.so.0

lrwxrwxrwx 1 root root 21 Oct 30 21:24 libc.so.0 -> libuClibc-0.9.33.2.so busybox |head -1

BusyBox v1.23.2 (2017-09-06 11:27:56 UTC) multi-call binary. That’s fine; but we still need to know if the architecture is Big Endian or Little Endian, and of course if the processor is either MIPSR1, MIPSR2, or whatever. There are myriads of ways to do so, but we can just grab a binary from the squirrel and use readelf. The “busybox” binary will do: readelf -h busybox |more

ELF Header:

Magic: 7f 45 4c 46 01 02 01 00 01 00 00 00 00 00 00 00

Class: ELF32

Data: 2’s complement, big endian

Version: 1 (current)

OS/ABI: UNIX – System V

ABI Version: 1

Type: EXEC (Executable file)

Machine: MIPS R3000

Version: 0x1

Entry point address: 0x4038a0

Start of program headers: 52 (bytes into file)

Start of section headers: 0 (bytes into file)

Flags: 0x74001005, noreorder, cpic, o32, mips16, mips32r2

Size of this header: 52 (bytes)

Size of program headers: 32 (bytes)

Number of program headers: 7

Size of section headers: 0 (bytes)

Number of section headers: 0

Section header string table index: 0 Now we have everything we need to start the cross-compilation of TOR. The following table summarizes all of our findings: Component Software Version Standard C Library uClibc 0.9.33.2 SSL OpenSSL 1.0.0 Linux BusyBox 1.23.2 Kernel Kernel for MIPS 3.18.45 Architecture MIPS 32 Big Endian MIPS32R2 Setting up the cross-compilation framework Although there are a bunch of ways to setup a cross-compilation framework, I have chosen Buildroot. After downloading this version, I have changed some basic things according to our previous table. Mind me, this version of Buildroot ships with newer versions of uClibc and OpenSSL, but we can fix that later on. You can find my configuration file for the buildroot framework here. After performing the first compilation, I modified the uclibc and openssl packages to meet the Squirrel versions. According to the Buildroot documentation, there are some ways to customize your environment but I went the quick and dirty way instead. First, I did the following changes to build uClibc 0.9.33.2: I downloaded uClibc 0.9.33.2 under $BUILDROOT/dl: wget https://www.uclibc.org/downloads/uClibc-0.9.33.2.tar.xz.

I added the sha256sum of uClibc-0.9.33.2.tar.xz to $BUILDROOT/package/uclibc/uclibc.hash.

I changed uClibc version and package name in $BUILDROOT/package/uclibc/uclibc.mk accordingly. After that, I did the same with the libopenssl package: I downloaded libopenssl 1.0.0.s under $BUILDROOT/dl: wget https://www.openssl.org/source/old/1.0.0/openssl-1.0.0s.tar.gz.

I added its sha256sum to $BUILDROOT/package/libopenssl/libopenssl.hash

I changed libopenssl version and package name in $BUILDROOT/package/libopenssl/libopenssl.mk

I commented out the LIBOPENSSL_PATCH variable in $BUILDROOT/package/libopenssl/libopenssl.mk.

I moved all the patches to another directory to prevent the build system from applying them (because it was a different version, the patch command would fail): mv *.patch foo. After all these changes, I performed the “make -j8” once again. At some point, when the libopenssl package was about to be installed, I got an error concerning the “install_docs” and “doc” rules. So I removed the “doc” directory from the EDIRS variable in $BUILDROOT/output/build/libopenssl-1.0.0s/Makefile along with the “install_docs” rule in the install rule. After performing the compilation again, the following error showed up: ../libssl.so: file not recognized: File truncated. So I deleted this truncated file and executed “make -j8” again. This time the compilation ended without errors and the new libraries were sucessfully installed. Finally, I removed the entire libevent from my previous built: rm -rf $BUILDROOT/output/build/libevent* and then I re-compiled it using the new OpenSSL libraries: make -j8. The buildroot environment was ready to use. Cross-compiling TOR Because our Packet Squirrel does not include the libevent library, I decided to build TOR statically linking libevent with the resulting binary. The PAcket Squirrel does not have support for some well-known modern protections, so I disabled any hardening during the compilation as well. The configure command I issued was this: ./configure –target=mips-buildroot-linux-uclibc –host=mips-buildroot-linux-uclibc –build=x86_64-pc-linux-gnu –prefix=/home/tonic as/buildroot/target/opt/tor –enable-static-libevent –with-libevent-dir=/home/buildroot/buildroot/build/libevent-2.1.8-stable/.libs/ –e nable-static-zlib –with-zlib-dir=/home/buildroot/buildroot/build/libzlib-1.2.11 –disable-gcc-hardening –disable-linker-hardening –disable-tool-name-check –disable-threads –disable-asciidoc After that, I built and installed TOR: make -j8 install. Finally, I copied all the files under $BUILDROOT/output/target/opt/tor to the Packet Squirrel, on its USB pendrive (previously formatted using EXT4): scp -r $BUILDROOT/output/target/opt/tor root@172.16.32.1:/mnt/ The payload Because this device does not have too much free space, I had to setup some directories on the USB pendrive to accommodate some TOR files (logfiles and the like). With that done, I wrote the following payload: #!/bin/bash # TOR payload # 2018 by T. Castillo Girona # This is a simple payload that allows to route all the DNS queries and TCP # traffic from a TARGET through TOR. LOGFILE = / mnt / tor / logs / payload.log TOR = / mnt / tor / bin / tor TORCFG = / mnt / tor / etc / tor / torrc TORLOG = / mnt / tor / logs / tor.log IPTABLES = / usr / sbin / iptables function grab_target_ip ( ) { target_ip = ` cat / tmp / dhcp.leases | awk '{print $3}' ` if [ ! -z " $target_ip " ] ; then # Set the led to BLUE: LED B echo $target_ip else # Set the LED to fail: LED FAIL2 echo " `date` STAGE2: TARGET IP : Not a DHCP lease" >> $LOGFILE sync echo "" # Stop the payload: exit 1 fi } function start_tor ( ) { if [ -x $TOR -a -r $TORCFG ] ; then # Delete any previous log: rm -rf $TORLOG 2 >/ dev / null sync # Start tor: echo " `date` STAGE3: EXECUTING TOR" >> $LOGFILE sync $TOR -f $TORCFG 2 >& 1 & # It may take a while until tor is ready; that's when # its log file says: Bootstrapped 100%: Done echo " `date` STAGE3: WAITING TO HAVE A VALID CIRCUIT " >> $LOGFILE sync while [ true ] ; do cat $TORLOG | grep "Bootstrapped 100%: Done" 2 >/ dev / null sync if [ $? -eq 0 ] ; then # Perfect, we've got a circuit!: LED W echo " `date` STAGE3: WE HAVE A CIRCUIT " >> $LOGFILE break fi done else # No tor binary or no torrc. # We leave it here. LED FAIL3 echo " `date` NO TOR OR NO TORRC FILE." >> $LOGFILE sync fi } function set_ip_tables ( ) { # Enable redirection for UDP DNS packets: $IPTABLES -t nat -I PREROUTING 1 -p udp -i eth0 --dport 53 -j REDIRECT --to-ports 5353 # Enable TCP redirection through TOR: # (don't enable redirection for 172.16.32.0/24): $IPTABLES -t nat -I PREROUTING 2 -p tcp ! -d 172.16.32.0 / 24 -i eth0 -j REDIRECT --to-ports 9040 echo " `date` STAGE4: SETTING IPTABLES " >> $LOGFILE sync } function rerunTor ( ) { echo " `date` STAGE4: RE-EXECUTING TOR " >> $LOGFILE sync # Get pid of TOR process and kill it: ptor = ` pidof tor ` if [ $? -eq 0 ] ; then # Kill it: kill -9 $ptor fi # Re-execute it: start_tor } function run ( ) { # Set networking to NAT # (we get an IP from the network; we assign an IP to the target) # The target gets routed through the Squirrel. echo " `date` STAGE1: SETTING NETMODE NAT " > $LOGFILE NETMODE NAT sleep 20 # Now, make sure our target has a valid IP assigned # by the squirrel. Case it has not, stop the payload. LED STAGE2 targetip = ` grab_target_ip ` echo " `date` STAGE2: TARGET IP IS $targetip " >> $LOGFILE sync # Now, prepare our instance of Tor, make sure it is # running before doing anything else: LED STAGE3 echo " `date` STAGE3: STARTING TOR " >> $LOGFILE sync start_tor # Now set the iptables rules to redirect DNS and # TCP traffic trhough TOR transparently: LED STAGE4 set_ip_tables # Let's set the LED to Success: LED R SUCCESS # Every time the user press the button, we kill # tor, and re-run it again so that the circuit # gets changed every time. while [ true ] ; do NO_LED = 1 BUTTON # Once the button has been pressed, proceed: rerunTor LED R SUCCESS done } # This payload will only run if we have USB storage [ [ ! -f / mnt / NO_MOUNT ] ] && { LED ATTACK run & } || { LED FAIL1 } #!/bin/bash # TOR payload # 2018 by T. Castillo Girona # This is a simple payload that allows to route all the DNS queries and TCP # traffic from a TARGET through TOR. LOGFILE=/mnt/tor/logs/payload.log TOR=/mnt/tor/bin/tor TORCFG=/mnt/tor/etc/tor/torrc TORLOG=/mnt/tor/logs/tor.log IPTABLES=/usr/sbin/iptables function grab_target_ip() { target_ip=`cat /tmp/dhcp.leases |awk '{print $3}'` if [ ! -z "$target_ip" ]; then # Set the led to BLUE: LED B echo $target_ip else # Set the LED to fail: LED FAIL2 echo "`date` STAGE2: TARGET IP : Not a DHCP lease" >> $LOGFILE sync echo "" # Stop the payload: exit 1 fi } function start_tor() { if [ -x $TOR -a -r $TORCFG ]; then # Delete any previous log: rm -rf $TORLOG 2>/dev/null sync # Start tor: echo "`date` STAGE3: EXECUTING TOR" >> $LOGFILE sync $TOR -f $TORCFG 2>&1& # It may take a while until tor is ready; that's when # its log file says: Bootstrapped 100%: Done echo "`date` STAGE3: WAITING TO HAVE A VALID CIRCUIT " >> $LOGFILE sync while [ true ]; do cat $TORLOG|grep "Bootstrapped 100%: Done" 2>/dev/null sync if [ $? -eq 0 ]; then # Perfect, we've got a circuit!: LED W echo "`date` STAGE3: WE HAVE A CIRCUIT " >> $LOGFILE break fi done else # No tor binary or no torrc. # We leave it here. LED FAIL3 echo "`date` NO TOR OR NO TORRC FILE." >> $LOGFILE sync fi } function set_ip_tables() { # Enable redirection for UDP DNS packets: $IPTABLES -t nat -I PREROUTING 1 -p udp -i eth0 --dport 53 -j REDIRECT --to-ports 5353 # Enable TCP redirection through TOR: # (don't enable redirection for 172.16.32.0/24): $IPTABLES -t nat -I PREROUTING 2 -p tcp ! -d 172.16.32.0/24 -i eth0 -j REDIRECT --to-ports 9040 echo "`date` STAGE4: SETTING IPTABLES " >> $LOGFILE sync } function rerunTor() { echo "`date` STAGE4: RE-EXECUTING TOR " >> $LOGFILE sync # Get pid of TOR process and kill it: ptor=`pidof tor` if [ $? -eq 0 ]; then # Kill it: kill -9 $ptor fi # Re-execute it: start_tor } function run() { # Set networking to NAT # (we get an IP from the network; we assign an IP to the target) # The target gets routed through the Squirrel. echo "`date` STAGE1: SETTING NETMODE NAT " > $LOGFILE NETMODE NAT sleep 20 # Now, make sure our target has a valid IP assigned # by the squirrel. Case it has not, stop the payload. LED STAGE2 targetip=`grab_target_ip` echo "`date` STAGE2: TARGET IP IS $targetip " >> $LOGFILE sync # Now, prepare our instance of Tor, make sure it is # running before doing anything else: LED STAGE3 echo "`date` STAGE3: STARTING TOR " >> $LOGFILE sync start_tor # Now set the iptables rules to redirect DNS and # TCP traffic trhough TOR transparently: LED STAGE4 set_ip_tables # Let's set the LED to Success: LED R SUCCESS # Every time the user press the button, we kill # tor, and re-run it again so that the circuit # gets changed every time. while [ true ]; do NO_LED=1 BUTTON # Once the button has been pressed, proceed: rerunTor LED R SUCCESS done } # This payload will only run if we have USB storage [[ ! -f /mnt/NO_MOUNT ]] && { LED ATTACK run & } || { LED FAIL1 } This payload simply setup the Squirrel as a NAT device; it will get an IP from the network on its “ETH OUT” interface and it will assign a dynamic IP Address to the TARGET computer on its ETH IN device. All the traffic from the TARGET computer will be routed through the Squirrel, and thanks to the iptables rules, the UDP packets for DNS and all the TCP packets will be redirected through TOR. Everytime the button is pressed, TOR is killed and re-executed, so a new circuit is constructed. This payload is far from being perfect, but it delivers. Feel free to improve this version. If you do not want to go through all the burden of cross-compiling TOR, you can download the binaries here. Just unzip it directly on the USB pendrive on the Packet Squirrel, copy the “payload.sh” to the desired switch directory, and enjoy!