Attribution: It’s one of the most difficult parts of trying to tell people, “Hey… your fly is open.”
I’m not talking about the whole 21st century “spin the big wheel of attack attribution” game that various security firms like to play (“Aaaaaaaand… ittttttsssss… CHINA, No! Wait! It looks like it might spin past CHINA and on to… NORTH KOREAAAAAAAAA!!")
What I’m talking about here is real attack attribution. Identifying the owner of a compromised system that is attacking others on the ‘Net so I can contact them and get them to clean it up. It’s about making the ‘Net a better place, not about making headlines.
While I’m sure that there is little to no guesswork involved in any of the high profile “nation state” attack attributions that have taken place over the past few years (cough, cough… The bad guys may be sophisticated enough to hack our systems, but they can’t be smart enough to evade our monitoring, or to misdirect us into an incorrect attribution…)
Sadly, in my case, there’s a lot of guesswork involved: WHOIS sucks in a plethora of ways, reverse-DNS rarely works, and abuse@ ISP emails are a frickin’ black hole.
It’s tough, so I need to get a little creative at times.
Here’s a little trick that has been fairly helpful with identifying compromised Windows systems being used for RDP brute-force scanning. Generally, those boxes have, themselves, been compromised by an RDP brute-force attack and oftentimes have only 3389/TCP open to the ‘Net.
Enter the pentester’s BFF: Nmap.
I’ve found it incredibly helpful to take a look at the SSL certificate that RDP connections use to identify the server you’re connecting to. I’ve tried reading through Microsoft’s literature to figure out just how “default” support for RDP over SSL/TLS may be, but reading MS docs gives me a headache. I think that it’s been the default since Windows 2003 SP1 (which makes me REALLY wonder about the systems I’ve found that DON’T seem to support SSL/TLS). In any case, grabbing the SSL cert (self-signed by default) will sometimes cue me into what the machine itself thinks it is called.
The problem is, out of the box, Nmap doesn’t really consider port 3389/TCP a worthy target from which to gank SSL certificate details. We can fix this little oversight in a couple of different ways:
- We can force Nmap to run the “ssl-cert” script on a non-standard port, by putting a “+” in front of the script name:
sudo nmap --script=+ssl-cert -Pn -v -p 3389 ip address
- We can edit Nmap’s “shortport.lua” script so it’ll consider that port 3389/TCP might potentially be running SSL/TLS:
- On my system, the path to the script is: /usr/share/nmap/nseLib/shortport.lua
- Look for where local LIKELY_SSL_PORTS is defined, and add port 3389 to the list
Either way, running the “ssl-cert” script against 3389/TCP will give you output like the following:
Starting Nmap 6.00 ( http://nmap.org ) at 2016-05-23 15:25 UTC NSE: Loaded 1 scripts for scanning. NSE: Script Pre-scanning. Initiating Parallel DNS resolution of 1 host. at 15:25 Completed Parallel DNS resolution of 1 host. at 15:25, 0.04s elapsed Initiating SYN Stealth Scan at 15:25 Scanning [REDACTED] ([REDACTED]) [1 port] Discovered open port 3389/tcp on [REDACTED] Completed SYN Stealth Scan at 15:25, 0.18s elapsed (1 total ports) NSE: Script scanning [REDACTED]. Initiating NSE at 15:25 Completed NSE at 15:25, 0.45s elapsed Nmap scan report for [REDACTED] ([REDACTED]) Host is up (0.11s latency). PORT STATE SERVICE 3389/tcp open ms-wbt-server | ssl-cert: Subject: commonName=[REDACTED].local | Issuer: commonName=[REDACTED].local | Public Key type: rsa | Public Key bits: 2048 | Not valid before: 2016-03-05 04:16:22 | Not valid after: 2016-09-04 04:16:22 | MD5: 5c91 9462 be4e 0bef 820f a8b4 0026 c932 | SHA-1: ba2e 8bf0 a1a5 b14a ec96 49b3 2ae2 575d ba4b 5d66 | -----BEGIN CERTIFICATE----- | MIIC+jCCAeKgAwIBAgIQH4J1F+xOgIpBJq67+uKwVzANBgkqhkiG9w0BAQUFADAm | MSQwIgYDVQQDExtQVENEQi5wZWFjaHRyZWVjZW50cmUubG9jYWwwHhcNMTYwMzA1 | MDQxNjIyWhcNMTYwOTA0MDQxNjIyWjAmMSQwIgYDVQQDExtQVENEQi5wZWFjaHRy | ZWVjZW50cmUubG9jYWwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC0 | CssawyOUM4nvB4MqGy3QbJTl8SvGbHMASLQIhr2YVQ8B3DYkQZFIuIRtOiAvLdNx . . . | tVLLJ6nNYD8y/LKcrx4aZk7Re0fJuaF9yw49dQHAElXJMf+lQ0LdQMrjmcSQU9d6 | aoYVfjE21arWw+M0+1GVFVy9lv2Y/qmuCV699YpVp43I+P9O+vVw8HQH82izB6iR | uTm2/CApQ6gDryN/wCvbat0bRA1u9Oab6oMUFEMoJzOFsczTMoIkKQSxY6ghrom6 | dDnCkRCIID+HxQFUKQMdlCL4rgas4GO3We7aTtq7Fw7FZAR2jBy085uZq8+WbTld | cxmEqxtCr3hHHrULs3IZLup3sHi05z5diqQy3jF7UAonVlcq6XGyC1hVOk7ngA== |_-----END CERTIFICATE----- NSE: Script Post-scanning. Read data files from: /usr/bin/../share/nmap Nmap done: 1 IP address (1 host up) scanned in 1.37 seconds Raw packets sent: 1 (44B) | Rcvd: 1 (44B)
The “common name” found in that particular scan, coupled with some IP address geolocation information allowed me to contact some folks who had been compromised, making the Internet a safer place and getting me one step closer to the day when I am rightfully canonized by the Church of Flying the Spaghetti Monster as the Patron Saint of Compromised Hosts.
Owner, Principal Consultant
Bad Wolf Security, LLC
May 23, 2016
Update: I’ve since learned that this is fixed in the current version (7+) of Nmap. The “fix” is still relevant if you’re running an older version of Nmap, and the idea of getting identifying information via RDP is always valid :-)