2011-06-09 67 views
1

我必須在一個主要安全問題的舊站點上工作:SQL注入非常容易執行。準備語句時防止SQL注入的最佳方法是不可能的

很顯然,防止這種攻擊的最好方法就是逃避查詢中使用的內容(使用PDO編寫語句,使用MySql編寫mysql_real_escape_string等),但我們無法快速完成這些工作:整個站點都是程序化的PHP(沒有課程),查詢到處都是「準備好」的,每天有數百頁和數千用戶,而且新版本將盡快出現。

因此,從今天上午開始,每個請求都會調用以下函數,根據關鍵字檢測可疑的POST或GET參數。

const SQLI_UNSAFE = 3; 
const SQLI_WARNING = 2; 
const SQLI_SAFE = 1; 
const SQLI_MAIL_DEST = '[email protected]'; 

function sqlicheck() { 

    $params = array_merge($_GET, $_POST); 
    $is_warning = false; 

    foreach($params as $key=>$param) { 
     switch(getSafeLevel($param)) { 
      case SQLI_SAFE: 
       break; 
      case SQLI_WARNING: 
       $is_warning = true; 
       break; 
      case SQLI_UNSAFE: 
       mail(SQLI_MAIL_DEST, 'SQL INJECTION ATTACK', print_r($_REQUEST, true).' '.print_r($_SERVER, true));  
       header('Location: http://monsite/404.php'); 
       exit();  
      } 

    } 

    if($is_warning === true) { 
     mail(SQLI_MAIL_DEST, 'SQL INJECTION WARNING', print_r($_REQUEST, true).print_r($_SERVER, true)); 
    } 
} 
function getSafeLevel($param) { 

    $error_words = array('select%20','drop%20','delete%20','truncate%20','insert%20','%20tbclient','select ','drop ','delete ','truncate ','insert ',); 
    $warning_words = array('%20','select','drop','delete','truncate', ';','union'); 


    foreach($error_words as $error_word) { 
     if(stripos($param, $error_word) !== false) return SQLI_UNSAFE; 
    } 
    foreach($warning_words as $warning_word) { 
     if(stripos($param, $warning_word) !== false) return SQLI_WARNING; 
    } 

    return SQLI_SAFE; 
} 

這似乎可以檢測到某種類型的攻擊,但它顯然非常基本。任何想法來改善它?任何重大問題?

+0

有什麼用途來確定試圖進行注射的位置? – 2011-06-09 14:02:20

+0

準確地說:目的是檢測到哪裏和可能是誰,如果有任何風險立即糾正它,並且我們確定將黑客重定向到404。 – LFI 2011-06-09 14:13:23

+0

您還應該包含一個安全的詞,它是'香蕉'。 – 2011-06-09 14:18:59

回答

2

首先,確保執行查詢的數據庫用戶只有選擇,更新和刪除權限。如果用戶不能執行drop操作,則不會發生這種情況(這假定用戶永遠不需要創建或刪除表,但是如果他們這樣做,則可以創建表級權限來保護大表)。

其次,你的腳本只會告訴你人們在用什麼;它不會對可能的查詢進行全面的檢查;如果您網站的某個部分使用得不多,您將無法收到任何郵件。更好的是用搜索工具梳理代碼。

之後,您必須開始修改代碼並進行轉義和驗證,這只是需要一段時間。

+0

我同意:我們檢查數據庫用戶的權限,但我不明白你的第二個參數,因爲目標是防止大部分攻擊並知道新的攻擊。最後,我不能快速修改整個代碼,因爲很多黑魔法和沒有測試用例。 – LFI 2011-06-09 14:31:37

+0

我的意思是第二個參數是你的用戶沒有對你網站的所有功能進行均衡測試。你會在最常使用的部件上得到一堆郵件,而在未使用的部件上只有很少甚至沒有,但未知部件同樣易受攻擊。因此,這種方法將幫助您找到大部分攻擊,但不是全部,而且一旦您收到郵件並有時間解決它,可能就太遲了。 – 2011-06-09 14:37:28

+0

此外,如果您的網站允許用戶鍵入文字,他們會在以合法方式使用選擇,更新,刪除和刪除時感到失望。也許不是退出並重新定向,你可以替換單詞,使它們稍微有點不同,但不是那些單詞。就像使用select選擇select,使用change等更新等。或者將它們帶回到原來的位置,並顯示一條錯誤消息,告訴他們他們可以做的不同。 – 2011-06-09 14:41:03

0

爲什麼不使用PHP的real_escape_string()htmlentities()的stripslashes和過濾器類和日誌的SQL查詢,以便你可以看到什麼人送你,使用SHA256一些MD5,你會沒事的另一件事是迅速採取行動只是發送登錄以二進制格式的數據

相關問題