Flask框架远程命令执行-学习笔记

本文为学习笔记:

实验介绍

#coding=UTF-8

from flask import Flask, request, render_template_string, render_template
import os
import string

app = Flask(__name__)

@app.route('/news/')
def news():
    user = {'id':"admin", 'password':"admin888"}
    if request.args.get('id'):
        user['id'] = request.args.get('id')  #获取id参数
    with open('index.html', 'r', encoding='utf-8') as f:  #读取模板文件
        template = f.read() % user['id']    #通过客户端参数渲染模板
    return render_template_string(template, user=user)   #渲染页面


def run_cmd(cmd):                #命令执行函数
    result = os.popen(cmd)
    return result.readlines()

app.jinja_env.globals['run_cmd'] = run_cmd

if __name__ == "__main__":
    app.run(debug=False)

通过以上代码,我们可以看到

 template = f.read() % user['id']

读取了客户端的参数然后传递到模板中渲染。
这样的方法最后会导致我们传入{{user.password}}或者是{{run_cmd()}}等函数执行各种命令。
并且此编程方法也会导致xss的形成,如果我们传入跨站脚本攻击代码即可形成xss。

漏洞修复

 <center><h1>Hello %s</h1></center>

中的%s替换成{{id}}

return render_template_string(template, user=user)

修改成

return render_template(template, user=user)

分析和步骤

首先我们打开页面.发现访问的页面是正确的,登录名为admin
我们将鼠标移到admin上,会发现一个参数id为admin
这时候我们将链接中的id参数值admin改成test,并访问,显示为欢迎test。
然后我们把参数值改成如下poc?id={{run_cmd("cat /etc/passwd")}}即可执行远程命令

http://127.0.0.1:80/?id=poc?id={{run_cmd(%22cat%20/etc/passwd%22)}}

这样的话,模板代码就会变成:

poc?id={{run_cmd("cat /etc/passwd")}}

在解析Flask模板时,会把{{run_cmd("cat /etc/passwd")}}当成run_cmd("cat /etc/passwd")来执行。

Flask框架远程命令执行-学习笔记_第1张图片
在本案例中开发者并未使用官方推荐编程习惯来渲染模板,导致客户端可控花括号,即能正确使用模板语法来构造自己的恶意操作。

你可能感兴趣的:(安全实践)