Double encoding
Double percent encoding is the same as percent encoding with a twist that each character is encoded twice instead of once. This technique comes in pretty handy when attempting to evade filters which attempt to blacklist certain encoded characters, so we can double encode instead and let the filter decode to the original form. This technique only works where recursive decoding is done.
It is the same technique that was used in the infamous IIS 5.0 directory traversal exploit in 2001.
Double encoding sometimes works well in Local File Inclusion (LFI) or Remote File Inclusion (RFI) scenarios as well, in which we need to encode our path payload. Typically ../../
or ..\..\
is used to traverse back to the parent directory; some filters detect this and block the attempt. We can utilize the double technique to evade this.
Introducing double encoding
In percent encoding, if we had %3C
as our percent-encoded character then it gets decoded into <
. In double encoding, the percent-encoded character is again encoded, which means that the %
prefixed hex-character gets encoded again to %25
plus the hex-character of the original character. So if I had to encode <
using double encoding, I'll first encode it into its percent-encoded format, which is %3c
and then again percent encode the % character. The result of this will be %253c
. Normally, this should be decoded only once but there are scenarios where the developer makes the mistake of decoding it multiple times or situations in which this happens by design. This effectively results in bypasses of filters depending on the scenario:
- Normal URL:
http://www.example.com/derp/one/more/time.html
- Percent encoded:
http%3A%2F%2Fwww.example.com%2Fderp%2Fone%2Fmore%2Ftime.html
- Double encoded:
http%253A%252F%252Fwww.example.com%252Fderp%252Fone%252Fmore%252Ftime.html
IIS 5.0 directory traversal code execution – CVE-2001-0333
In 2001, a directory traversal vulnerability in Microsoft's popular IIS 5.0 web server appeared. The vulnerability was critical because it was a zero authentication code execution vulnerability. The vulnerability was due to double decoding of a URL passed into the request.
Microsoft issued security bulletin MS01-026 to address this flaw and also described the vulnerability in their own words. I'll quote the technical advisory published at Microsoft's website:
A vulnerability that could enable an attacker to run operating system commands on an affected server. When IIS receives a user request to run a script or other server-side program, it performs a decoding pass to render the request in a canonical form, then performs security checks on the decoded request. A vulnerability results because a second, superfluous decoding pass is performed after the security checks are completed. If an attacker submitted a specially constructed request, it could be possible for the request to pass the security checks, but then be mapped via the second decoding pass into one that should have been blocked -- specifically, it could enable the request to execute operating system commands or programs outside the virtual folder structure. These would be executed in the security context of the IUSR_machinename account which, by virtue of its membership in the Everyone group, would grant the attacker capabilities similar to those of a non-administrative user interactively logged on at the console.
This excerpt mentions specifically that a vulnerability results because a second, superfluous decoding pass is performed after the security checks are completed. This clearly speaks by itself that double decoding is done by mistake in the IIS server that allows someone to traverse path names and execute commands by communicating with the cmd.exe parser; the code gets executed under the rights of the IIS webserver account.
Whenever IIS was asked to serve a CGI page with ../../
in the path which goes outside the root directory then the request would have got blocked as it is a clear path traversal outside of the root directory.
Assuming that the root directory is a Windows
folder, if we send the following request, it will be blocked as it contains ../../
for directory traversal inside the path name.
Normal URL:
http://example.com/scripts/../../winnt/system32/cmd.exe?/c+dir+c:\
Then using the superfluous second decoding, as Microsoft likes to call it. We can perform path traversal and execute commands by hitting the command-line parser of Windows.
So the following double-encoded URL will bypass and execute code under the context of IIS server account name.
Double-encoded URL:
http://example.com/scripts/%252E%252E%252F%252E%252E%252Fwinnt/system32/cmd.exe?/c+dir+c:\
Using double encoding to evade XSS filters
We have covered a directory traversal security check bypass through the double encoding technique. In this section, I'll cover how we can evade some XSS filters or checks that perform double decoding of the input.
Assuming that we've an XSS filter that detects <
, >
, /
, or their percent-encoded forms, we can apply the double encoding technique to our XSS payload, if our input gets recursively decoded.
Original request with XSS payload (blocked): http://www.example.com/search.php?q=<script>alert(0)</script>
Percent-encoded XSS payload (blocked):
http://www.example.com/search.php?q=%3Cscript%3Ealert(0)%3C%2Fscript%3E
Double-percent-encoded payload (allowed): http://www.example.com/search.php?q=%253Cscript%253Ealert(0)%253C%252Fscript%253E
Basically, we can tabulate the encodings that we've just done:
Character | Percent encoded | Double encoded |
---|---|---|
|
|
|
|
|
|
|
|
|
Before I end this topic, I must say the double encoding technique to bypass countermeasures is very powerful provided that our requirements (such as recursive decoding). It can be applied to other attack techniques such as SQL injections.
Double encoding can be further extrapolated into triple encoding and so on. For triple encoding, all we need to is prefix %25
then append 25
then the hex code; the triple encoding for <
will be %25253C
.