你的应用程序存在一个严重的安全问题,被称为SQL注入。请查看http://bobby-tables.com/。
当然,O'Brian
会导致错误,但是如果输入');DROP SCHEMA public;--
或者 ');DELETE FROM users;--
呢?第一个不应该起作用,因为你的应用程序不应该以超级用户或拥有表的用户身份运行,但很少有应用程序设计人员会付出实际努力去做到这一点,并经常在生产中运行特权用户。在大多数应用程序中,第二个将起作用;有关详情,请参见文章末尾。
最简单和最好的预防措施是在客户端库中使用参数化语句*。对于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;
(我从未使用过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
中的所有行 - 然后是一个没有任何作用的注释。砰。你的数据就没了。
*参数化语句有时被错误地称为预处理语句。这是不正确的,因为预处理语句不一定是参数化的,而参数化语句也不一定是预处理的。造成混淆的原因是许多编程语言的数据库接口没有提供使用参数化语句而不使用预处理语句的方法。
QuotedStr
函数(尝试进行 SQL 注入...) - kobik