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查询参数?
解决方法
当然,O’Brian导致错误,但是’); DROP SCHEMA公开; – ?或者’); DELETE FROM users; – ?第一个应该不起作用,因为您的应用程序永远不应该以超级用户或拥有表的用户身份运行,但很少有应用程序设计人员努力实际执行此操作并经常在生产中运行特权用户.第二个将适用于大多数应用程序;有关详细信息,请参阅帖子的结尾.
最简单和最好的预防措施是在客户端库中使用参数化语句*.有关Delpi,请参阅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,最后在1995年写过Pascal代码;我只是引用给出的例子).
你目前正在做的是参数的字符串插值.这很危险.只有当你有一个强大的引用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用户;语句 – 删除用户中的所有行 – 然后是不执行任何操作的注释.啪.有你的数据.
*参数化的状态有时被错误地称为预准备语句.这是不正确的,因为准备好的语句不一定是参数化的,并且不一定准备参数化语句.由于许多语言的数据库接口没有提供使用参数化语句的方法而不使用预准备语句,因此产生了混淆.