Unique XXE to AWS Keys journey
Version en español: acá
Always trust your feelings and try everything, even if you think its crazy or will not work… it may work. If you run out of ideas, go away and they will come
Been asked to do a private web pentest (too bad it was not a bugbounty program). It’s my first paid one so I wanted to do it as best as I can. The client is a company with presence in 15+ countries, 120+ clients worldwide and 12+ million final users. So that’s a lot.
I will go directly to relevant results, so don’t think it was all open doors. When I ask a question to you or there is an image, please take a time to think what would you do next before reading what I did, take it as a practice.
I been given a domain to test and a user/password, so let’s get started. At first sight I can see the application is huge and very robust. It has many functions to test, many profiles, so I start runing a basic dirsearch just to see what is there in the background.
Some xml configuration files appeared implying there is a Tomcat somewhere. Reading the contents of the xml file I notice some <url-pattern> tag, so mi instinct told me to try some GET requests with Burp to see what response I get.
Response has Server: nginx header… so what does this architecture looks like? Like this
So the endpoint exists but it did not like GET request type so I tried POST.
In response you can see there is a Content-type header with text/xml value, so the response should contain a valid XML. In this case I only got “Could not access envelope: Unable to create…” error.
So, what would you try?
I went directly to the worst case escenario I thought of where there is an XXE vulnerabily. So I got some XXE payloads googling “XXE payloads”.
I added Content-type Request header with text/xml (because that is what the server is expecting and I have to tell him what the hell am I sending) and I copypasted the very first payload which tries to access /etc/passwd file. And this happened
So what’s going on ?
Response code was 200 (OK). Its seems like server is trying to read the contents of /etc/passwd file and make a valid XML file to craft a Response, but the final XML is not well formed because some thing in line 33 of /etc/passwd breaks parsing.
Now we know that maybe /etc/passwd file has 33 lines. I asked the Client that and he confirmed that the web server has a /etc/passwd file with 33 lines long.
So the next thing is to try to get the contents and we are done! Until now, in a bugbounty program this may not be considered as a POC, because we cannot do any harm to anyone with this. So you must keep digging until you have some hot pottatoe.
I made a SSRF Request and it worked! I knew port 8080 was the default port for Tomcat server.
So I tried that
The server made a request to himself to obtain the external DTD and answered with an error. It tried to parse the HTML I requested and it raises an error. Later I found the HTML code was this
So I tried another port to see how it behaves
So port 8081 is closed. We can check every port with Burp Intruder and see responses (its like an nmap but HTTP) just to check what other services are there (until now we only know port 8080).
There were at least 8 ports open (only tried nmap top 1000)
So I wanted to get some juicy files contents and here comes the “try harder” part. Tried maaany payloads (except DoS ones) one by one, modified them in every way I could think of, tried wrappers like file://, php://, dict://, expect:// etc., but they were disabled, read many writeups, and nothing… until I managed to make one payload to work but with an UNIQUE TWIST.
The mechanisms looks like this:
So, instead of sending the Request with all the XML file at once like before, some part of it is hosted on my own host (External DTD). So the web application has to gather all parts of the XML to understand it and then make some Response (we already demonstrate local resources access with SSRF, but.. what about internet resources?)
What do you see in External DTD that’s weird?
I hosted the External DTD file (a.dtd) in my own host. So the weird part comes as I didn’t request /etc/passwd file (I did it like before and receive the same “Error on line 33…” Response).
I requested /
And this was the response
Wait, WHAT?
YES! Thats the weird and amazing part! Instead of getting an error, I got directory listing ! Never read/heard of this behavior before in any writeup I have ever read, but this is GOLD! Do you know why it happens? I didn’t… some days after this found this. It seems that Java lists directory contents when a directory is requested instead of a file.
So instead of trying to guess some files and directories, I took my time to manually browse many folders to gain more impact.
Ended up finding a lot of private keys, config files, sensitive data, third party service passwords, clients information, etc.
But the most important data I found was… AWS credentials! Tried to get some through AWS metadata but I received ones with 0 (zero) privileges.
In a folder like /xxx/xxx/xxx/xxx/credentials was this
I run out to find what privileges they have with PACU and AWS CLI.
Found out that they had root access, so… what’s there more juicy than that?
What would you do with that kind of access?
For example, a cybercriminal could:
- Change instances states: he could terminate all of them (there is no more service, or.. no more Company?), start, stop or create new ones
- Make use of them (mine bitcoins, deploy backdoors, scripts). Imagine billings…
- Steal data (credit cards, personal information),
- Deny access
- Anything…
So, just to check since the application is hosted on an AWS EC2 (just a cloud computer hosted on Amazon’s datacenter) I tried to acces it’s metadata through SSRF like before. It also worked! (with external DTD, not with the basic payload, requesting http://169.254.169.254/latest/meta-data/iam instead of file:///)
At this point the contents of /etc/passwd were trivial
Conclusions
I am super happy with the results I got. Managed to find some other things like XSS, outdated software and some more.
So I learnt:
- XXE
- SSRF
- Port scanning with SSRF
- Proxy / Backend architecture
- To have patience
Takeaways
- Always try to escalate bugs and go as deep as you can
- Do manual testing, so far I got the best results rather than automating (was useful for port scanning part with SSRF)
- When you face a problem, try all the things that comes to your mind like I did (a lot will come if you had read consciously writeups and information and suddenly all dots and info comes togheter to aid you!! )
- Be organized and take notes & screenshots (maybe the client fixes the problem in the meantime and you have nothing otherwise)
- If you get stuck, take some time off and come back with new fresh ideas
- Try to chain bugs or vulnerabilities you found and use them togheter for your advantage
- We know nothing (right? this is a neverending learning journey), so ask for help, advice or directions if you need to (you can do it in an anonymously way too)
- Be ethical and humble with the Client, they have developers / infra people that are humans and made mistakes like we do. Work with them to solve the issues
- Learn from all the things you did. Notice that if you have to do some testing with similar infrastructure you have experience already! You will try to go directly to the hot part !
- Take some time off and sleep well, your brain will continue to process all what you have learn so far
- Share with the community !
Hope you enjoyed, thanks for reading so far !!!