簡體   English   中英

Double轉義字符串是錯誤的嗎?

[英]Is Double escaping a String wrong?

我有一個數據庫類,在使用mysqli_real_escape_string()構建查詢之前自動轉義輸入字符串。 但可能是在腳本中,字符串被轉義然后傳遞給再次轉義它的數據庫類。 這可能是錯的嗎? 怎么會發生什么?

由於你沒有好的方法告訴另一端(當你從數據庫中提取數據時)它被轉義了多少次,不一致的雙重轉義字符串將最終導致你在最終數據中丟失了數據之前沒有 - 因為你將添加兩層逃逸但只有一層。

基本上,你需要有一個恆定的轉義級別 - 要么總是逃避一次(並且一次性轉移它們),要么總是逃避它們兩次(並且兩次轉換它們)等等 - 但從不混合。

在第一次通過mysqli_real_escape_string ,通過在每個危險字符之前插入\\來轉義以下字符:

NUL(ASCII 0),\\ n,\\ r,\\,',“和Control-Z:

NUL (chr(0)) becomes "\0" (chr(92).chr(48))
\n (chr(13)) becomes "\n" (chr(92).chr(110))
\r (chr(10)) becomes "\r" (chr(92).chr(114))
\ (chr(92)) becomes "\\" (chr(92).chr(92))
' (chr(39)) becomes "\'" (chr(92).chr(39))
" (chr(34)) becomes "\"" (chr(92).chr(34))
Control-Z (chr(26)) becomes "\Z" (chr(92).chr(90))

在第二次通過mysqli_real_escape_string\\再次轉義:

"\0" (chr(92).chr(48)) becomes "\\0" (chr(92).chr(92).chr(48))
"\n" (chr(92).chr(110)) becomes "\\n" (chr(92).chr(92).chr(110))
"\r" (chr(92).chr(114)) becomes "\\r" (chr(92).chr(92).chr(114))
"\\" (chr(92).chr(92)) becomes "\\\\" (chr(92).chr(92).chr(92).chr(92))
"\'" (chr(92).chr(39)) becomes "\\'" (chr(92).chr(92).chr(39))
"\"" (chr(92).chr(34)) becomes "\\"" (chr(92).chr(92).chr(34))
"\Z" (chr(92).chr(90)) becomes "\\Z" (chr(92).chr(92).chr(90))

雙重轉義字符串不會產生任何類型的漏洞,但它會在您保存到數據庫中的字符串中插入許多額外的“\\”字符。

轉義的最佳方法是:1)關閉魔術引號2)僅使用帶有命名參數的查詢,在將其傳遞給查詢之前不要轉義任何內容。 MySQL(以及所有其他數據庫供應商)將正確地逃避字符串。 (但是,您可能會遇到chr(0)終止字符串的問題)。

如果您絕對必須使用字符串查詢,請在將數據插入查詢之前將數據轉義一次,並且只轉義一次。 不要逃避整個查詢。

雙重轉義字符串沒有任何問題,只要您在使用前保證雙重轉義它。

如果你忘了雙重瀏覽它,那么用戶最終會讀取一個轉義字符串,這不是很好。

除非您考慮到這一點,否則雙重轉義的字符串將呈現錯誤。 您可能已經看到了文本偶爾以轉義形式呈現的示例(例如,使用額外的反斜杠或HTML實體)。

是的,這可能是錯的,因為你可以在你的數據庫中使用像我們這樣的東西。

您正在逃避以避免SQL注入或查詢語法錯誤,而不是“轉換”您要存儲的數據。 如果你想存儲讓我們進入數據庫,你應該在構建查詢時只轉義它一次。 您不應該“unes​​cape”來自數據庫的值。 當您查看數據庫時,您永遠不會看到帶有轉義字符的值。

對於PHP中的初學者來說,轉義是一個真正的問題,這可能是由於magic_quote()函數。 你應該看看http://php.net/manual/en/security.magicquotes.php你不應該使用這個功能,這是令人困惑的。 在您的腳本中,如果您無法修改php.ini以禁用此功能,則可以在運行時使用以下命令執行此操作:

if (get_magic_quotes_gpc()) {
$process = array(&$_GET, &$_POST, &$_COOKIE, &$_REQUEST);
while (list($key, $val) = each($process)) {
    foreach ($val as $k => $v) {
        unset($process[$key][$k]);
        if (is_array($v)) {
            $process[$key][stripslashes($k)] = $v;
            $process[] = &$process[$key][stripslashes($k)];
        } else {
            $process[$key][stripslashes($k)] = stripslashes($v);
        }
    }
}
unset($process);
}

請注意,此代碼來自http://www.php.net/manual/en/security.magicquotes.disabling.php

花點時間正確理解如何處理逃逸,將來會節省大量時間。

對於MySQL,使用預處理語句,您不需要在數據庫級別轉義字符串。

對於PHP,請記住,您可以使用“和”來構建字符串。這可以用來避免引用字符串。如果字符串以“開頭”,那么您不必引用您的'。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM