Tips
Some tips for web pentesting
Context-specific decoding
URL => try URL encoding (query parameter is decoded server side)
HTML => try HTML encoding (may be decoded client side, always check where the payload is injected)
Understanding the context of the targeted input fields can help to identify how the data is being decoded.
Decoding Discrepancies
Payloads usually have recognizable patterns like <script> for XSS, SELECT for SQLi. So websites will often implement defenses to block these requests containing these inputs.
These kinds of input filters need to decode the input in order to check if the data is safe or not.
If these filters do not use the same decoding procedures that the back-end server or browser uses then this can enable an attacker to sneak harmful payloads past the filter by applying different encodings that will automatically be removed later.
Example: Website URL decodes the data once to identify if the input is safe. However, the back-end server performs double URL decoding.
Obfuscation via URL encoding
Any URL based input is automatically URL decoded server-side before it is assigned to the relevant variables.
WAFs sometimes can fail to properly URL decode the input when checking it. We may be able to smuggle payload by encoding any characters or words that are blacklisted.
Obfuscation via double URL encoding
Servers may perform 2 rounds of URL decoding, where as the WAF performs only 1 round of URL decoding. In this scenario we can encode or payload twice to bypass the filters and inject the data to the application.
Example: The application is blocking the <> tags to prevent XSS and the WAF URL decodes the injected input only once.
Example of double URL encoded payload
Obfuscation via HTML encoding
In specific locations within the HTML, such as the content of an element or value of an attribute, browsers will automatically decode those values when they parse the document.
Alternatively, the reference may be provided using the character's decimal or hex code point, in this case, : and : respectively.
We can take advantage of this behavior to obfuscate payloads for client-side attacks like XSS, which hides them from server-side checks.
Example: The server-side application is checking for the alert() payload and rejecting requests with that input.
When the browser renders the page, it will decode and execute the injected payload.
Leading zeros
If your payload still gets blocked after HTML encoding it, you may find that you can evade the filter just by prefixing the code points with a few zeros:
Obfuscation via XML encoding
XML is closely related to HTML and also supports character encoding using the same numeric escape sequences. This enables you to include special characters in the text content of elements without breaking the syntax, which can come in handy when testing for XSS via XML-based input, for example.
This behavior can be useful to obfuscate payloads which will be decoded server-side instead of client-side by a browser.
Obfuscating via unicode escaping
Unicode escape sequences consist of the prefix \u followed by the four-digit hex code for the character. For example, \u003a represents a colon. ES6 also supports a new form of unicode escape using curly braces: \u{3a}.
For example, let's say you're trying to exploit DOM XSS where your input is passed to the eval() sink as a string. If your initial attempts are blocked, try escaping one of the characters as follows:
As this will remain encoded server-side, it may go undetected until the browser decodes it again.
It's also worth noting that the ES6-style unicode escapes also allow optional leading zeros, so some WAFs may be easily fooled using the same technique we used for HTML encodings. For example:
Obfuscation via hex escaping
Obfuscation via octal escaping
Obfuscation via multiple encodings
We can combine multiple encodings to hide payloads behind multiple layers of obfuscation.
Payload
Browsers will first HTML decode "\" resulting in "\". This has the effect of turning the otherwise arbitrary u0061 characters into the unicode escape \u0061
This is then decoded further to form the original payload
Obfuscation via the SQL CHAR() function
If instructions like "SELECT" are blocked/blacklisted try
When this is processed as SQL by the application, it will dynamically construct the SELECT keyword and execute the injected query.
Last updated