打seccon的第一年,为了队友的日本旅行梦,跟他们爆了!
WEB
ssrforlfi
主要代码如下

import os
import re
import subprocess
from flask import Flask, request
app = Flask(__name__)
@app.route("/")
def ssrforlfi():
url = request.args.get("url")
if not url:
return "Welcome to Website Viewer.<br><code>?url=http://example.com/</code>"
# Allow only a-z, ", (, ), ., /, :, ;, <, >, @, |
if not re.match('^[a-z"()./:;<>@|]*$', url):
return "Invalid URL ;("
# SSRF & LFI protection
if url.startswith("http://") or url.startswith("https://"):
if "localhost" in url:
return "Detected SSRF ;("
elif url.startswith("file://"):
path = url[7:]
if os.path.exists(path) or ".." in path:
return "Detected LFI ;("
else:
# Block other schemes
return "Invalid Scheme ;("
try:
# RCE ?
proc = subprocess.run(
f"curl '{url}'",
capture_output=True,
shell=True,
text=True,
timeout=1,
)
except subprocess.TimeoutExpired:
return "Timeout ;("
if proc.returncode != 0:
return "Error ;("
return proc.stdout
if __name__ == "__main__":
app.run(debug=True, host="0.0.0.0", port=4989)
其实一开始看到这即过滤localhost又过滤file://的思路很容易被带着跑,就想着要怎么通过域名打ssrf。但是如果仔细看就会发现就算我现在有办法访问到127.0.0.1或者localhost也无济于事,根本不知道下一步要干嘛
之后又把目光放在了curl '{url}'
,想直接RCE,但由于反引号没在白名单所以也没用
最后通过尝试后发现file:///
虽然被干掉了,但是file://
是正常的,原因就在于在这个判断条件中
path = url[7:]
if os.path.exists(path) or ".." in path:
return "Detected LFI ;("
file://
正好占了7个字符,而os.path.exists(path)
是来判断后面路径是否存在的,所以当输入诸如file:///etc/passwd
这样的payload时就会因为/etc/passwd
真实存在被干掉
绕过也很简单,只要换成file://localhost/etc/passwd
就行了,这时候path就变成了localhost/etc/passwd
,显然不存在。最后直接读环境变量即可file://localhost/proc/self/enviro
MISC
commentator

主要代码如下
python = ""
while True:
line = input(">>> ").replace("\r", "")
if "__EOF__" in line:
python += 'print("thx :)")'
break
python += f"# {line}\n" # comment :)
pyfile = f"/tmp/{uuid.uuid4()}.py"
with open(pyfile, "w") as f:
f.write(python)
os.system(f"python {pyfile}")
os.remove(pyfile)
乍一看就是要绕注释,但是之前没碰到过这种题。这里记录一下比赛结束后有人分享的一篇wpCTFtime.org / THC CTF 2021 / TheHiddenOne / Writeup
简单来说就是利用头部声明使得\n
可以被编码成unicode,从而不会被input函数给吞掉并且能够正常执行,常见的头部声明有像下面这样
# -*- coding: UTF-8 -*-
或者
# coding=utf-8
为此我专门去了解了另外一个很像这种头部声明并且也经常在脚本中见到的东西
#!/usr/bin/env python
这是一种叫shebang的语法,以上面这句为例,说就是可以让写了这行的文件被当成可执行文件,并使用指定的这个路径去执行这个文件。比如下面这样

假设这个脚本的名字是1.py,那么我就可以直接用./1.py
去执行这个脚本,来替代python 1.py
所以下次再在dockerfile里见到python脚本被丢到一个没后缀的文件里就不用奇怪了,因为没后缀也是可以执行的

总结
个人感觉是非常非常非常考验经验的一场比赛,这次我们的银河战舰Echo排在了第65名

(前期稳定第一将近四个小时,直到国际高手们陆续出现😂)
commentator这题被放在了misc方向,但是和我在lab上布置的往年题一样都是参杂着浓浓web味的misc题
挺有意思的,不过这也只是Beginner,希望几个月后的正式赛能够稳住前十