专栏名称: 衡阳信安
船山院士网络安全团队唯一公众号,为国之安全而奋斗,为信息安全而发声!
目录
相关文章推荐
北美留学生观察  ·  日本县城高中,挤满中国中产娃... ·  5 小时前  
北美留学生观察  ·  藤校进入9万美元时代!扩招、涨价、割中产娃韭菜… ·  2 天前  
BioArt  ·  Cell | ... ·  3 天前  
51好读  ›  专栏  ›  衡阳信安

浅谈FastAPI框架下的内存马

衡阳信安  · 公众号  ·  · 2024-09-20 01:00

正文

什么是 FastAPI ?

fastapi文档 FastAPI - FastAPI (tiangolo.com)

FastAPI 是一个现代的、快速(高性能)的 Web 框架,用于构建 API。它基于 Python 3.6+ 的类型提示,使用 Starlette 作为其底层 ASGI 框架,并使用 Pydantic 进行数据验证。以下是一个简单的 FastAPI 示例

示例代码

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def read_root():
return {"Hello": "World"}

@app.get("/items/{item_id}")
def read_item(item_id: int, q: str = None):
return {"item_id": item_id, "q": q}

if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)

解释

  1. 导入 FastAPI :

    from fastapi import FastAPI
    导入 FastAPI 框架。

  2. 创建 FastAPI 实例 :

    app = FastAPI()
    创建一个 FastAPI 应用实例。

  3. 定义路由 :

  • @app.get("/") : 定义根路由的处理函数,响应 HTTP GET 请求。

  • read_root() : 根路由处理函数,返回一个 JSON 响应 {"Hello": "World"}

  • @app.get("/items/{item_id}") : 定义带路径参数的路由。

  • read_item(item_id: int, q: str = None) : 处理路径参数 item_id 和可选的查询参数 q ,返回 JSON 响应。

  • 运行应用 :

    if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000)
    使用 Uvicorn 运行应用,监听 8000 端口。

  • 运行应用

    保存代码为 main.py ,然后运行以下命令启动 FastAPI 应用:

    uvicorn main:app --reload

    访问 API

    • 根路由: http://localhost:8000/

    • 带路径参数的路由: http://localhost:8000/items/42?q=search

    文档

    FastAPI 会自动生成 API 文档,你可以通过以下 URL 访问:

    • 自动生成的文档 : http://localhost:8000/docs

    • 原始文档 : http://localhost:8000/redoc

    这就是 FastAPI 的基本用法!

    巅峰极客2024 GoldenHornKing

    源码如下

    import os
    import jinja2
    import functools
    import uvicorn
    from fastapi import FastAPI
    from fastapi.templating import Jinja2Templates
    from anyio import fail_after


    # Decorator to add a timeout to async functions
    def timeout_after(timeout: int = 1):
    def decorator(func):
    @functools.wraps(func)
    async def wrapper(*args, **kwargs):
    with fail_after(timeout):
    return await func(*args , **kwargs)
    return wrapper
    return decorator

    # Initialize FastAPI app
    app = FastAPI()
    access = False

    # Set up Jinja2 template directory
    _base_path = os.path.dirname(os.path.abspath(__file__))
    t = Jinja2Templates(directory=_base_path)

    @app.get("/")
    @timeout_after(1)
    async def index():
    # Read and return the content of the current file
    return open(__file__, 'r').read()

    @app.get("/calc")
    @timeout_after(1)
    async def ssti(calc_req: str ):
    global access
    if (any(char.isdigit() for char in calc_req)) or ("%" in calc_req) or not calc_req.isascii() or access:
    return "bad char"
    else:
    print(calc_req)
    template = jinja2.Environment(loader=jinja2.BaseLoader()).from_string(f"{{{{ {calc_req} }}}}")
    rendered_template = template.render({"app": app})
    return rendered_template
    return "fight"
    # Run the application with Uvicorn server
    if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8080)

    分析

    if的条件判断access这个变量是否为true,如果为true就不渲染了,所以只能渲染一次,并且渲染是不能有数字的

    这里为了本地方便测试,修改渲染一次的限制

    @app.get("/calc")
    @timeout_after(1)
    async def ssti(calc_req: str ):
    global access
    if (any(char.isdigit() for char in calc_req)) or ("%" in calc_req) or not calc_req.isascii() or access:
    return "bad char"
    else:
    print(calc_req)
    template = jinja2.Environment(loader=jinja2.BaseLoader()).from_string(f"{{{{ {calc_req} }}}}")
    rendered_template = template.render({"app": app})
    return rendered_template

    由于不能有数字,我们直接从 lipsum 出发得到 __builtins__
    payload:

    /calc?calc_req=lipsum.__globals__.__builtins__

    但是目标不出网且无回显,所以我们需要写内存马

    寻找Fastapi框架的添加路由函数

    本题用的是 fastapi 的web框架而不是 flask ,需要自己寻找可用方法

    通过寻找我们发现添加路由方法 add_route , add_middleware , add_route , add_api_route

    通过搜索发现 add_api_route 可以用来自定义创建路由

    示例如下:

    from fastapi import FastAPI, APIRouter

    class Hello:

    def __init__(self, name: str):
    self.name = name
    self.router = APIRouter()
    self.router.add_api_route("/hello", self.hello, methods=["GET"])

    def hello(self):
    return {"Hello": self.name}

    app = FastAPI()
    hello = Hello("World")
    app.include_router(hello






    请到「今天看啥」查看全文