*本文作者:m09046105;本文属 FreeBuf 原创奖励计划,未经许可禁止转载。
笔者将自己在渗透实战中使用到的有关SQL注入的冷门姿势,拿粗来做个分享。SQL注入已经存在很多年了,其中的技巧也似乎被大家玩遍了,笔者分享几个渗透实战中遇到的一些SQL注入中的冷门知识。
当提到sql注入的防御方式,大家就想到了预编译或者参数化查询,然而参数化查询并不是万能的,也有自己的盲点。
(1)参数占位符不能用于指定查询中的表和列的名称。
(2)参数占位符不能用于查询的其他部分,比如ORDER BY子句中的ASC或者DESC关键词等。
Select * from admin where name = ’test’ order by id asc/desc;
上述一条语句,依据id值以升序或降序的方式,查询admin数据表中用户为test的所有字段。
常规的注入点位于test字段处,这时可以用参数话查询来从根本上杜绝SQL注入的产生,但是假设注入点位于表名admin、列名id或者asc和desc关键字处,这时便无法使用参数化查询。
因此在渗透测试中我们需要根据实际情况,来猜测注入点的位置。
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。
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
MyBatis作为一个轻量级的orm框架,跟spring mvc的组合,大有逐渐取代Hibernate的趋势。MyBatis作为一个半自动化的orm框架,相比hibernate可以通过配置文件的方式定制SQL语句,更为灵活。Ibatis是MyBatis的前身,随着其开发团队纷纷转到Google Code旗下,ibatis3.x 正式被命名为Mybatis。Mybatis的SQL语句可以基于注解的方式写在类方法上面,更多的是以xml的方式写到xml文件。
(1) #{} 和 ${}
#{} 采用预编译的形式 ,${} 采用拼接的方式。当原生jdbc不支持预编译的位置 ,比如 表名、排序等位置,这时需要采用 直接拼接的方式。因此要格外重视 可能产生sql注入。
预编译形式:
SELECT *
FROM blog
WHERE id=
拼接形式:
<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注入。
当我们在sql 注入的时候,经常碰到sql 盲住。sleep() 函数有一个不为人熟知的特点,这是笔者在某次渗透中跟同事一起偶然发现的。
Select * from where id =2 and sleep(5);
这条语句查询admin表中 id=1的字段并且等待五秒后返回,即使网站没有将id=1的内容返回,渗透测试人员可以根据返回的时间来判断是否有盲住。
但是,假如admIn表中没有id=2的字段,数据库这时会立即返回空而没有等待五秒。遇到这种情况,便不能跟根据返回的时间来判断是否有盲住了。
mysql这款数据库本身有很大的兼容型 或者说容错性,这确实为开发者提供了很多便利,但也隐藏着巨大的安全隐患,尤其是对不懂安全的web或waf的开发者来说。
比如:select * from admin where user=“Admin” 可以执行, mysql为了 使用的便利性 会允许一些 ‘错误’, select * from admin where user=“ Àdmin” 依然可以执行。
在实际的渗透场景中,有些waf或应用或拦截到”admin”等关键字,这时便可以利用“Àdmin”来实现绕过。
1.《Spring MyBatis 企业应用实战》
2.http://www.freebuf.com/articles/web/33954.html
*本文作者:m09046105;本文属 FreeBuf 原创奖励计划,未经许可禁止转载。