`
李大龙
  • 浏览: 71404 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

读《Oracle编程艺术》有感之一有关SQL注入与绑定变量

阅读更多
Oracle Database 9i/10g/11g编程艺术 深入数据库体系结构第2版 写道
SQL注入是一个安全漏洞,如果开发人员接受来自最终用户的输入,把这个输入拼接到查询中,然后编译和执行这个查询,就会存在这种安全漏洞。实际上,开发人员可能会接受来自最终用户的SQL代码段,然后编译和执行这些代码段。利用这种方法,最终用户就有可能修改SQL语句,做一些应用开发人员原来不打算做的事情。这就像是你打开终端,登陆一个SQLPlus会话并作为SYSDBA连接。你希望有人来键入某个命令,然后编译并执行这个命令。结果将是灾难性的。

      所谓SQL注入,就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。根据《Oracle编程艺术》上面的引用,简单地说,SQL注入就是通过传入特定参数,然后把这个参数以SQL段形式拼接之后编译执行,重点是SQL “拼接”!

     为了说明SQL注入攻击的危险性,《Oracle Database 编程艺术》举了一个例子,下面我们主要是一个更简单的例子去感受一下SQL注入的危险性。

 

SELECT STUNO, STNAME FROM STUDENT T
WHERE T.CREATE_DATE = 

     假如我们的程序从学生信息表里读学生学号和姓名信息,通过传入的入学日期(创建日期)参数返回指定学生的信息。

     当我们程序使用的是拼接的模式,例如:

DBMS_OUTPUT.PUT_LINE('
     SELECT STUNO, STNAME FROM STUDENT T
     WHERE T.CREATE_DATE =' || P_CREATE_DATE );

     把传入参数直接拼接到SQL语句,然后编译执行。

     当 CREATE_DATE 为 VARCHAR 类型,例如存储的格式是'YYYY-MM-DD'这样的字符串格式,有了解过SQL注入的童鞋们一眼就可以看出这个语句灰常容易遭到SQL注入攻击。

     在这里,为了说明问题,我们再引入一个表 T_PASSWORD, 存放的是机密的用户密码信息等,当然,我们不想向所有人展示这个表的数据,更甚至的我们不希望那些不必要的人知道有这么一个表。但是,黑客(或者一些恶意的开发人员)可以在上面这个段SQL段利用SQL注入可以读取得到这个表数据。

    

    首先,恶意的开发人员或者用户并不知道有这个表,但是他们可以通过传入的参数 P_CREATE_DATE 等于

'' UNION ALL SELECT '', T.OWNER||'.'||T.TABLE_NAME FROM ALL_TABLES T

    这样,那些坏蛋们就可以通过前台我们开发人员提供的这么一个参数端口查看到我们库的库表信息。T_PASSWORD表的存在当然也就暴露咯~

   

    也许,你会说,他们不知道我们的T_PASSWORD有什么字段。是的,他们现在还不知道,但是,他们下一步就会知道了。他们知道了T_PASSWORD表之后,想要了解这个表的字段,一样可以通过传入参数 P_CREATE_DATE 等于

'' UNION ALL SELECT '' , T.COLUMN_NAME ||'.'||T.DATA_TYPE FROM ALL_TAB_COLS T
                    WHERE T.OWNER = ... AND T.TABLE_NAME = ...

   

    到了这里,你也知道他们可以可以查看 T_PASSWORD 表数据了吧。

 

    上面是假设 CREATE_DATE 为 VARCHAR 类型的字段,这里只是一个假设,并不是一个限制!也许有人会问,不是VARCHAR类型的字段,传入的参数不就是不合法了吗?这样不就可以避免了SQL注入攻击了吗?其实,不然。我们可以拿 CREATE_DATE 为 DATE 类型继续说明一下,即使像 DATE 这样的7字节二进制格式也没有办法避免拼接SQL语句受到SQL注入的攻击。

Oracle Database 9i/10g/11g编程艺术 深入数据库体系结构第2版 写道
目前,我认识的大多数开发人员查看代码后都会说:这个代码不会受到SQL注入攻击。他们还会解释说,这是因为这个例程的输入必须是一个ORACLE DATE变量, DATE 是一个表示世纪、年、月、日、时、分和秒的7字节二进制格式。他们认为DATE变量根本没办法改变SQL语句的含义。但事实上,他们都错了!这个代码确实可以“被注入”,有办法的人(显然,确实有很多人知道怎么做)能轻轻松松地再运行时作出修改。

    例如恶意的开发人员或用户只需执行下面代码就可以了:

ALTER SESSION SET
    NLS_DATE_FORMAT = ' '' ' ' UNION SELECT TNAME,0,NULL FROM TAB-- '' ';

 

Oracle Database 9i/10g/11g编程艺术 深入数据库体系结构第2版 写道
这个 NLS_DATE_FORMAT 很有意思,大多数人甚至不知道可以用 NLS_DATE_FORMAT 包含字符串字面量。(另外,很多人还不知道即使不使用 NLS_DATE_FORMAT 这个“技巧”,也可以像这样改变日期格式。)

    事实证明, 通过 NLS_DATE_FORMAT 的设置,类似上面的方法,也是可以进行SQL注入的!

 

(注:上面提到的改变日期格式,本人还没有去了解过。后面有时间去研究研究

 

 

 

 

     那么,我们如何保护自己呢?最直接的办法就是使用绑定变量。

OPEN C_CURSOR FOR 
' SELECT STUNO, STNAME FROM STUDENT T
  WHERE T.CREATE_DATE = :P_CREATE_DATE '  USING P_DATE

 

    使用绑定变量,就不会遭遇SQL注入攻击。 其实,绑定变量还能提升程序的运行速度,但是本文旨在提到SQL注入攻击的思想,了解这个黑客常用的手段以及防范方法,其他的不在本文讨论的范围之内,所以就不在此做过多的描述了。

 

分享到:
评论
1 楼 sea0108 2011-12-06  
向龙哥致敬!你的博文是我永远关注的目标!
Happiness only when shared.

相关推荐

Global site tag (gtag.js) - Google Analytics