文件名:123.php
<?php
function waf($a){
foreach($a as $key => $value){
if(preg_match('/flag/i',$key)){
exit('are you a hacker');
}
}
}
foreach(array('_POST', '_GET', '_COOKIE') as $__R) {
if($$__R) {
foreach($$__R as $__k => $__v) {
if(isset($$__k) && $$__k == $__v)
unset($$__k);
}
}
}
if($_POST) { waf($_POST);}
if($_GET) { waf($_GET); }
if($_COOKIE) { waf($_COOKIE);}
if($_POST) extract($_POST, EXTR_SKIP);
if($_GET) extract($_GET, EXTR_SKIP);
//var_dump($_GET);
if(isset($_GET['flag'])){
if($_GET['flag'] === $_GET['daiker']){
exit('error');
}
if(md5($_GET['flag'] ) == md5($_GET['daiker'])){
include($_GET['file']);
}
}
首先分析一下
foreach(array('_POST', '_GET', '_COOKIE') as $__R) {
if($$__R) {
foreach($$__R as $__k => $__v) {
if(isset($$__k) && $$__k == $__v)
unset($$__k);
}
}
}
这边就是一个典型的foreach遍历取$_POST,$_GET,$_COOKIE中的键值对进行判断
function waf($a){
foreach($a as $key => $value){
if(preg_match('/flag/i',$key)){
exit('are you a hacker');
}
}
}
这里的话就定义了一个waf的函数 进行正则匹配 ‘flag’ 如果匹配到的话 那么直接exit了 这里肯定要绕过了
if($_POST) extract($_POST, EXTR_SKIP);
if($_GET) extract($_GET, EXTR_SKIP);
//var_dump($_GET);
if(isset($_GET['flag'])){
if($_GET['flag'] === $_GET['daiker']){
exit('error');
}
if(md5($_GET['flag'] ) == md5($_GET['daiker'])){
include($_GET['file']);
}
extract 变量覆盖
后面的判断 就是典型的弱类型0e 进行绕过
现在我们开始绕过
foreach(array('_POST', '_GET', '_COOKIE') as $__R) {
if($$__R) {
foreach($$__R as $__k => $__v) {
if(isset($$__k) && $$__k == $__v)
unset($$__k);
}
}
}
绕过后面的waf函数的判断主要就是考察如何绕过这个地方
if(isset($$__k) && $$__k == $__v) unset($$__k);
foreach里面的判断先是遍历$_POST然后再遍历$_GET
后面的isset($$__k) && $$__k ==$__v
需要成立 才能进行unset的操作
又看下这边的waf函数如果匹配到flag就会直接exit 而后面又需要$_GET[flag] 进行判断
那么我们绕过的话 必须得先绕过这里
if($_POST) { waf($_POST);}
if($_GET) { waf($_GET); }
if($_COOKIE) { waf($_COOKIE);}
测试可以发现 当 GET :http://127.0.0.1/123.php?x=1
POST :_$GET[x] =1 的时候
我这边var_dump($_GET)
发现是NULL 分析下代码发现是 unset了$_GET了 所以导致$_GET 直接为空
我们可以先分别var_dump($_GET)和var_dump($_POST)
var_dump(\$_GET):
array(1) { ["x"]=> string(1) "1" }
var_dump(\$_POST):
array(1) { ["_GET"]=> array(1) { ["x"]=> string(1) "1" } }
可以发现在foreach的时候遍历$_GET的时候 isset($$__k) && $$__k == $__v
成立了
所以导致了之后的var_dump($_GET) 为NULL
extract($_POST,EXTR_SKIP)导致的覆盖变量可以使$_GET成功生成 那么最后的弱类型判断就可以直接成立
从而导致绕过 因为我们最后还需要file来读取flag.php
所以这道题还需要
allow_url_include = On
allow_url_fopen = On
那么最后的payload就是这样子的