This was one of the web challenges. Congrats to 0daysober and LC/BC for solving it!
To run it locally just do
docker-compose build && docker-compose up.
There are several steps to successfully exploit it.
You can leak the source code by navigating to
After auditing the source code, you will find that the application unserializes strings from the database that have the prefix
$serializedobject$. However, there is a check to prevent you from injecting strings of that form into the database. Luckily, MSSQL automatically converts full-width unicode characters to their ASCII representation. For example, if a string contains
0xEF 0xBC 0x84, it will be stored as
SoapClient can perform POST requests if any method is called on the object. The
Attachmentclass implements a
__toStringmethod, which calls
zaproperty. Serializing a SoapClient as
zaproperty will therefore lead to SSRF.
SoapClient CRLF injection
There is a proxy running on
127.0.0.1:8080, which you want to reach. Looking at the nginx configuration, it only accepts GET requests. However, SoapClient generates POST requests. But the
_user_agentproperty of SoapClient is vulnerable to CRLF injection and thus you can perform a request splitting. By injection
\n\nfollowed by a valid GET request, you can reach the proxy via a GET.
miniProxy URL scheme bypass
Here I fucked up a bit. Intended solution was to bypass the check for http/https in miniProxy. This is possible by using
gopher:///...as miniProxy only verifies http/https if the host is set. Unfortunately, you can also just bypass it with a 301 redirect to gopher... SAD! :D
Connect to MSSQL via gopher
Final step was to connect to MSSQL via gopher using the credentials from the source code leak. The only thing to look out for here is that gopher automatically adds a
\r\nto the request, which has to be accounted for when creating the MSSQL packets.
The miniProxy does not return the output of the request if the resulting URL is different from the requested URL (which it is in our case). Therefore to get the flag you want to copy it to one of your posts:
INSERT INTO posts (userid, content, title, attachment) VALUES (123, (select flag from flag.flag), "foo", "bar");-- -. You can find your user id by sending a request to the application with the header
To run the exploit do