题目如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php
error_reporting(0);
echo "<!--index.phps-->";
if(!$_GET['id'])
{
header('Location: index.php?id=1');
exit();
}
$id=$_GET['id'];
$a=$_GET['a'];
$b=$_GET['b'];
if(stripos($a,'.'))
{
echo 'Hahahahahaha';
return ;
}
$data = @file_get_contents($a,'r');
if($data=="1112 is a nice lab!" and $id==0 and strlen($b)>5 and eregi("111".substr($b,0,1),"1114") and substr($b,0,1)!=4)
{
require("flag.txt");
}
else
{
print "work harder!harder!harder!";
}
?>

首先定位到得到flag的代码的位置:

1
2
3
4
if($data=="1112 is a nice lab!" and $id==0 and strlen($b)>5 and eregi("111".substr($b,0,1),"1114") and substr($b,0,1)!=4)
{
require("flag.txt");
}

从这里我们可以知道要得到flag需要满足的条件:

  • $data==”1112 is a nice lab!”
  • $id==0
  • strlen($b)>5 and eregi(“111”.substr($b,0,1),”1114”) and substr($b,0,1)!=4

如果我们能够满足上面这些条件,那么flag就出来了,所以我们要绕过限制,使上面的条件成立。

我们先来分析$data==”1112 is a nice lab!”

1
$data = @file_get_contents($a,'r');

$data的值是通过读取文件$a得到的,而$a的值是GET参数a的值。
所以a变量只能是一个文件名称,按照常规思路:
我们可以在服务器上面建立一个文件,然后文件的内容为”1112 is a nice lab!”
但是:

1
2
3
4
5
if(stripos($a,'.'))
{
echo 'Hahahahahaha';
return ;
}

我们可以看到,这里使用了stripos函数来匹配GET参数a中的’.’,我们知道,服务器的ip或者域名中是一定会存在’.’的
如果我们读取一个远程服务器上面的文件的话,那么就会匹配到’.’,结果就会像这样:

那么我们怎么绕过呢,这时我们要用到php的伪协议:php://input
php://input 是个可以访问请求的原始数据的只读流。
file_get_contents()可以读取php://input通过post提交的数据
具体做法如下:
a=php://input然后post一个字符串,就等价于文件a的内容为post的那个字符串
所以GET参数a=php://input
然后post:1112 is a nice lab!

好了,第一个已经成功绕过限制,下面来看下一个:
$id==0
$id参数的值是GET参数id的值
如果我们直接给GET参数id赋值为0的话:

1
2
3
4
5
if(!$_GET['id'])
{
header('Location: index.php?id=1');
exit();
}

那么if语句内的(!$_GET[‘’id])就为1,然后{}内的语句就会执行导致程序退出,因此,id的值不能为0
那么该怎么绕过呢?
我们注意到:
$id和0是用”==”来进行比较的,那么这就是一个很简单的弱类型了,字符和0比较时会被转换为0,所以一个id=a就ok了。

然后就只剩下一个strlen($b)>5 and eregi(“111”.substr($b,0,1),”1114”) and substr($b,0,1)!=4了
首先我们先介绍下eregi和substr函数:
eregi()该函数有两个参数,如果第一个参数时第二个参数的子串,那么就返回1,否则就返回空。
substr(string,start,length) start是从0开始的,然后返回匹配到的子串。
我们来分析下这个条件,要$b的长度大于5,但是”111”.substr($b,0,1)是”1114”的子串,而1114的长度才为4而已,而且后面的substr($b,0,1)!=4还限定了$b不能为4.

这时,我们要利用substr和eregi会被00截断的特性,而strlen不会,strlen中的%00会被当作0。
所以我们这样构造 b=%0012345就OK了。
最终的payload:
?id=a&a=php://input&b=%00123456
然后post一个:1112 is a nice lab!

最后更新: 2018年04月12日 22:37

原始链接: http://drac0nids.top/2018/04/11/challenge10/

× 请我吃糖~
打赏二维码