今天做到一道比较有意思的php弱类型题目,分享给大家 源码如下: - <?php
- show_source(__FILE__);
- $v1=0;$v2=0;$v3=0;
- $a=(array)json_decode(@$_GET['foo']);
- if(is_array($a)){
- is_numeric(@$a["bar1"])?die("nope"):NULL;
- if(@$a["bar1"]){
- ($a["bar1"]>2016)?$v1=1:NULL;
- }
- if(is_array(@$a["bar2"])){
- if(count($a["bar2"])!==5 OR!is_array($a["bar2"][0])) die("nope");
- $pos = array_search("nudt", $a["a2"]);
- $pos===false?die("nope"):NULL;
- foreach($a["bar2"] as $key=>$val){
- $val==="nudt"?die("nope"):NULL;
- }
- $v2=1;
- }
- }
- $c=@$_GET['cat'];
- $d=@$_GET['dog'];
- if(@$c[1]){
- if(!strcmp($c[1],$d) && $c[1]!==$d){
- eregi("3|1|c",$d.$c[0])?die("nope"):NULL;
- strpos(($c[0].$d), "htctf2016")?$v3=1:NULL;
- }
- }
- if($v1 && $v2 && $v3){
- include "flag.php";
- echo $flag;
- }
- ?>
复制代码目标是令v1=1,v2=1,v3=1,从而echo flag
第一步: - $a=(array)json_decode(@$_GET['foo']);
- if(is_array($a)){
- is_numeric(@$a["bar1"])?die("nope"):NULL;
- if(@$a["bar1"]){
- ($a["bar1"]>2016)?$v1=1:NULL;
- }
复制代码这里要令a[bar1]在is_numeric判断下为非数字,而又使其大于2016,所以考虑到这里,通过php语言弱类型的特性构造a[bar1]=2017a
第二步: - if(is_array(@$a["bar2"])){
- if(count($a["bar2"])!==5 OR!is_array($a["bar2"][0])) die("nope");
- $pos = array_search("nudt", $a["a2"]);
- $pos===false?die("nope"):NULL;
- foreach($a["bar2"] as $key=>$val){
- $val==="nudt"?die("nope"):NULL;
- }
- $v2=1;
复制代码这样,首先需要$a[bar2]为一个有5个元素的数组,$a["bar2"][0]也是数组,然后$a["a2"]要包含nudt,$a["bar2"]不包含nudt,于是让$a[bar2]=[1],1,2,3,4,$a[a2]为数组[“nudt”](或者取0或者true)。
由于$a=(array)json_decode(@$_GET['foo']); 所以构造 - foo={"bar1":"2017a","bar2":[[1],1,2,3,4],"a2":["nudt"]}
复制代码第三步: - $c=@$_GET['cat'];
- $d=@$_GET['dog'];
- if(@$c[1]){
- if(!strcmp($c[1],$d) && $c[1]!==$d){
- eregi("3|1|c",$d.$c[0])?die("nope"):NULL;
- strpos(($c[0].$d), "htctf2016")?$v3=1:NULL;
- }
- }
复制代码strcmp()和!==利用数组的方式绕过,eregi则考虑通过%00方式截断,构造: $c[1][]=%00htctf2016 $d=%00htctf2016
综上: - Payload: ?foo={"bar1":"2017a","bar2":[[1],1,2,3,4],"a2":["nudt"]}&cat[1][]=%00htctf2016&dog=%00htctf2016
复制代码附乌云知识库一则: 浅谈PHP弱类型安全 | WooYun知识库 http://drops.wooyun.org/tips/4483
|