2010-06-14 64 views
4

我正在努力加強我的一些PHP代碼,並使用mysqli準備好的語句來更好地驗證用戶輸入並防止注入攻擊。哪些字符不能用mysqli預處理語句轉義?

我離開了mysqli_real_escape_string as it does not escape % and _。但是,當我將查詢創建爲mysqli準備語句時,同樣的缺陷仍然存在。查詢根據用戶名抽取用戶salt值。我會做類似的密碼和其他查找。

代碼:

$db = new sitedatalayer(); 

if ($stmt = $db->_conn->prepare("SELECT `salt` FROM admins WHERE `username` LIKE ? LIMIT 1")) { 

    $stmt->bind_param('s', $username); 
    $stmt->execute(); 
    $stmt->bind_result($salt); 


    while ($stmt->fetch()) { 
    printf("%s\n", $salt); 
    } 

    $stmt->close();  

} 

else return false; 
  • 我是否正確撰寫的聲明?
  • 如果我是其他角色需要檢查?還有什麼其他缺陷?
  • 做這些類型的選擇的最佳做法是什麼?

感謝,

+2

爲什麼一個'LIKE'子句,而不是一個確切的比較'='? – BoltClock 2010-06-14 16:05:01

+0

忽略LIKE-hating,就「注入」而言,使用綁定變量(只要你專門使用它們)就不可能退出var,所以使用mysqli阻止注入其他查詢。其他人已經涵蓋了LIKE的語義問題。 – 2010-06-14 16:09:10

回答

8

%不是天生有害的字符。

問題是:您爲什麼首先使用LIKE?有沒有任何的情況下,你不會要求確切匹配的用戶名?

查詢應該是簡單的:

SELECT `salt` FROM admins WHERE `username` = ? LIMIT 1 

在這種情況下,如果我是爲了進軍%bsmith我的用戶名必須是(直譯)「%BSMITH」爲您找到一個匹配。

+0

謝謝 - 我曾嘗試過使用=標誌,並且我的查詢沒有奏效。必須在其他地方發生錯誤。現在工作。 – barfoon 2010-06-14 16:10:37

1

您在這裏混淆了兩個不同級別的評估。

LIKE運算符接受一個字符串並將任何'%''_'作爲佔位符進行評估。

查詢參數的工作僅僅是將值(例如字符串)逐字帶到數據庫引擎,因此它們不能被誤認爲是SQL代碼。他們並不關心LIKE運營商如何特別使用他們剛剛運輸的字符串內的某些字符。一切正如這裏設計的那樣工作。

如果您想要完全匹配,請使用=運算符代替LIKE

如果您必須使用LIKE(即使您的LIMIT 1在此處另有說明),請自行填寫escape the the special characters accordingly

+0

如果它們是逐字放置的,那麼爲什麼要使用預準備語句,而不是直接將$ username插入到字符串中? – barfoon 2010-06-14 16:09:18

+0

@barfoon:正如我所說的,參數在「SQL字符串文字」級別上工作。他們確保字符串文字不會中斷。 「LIKE」的抽象級別更高,因爲它根據自己的規則解釋字符串*內容*。參數再也不參與了,他們所做的只是確保你的SQL語句不會中斷。 – Tomalak 2010-06-14 16:12:17

-1

這是一個誰正在使用LIKE匹配用戶名怪,而不是逃避功能。

而且,只是爲了您的信息:原生準備好的語句不會逃脫任何東西

+0

PHP的ADODB和PDO使用mysql_real_escape_string(),如果您不相信我,請查看我的代碼。我應該給你一個-1,但我想我已經給了你足夠的'他們:p – rook 2010-06-14 16:20:36

+0

好吧,我仍然在意不正確的陳述'準備好的陳述不會逃脫任何事情。' – rook 2010-06-14 16:52:02

+0

爲記錄我沒有給你-1。 – rook 2010-06-14 17:41:31

-1

這些是不是通過準備的語句轉義的字符%_ \

相關問題