PHP_Code_Challenge-3-弱比较&00截断substr&获取请求原始数据流

题目

<?php
error_reporting(0);
echo "<!--challenge3.txt-->";
require __DIR__.'/lib.php';
if(!$_GET['id'])
{
    header('Location: challenge3.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)
{
    echo $flag;
}
else
{
    print "work harder!harder!harder!";
}
?>

分析

$id

if(!$_GET['id'])
{
    header('Location: challenge3.php?id=1');
    exit();//die()
}

id不为0或null

and $id==0 

利用php弱类型比较,数字与字符串等值比较时,字符串取开头的有效数字,无则为0,结合id不为0或null,id可取值开头不带有效数字的字符串,$id=abc123

$a

if(stripos($a,'.'))
{
    echo 'Hahahahahaha';
    return ;
}

$a要么没有. 要么.在字符串的第一位

$data

$data = @file_get_contents($a,'r');
$data=="1112 is a nice lab!"

当$a=php://input,即file_get_contents('php://input','r')
$data取请求原始数据流,即post的内容,$a=php://input
$data取post的数据,post 1112 is a nice lab! 即可

$b

strlen($b)>5

$b字符串长度大于5

eregi("111".substr($b,0,1),"1114")

111与$b字符串被截取的第一位字符连结后形成的字符串能在1114中匹配到,即连结后的字符串可以是111也可以是1114

substr($b,0,1)!=4

$b字符串第一位字符不为4
综上所述
利用%00截断,使substr截取$b字符串时被截断,从而形成eregi("111","1114"),匹配成功,同时%00不会对strlen截断,$b=%0012345

知识点

弱比较

字符串与整数比较时,取字符串中开头的整数部分

截断

%00能截断substr,但注意get传递时会自动解码一次

获取请求原始数据流

https://blog.csdn.net/qq_41445224/article/details/88890323
获取post的数据,有三种方式。
第一种是通过$HTTP_RAW_POST_DATA这个变量,开启需要修改ini
第二种是file_get_contents(php://input),不需要修改配置文件
在项目应用中,如摄像头拍照,上传保存,就可以用到php://input。客户端拍照后,把图片流传送到服务端,服务端使用file_get_getcontents(‘php://input’)就能获取到图片流,然后把图片流保存到一个文件,这个文件就是图片了。
第三种是通过$_POST,其与第二种区别如下

<?php
$raw_post_data = file_get_contents('php://input');
echo "-------\$_POST------------------<br/>";
echo var_dump($_POST) . "<br/>";
echo "-------php://input-------------<br/>";
echo $raw_post_data . "<br/>";
?>
<form action="a.php" method="post" >
   <input type="text" value="zhangsan" name="name"/></br>
   <input type="password" value="zhangsan" name="pwd"/></br>
   <input type="submit" value="提交" /></br>
</form>

提交后显示的结果为:

-------$_POST------------------
array(2) { [“name”]=> string(8) “zhangsan” [“pwd”]=> string(8) “zhangsan” }
-------php://input-------------
name=zhangsan&pwd=zhangsan

解法

<?php
error_reporting(0);
echo "<!--challenge3.txt-->";
require __DIR__.'/lib.php';
//$_GET['test']='abc123';
//var_dump(!$_GET['test']);//bool(false)

//if($_GET['test']==0)var_dump('yes');

//var_dump(!'abc123');//要为false

//var_dump(substr(urldecode('%0012345'),0,1));//注意url中通过get传递的数据会被url解码一次

//var_dump(urldecode('%0012345'));

//die;
if(!$_GET['id'])//id不为0或null
{
    header('Location: challenge3.php?id=1');
    exit();//die()
}
$id=$_GET['id'];
$a=$_GET['a'];
$b=$_GET['b'];
if(stripos($a,'.'))//$a要么没有. 要么.在字符串的第一位
{
    echo 'Hahahahahaha';
    return ;
}

$data = @file_get_contents($a,'r');//当$a=php://input,即file_get_contents('php://input','r')时,$data取请求原始数据流,即post的内容,$a=php://input
//$data [取post的数据,post 1112 is a nice lab! 即可]
//$id == 0 [利用php弱类型比较,数字与字符串等值比较时,字符串取开头的有效数字,无则为0,结合id不为0或null,id可取值开头不带有效数字的字符串,$id=abc123]
//strlen($b)>5 [$b字符串长度大于5]
//eregi("111".substr($b,0,1),"1114") [111与$b字符串被截取的第一位字符连结后形成的字符串能在1114中匹配到,即连结后的字符串可以是111也可以是1114]
//substr($b,0,1)!=4 [$b字符串第一位字符不为4]
//利用%00截断,使substr截取$b字符串时被截断,从而形成eregi("111","1114"),匹配成功,同时%00不会对strlen截断,$b=%0012345
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)
{
    echo $flag;
}
else
{
    print "work harder!harder!harder!";
}
?>

参考

https://blog.csdn.net/qq_41445224/article/details/88890323
https://www.php.net/manual/zh/reserved.variables.httprawpostdata.php

posted @ 2020-03-19 19:27  雨九九  阅读(770)  评论(0编辑  收藏  举报