SQLite 注入
如果您通过网页接受用户输入并将其插入SQLite数据库,则有可能为SQL注入这样的安全问题敞开大门。在本章中,您将学习如何防止此类问题发生,并帮助您保护脚本和SQLite语句的安全性。
注入通常发生在您请求用户输入时,比如要求他们提供姓名,但他们却提供了一个您不知情的SQLite语句,然后您会在数据库中运行它。
永远不要信任用户提供的数据,仅在验证后处理此数据;通常,这可以通过模式匹配来完成。在下面的示例中,用户名限制为字母数字字符和下划线,并且长度在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";
}
为了演示问题,考虑以下摘录−
$name = "Qadir'; DELETE FROM users;";
@$db->query("SELECT * FROM users WHERE username = '{$name}'");
该函数调用应该从用户表中检索一条记录,其中的name列和用户指定的名字匹配。在正常情况下, $name 只包含字母和数字字符,以及空格,比如字符串ilia。然而,在这种情况下,通过将一个全新的查询附加到$name,对数据库的调用变成了一个灾难:注入的DELETE查询将删除用户表中的所有记录。
有一些数据库接口不允许查询堆叠或在一个函数调用中执行多个查询。如果尝试堆叠查询,调用将失败,但SQLite和PostgreSQL会愉快地执行堆叠查询,执行提供的所有查询字符串,从而创建了严重的安全问题。
防止SQL注入
你可以在像PERL和PHP这样的脚本语言中聪明地处理所有转义字符。编程语言PHP提供了函数 string sqlite_escape_string() ,用于转义对SQLite特殊的输入字符。
if (get_magic_quotes_gpc()) {
name = sqlite_escape_string(name);
}
result = @db->query("SELECT * FROM users WHERE username = '{$name}'");
尽管编码使得插入数据变得安全,但对于包含二进制数据的列,它将使简单的文本比较和 LIKE 子句在查询中无法使用。
注意 - addslashes() 不应该用来在SQLite查询中引用字符串;在检索数据时,它会导致奇怪的结果。