The approach to this challenge was completely different from the past two months, as the vulnerable component was on the backend, forcing us to approach it as a black box scenario.
The page presents a simple submittable get form providing the open and payload parameters. To reach that from the UI, a user has to click the candy multiple times, until it opens and shows the input field.
1. Finding reflection points
Following the form structure, the page accepts a payload parameter which would be reflected inside of an h4 tag if supplied.
Right after the reflection point, a comment saying “Referer:” si shown, but not holding any value. This is happening because I’m using burp suite, which gives you full control on the request avoiding
any built-in browser behavior, such as the Referer header. mentioning the mozilla documentation:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/RefererThe Referer HTTP request header contains an absolute or partial address of the page that makes the request. The Referer header allows a server to identify a page where people are visiting it from.
This header is usually automatically set by the browser, so using a proxy would require to set it manually.
Once submitted a request containing a referer header, it gets reflected inside of the comment, so at this point two injection points are available: the payload GET parameter, and the Referer header.
2. Input sanitation detection and bypass
Going back to the payload parameter, some input sanitation is being made, removing anything between < and >, recursively.
This filter is effectively avoiding HTML Injections, as any valid or invalid tag would be removed.
This scenario was pretty familiar to me, so i decided to move on to the referer header without wasting too much time.
This kind of sanitation “sounded” even worse to me. Encoding HTML Entities should be one of the correct ways to handle this kind of injection hardening, but things can go wrong.
I started googling on how to encode HTML entities in PHP, finding the htmlentities method. https://www.php.net/manual/en/function.htmlentities.php
warning: the next paragraph is just a supposition. Other methods could have been used, and i could be completely wrong.
htmlentities accepts 3 parameters: a string to escape, the “configuration flags”, and the text encoding.
researching about bypasses for such method, i encountered this thread https://stackoverflow.com/quest ions/1891392/is-htmlentities-bullet-proof mentioning this article https://shiflett.org/blog/2005/google-xs s-example.
Tl.Dr. if no encoding is specified, it could be possible to bypass the sanitation by providing a different text-encoding than the one used from the application.
Another scenario would comprend some explicit unicode normalization. https://unicode-programming.re adthedocs.io/en/latest/normalization/php/, but I tought that it was really unlikely possible.
in both supposed cases, the exploit approach would be the same.
I knew this kind of vulnerability as Unicode Smuggling.
from now on I followed this article https://jlajara.gitlab.io/web/2020/02/19/Bypass_WAF_Unicode.html.
The trick here happens when the application doesn’t recognize a character into its charset and tries to normalize it into a known one. So in our case, we are looking for a valid equivalent char for < and > in a charset unknown to the application.
To detect unicode normalization, i tried by supplying %F0%9D%95%83%E2%85%87%F0%9D%99%A4%F0%9D%93%83%E2%85%88%F0%9D%94% B0%F0%9D%94%A5%F0%9D%99%96%F0%9D%93%83, which is the url encoded value for
3. Triggering self XSS
The used payload is:
-->test<img src=x onerror=alert(document.domain)>
which URL encoded results into:
Note that the special chars are multibytes, so they take more than 3 url chars to be represented.
So by sending the request to the browser, an alert is triggered, because burp suite keeps the referer header.
4. Delivering the exploit
The injection point is not the URL, so things are different than usual. I’ve actually never exploited a scenario like this, so it was really interesting.
As mentioned before, the Referer header is where the user got the reference to the page.
For example, if a user click a link to http://target from http://acoolblog/article.php?id=1, the referer would be http://acoolblog/article.php?id=1.
my first approach has been really similiar to a cross site request forgery, where the initial URL was containing the payload. Unfortunately only the domain was getting reflected, missing the URI containing the payload, so I moved on another approach, using GitHub.
Edit: The referer header was missing the URI because of the referer policy, which I should have set to “unsafe-url“.
More information at https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy
I started by creating and locally cloning a public repository.
Once cloned, I created a markdown (.md) file named as the payload, containing a clickable link to the challenge website
then, I pushed it on github
Once pushed, it’s possible to view it on my repository at https://github.com/imMentats/weird
When a user clicks on “click to get a cookie”, it gets redirect to the challenge website sending a request having the referer header set as the repo URL. Because of this, the reflected referrer break out of the comment, and triggers an alert.