📜 ⬆️ ⬇️

Waf eyes hackers

Hi, Habr! Today we will talk about one of the modern mechanisms for protecting web applications, namely, WAF, Web Application Firewall. We will describe what modern WAFs are based on and how they work, what are the workarounds and bypass techniques, how to use them, and why you shouldn’t rely entirely on WAF by any means. We will present our view of pentesters who have never participated in the development of WAF and who collected information from open sources and based on their experience, so we may not even be aware of some subtleties of the work of WAF.



Content


  1. Introduction
  2. What is the modern WAF
  3. Identify WAF
  4. WAF bypass cheatsheet
  5. Bypassing WAF in practice
  6. Conclusion

The article turned out to be quite large, so technical specialists and those who are not interested in reading, why WAFs are used, as well as those who do not need to describe the mechanisms of WAF work, can immediately proceed to the presentation of workarounds and practical examples.

Introduction


Recently, WAFs have become extremely popular, vendors offer a variety of solutions in different price categories, delivery packages and options designed for different consumers - from small businesses to large corporations. Modern WAF is popular because it is considered a comprehensive means of protecting web applications and has a wide range of tasks covered, so web application developers can rely on it in some security issues, but with the proviso that this solution cannot guarantee absolute protection.


')
So, what should WAF be able to, so that its implementation is justified in a real project? Its main function is to detect and block requests, in which, according to WAF analysis, there are some anomalies or an attacking vector is traced. Such an analysis should not make it difficult for legitimate users to interact with a web application, but at the same time should accurately and timely detect any attack attempts. In order to implement this functionality, WAF developers typically use regular expressions, tokenizers, behavioral analysis, reputational analysis, and machine learning, and often all of these technologies are used together. In addition, WAF can also provide other functionality: protection against DDoS, blocking the IP addresses of attackers, tracking of suspicious IP addresses, adding security headers (X-XSS-Protection, X-Frame-Options, etc ...), adding http -only the flag to the cookie, the introduction of the HSTS mechanism, the addition of the functionality of CSRF tokens. Also, some WAFs have a client module embedded in the site written in JavaScript.

Of course, WAF creates a number of difficulties for the work of hackers and pentesters. Detection and exploitation of vulnerabilities becomes a more time-consuming task, unless, of course, the attacker is not aware of effective 0day ways of circumventing a specific WAF. Using automated scanners to analyze web applications under the protection of WAF is almost useless. WAF reliably protects sites at least from scriptkiddies. However, an experienced specialist or hacker, without proper motivation, may also decide not to spend a lot of time searching for workarounds. Separately, we note that the more complex and multifunctional the web application, the greater the possible area of ​​attack, and the easier it will be to find a way around the WAF.

Recently, quite often in our audits there are different WAFs, we will even tell about some cases below. We have already tested some proprietary WAFs in two main scenarios:


But first, let us dwell in more detail on the basic mechanisms of the work of the WAF and see what problems exist with this.

What is the modern WAF


In order to effectively detect various WAF bypass methods, a specialist needs to understand the modern query classification mechanisms. Each WAF is individual and has a unique internal structure; however, there are some typical methods used for analysis. Let's take them and consider.



Regular Expression Based Rules


Most existing WAFs are based on regular expression based rules. To create them, a certain known set of attacks is studied by the WAF developer, as a result, key syntactic constructions are determined, by the presence of which it is possible to assert that an attack has been carried out. Based on the results obtained, regular expressions are written that can find such constructions. It seems that everything is simple, but this approach has several disadvantages. The zone of applicability of a regular expression is limited to one request, and more often even to a specific request parameter, which obviously reduces the effectiveness of such rules and creates a number of “blind zones” for such a mechanism. Secondly, the syntax of regular expressions, the complex logic of text protocols, which can be replaced by equivalent constructs and the use of different representations of characters, lead to errors in creating such rules. There is a great study on this topic from Vladimir Ivanov.

Scorebuilding


This mechanism should be familiar to anyone who was interested in building firewalls and antiviruses. By itself, it does not detect attacks, but it complements other methods, making them more accurate and flexible. The reason for the appearance of the tool is that the presence of some “suspicious” construct in the request is not a sufficient condition for detecting an attack or, on the contrary, can lead to a large number of false-positive errors. This problem is solved by the introduction of a point system. For example, each rule based on regular expressions is supplemented with information on the criticality of its operation; after identifying all the rules that have worked, their criticality is summarized. In the case of overcoming a certain threshold value, the attack is detected, and the request is blocked. This mechanism, despite its simplicity, has proven itself in tasks of this class and is used everywhere.

Tokenizers


This approach to detecting attacks was introduced at Black Hat 2012 as a C / C ++ library of libinjection , which allows you to quickly and accurately detect attacks of the SQL injection class. At the moment, for the library of libinjection, there are ports for various programming languages, including PHP, Lua, Python, etc ... In fact, the mechanism boils down to finding signatures represented as a sequence of tokens. A certain number of signatures is entered into the built-in blacklist and is considered invalid or malicious. In other words, before analyzing any request, it first leads to a set of tokens. Tokens are divided into different types, for example, variable, string, regular operator, unknown, number, comment, union-like operator, function, comma, etc ... One of the main disadvantages of this method is that it is possible to build such a structure, which will lead to incorrect formation of tokens, therefore, the request signature will be different from the expected one. Such constructions are usually called token breakers, we will tell about them a bit later.

Behavior analysis


Detection of exploitation attempts in the request parameters is not the only task of WAF. It is important to identify the very procedure of searching for vulnerabilities, which can manifest itself in attempts to scan, brute force directories, fuzzing parameters and other methods of vulnerability detection that are often used by automated tools, and react accordingly to them. More advanced WAFs even know how to build chains of requests, “typical” for normal user behavior, and block attempts to send requests in a different way than standard behavior. This mechanism does not so much counteract attacks as complicates the process of finding vulnerabilities. The limit on the number of requests per minute does not affect the typical user, but it will be a significant obstacle for the scanner working in several streams.

Reputation Analysis


Another mechanism directly inherited from firewalls and antiviruses. Today, almost any WAF includes address lists of VPN services, anonymizers, Tor network nodes, botnet members, which can be used to block requests originating from suspicious addresses. More advanced WAFs are able to automatically update their databases and add additional entries to them based on the analyzed traffic.

Machine learning


One of the most controversial points in the WAF. This mechanism is the most difficult to describe, and there are many reasons. For a start, it is worth noting that the very concept of “machine learning” is very extensive and in fact includes many technologies and techniques. In addition, “machine learning” is considered only one of the classes of AI methods. “Implementing machine learning” or “using AI” is a very popular marketing move. It is often unclear what methods and algorithms are used in practice, and sometimes from the attacker, it seems that machine learning in WAF is just beautiful words. Among those market players who were really able to subdue the full power of machine learning, few people are willing to share their experiences. All this adds up to a rather sad picture for a “person from the outside” who wants to understand the question. And still try to select at least a couple of sound ideas based on available information.

First, machine learning is completely dependent on the data on which it was based, and this is often a big problem. It requires that the company-developer has an up-to-date and complete collection of existing attacks and their methods of application, which is rather difficult. For this reason, many suppliers carefully log the results of their WAF and work with other companies that offer IDS, SIEM systems to access real-world examples of attacks. Secondly, a model trained on a “spherical web application in vacuum” may simply be ineffective when installed on a real client web application. For the best effect, it is considered correct to conduct additional model training at the WAF implementation stage at the client, which requires additional expenses, time, organizational difficulties, and also does not guarantee a better result.

Identify WAF


WAF developers have a different approach to notifying the user that WAF has blocked the request. Therefore, analyzing the response to our attacking request, we can understand how WAF is protected by the web application. For this, the term WAF Fingerprint is often used. This may help if the WAF is not updated for any reason (this usually refers to open source WAF). Proprietary WAF developers take care of customers and implement an auto-update mechanism. Also, if we were able to identify WAF and it was updated to the latest version, anyway, information about a specific WAF will help us learn a little about the specifics of its work.

We list the main places by which WAF can be identified:


For clarity, we give a few examples.

PT AF
Response code when blocking: 403
It can be embedded in the response page client module waf.js.
Response body when blocking:

<h1>Forbidden</h1> <pre>Request ID: 2017-07-31-13-59-56-72BCA33A11EC3784</pre> 

Additional header that adds waf.js:

 X-RequestId: cbb8ff9a-4e91-48b4-8ce6-1beddc197a30 

Nemesida WAF
Response code when blocking: 403
Response body when blocking:

 <p style="font-size: 16px; align: center;"> Suspicious activity detected. Access to the site is blocked. If you think that is's an erroneous blocking, please email us at <a href="mailto:nwaf@pentestit.ru">nwaf@pentestit.ru</a> and specify your IP-address. </p> 

Wallarm
Response code when blocking: 403
Additional title: nginx-wallarm

Citrix NetScaler AppFirewall
Additional cookies:

 ns_af=31+LrS3EeEOBbxBV7AWDFIEhrn8A000; ns_af_.target.br_%2F_wat=QVNQU0VTU0lP TklEQVFRU0RDU0Nf?6IgJizHRbTRNuNoOpbBOiKRET2gA 

Mod_Security ver. 2.9
Response code when blocking: 403
Response body when blocking:

 <head> <title>403 Forbidden</title> </head><body> <h1>Forbidden</h1> <p>You don't have permission to access /form.php on this server.<br /></p> 

Mod_Security ver. <2.9
Response code when blocking: 406 or 501
Response body when blocking:
In the response body you can find mod_security, Mod_Security or NOYB

Varnish FireWall
Adds view headers to the response:

 X-Varnish: 127936309 131303037. X-Varnish: 435491096 Via: 1.1 varnish-v4 

The WAF developers themselves decide which response code to return in the event of a request blocking, there are also specific codes. For example, code 999 will return Web_Knight WAF if the request is blocked, and dotDefender will return code 200 with an empty response body or containing an error message.

Also, do not forget that WAF, like any other application, is being developed and modified. Therefore, it is always important to check the relevance of the “prints” known to you. In addition, developers can make a custom response page when blocking with any other content.

WAF bypass cheatsheet


The general idea of ​​finding ways to bypass WAF is to bring the request we need to a form in which it is still understandable to the attacked web application, but it is not clear or seems harmless to WAF. It is important to note that one type of WAF must be able to serve a large number of different types of servers, including exotic, such as Unicorn, Tornado, Weblogic, Lighttpd etc ... Each server can perceive different or other exceptional cases of HTTP request parsing, which should be counted in the WAF. Thus, an attacker can use the specifics of parsing an HTTP request from the server being attacked in order to find a way to bypass WAF.



All possible ways of circumventing WAF are difficult to classify in any way according to the WAF protection mechanisms against which they may be used, or according to the application. The same workarounds can be interconnected with each other and affect simultaneously the various components of the WAF. Also it is necessary to take into account the large possible area of ​​application of detection bypass techniques, both by the types of attacks and by the specific place of their use. The techniques described below were collected from open sources and found in the course of their own research, and proved to be one of the most effective. Special thanks to want to express Bo0oM and its channel in the Telegram.

Adding special characters


Various special characters can violate the logic of WAF and at the same time be understandable to the server itself. Variations of special characters can also be any: they can be converted to urlencode (but most WAFs have been doing this for a long time) or other encodings. You can also insert special characters in the request without any encoding, in raw format, which can be quite unexpected for WAF. For example, \ r \ n \ r \ n in this form can be interpreted as the end of the HTTP-request body, and null byte can break the logic of regular expressions and parsers of various data formats in general. Other special characters from the first two dozen ASCII-table characters may also be useful.

Examples of useful special characters:


When searching for bypass, it will be useful to insert special characters in various places in the request body, not limited to including the parameter in the value. For example, if the request is in JSON format, then you can insert null byte both in one of the parameters, and between the parameters, and at the beginning of JSON, and at the end. The same applies to the other body formats of the POST request. In general, we recommend exploring and having fun, looking for places that can be checked or parsed by WAF, and try different special characters there.

For example:

 {"id":1337,"string0x00":"test' or sleep(9)#"} {"id":1337,"string":"test'/*0x00*/ or sleep(9)#"} {"id":1337,"string"0x0A0x0D:"test' or sleep(9)#"} 

 <a href="ja0x09vas0x0A0x0Dcript:alert(1)">clickme</a> <a 0x00 href="javascript:alert(1)">clickme</a> <svg/0x00/onload="alert(1)"> 

 id=1337/*0x0C*/1 UNION SELECT version(), user() -- 

For clarity, we replaced the special characters with their hex representation.

Replacing whitespace characters


A separate category is to allocate the replacement of spaces with equivalent characters. For example, most syntaxes presuppose the separation of keywords and operators by whitespace, but it does not strictly indicate which character should be used. Thus, instead of the usual 0x20 (Space), 0x0B (Vertical Tab), 0x09 (Horizontal tab) can be used. Also in this category is to include the replacement of whitespace characters on the dividing structures that do not carry the semantic load. In SQL, for example, this is / ** / (multi-line SQL comment), # \ r \ n (single-line SQL comment, ending with a line break), - \ r \ n (alternative single-line SQL comment, ending with a line break). Here are some examples:

 http://test.com/test?id=1%09union/**/select/**/1,2,3 http://test.com/test?id=1%09union%23%0A%0Dselect%2D%2D%0A%0D1,2,3 

You can also change the expression so that, using the syntax of the language, get rid of spaces. For example, in SQL, you can use brackets:

 UNION(SELECT(1),2,3,4,5,(6)FROM(Users)WHERE(login='admin')) 

And in JS use the symbol /:

 <style/onload=confirm(1)> 

Change encoding


The method is based on the use of different encodings in such a way that WAF does not decode data in certain places. For example, after replacing one character with its url-code, WAF will not be able to decode the data and skip the request, while the same parameter will be accepted and successfully decoded by the web application.

HTML character decimal representation: & # 106 or & # 0000106 . WAF may be aware of a short representation of characters (as in the first option), but not aware of the option with the addition of additional zeros, the total number of characters should not be more than 7. Similarly, the hexadecimal representation of the HTML character: & # x6A or & # x000006A .

There is also a trick with escaping some characters with the \ character, for example:

 <svg/on\load=a\lert(1)> 

However, this depends on how the web application handles such input. That is, the sequence of characters \ l will be perceived as shielded l and converted to one character, WAF can perceive each character separately. Thus, WAF will not see the keywords. Using this technique, you cannot escape the \ n , \ r , \ t characters, since they will be converted to completely different characters: line breaks, carriage returns and tabs.

HTML-encode can also be used inside tag properties, for example:

 <a href="javascript&colon;alert(1)">clickme</a> <input/onmouseover="javascript&colon;confirm&lpar;1rpar;"> 

Instead of such characters, it is quite realistic to substitute any other HTML representation of the target characters. Various options for character conversion can be found here .

In addition to HTML encode, you can insert characters using \ u:

 <a href="javascript:\u0061lert(1)">Clickme</a> <svg onload=confir\u006d(1)> 

Another separate touch on the vector associated with the insertion of special characters. We divide payload using HTML encode:

 <a href="ja&Tab;vas&#x0000A;cript:alert(1)">clickme</a> 

In this case, you can substitute other separating characters.

Thus, we recommend combining different encodings with other methods, for example, to encode special characters.

Search for atypical equivalent syntax


This method is to find a method of operation that could not be taken into account by the WAF developers, or the vector was missing in the training set for machine learning. Some simple javascript functions include: this, top self, parent, frames, tag properties: data-bind, ontoggle, onfilterchange, onbeforescriptextete, onpointerover, srcdoc, and SQL statements: lpad, field, bit_count.

Here are some examples:

 <script>window['alert'](0)</script> <script>parent['alert'](1)</script> <script>self['alert'](2)</script> 

 SELECT if(LPAD(' ',4,version())='5.7',sleep(5),null); 

You can also use the symbolic representation of JavaScript expressions:


The obvious problem with this JS view is the large length of the resulting payload.

Separately, we note that bypassing WAF using this technique depends on the specific attack and exploited technology stack. As an example, we can take the situation with the sensational ImageTragick exploit.

Most WAFs for protection against this attack blacklisted the keywords url, capacity, label that were used in most articles and PoC describing this vulnerability. However, it was soon discovered that in addition to these keywords, others could be used, for example, ephemeral, pango. As a result, WAF could be circumvented by using these keywords as a vector.

HTTP Parameter Pollution (HPP) and HTTP Parameter Fragmentation (HPF)


HPP’s attack uses a server-specific parameter handling feature. Here are some possible ways to work around WAF:

The server uses the last parameter received, and WAF only checks the first one.
The server combines the value of all the same parameters, and the WAF checks them separately. You can compare the difference in processing the same parameters by different servers using the following table:



In turn, the HPF attack is that if the logic of the web application combines two or more parameters in the request, then the attacker can break his request into parts, and thereby bypass some WAF checks.

An example of such an attack is an SQL injection of the form:

 http://test.com/url?a=1+select&b=1+from&c=base 

HPF and HPP are very similar attacks, but if the first is directed at a web application, then the second is on the environment in which it operates. The use of these techniques simultaneously increases the chances of circumventing WAF.

Unicode normalization


Unicode has one feature - Unicode Normalization. This was done in order to be able to compare some Unicode characters that are similar in spelling, for example, the characters ' ' and ' ᵃ ' have different codes, but they don’t differ much more, after normalization, both of them will be converted to the simple character ' a ' and will be considered the same. Normalization allows you to convert some complex Unicode characters to their simpler counterparts. There is a table that lists all possible Unicode characters with their possible normalization. With it, you can make various payload and combine them with other methods. However, this does not work in all web applications.

For example, in the table above, you can find that the characters and converted to the character < . But it should be noted that the stage at which normalization takes place is important, because if the application uses HTML encoding after normalization, then most likely the < character received after normalization will be encoded in &lt; . However, otherwise, the developers might well have ignored this feature and did not encode Unicode characters. Thus, we get unencoded characters < and > that can be turned into XSS. WAF may also have problems understanding Unicode characters, it may simply have no rules for such tricks, and machine learning may also be powerless. If you find a way to bypass WAF in web applications that have Unicode normalization, you can also replace not only the characters <> , but also change other characters from the payload.

For example:

 <img src﹦x onerror=alert︵1)> 

Recently, Rockstar on HackerOne also found this problem, but there was no WAF there, and there was only hard filtering of user input:

hackerone.com/reports/231444
hackerone.com/reports/231389

Token Breakers


Attacks aimed at tokenizers are associated with attempts to disrupt the logic of dividing a request into tokens with the help of so-called token breakers. These are characters that allow you to influence the choice of matching a line item to a specific token, and thus bypass the search by signatures. An example of an attack using a token breaker is the following query:

 SELECT-@1,version() 

where - @ - this is the token breaker.

In open access there is some cheat sheet, obtained by fuzzing mysql and then checking queries in libinjection, it can be found here .

The topic of finding problems in libinjection has long been new, more details can be found here:

Another phaser
Article once
Article two

Using RFC features


In the specifications for the HTTP / 1.1 protocol and various request formats, such as multipart / form-data, you can find some interesting points related to boundary cases or tricks when processing headers and parameters. WAF developers often do not take into account such moments, which is why WAF can incorrectly parse the request and miss part of the data in which the attacking vector can hide. Most of the problems in WAF are related to the processing of multipart / form-data and specific values ​​of the boundary parameter, which defines the boundaries of the parameters in such requests. In addition, server developers can also be mistaken and do not always fully support the specifications, which is why undocumented features can be found in the server's HTTP parser.

The boundary parameter in an HTTP request with multipart / form-data, as we wrote above, is responsible for distinguishing between various parameters in the request body. According to the RFC, before each new POST parameter, the previously designated boundary is indicated with a prefix containing “-”, thus the server distinguishes various request parameters.

 POST /vuln.php HTTP/1.1 Host: test.com Connection: close Content-Type: multipart/form-data; boundary=1049989664 Content-Length: 192 --1049989664 Content-Disposition: form-data; name="id" 287356 --1049989664-- 

The attack may be that the server and WAF handle the situation differently when the boundary parameter is empty. Based on the RFC, in such a situation the boundary between the parameters will be a sequence of characters “-”. However, the WAF can use a parser that does not take into account this feature, which is why WAF will skip the request, because the data from the POST request parameters simply will not get into the analyzer. The web server, in turn, can parse such a situation without problems and transfer data further for processing.

 POST /vuln.php HTTP/1.1 Host: test.com Connection: close Content-Type: multipart/form-data; boundary= Content-Length: 192 -- Content-Disposition: form-data; name="id" 123' or sleep(20)# ---- 

We will give some more interesting examples from the Bo0om report at ZeroNights 2016 and explain them:

 POST /vuln.php HTTP/1.1 Host: test.com Content-Type: multipart/form-data; boundary=FIRST; Content-Type: multipart/form-data; boundary=SECOND; Content-Type: multipart/form-data; boundary=THIRD; --THIRD Content-Disposition: form-data; name=param UNION SELECT version() --THIRD-- 

In this attack, we are trying to determine which of the boundary parameters will be accepted by WAF and which web server. Accordingly, if the web server and WAF take on various boundary parameters, it is possible to conduct an attack by specifying a final boundary that WAF will not see. Such an attack is somewhat similar to HPP.

 POST /vuln.php HTTP/1.1 Host: test.com Content-Type: multipart/form-data; xxxboundaryxxx=FIRST; boundary=SECOND; --FIRST Content-Disposition: form-data; name=param UNION SELECT version() --FIRST-- 

This attack is designed for another possible difference in the HTTP request parsing between the WAF and the web server. The difference should be as follows, the parser on the side of the web server searches for the first occurrence of the boundary, then searches for the '=' sign and only then determines the value of the boundary, the WAF parser in turn only searches for the entry of the string 'boundary =' and then determines boundary value If these conditions are met, then upon receiving such a request, WAF will not be able to find the specified boundary and, therefore, will not be able to find and analyze the parameter. The web server will receive the request and process the parameter. This attack can work, and vice versa, when the web server parser is looking for an 'boundary =', and the WAF parser is only looking for a 'boundary', in which case you only need to change the real boundary from FIRST to SECOND.

 POST /somepage.php HTTP/1.1 Host: test.com Content-Type: multipart/form-data; boundary=Test0x00othertext; --Test Content-Disposition: form-data; name=param Attack --Test-- 

This attack is also connected with the addition of special characters. A null byte has been added to the boundary parameter with the expectation that the web server will cut the boundary parameter to null byte, and WAF will accept it entirely. In this case, WAF again will not be able to analyze the parameter, since it will not find its boundaries.

Learning bypass


The essence of the detour is obvious - to make such an attack that would satisfy the parameters of a trained statistical model. But it very much depends on how and on which sample WAF was trained. Sometimes a loophole can be found, and sometimes a detour is not possible in principle. Typically, when deploying to a client, a machine-learning WAF needs some additional training based on the requests that come into the client's web application. And the problem for pentesters here may be the following: parameters that have the same appearance or do not vary greatly from request to request will be impossible to test in any way, since any step away from the usual type of parameter may already be perceived as an anomaly. Let's explain with an example. Suppose we have a conditional query to http://api.test.com/getuser?id=123 , the id parameter is always numeric, and in the training set it also always remained numeric. If the machine learning module detects anything other than numbers in this parameter, it will most likely decide that this is an anomaly. In another case, suppose that WAF was trained to classify a POST request to http://api.test.com/setMarkDown with POST parameters in which there is a markaun. Of course, quotes, special characters, and anything else may be present in Markdown. In this case, the machine learning module will be much easier to get around, since WAF will be tolerant of quotes and special characters.

Also, using examples from practice, we will show that the matter may not always reach the machine learning module, due to the problems with parsing the parameters caused by the circumvention methods described above.

In general, it is necessary to take into account the specifics of the test query and the parameters in it, to assume possible options for the values ​​of the parameters to which WAF can tolerate, and then to build on them.

When does WAF not help?


WAF focuses on analyzing queries and looking for abnormal behavior in them, but there are several classes of vulnerabilities that WAF cannot detect. These may be any logical vulnerabilities, in this case, the requests do not have any abnormal behavior, but there are some actions that violate the logic of the web application. WAF is also likely to be useless when detecting vulnerabilities such as race condition, IDOR and unsafe user authentication.

Existing Applications


To automate the search for WAF workarounds, there are some tools written by enthusiasts in this area.

Here are the most interesting ones that you should pay attention to:

lightbulb-framework is a whole framework for testing WAF-protected web applications. It is written in Python and additionally ported as a plugin for Burp Suite. Its main feature is two algorithms:


Bypass WAF - plugin for Burp Suite, which allows you to easily configure the automatic change of elements in the request body by various rules and encoding changes, including automates the HPP attack.

WAFW00F is a WAF identification program written in Python. It has a pretty good base WAF and is maintained to this day. However, the result may still be inaccurate, since different WAFs update much faster than the project itself.

Bypassing WAF in practice




Let's pass to real cases from our practice. We conducted an audit of some online store, whose site was protected by PT AF. Because of the WAF, it was difficult to find a vulnerable spot that could be repelled and looked for workarounds. But soon non-standard behavior on the part of the web application was discovered, which WAF did not filter. The anomaly was found in the functionality of the search for the history of purchased goods and was as follows: The

request was transmitted in JSON format and looked like this:

 {"request":{"Count":10,"Offset":0,"ItemName":"Phone"}} 

When substituting the Phone ' and Phone' + ' values ​​in the ItemName parameter , it was discovered that the server returned different answers for these two cases. The answer to the request with Phone ' was empty, and the answer to the request with Phone' + ' contained the same data about the goods with the word Phone in the title, as if the ItemName parameter would have just the value Phone . This behavior is familiar to many hackers and pentesters, and clearly indicates that the web application has a problem with filtering user input, which leads, among other things, to SQL injections.

Let us explain why this happens on the example of SQL injection for those who do not know about it. The point is that if this behavior is detected in the web application, then most likely the data for the SQL query is simply concatenated with the query itself, and in the first case, when the Phone parameter is passed , the SQL query will be generated:

 SELECT item FROM items WHERE item_name='Phone'' 

Such a request will obviously not be executed due to incorrect syntax and will not return any result. And the second request with the Phone '+' parameter , in turn, will look like this:

 SELECT item FROM items WHERE item_name='Phone'+'' 

Such a query has the correct syntax and will fetch goods by the name of Phone.
This method of detecting vulnerabilities has a great advantage when testing a web application that is protected by WAF. The single quote character is not considered by most modern WAFs as a sufficient anomaly in the parameter and skips the query with it.

With the detection, we figured out, and how now to bypass the WAF and exploit the vulnerability? After going through some of the workarounds, a problem was found in the WAF under study. It turned out that WAF is vulnerable to special characters added to JSON parameters. In fact, substituting the characters \ r \ n into any JSON text fieldin raw format without any encoding, WAF simply missed the request, and the web application considered the data correct and processed. Apparently, the problem was in the JSON parser, which was not designed for the appearance of special characters and parsed JSON exactly to the place of the appearance of these characters. Thus, an incomplete request got into the WAF analyzer, and after the special characters any attack vector could be inserted. In addition to line breaks, other special characters also worked, for example, null byte. As a result, it was possible to create the following request, which in fact disconnected WAF when trying to verify the entire request (the characters of the line break and carriage return are replaced with their textual representation):

 {"request":{"kill-waf":"die\r\n", "Count":10,"Offset":0,"ItemName":["'+(SELECT 'Phone'+CHAR(ASCII(substring(@@version,1,1))-24))+'"]}} 

As a result, it was possible to quickly and conveniently test all the parameters for the presence of any vulnerabilities (as a result, the couple was found in other queries). Bypassing WAF and operating this injection completely compromised all users of the web application.

Similar problems were also found in Nemesida WAF. The only difference was that the request was not in JSON format, but was a regular POST request with parameters, and the parameter in the web application was substituted into the SQL query as a number. Unfortunately, we can not publish now the technical details, because the developer of Nemesida WAF has forbidden them to publish at the moment. However, we will publish them later. Problems were reported to Pentestit and they were fixed.

As we see, WAFs can be very modern and very intelligent, but, unfortunately, they can sometimes be circumvented by simply inserting one special character. The problem here is that in WAF it is currently impossible to lay all possible input data for all possible servers, and machine learning, which, it would seem, is exactly what WAF needs, stumbles over parsers, which at the sight of some special characters horrified.

Conclusion


So, is it worth fully relying on WAF? The answer is no.

Unfortunately, not all developers understand this and for some reason consider WAF a silver bullet from hackers. For example, in one of the audits, we also discovered a WAF workaround that allowed us to exploit vulnerabilities. As we learned after the audit, the developers had already conducted an audit of the web application when it was not yet protected by WAF, and during the last audit these vulnerabilities were already found, but instead of closing them, it was decided to buy modern WAF with machine learning and fully rely on it. It is unfortunate that the WAF vendor did not insist on web application developers fixing known vulnerabilities. Either the developers themselves decided that WAF would protect them better than fixing bugs in the code. But we do not know the details. One way or another, both are very bad practices from both the WAF vendor,and from the developers.

I would also like to note that while machine learning in WAF remains a black box, it will be perceived rather as a marketing move, rather than a real effective way of protection.

In general, Web Application Firewall is a modern and good protection tool, and it will never be more than enough for your web applications. But it is necessary to remember once and for all that WAF currently only complicates the search for vulnerabilities and their exploitation, and does not completely eliminate you from vulnerabilities. And this situation, apparently, will continue for a long time. You can get rid of vulnerabilities in a web application only by fixing the code that causes these vulnerabilities, otherwise nothing and no one will protect you.

Bypassed the WAFs and collected material:

Bulatov Ilya barracud4
Rybin Denisthefaeriedragon
Alexander Romanov web_rock

Source: https://habr.com/ru/post/340144/


All Articles