oracle防止sql注入proc,关于oracle:Delphi – 防止SQL注入

我需要保护应用程序免受SQL注入。 应用程序使用ADO连接到Oracle,并搜索用户名和密码以进行身份验证。

从我读到现在开始,最好的方法是使用参数,而不是将整个SQL分配为字符串。 像这样的东西:

query.SQL.Text := 'select * from table_name where name=:Name and id=:ID';

query.Prepare;

query.ParamByName( 'Name' ).AsString := name;

query.ParamByName( 'ID' ).AsInteger := id;

query.Open;

另外,我正在考虑验证来自用户的输入,并删除删除,插入,选择等SQL关键字......任何不同于普通ASCII字母和数字的输入字符都将被删除。

这样可以保证我的安全级别最低?

我不想使用除Delphi 7标准和Jedi之外的任何其他组件。

安全

query.SQL.Text := 'select * from table_name where name=:Name';

此代码是安全的,因为您正在使用参数。

从SQL注入开始,参数始终是安全的。

不安全

var Username: string;

...

query.SQL.Text := 'select * from table_name where name='+ UserName;

不安全,因为用户名可能是name; Drop table_name;

导致执行以下查询。

SELECT * FROM TABLE_NAME WHERE name=name; DROP TABLE_NAME;

也不安全

var Username: string;

...

query.SQL.Text := 'select * from table_name where name='''+ UserName+'''';

因为如果用户名是' or (1=1); Drop Table_name; --

它将导致以下查询:

SELECT * FROM TABLE_NAME WHERE name='' OR (1=1); DROP TABLE_NAME; -- '

但是这段代码是安全的

var id: INTEGER;

...

query.SQL.Text := 'select * from table_name where id='+IntToStr(id);

因为IntToStr()只接受整数所以没有SQL代码可以这种方式注入查询字符串,只有数字(这正是你想要的,因此允许)

但我想做一些无法用参数完成的事情

参数只能用于值。它们不能替换字段名称或表名称。

所以如果你想执行这个查询

query:= 'SELECT * FROM :dynamic_table '; {doesn't work}

query:= 'SELECT * FROM '+tableName;      {works, but is unsafe}

第一个查询失败,因为您不能使用表或字段名称的参数。

第二个查询是不安全的,但这是完成此任务的唯一方法。

如何保持安全?

您必须根据已批准的名称列表检查字符串tablename。

Const

ApprovedTables: array[0..1] OF string = ('table1','table2');

PROCEDURE DoQuery(tablename: string);

var

i: INTEGER;

Approved: BOOLEAN;

query: string;

BEGIN

Approved:= FALSE;

FOR i:= lo(ApprovedTables) TO hi(ApprovedTables) do BEGIN

Approved:= Approved OR (lowercase(tablename) = ApprovedTables[i]);

END; {FOR i}

IF NOT Approved THEN exit;

query:= 'SELECT * FROM '+tablename;

...

这是我知道的唯一方法。

BTW您的原始代码有错误:

query.SQL.Text := 'select * from table_name where name=:Name where id=:ID';

应该

query.SQL.Text := 'select * from table_name where name=:Name and id=:ID';

在一个(子)查询中不能有两个where

谢谢约翰。我已经纠正了这个问题。+ 1

+1用于覆盖多个场景

但是如果用户在这种输入框中输入了SQL参数,你仍然可以用name; Drop table_name;注入SQL参数

@daemon_x:在第一个场景中,在文本框中输入name; Drop table_name;将导致查询select * from table_name where name='name; Drop table_name;';,这将是非常安全的。

@Allan - 如果我使用name'; Drop table_name; Select '0该结果是select * from table_name where name='name'; Drop table_name; Select '0'怎么办?我不是参数用户所以我不知道单引号是否会加倍(但我希望它们是)。

@daemon_x,参数永远不会进入实际的SQL,总是直接进入字段。就像字段的内容永远不会是SQL语句的一部分。 select * from table1 where a = 'hello'. If field a`包含name'; Drop table1;它没有做任何坏事,这是参数之美。

@Johan - 现在我看到了;我认为客户端通过替换参数值来准备最终查询,但它们作为真正的SQL参数(@)传递给数据库引擎。所以+1(当我明天获得投票:))

那么在登录表单上,如何将参数设置为等于username和password的用户输入?如果我有SELECT * FROM [users] WHERE username = :username AND password = :password我在哪里告诉页面$username = $_POST['username']和$password = $_POST['password']还是那个变量形成的方式?

@jlg,您可以使用salted哈希来显示密码。在delphi中,你说:query1.parambyname('username').AsString:= UsernameFromForm;

Btw jedi tjvquery有宏,您可以使用它们来更改表名,列名等内容.sql在jedi中进行预处理,宏值为文本。 Taje关心这可能会导致sql注入攻击。请务必根据白名单编辑值,否则只能确保vsl I d值

如果您允许用户仅影响将使用占位符绑定到sql命令文本的参数值,那么您实际上不需要检查用户输入的内容:正如您所提到的,避免SQL注入的最简单方法是,是避免连接SQL,并使用绑定变量(或调用过程)这样做(它还有一个优点 - 里程/相关性取决于数据库 - 允许引擎重用查询计划)。

如果您使用的是Oracle,那么您需要有一个非常好的理由不使用绑定变量:Tom Kyte在他的网站http://asktom.oracle.com上有很多关于此的信息。只需在搜索框中输入"绑定变量"即可。

+1 - 避免SQL注入的最佳方法是不通过网络发送SQL。

This will assure me a minimum of security level?

是参数化查询应该保护您免受SQL注入,这很容易测试。只需在name变量中输入一些危险的字符串,看看会发生什么。通常你应该返回0行而不是错误。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值