Attackers stand up SOCKS proxies on compromised hosts to reach segments they cannot route to directly, using SSH -D, Chisel, Meterpreter, Cobalt Strike or a bespoke listener. The proxy is rarely noisy on the host, so the useful signals are an unexpected listening socket and east-west traffic that follows the SOCKS handshake.
Signals at a Glance
| Signal | Where | ATT&CK |
|---|---|---|
| New TCP listener on 1080, 9050, 8888 or high port by a non-proxy process | EDR listening-connection events | T1090.001 |
| SOCKS4/5 protocol records between internal hosts | Zeek socks.log, NGFW app-ID | T1090.001 |
| ssh -D or plink -D opening a local dynamic forwarder | Sysmon 1, auditd, EDR | T1572 |
| One workstation initiating connections to many internal hosts on behalf of a single inbound session | Flow, EDR | T1090 |
| Proxy tooling arguments (socks, -D, R:socks) on the command line | Process creation | T1090.001 |
Unexpected Listeners
Most workstations have no reason to accept a SOCKS connection. EDR platforms record listening sockets, which lets us flag any process that opens a listener on a classic proxy port or an unusual high port outside the normal application set:
// Microsoft Defender XDR (KQL) - new proxy-like listeners
DeviceNetworkEvents
| where Timestamp > ago(7d)
| where ActionType == "ListeningConnectionCreated"
| where LocalPort in (1080, 1081, 9050, 9150, 8888, 10808)
| where InitiatingProcessFileName !in~ ("tor.exe", "firefox.exe", "chrome.exe")
| project Timestamp, DeviceName, LocalPort, InitiatingProcessFileName,
InitiatingProcessCommandLine, InitiatingProcessAccountName
// tune/validate: the port list is a hunt starting point, not a boundary;
// pair with first-seen listening process per host to catch random ports.
Wire-Level SOCKS Handshakes
Zeek parses SOCKS4 and SOCKS5 requests into socks.log, recording the requested host, port and whether the proxy replied with success. Internal-to-internal SOCKS is rarely legitimate, which makes it a high-value hunt:
# Splunk (Zeek socks.log) - internal SOCKS use, ranked by distinct targets
index=zeek sourcetype=bro_socks
| where cidrmatch("10.0.0.0/8", 'id.resp_h') OR cidrmatch("192.168.0.0/16", 'id.resp_h')
| stats count AS requests, dc(request.host) AS targets, values(request.port) AS ports
BY id.orig_h, id.resp_h, version
| where requests > 5
| sort - targets
# tune/validate: adjust the RFC 1918 ranges to your network and exclude
# approved forward proxies and security tooling.
- Follow the chain: the host with the listener is the pivot, and its outbound connections to internal services are the operator’s actions.
- Treat a SOCKS listener that appears minutes after an inbound administrative logon as higher risk than one on a developer machine.
- Alert on proxy settings that point a browser or tool at 127.0.0.1 on a high port when the process is a script interpreter.
- Use NGFW app-ID for socks to catch listeners on non-standard ports.
Use the Zeek SOCKS analyzer documentation, SigmaHQ rules for proxy and tunneling tool execution, Elastic rules covering internal proxy behaviour and your firewall app-ID. Always baseline your own environment — legitimate forward proxies and developer tooling will appear, so build an allow-list before alerting.
Build Detections That Fire
Mjolnir Security helps blue teams turn threat intelligence into high-fidelity detections across endpoint, network, identity and cloud telemetry.
- Detection Engineering We build and tune detections mapped to ATT&CK from your own telemetry.
- Threat Hunting as a Service Hypothesis-driven hunts for the behaviours on this page.
- 24/7 Incident Response Containment when a detection fires. Call +1 833 403 5875.
Stay ahead of emerging threats. Get notified when we publish new intelligence reports and advisories.
Subscribe to Alerts