您的位置:首页 > 数据库

参数化 SQL 能防止注入的原理

2016-03-25 15:47 323 查看
转载:http://bbs.csdn.net/topics/390667952

基本的注入方式

注入的思想就是构造非法的sql语句。

string sql="select * from tb where username='" + username + "'";


现在如果,我大概知道你的管理员表的表名是
admins
, 我要往里面加一条记录,或者清空你的管理员表, 针对于上面一条语句, 我需要构造的sql 语句原型是:

select * from tb where username='xxx'; truncate table admins


然后,注入的本质,就是通过构造字串, 让
string sql
这个变量的值成为我们想要构造的那条语句

username
的值为
aa';truncate table admins --


拼接的结果就成了

string sql = "select * from tb where username='aa';truncate table admins --'";


那么目的就达到了。

这种是最简单和基础的注入。

我们知道,
.net
或者其它语言里,在使用
sqlserver
为数据库, 以传参的方式执行的时候,在数据库端实际上是以
sp_executelsql
的方式实现的(关于这一点,你通过事件探查器就可以看到).

当给
string sql= "select ...where username=@username"


@username
已经在
param
里被定义为了字串类型, 即便 字串里有单引号,分号,
SQL
里的注释号, 这些都会被当作字串来处理,而不会当作
sql
里的定界符、指定符等等

当给
@username
传值为
"aa';truncate table admins --"


单引号被转义了, 用
SQL
来描述的话

相当于

declare @username varchar(xxx)


@username='aa'';truncate table admins --'


整条
SQL
语句的作用实际上把
'aa'';truncate table admins --'
当作
name
值代入表中进行检索, 避免了注入的问题.

这样说应该可以理解吗?

同理,像
string sql="select ... where id=" + id.tostring();


c#
这样的语言,因为
id
强类型为
int
, 这里一般情况下
.net
代码会报错,也能避免这种问题

vb
这类弱类型的语言,
where id=" + id
, 就经常出现这种问题, 对于这类语言,一种是强制要求变量及类型定义, 一种是用类似于
isnumeric
之类的函数去检测.

现在举个反例, 倒底参数方式能不能防注入

实际注入中,并不是我上面写的那么简单,因为一般情况,你不知道别人的库结构是如何的,

这时候其实要靠注入经验、猜测、还要看当前的数据库帐号权限有多大等等。

当然, 即便当前帐号只有对业务表的操作权 不能威胁到服务器,那么你想想, 一条
update
金额已经有足够大的损失了。

最直观的反例是
sql_excutesql
里面还在拼
SQL
,这个是最容易表述也是最简单的, 这样的方式就完全没有用。 这个告诉我们, 不要以为别人说怎么样就可以怎么样了, 你懂了原理,就知道这些东西不能道听途说。 区分真伪的能力在于你掌握了多少。

create proc p
(@id int,
@name varchar(10))
as
begin
execute('select * from tb where id=' + @id + ' and name=''' + @name + '''')
end
go


c#
里,调用这个存储过程,给了两个参数,一个
@id
,一个
@name


是的,
@name
,
@id
被定义了类型,
@name
里的字串被进行了转义, 乍一看没问题, 事实呢? 只是构造相对再复杂一点而已, 只要你脑子够清楚不被’和”搞晕, 一样的。

sqlparamepter pm = ....

pm[0].value=1;
pm[1].value="a'";


那么在execute里执行里面拼的语句已经是

select * from tb where id=1 and name=''a'''


你会说这条语句报错,因为定界符不匹配,

对的,你说对了, 为什么定界符不匹配,因为构造非法的字符串造成了定界符不匹配,既然已经干扰了定界符, 能过合理构造,你就能构造出你想要的语句。

这么说应该能说明吧, 不用我再构造清一次你的
admins
表吧。

这些是最直观的例子。

你会说,你通过避免拼动态语句来解决这个问题, 对的,可以解决。

但是会有更高阶的东西, 利用本身操作系统或者数据库服务器的一些漏洞(一般是较低层的,比如某某溢出),通过
SQ
L注入,结合一些方法,完成攻破。 这个就不光是纯
SQL
的注入了,就不多介绍了。

9年前对这些东西感兴趣,弄过一些,包括国内知名的两个商业论坛, 后来淡了,这些东西没有再过多了解, 但是原理是不变的。

随手敲的,可能手误,见谅。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: