2013-05-15 34 views
0

在開發PHP應用程序時,我考慮過這種情況:用戶在表單中提交某種文本,然後在服務器上將文本轉義並插入到數據庫中。問題是:最後一個查詢中的SQL注入(使用DB的值)是否可能?通過輸入從逃脫的數據庫輸入SQL注入可能?

實例(我不認爲我要解釋我的數據庫類):

$db->query("INSERT INTO accounts SET test='".$db->escape($_POST["sometext"])."'"); 

好了,到目前爲止,我什麼都不知道會發生,在理論上我可以這樣做有準備的語句太,沒有區別。

有時以後需要在另一個腳本中使用列測試的值,並且需要將值插入其他位置。

所以列被選中,然後插入。

$db->query("SELECT test FROM accounts WHERE ... LIMIT 1"); 
$row = $db->fetchRow(); 
$db->query("INSERT INTO secoundtable SET test='".$row["test"]."'"); 

因此,您可以看到,數據庫的值用於上次查詢中。我必須在這裏逃生嗎?

+0

是的,這可以像用戶最初發布時一樣注入。對於始終清理變量即使它來自您認爲是可信來源的變量,也有一個參數 – Orangepill

+1

Escape **任何**和**全部**參數用於查詢。這裏沒有假設的餘地。即使錯過一次注入漏洞的代價也是巨大的。 – tadman

回答

2

這個問題的答案在很大程度上取決於函數$ db-> escape的作用。我的猜測是,它只是簡化傳入變量,以便它們對輸入「安全」?如果是這樣,那麼在第二個查詢中,您仍然容易受到SQL注入攻擊,這僅僅是因爲您信任用戶數據。

測試它自己運行的腳本:

//First query shouldn't cause you any issues (I'm assuming your function is safe). 
$test = "'"; 
$db->query("INSERT INTO accounts SET test='" . $db->escape($test) . "'"); 

//Second query will cause you issues because you're taking the single quote from your 
//table column and inserting it directly into the last query. 
$db->query("SELECT test FROM accounts WHERE ... LIMIT 1"); 
$row = $db->fetchRow(); 
$db->query("INSERT INTO secoundtable SET test='".$row["test"]."'"); 

順便說一句,如果你想成爲對SQL注入完全安全的,你應該考慮使用預處理語句。 This topic here非常值得一讀。

2

你應該養成總是使用正確的參數化查詢的習慣。

在第一種情況下,它可能是:

  • escape方法,導致它不能在一些地方適當逃避錯誤
  • 的代碼可能會意外地被更新,刪除escape呼叫

在第二種情況下,test列可能有一個撇號。這已經夠糟糕了,但是如果它來自用戶輸入,那就更糟了。你可以對你的手發動全面的攻擊。

我不認爲有任何理由避免準備好的語句/參數化查詢。它們更容易閱讀,安全(r),易於重複使用等。