简体   繁体   English

对于FreePascal和Delphi,是否有用于清理PostgreSQL或SQL的查询参数的库?

[英]Is there a library for sanitizing query parameters for PostgreSQL or SQL in general, for FreePascal and Delphi?

I got bitten my first sql escaping error (it was long overdue) when I tried to execute the PostgreSQL query below with a value containing an apostrophe eg. 当我尝试使用包含撇号的值执行下面的PostgreSQL查询时,我遇到了我的第一个sql转义错误(它已经过期了)。 O'Brien , using FreePascal and Lazarus 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)]));

In the query above SQuote is a function that wraps a string in single quotes. 在上面的查询中,SQuote是一个用单引号包装字符串的函数。 Is there some standard library for sanitizing SQL query parameters for Lazarus/FreePascal or Delphi for that matter? 是否有一些标准库用于清理Lazarus / FreePascal或Delphi的SQL查询参数?

Your application is vulnerable to a serious class of security problems called SQL injection . 您的应用程序容易受到称为SQL注入的严重安全问题的影响。 See http://bobby-tables.com/ . http://bobby-tables.com/

Sure, O'Brian causes an error, but what about ');DROP SCHEMA public;-- ? 当然, O'Brian导致错误,但是');DROP SCHEMA public;-- Or ');DELETE FROM users;-- ? 或者');DELETE FROM users;-- The 1st shouldn't work because your app should never run as a superuser or the user that owns the tables, but few application designers make the effort to actually do that and often run privileged users in production. 第一个应该不起作用,因为您的应用程序永远不应该以超级用户或拥有表的用户身份运行,但很少有应用程序设计人员努力实际执行此操作并经常在生产中运行特权用户。 The 2nd will work in most applications; 第二个将在大多数应用程序中工作; see the end of the post for details. 有关详细信息,请参阅帖子的结尾。

The easiest and best preventative measure is to use parameterized statements * in your client library. 最简单和最好的预防措施是在客户端库中使用参数化语句 * See this example for Delpi: 请参阅Delpi的这个示例

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;

(I've never used Delphi and last wrote Pascal code in 1995; I'm just quoting the example given). (我从未使用过Delphi,最后在1995年写过Pascal代码;我只是引用给出的例子)。

What you are doing currently is string interpolation of parameters. 你目前正在做的是参数的字符串插值 It is very dangerous. 这非常危险。 It can be done safely only if you have a robust function for quoting SQL literals , one that doesn't just bang quotes on each end, but also handles other escapes, quote doubling, etc. It is the approach of last resort; 只有当你有一个强大的引用SQL文字的功能时,它才能安全地完成,它不仅会在每一端引用引号,还会处理其他转义,引用加倍等等。这是最后的方法; it's strongly preferable to use a parameterized statement. 但是强烈最好使用参数化的语句。


Here's an expansion of the example I gave above. 这是我上面给出的例子的扩展。 Say you're doing a perfectly ordinary insert of a user by username, where 'Fred' is an example username input by the client: 假设您正在通过用户名完成普通的用户插入,其中'Fred'是客户端输入的示例用户名:

INSERT INTO users ( user_name ) VALUES ('Fred');

Now some unpleasant person sends the username ');DELETE FROM users;-- . 现在一些不愉快的人发送用户名');DELETE FROM users;-- Suddenly your application is running: 突然你的应用程序正在运行:

INSERT INTO users ( user_name ) VALUES ('');DELETE FROM users;--');

which when expanded is: 扩展后的是:

INSERT INTO users ( user_name ) VALUES ('');
DELETE FROM users;
--');

or in other words an insert that inserts an empty string (though they could just as easily put a perfectly valid username in), followed by a DELETE FROM users; 或者换句话说插入一个空字符串的插入(虽然它们可以很容易地放入一个完全有效的用户名),然后是DELETE FROM users; statement - deleting all rows in users - then a comment that does nothing. 语句 - 删除users所有行 - 然后是不执行任何操作的注释。 Splat. 啪。 There goes your data. 有你的数据。


* Parameterized statemments are sometimes incorrectly referred to as prepared statements . *参数化的状态有时被错误地称为预准备语句 That's incorrect because a prepared statement isn't necessarily parameterized, and a parameterized statement isn't necessarily prepared. 这是不正确的,因为准备好的语句不一定是参数化的,并且不一定准备参数化语句。 The confusion has arisen because the database interfaces of many languages don't provide a way to use parameterized statements without also using prepared statements. 由于许多语言的数据库接口没有提供使用参数化语句的方法而不使用预准备语句,因此产生了混淆。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM