MISC
Shadow
题目
这里是影子的领域,这里藏着光与影的秘密。 那是转瞬即逝的光,还是永恒的影?
题解
用nc连环境,得到一些提示

用python连一下,结果复制出来,替换掉特殊字符,可以看见flag

神秘数据
题目
小明收到一份神秘的文件,观察了文章的段落很久之后终于露出了笑容,你能找到里面隐藏的数据吗? flag格式,flag{xxx},其中xxx为解码得到的值
题解

题目是一段文章,观察可以发现有的后面空一行,有的后面空两行,记录为二进制01,然后二进制转字符获得flag。

Cypto
猜猜我是谁
LQGSK6GUJWNAK4GOJMIIG=J2NWURVU5MJWEMJUZ25TA=WC2SYDMLKCVLYSGLWKMS6=X2GEUHX2GOT2ENUXVNTYQ=
题目
四段同样类型的文本,先栅栏,得到一串base64,解码获得flag。
Web
Nodejs Bypass
题目
没有人比我更懂 nodejs
题解
附件中有两个js文件
const fs = require("fs");
const SECRET_COOKIE = process.env.SECRET_COOKIE || "this_is_testing_cookie"
const flag1 = fs.readFileSync("/flag1")
const flag2 = fs.readFileSync("/flag2")
function merge(target, source) {
for (let key in source) {
if (key == "__proto__") {
continue; // no proto, please bypass
}
if (key in target && key in source) {
merge(target[key], source[key])
} else {
target[key] = source[key]
}
}
}
function LoginController(req, res) {
try {
let user = {}
merge(user, req.body)
if (user.username !== "admin" || user.password !== Math.random().toString()) {
res.status(401).type("text/html").send("Login Failed")
} else {
res.cookie("user", SECRET_COOKIE)
req.user = "admin"
res.redirect("/flag1")
}
} catch (e) {
console.log(e)
res.status(401).type("text/html").send("What the heck")
}
}
function Flag1Controller(req, res) {
try {
if (req.cookies.user === SECRET_COOKIE || req.user == "admin") {
res.setHeader("This_Is_The_Flag1", flag1.toString().trim())
res.status(200).type("text/html").send("Login success. Welcome,admin!")
} else {
res.status(401).type("text/html").send("Unauthorized")
}
} catch (__) { }
}
function Flag2Controller(req, res) {
let checkcode = req.body.checkcode ? req.body.checkcode : 1234;
console.log(req.body)
if (checkcode.length === 16) {
try {
checkcode = checkcode.toLowerCase()
if (checkcode !== "aGr5AtSp55dRacer") {
res.status(403).json({ "msg": "Invalid Checkcode1:" + checkcode })
}
} catch (__) { }
res.status(200).type("text/html").json({ "msg": "You Got Another Part Of Flag: " + flag2.toString().trim() })
} else {
res.status(403).type("text/html").json({ "msg": "Invalid Checkcode2:" + checkcode })
}
}
module.exports = {
LoginController,
Flag1Controller,
Flag2Controller
}
const express = require("express")
const fs = require("fs")
const cookieParser = require("cookie-parser");
const controller = require("./controller")
const app = express();
const PORT = Number(process.env.PORT) || 80
const HOST = '0.0.0.0'
app.use(express.urlencoded({ extended: false }))
app.use(cookieParser())
app.use(express.json())
app.use(express.static('static'))
app.get("/", (res) => {
res.sendFile(__dirname, "static/index.html")
})
app.post("/", (req, res) => {
controller.LoginController(req, res)
})
app.get("/flag1", (req, res) => {
controller.Flag1Controller(req, res)
})
app.post("/flag2", (req, res) => {
controller.Flag2Controller(req, res)
})
app.listen(PORT, HOST, () => {
console.log(`Server is listening on Host ${HOST} Port ${PORT}.`)
})
审计代码,发现存在flag1和flag2两个入口
先看flag1,需要检测req.user==admin。
通过constructor进行原型链污染,把用户设置为admin。
然后访问flag1,发现已经成功登录。
重放这个请求,可以得到前半截flag。
然后审计flag2,发现需要传入checkcode,长度为16,并且要与指定字符串相等,因为先执行了toLowerCase函数,因此不能直接传入,需要产生异常跳出try代码块才能执行后续部分。
传入数组,进行比较时会抛出异常,因为长度要求是16,因此构造长度为16的数组。
用GET会提示错误,那就用POST。
One Number SQL
题目
GZTime 把 flag 藏到数据库里,只给大家看 flag 的一小截,但是这不影响你拿到 flag 吧 ~
题解
访问页面,得到一句提示
小 GZ 露出 flag 的一角,但是这离成功远远不够,你能将 flag 整条拖出来吗
审计代码,发现存在隐藏提示。
<p class="secret">something secrets in /hint <span class="emoji key"></span></p>
访问hint,得到代码。
def waf(str):
length = 0
for c in str:
if(c.isdigit()):
length += length * 10 + int(c)
return length > 0 and length < 10
@app.route('/getFlag')
def getFlag():
flag_len = request.args.get("len")
try:
if(waf(flag_len)):
result = cursor.execute(f"select substr(flag,1,{flag_len}) from flag")
result = result.fetchone()
print(len(result[0]))
if(len(result[0])):
return render_template('getflag.html',message=result[0]) # Only the first query information of sql can be obtained
else:
return render_template('getflag.html',message="nothing here")
else:
return render_template('getflag.html',message="len should be 0 < len < 10")
except:
return render_template('getflag.html',message="Error! Please Try Again Meow~ ")
审计代码发现,需要访问getFlag,传入参数len,用于执行select语句,但是len最大不能超过10,因此构造语句,断开并重新构造查询语句。
传入一个小于10的数字绕过WAF,然后同步构造from flag where 'a'='b',通过假条件让返回的结果为空,再通过union select执行我们的真实操作,select flag from flag,添加两个减号,注释掉后续内容。
len=1) from flag where 'a'='b' union select flag from flag--
The Moment of Token
题目
转瞬即逝的时机,转瞬即逝的宝藏。
题解
审计代码,发现有一句提示。
<!-- maybe... int(time.time()) - int(password) < 5 -->
那么输入的密码要和时间戳的差要小于5,抓包改时间戳,header里面发现一个jwt的token。
在线JWT解密,发现有个gift字段,是base32加密后的flag。
文章评论