当我尝试使用包含撇号的值执行下面的 PostgreSQL 查询时,我遇到了我的第一个 sql 转义错误(早就应该了),例如。 O'Brien
,使用 FreePascal 和 Lazarus
SQL.Add(format('select * from zones where upper(zn_name) >= %s and upper(zn_name) < %s order by zn_name',[sQuote(zoneMin), sQuote(zoneMax)]));
在上面的查询中,SQuote 是一个将字符串用单引号引起来的函数。是否有一些标准库可以为 Lazarus/FreePascal 或 Delphi 清理 SQL 查询参数?
最佳答案
您的应用程序容易受到名为 SQL injection 的一类严重安全问题的攻击。 .参见 http://bobby-tables.com/ .
当然,O'Brian
导致错误,但是 ');DROP SCHEMA public;--
呢? ?或者 ');DELETE FROM users;--
?第一个不应该工作,因为您的应用程序永远不应该以 super 用户或拥有表的用户身份运行,但很少有应用程序设计者努力真正做到这一点,并且经常在生产中运行特权用户。第二个适用于大多数应用程序;详情见文末。
最简单和最好的预防措施是在您的客户端库中使用参数化语句*。参见 this example对于德尔皮:
To use a prepared statement, do something like this:
query.SQL.Text := 'update people set name=:Name where id=:ID';
query.Prepare;
query.ParamByName( 'Name' ).AsString := name;
query.ParamByName( 'ID' ).AsInteger := id;
query.ExecSQL;
(我从未使用过 Delphi,最后一次编写 Pascal 代码是在 1995 年;我只是引用给出的示例)。
您目前正在做的是参数的字符串插值。这是非常危险的。只有当你有一个强大的引用 SQL 文字 的函数时,它才能安全地完成,这个函数不仅在每一端加上引号,而且还处理其他转义、引用加倍等。它是最后手段的方法; 强烈最好使用参数化语句。
这是我上面给出的示例的扩展。假设您正在通过用户名对用户进行完全普通的插入,其中“Fred”是客户端输入的示例用户名:
INSERT INTO users ( user_name ) VALUES ('Fred');
现在一些不愉快的人发送用户名');DELETE FROM users;--
.突然你的应用程序开始运行:
INSERT INTO users ( user_name ) VALUES ('');DELETE FROM users;--');
展开后是:
INSERT INTO users ( user_name ) VALUES ('');
DELETE FROM users;
--');
或者换句话说,插入一个空字符串(尽管他们可以很容易地放入一个完全有效的用户名),然后是一个 DELETE FROM users;
语句 - 删除 users
中的所有行- 然后是一个什么都不做的评论。扑通一声。你的数据不见了。
* 参数化语句有时被错误地称为准备好的语句。这是不正确的,因为准备好的语句不一定是参数化的,参数化的语句也不一定是准备好的。之所以会产生混淆,是因为许多语言的数据库接口(interface)不提供在不使用预准备语句的情况下使用参数化语句的方法。
关于sql - 对于 FreePascal 和 Delphi,是否有用于清理 PostgreSQL 或 SQL 查询参数的库?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13171048/