SQLite 注入

SQLite 注入

如果您的站點允許使用者通過網頁輸入,並將輸入內容插入到 SQLite 資料庫中,這個時候您就面臨著一個被稱為 SQL 注入的安全問題。本章節將向您講解如何防止這種情況的發生,確保指令碼和 SQLite 語句的安全。

注入通常在請求使用者輸入時發生,比如需要使用者輸入姓名,但使用者卻輸入了一個 SQLite 語句,而這語句就會在不知不覺中在資料庫上執行。

永遠不要相信使用者提供的資料,所以只處理通過驗證的資料,這項規則是通過模式匹配來完成的。在下面的例項中,使用者名稱 username 被限制為字母數字字元或者下劃線,長度必須在 8 到 20 個字元之間 - 請根據需要修改這些規則。

if (preg_match("/^\w{8,20}$/", $_GET['username'], $matches)){
   $db = new SQLiteDatabase('filename');
   $result = @$db->query("SELECT * FROM users WHERE username=$matches[0]");
}else{
   echo "username not accepted";
}

為了演示這個問題,假設考慮此摘錄:To demonstrate the problem, consider this excerpt:

$name = "Qadir'; DELETE FROM users;";
@$db->query("SELECT * FROM users WHERE username='{$name}'");

函式呼叫是為了從使用者表中檢索 name 列與使用者指定的名稱相匹配的記錄。正常情況下,$name 只包含字母數字字元或者空格,比如字串 ilia。但在這裡,向 $name 追加了一個全新的查詢,這個對資料庫的呼叫將會造成災難性的問題:注入的 DELETE 查詢會刪除 users 的所有記錄。

雖然已經存在有不允許查詢堆疊或在單個函式呼叫中執行多個查詢的資料庫介面,如果嘗試堆疊查詢,則會呼叫失敗,但 SQLite 和 PostgreSQL 裡仍進行堆疊查詢,即執行在一個字串中提供的所有查詢,這會導致嚴重的安全問題。

防止 SQL 注入

在指令碼語言中,比如 PERL 和 PHP,您可以巧妙地處理所有的轉義字元。程式語言 PHP 提供了字串函式 SQLite3::escapeString($string)sqlite_escape_string() 來轉義對於 SQLite 來說比較特殊的輸入字元。

注意:使用函式 sqlite_escape_string() 的 PHP 版本要求為 PHP 5 < 5.4.0

更高版本 PHP 5 >= 5.3.0, PHP 7 使用以上函式:

SQLite3::escapeString($string);//$string為要轉義的字串

以下方式在最新版本的 PHP 中不支援:

if (get_magic_quotes_gpc()) 
{
  $name = sqlite_escape_string($name);
}
$result = @$db->query("SELECT * FROM users WHERE username='{$name}'");

雖然編碼使得插入資料變得安全,但是它會呈現簡單的文字比較,在查詢中,對於包含二進位制資料的列,LIKE 子句是不可用的。

請注意,addslashes() 不應該被用在 SQLite 查詢中引用字串,它會在檢索資料時導致奇怪的結果。