It's easy to find attack surfaces that others haven't.
You just need to think creatively.
"But Corben, I don't know how!"
That's what I'm here for.
I'll share some simple methodology that works.
(so you can find vulnerabilities...and make money)
A story:
You just need to think creatively.
"But Corben, I don't know how!"
That's what I'm here for.
I'll share some simple methodology that works.
(so you can find vulnerabilities...and make money)
A story:
1/ I went to Shodan.
Searched for my target with the SSL certificate name filter:
> ssl.cert.subject\.cn:*.example[.]com
I came across a server that had a certificate for:
"*.apps.███\.com"
Interesting.
When I see wildcards, I immediately think that the server
Searched for my target with the SSL certificate name filter:
> ssl.cert.subject\.cn:*.example[.]com
I came across a server that had a certificate for:
"*.apps.███\.com"
Interesting.
When I see wildcards, I immediately think that the server
2/ Is an ingress endpoint.
Think load balancer: routing hostnames (via the Host header) to their respective microservice.
Still confused?
Here.
Think of it as a magic door at a hotel:
• The door (load-balancer) has a list of names
• You tell the door your name and
Think load balancer: routing hostnames (via the Host header) to their respective microservice.
Still confused?
Here.
Think of it as a magic door at a hotel:
• The door (load-balancer) has a list of names
• You tell the door your name and
3/ The door checks the list.
• If you're on it, it sends you to a room.
• If you say a different name (that's still on the list) you get a different room.
• If you say a name that's not on the list, you get turned away.
So,
• If you're on it, it sends you to a room.
• If you say a different name (that's still on the list) you get a different room.
• If you say a name that's not on the list, you get turned away.
So,
4/ In this scenario we're guessing "names" via the Host header.
Hoping it will return internal applications (or apps others haven't seen).
So,
I grabbed the default response (when sending an invalid host) using cURL:
Hoping it will return internal applications (or apps others haven't seen).
So,
I grabbed the default response (when sending an invalid host) using cURL:
3/
$ curl https://██ -H "Host: invalid12345.apps.███\.com"
Response:
> 404 Not Found: Requested route ('invalid12345.apps.███\.com') does not exist.
So I brute-forced it with ffuf:
$ ffuf -u https://██ -H "Host: FUZZ.apps.███\.com" -mc all -fw 9
And
$ curl https://██ -H "Host: invalid12345.apps.███\.com"
Response:
> 404 Not Found: Requested route ('invalid12345.apps.███\.com') does not exist.
So I brute-forced it with ffuf:
$ ffuf -u https://██ -H "Host: FUZZ.apps.███\.com" -mc all -fw 9
And
4/ I got a lot of hits!
One of them was the hostname:
spl-api.apps.███\.com
Remember.
We are routing to these hosts via a load-balancer.
By specifying them in the "Host:" header.
Next was content-discovery.
So,
One of them was the hostname:
spl-api.apps.███\.com
Remember.
We are routing to these hosts via a load-balancer.
By specifying them in the "Host:" header.
Next was content-discovery.
So,
5/ I ran ffuf:
$ ffuf -u https://LOADBALANCER/FUZZ -H "spl-api.apps.███\.com" -mc 200
I came across "/v2/api-docs"
That's SwaggerUI docs.
It has definitions of API routes.
Where they are.
What they accept (HTTP method, params).
So,
$ ffuf -u https://LOADBALANCER/FUZZ -H "spl-api.apps.███\.com" -mc 200
I came across "/v2/api-docs"
That's SwaggerUI docs.
It has definitions of API routes.
Where they are.
What they accept (HTTP method, params).
So,
6/ One route stuck out:
"/spl/api/teardown/file"
It accepted a query parameter: "fileName".
So I tried the following:
$ curl "https://LOADBALANCER/spl/api/teardown/file?fileName=/etc/passwd" -H "spl-api.apps.███\.com"
Response:
> "File not found"
Hmm, what about trying
"/spl/api/teardown/file"
It accepted a query parameter: "fileName".
So I tried the following:
$ curl "https://LOADBALANCER/spl/api/teardown/file?fileName=/etc/passwd" -H "spl-api.apps.███\.com"
Response:
> "File not found"
Hmm, what about trying
7/ to traverse back with "../"
The app might be joining paths like
> path.Join("/documents", fileName);
So I tried:
$ curl "https://LOADBALANCER/spl/api/teardown/file?fileName=../../../../../etc/passwd" -H "spl-api.apps.███\.com"
And
The app might be joining paths like
> path.Join("/documents", fileName);
So I tried:
$ curl "https://LOADBALANCER/spl/api/teardown/file?fileName=../../../../../etc/passwd" -H "spl-api.apps.███\.com"
And
8/ It worked!
Got the contents of /etc/passwd :)
Easy path traversal just by finding attack surface others hadn't.
Got the contents of /etc/passwd :)
Easy path traversal just by finding attack surface others hadn't.
TLDR:
• Found a server that had a wildcard certificate
• Brute-forced Host headers with FFUF
• Found an API, then found /v2/api-docs
• Discovered an endpoint that had a parameter "fileName"
• Tried path traversal and it worked.
I spend a lot of time writing these stories.
So, if you enjoyed:
• I have a newsletter! Sign up if you want: newsletter.threat.dev
• feel free to follow @hacker_ (or don't!)
• consider my caffeine addiction: buymeacoff.ee
So, if you enjoyed:
• I have a newsletter! Sign up if you want: newsletter.threat.dev
• feel free to follow @hacker_ (or don't!)
• consider my caffeine addiction: buymeacoff.ee
Loading suggestions...