This post spoils a CTF challenge … Don’t read if you want to try it !
ECW (European Cyber Week) is a Jeopardy student CTF challenge. It is organized by Thales, Airbus and the Bretagne region. I had a great time solving these challenges, despite a little abusive guessing in stegano challenges. Hurry to hand over this !
Troll.JSP is a Web challenge based on CVE-2017-5638. Several hints were present in hashes to guide us but I totally missed them, so I had to guess some parts and bypass some filters. You can check Haax’s write-up or maki’s write-up to see different solutions.
We are facing a simple website :
No information at first sight… but HTML comments are our friends.
Let’s request this non-indexed page :
Hum, this is not really verbose. But at least, we know something : if we can inject something in #session variable, we will be able to see the output on this page.
A flag page is available, let’s request it too.
Obviously, this is a troll flag. But this hash is a known one, and it contains an hint about one way to solve the challenge. I totally missed the hint, but you can check Haax’s write-up to see a solution which use it.
After trying a few pages, I noticed an error message on some requests, indicating that the web server is using Apache Struts and Apache Tomcat. I started testing all known Tomcat and Struts vulnerabilities.
Some tries later, I noticed that the Content-Type header was filtered against dots, parenthesis etc… (returns blank page). This uncommon behavior reminded me the CVE-2017-5638 in Apache Struts, which is precisely an exploit based on Content-Type header.
I first tried to confirm that the vulnerability was working. Let’s input a simple payload which is not filtered in the Content-Type header and request debug.jsp page.
But many characters are filtered, so we can’t use common payloads… There are several solutions to bypass this : the most clever solution I saw is maki’s one, which exploit a CVE-2017-5638 variant where the payload is located in the Content-Disposition header so it bypasses the Content-Type filtering in place here.
I found that another simple way to bypass the filtering was to use UTF encoding with \uXXXX.
Final payload is :
After encoding :
The flag is hardcoded in flag.jsp source, so we can retrieve it with
Thanks to Haax for the screenshots ! I totally forgot to take some during the CTF :(
Feel free to tell me what you think about this post :)