参数化 SQL 能防止注入的原理
2016-03-25 15:47
323 查看
转载:http://bbs.csdn.net/topics/390667952
现在如果,我大概知道你的管理员表的表名是
然后,注入的本质,就是通过构造字串, 让
当
拼接的结果就成了
那么目的就达到了。
这种是最简单和基础的注入。
我们知道,
当给
当给
单引号被转义了, 用
相当于
整条
这样说应该可以理解吗?
同理,像
像
像
这时候其实要靠注入经验、猜测、还要看当前的数据库帐号权限有多大等等。
当然, 即便当前帐号只有对业务表的操作权 不能威胁到服务器,那么你想想, 一条
最直观的反例是
在
是的,
那么在execute里执行里面拼的语句已经是
你会说这条语句报错,因为定界符不匹配,
对的,你说对了, 为什么定界符不匹配,因为构造非法的字符串造成了定界符不匹配,既然已经干扰了定界符, 能过合理构造,你就能构造出你想要的语句。
这么说应该能说明吧, 不用我再构造清一次你的
这些是最直观的例子。
你会说,你通过避免拼动态语句来解决这个问题, 对的,可以解决。
但是会有更高阶的东西, 利用本身操作系统或者数据库服务器的一些漏洞(一般是较低层的,比如某某溢出),通过
9年前对这些东西感兴趣,弄过一些,包括国内知名的两个商业论坛, 后来淡了,这些东西没有再过多了解, 但是原理是不变的。
随手敲的,可能手误,见谅。
基本的注入方式
注入的思想就是构造非法的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表吧。
这些是最直观的例子。
你会说,你通过避免拼动态语句来解决这个问题, 对的,可以解决。
但是会有更高阶的东西, 利用本身操作系统或者数据库服务器的一些漏洞(一般是较低层的,比如某某溢出),通过
SQL注入,结合一些方法,完成攻破。 这个就不光是纯
SQL的注入了,就不多介绍了。
9年前对这些东西感兴趣,弄过一些,包括国内知名的两个商业论坛, 后来淡了,这些东西没有再过多了解, 但是原理是不变的。
随手敲的,可能手误,见谅。
相关文章推荐
- 学习创建索引sql
- 把数据库干挂了
- linux下安装oracle11G R2全过程整理
- 常用图像数据库
- mysql登录
- linux下安装配置redis服务
- Oracle 数据库共享内存分配不足
- MySQL 中的 base64 函数
- Mssql存储过程大杂烩
- MySQL5.7.6: 通过序列区间来优化并行复制性能
- redis持久化
- oracle中nvl()函数
- mongodb 集群搭建
- MySql安装步骤详解,MySql的root密码设置,启动MySql服务。
- [PL/SQL工具]绿色版PLSQL工具登录时提示初始化失败,无法锁定OCI.dll错误
- Oracle的添加主键
- MySQL性能优化——索引
- mysql分表分区
- 关于sqlite数据库的优化
- ibaits防止sql注入