笔者将自己在渗透实战中使用到的有关SQL注入的冷门姿势,拿粗来做个分享。SQL注入已经存在很多年了,其中的技巧也似乎被大家玩遍了,笔者分享几个渗透实战中遇到的一些SQL注入中的冷门知识。

一、预编译不是万能的

当提到sql注入的防御方式,大家就想到了预编译或者参数化查询,然而参数化查询并不是万能的,也有自己的盲点。

(1)参数占位符不能用于指定查询中的表和列的名称。

(2)参数占位符不能用于查询的其他部分,比如ORDER BY子句中的ASC或者DESC关键词等。

 Select  *   from admin   where name = ’testorder by id        asc/desc;   

上述一条语句,依据id值以升序或降序的方式,查询admin数据表中用户为test的所有字段。

常规的注入点位于test字段处,这时可以用参数话查询来从根本上杜绝SQL注入的产生,但是假设注入点位于表名admin、列名id或者asc和desc关键字处,这时便无法使用参数化查询。

因此在渗透测试中我们需要根据实际情况,来猜测注入点的位置。

二、Java ORM 可能的安全隐患

Java先后出现过的的orm框架,包括EJB、TopLink、OJB、Mybatis、Hibernate。最早的ORM就是Entity EJ(Enterprise  JavaBean),EJB 是经典Java EE的核心,从EJB1.0到EJB2.x,许多人觉得EJB非常繁琐,所以导致EJB备受诟病。Oracle的TopLink和Apache的OJB,由于种种原因,他们并未得到市场额广泛支持,所以这两个框架的资料、文档很少,使用的人自然也不多。

目前市场使用比较多的ORM就是Hibernate和Mybatis。

1.Hibernate

Hibernate是一款重量级的全自动化ORM框架,它将SQL的操作封装起来。通常情况下,开发者需要通过操作xml配置文件,来进行数据库的操作。但有时为了灵活方便,开发者可以在工具类中通过扩展hibernate  API 操作持久化对象来进行增删改查,此时要用到HQL,HQL(Hibernate Query Language) 是面向对象的查询语言, 它和 SQL 查询语言有些相似。HQL查询并不直接发送给数据库,而是由hibernate引擎对查询进行解析并解释,然后将其转换为SQL。HQL的注射模式非常有限,因为没有系统函数也没有源数据表,十分鸡肋,在实战中可以若发现了HQL注入,若正好位于登入框出,则可以构造万能密码,其他情况下利用方式十分有限。使用HQL的时候需要用到session.createQuery()。

下面给出程序员在代码中常用到的两种HQL查询代码:

(1)参数绑定(安全的写法)


String queryString = "from Item item where item.description like :searchString”;

List result = session.createQuery(queryString)

.setString("searchString", searchString)

.list();

(2)直接拼接(不安全的写法)


final String sql = "select * from product where pname =“;

sql.append(request.getParameter('pname')) ;

目前互联网上关于HQL的注入工具很少,并且只能有限的暴力破解处实体和列名,推荐一看HQL注入的工具:HQLmap    https://github.com/PaulSec/HQLmap

2.Mybatis 

MyBatis作为一个轻量级的orm框架,跟spring mvc的组合,大有逐渐取代Hibernate的趋势。MyBatis作为一个半自动化的orm框架,相比hibernate可以通过配置文件的方式定制SQL语句,更为灵活。Ibatis是MyBatis的前身,随着其开发团队纷纷转到Google Code旗下,ibatis3.x 正式被命名为Mybatis。Mybatis的SQL语句可以基于注解的方式写在类方法上面,更多的是以xml的方式写到xml文件。

(1) #{}   和 ${}

#{}  采用预编译的形式  ,${} 采用拼接的方式。当原生jdbc不支持预编译的位置 ,比如 表名、排序等位置,这时需要采用 直接拼接的方式。因此要格外重视   可能产生sql注入。

预编译形式:


<select id="getBlogById" resultType="Blog">

         SELECT *

         FROM blog

         WHERE id=#{id}

</select>

拼接形式:


<select id="getBlogById" resultType="Blog" >

         SELECT *

         FROM blog

         WHERE id=${id}

</select>

(2)In 后面的注入点

在sql语句中的In之后常常存在注入点,当进行同条件多值查询的时候,Select * from admin where id in (#{id}) 这种形式的语句会报错

因此需要这样写 select  * from admin where id in {${id}} 导致SQL拼接。

(3)模糊查询

在渗透实战中经常发现一些采用了MyBatis框架网站的搜索功能处常常存在SQL注入,原因就是模糊查询的时候,有时会用到参数拼接的形式,比如 : select * from admin where name like ‘%${name}%’,这种情况就存在 SQL注入。

三、Mysql 花式技巧

1.sleep() 的一个特性

当我们在sql 注入的时候,经常碰到sql 盲住。sleep() 函数有一个不为人熟知的特点,这是笔者在某次渗透中跟同事一起偶然发现的。

Select * from  where id =2 and sleep(5);

这条语句查询admin表中 id=1的字段并且等待五秒后返回,即使网站没有将id=1的内容返回,渗透测试人员可以根据返回的时间来判断是否有盲住。

SQL注入的“冷门姿势”

SQL注入的“冷门姿势”

但是,假如admIn表中没有id=2的字段,数据库这时会立即返回空而没有等待五秒。遇到这种情况,便不能跟根据返回的时间来判断是否有盲住了。

SQL注入的“冷门姿势”

2.mysql强大的容错性

mysql这款数据库本身有很大的兼容型 或者说容错性,这确实为开发者提供了很多便利,但也隐藏着巨大的安全隐患,尤其是对不懂安全的web或waf的开发者来说。

比如:select * from admin where user=“Admin”   可以执行,  mysql为了 使用的便利性 会允许一些 ‘错误’, select * from admin where user=“ Àdmin” 依然可以执行。

SQL注入的“冷门姿势”

在实际的渗透场景中,有些waf或应用或拦截到”admin”等关键字,这时便可以利用Àdmin”来实现绕过。

参考资料:

1.《Spring MyBatis 企业应用实战》

2.http://www.freebuf.com/articles/web/33954.html

*本文作者:m09046105