mcpField
I
injection

injection

github.com/scholarly360安全2248 次安装29 周前更新
代码仓库

关于 injection

injection 是面向 Python 项目的注入漏洞安全测试技能,供审查代码和测试 Web 应用的开发者使用。它汇总 SQL 注入、XSS、SSTI、命令注入和输入验证检查,并给出 Bandit 与 OWASP ZAP 扫描流程。

主要功能

  1. 01SQL、XSS、SSTI 与命令注入检查
  2. 02输入验证风险检查
  3. 03安全与易受攻击代码模式示例
  4. 04Bandit 静态扫描流程
  5. 05OWASP ZAP 动态扫描流程

适用场景

  1. 01审查 Python 项目中的原始 SQL 和命令调用
  2. 02检查模板渲染及用户输入处理风险
  3. 03在 CI/CD 中运行注入漏洞扫描

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/scholarly360/owasp-top10-web-skills --skill injection

安装后在 Claude Code 中输入/injection确认已加载。

附带文件references/payloads.md

详细介绍

OWASP A05:2025 — 注入:Python 安全测试技能

概述

当不可信用户输入到达解释器(例如数据库、OS shell、模板引擎或浏览器),并作为命令或查询的一部分执行时,就会发生注入。尽管注入在 2025 年的排名从第 3 位降到了第 5 位,但它仍是 CVE 数量最多的 OWASP 类别:62,445 个,其中仅 XSS 就有 30,000 多个。

此技能涵盖的注入类型:

  • SQL 注入(SQLi)—— CWE-89
  • 跨站脚本(XSS)—— CWE-79
  • 服务端模板注入(SSTI)—— CWE-94
  • OS 命令注入—— CWE-78 / CWE-77
  • ORM 注入
  • 输入验证失败—— CWE-20
  • LLM 提示词注入(相关类别,OWASP 2025 中有提及)

检测清单

1. SQL 注入(CWE-89)

需要标记的高风险模式:

# ❌ VULNERABLE — f-string in raw SQL
db.execute(f"SELECT * FROM users WHERE email = '{email}'")

# ❌ VULNERABLE — .format() in SQLAlchemy text()
db.execute(text("SELECT * FROM users WHERE id = {}".format(user_id)))

# ❌ VULNERABLE — string concatenation in ORM raw query
User.query.filter(text("name = '" + name + "'"))

需要强制执行的安全模式:

# ✅ SAFE — bound parameters in SQLAlchemy text()
db.execute(text("SELECT * FROM users WHERE email = :email"), {"email": email})

# ✅ SAFE — ORM method (avoids interpreter entirely)
User.query.filter_by(email=email).first()

# ✅ SAFE — FastAPI with Pydantic + SQLAlchemy ORM
async def get_user(user_id: int, db: Session = Depends(get_db)):
    return db.query(User).filter(User.id == user_id).first()

测试方法:

  1. 在代码库中搜索 text(、execute(、raw(、cursor.execute( 加字符串插值的用法
  2. 运行 Bandit:bandit -r . -t B608(硬编码 SQL 表达式)
  3. 注入有效载荷:' OR '1'='1、'; DROP TABLE users; --、1 UNION SELECT null,null--
  4. 对所有接受字符串参数的端点使用 OWASP ZAP 执行主动扫描

2. XSS — 跨站脚本(CWE-79)

需要标记的高风险模式:

# ❌ VULNERABLE — Jinja2 auto-escaping disabled globally
app = Flask(__name__)
# Missing: app.jinja_env.autoescape = True  (it IS on by default for .html — verify!)

# ❌ VULNERABLE — |safe filter on untrusted data
# In template: {{ user_comment | safe }}

# ❌ VULNERABLE — render_template_string with user input
@app.route("/greet")
def greet():
    name = request.args.get("name")
    return render_template_string(f"<h1>Hello {name}</h1>")  # Also SSTI risk!

需要强制执行的安全模式:

# ✅ SAFE — auto-escaping on (Flask default for .html/.htm/.xml/.xhtml)
# Verify: app.jinja_env.autoescape is True for the template extension

# ✅ SAFE — explicit escaping when rendering HTML from user input
from markupsafe import escape
safe_name = escape(request.args.get("name", ""))

# ✅ SAFE — Content-Security-Policy header
@app.after_request
def set_csp(response):
    response.headers["Content-Security-Policy"] = "default-src 'self'"
    return response

测试方法:

  1. 在模板中搜索 | safe——每次使用都需要人工审查
  2. 确认 Jinja2 环境中的所有模板类型都设置了 autoescape=True
  3. 注入:<script>alert(1)</script>、"><img src=x onerror=alert(1)>
  4. 检查响应中的 Content-Security-Policy 和 X-XSS-Protection 标头

3. SSTI — 服务端模板注入(CWE-94)

对于使用 Jinja2 的 Flask 应用,这是最严重的注入风险。将用户输入作为模板字符串渲染,可能导致完整的 Python 表达式执行。

需要标记的高风险模式:

# ❌ VULNERABLE — user input in template constructor
from jinja2 import Template
user_template = request.args.get("template")
return Template(user_template).render()

# ❌ VULNERABLE — render_template_string with user data in template itself
return render_template_string(user_provided_content)

# ❌ VULNERABLE — format string from user input
msg_template = user_input  # "Hello {user.name}"
msg_template.format(user=current_user)  # exposes user object attributes

需要强制执行的安全模式:

# ✅ SAFE — only render static template files; pass user input as context variables
return render_template("greet.html", name=user_name)  # name is escaped, not executed

# ✅ SAFE — if dynamic templates needed, use sandboxed environment
from jinja2.sandbox import SandboxedEnvironment
env = SandboxedEnvironment()
env.from_string(template_str).render(data=safe_data)

测试方法:

  1. 搜索 render_template_string(、Template(,以及源代码包含用户数据的 .format(
  2. 注入 SSTI 探测载荷:{{7*7}}(预期结果为 49)、{{config}}、{{''.__class__.__mro__}}
  3. 权限提升载荷:{{''.__class__.__mro__[1].__subclasses__()}},用于枚举类

4. OS 命令注入(CWE-78、CWE-77)

需要标记的高风险模式:

# ❌ VULNERABLE — shell=True with user input
import subprocess
filename = request.args.get("file")
subprocess.call(f"cat {filename}", shell=True)

# ❌ VULNERABLE — os.system with any user-controlled string
os.system("convert " + user_filename + " output.jpg")

# ❌ VULNERABLE — os.popen
result = os.popen(f"ls {directory}").read()

需要强制执行的安全模式:

# ✅ SAFE — shell=False (default) with argument list
subprocess.run(["cat", filename], shell=False, capture_output=True)

# ✅ SAFE — validate and sanitize before passing to any subprocess
import re
if not re.match(r'^[a-zA-Z0-9._-]+$', filename):
    raise ValueError("Invalid filename")
subprocess.run(["convert", filename, "output.jpg"])

# ✅ SAFE — avoid shell entirely when possible (use Python libraries)
# Instead of: os.system("rm " + path)
import pathlib
pathlib.Path(path).unlink()

测试方法:

  1. Bandit:bandit -r . -t B602,B603,B605,B606,B607(subprocess 和 shell 问题)
  2. 搜索:os.system(、os.popen(、shell=True
  3. 注入:; cat /etc/passwd、| id、&& whoami、`id`

5. 输入验证失败(CWE-20)

FastAPI(Pydantic — 推荐):

# ✅ SAFE — Pydantic enforces types, lengths, patterns at parse time
from pydantic import BaseModel, Field, constr

class UserCreate(BaseModel):
    username: constr(min_length=3, max_length=50, pattern=r'^[a-zA-Z0-9_]+$')
    age: int = Field(ge=0, le=150)
    email: str = Field(max_length=255)

@app.post("/users")
async def create_user(user: UserCreate):
    ...  # Input already validated
# ❌ VULNERABLE — bypassing Pydantic by reading raw request body
body = await request.body()
data = json.loads(body)  # No validation!

Flask(需要手动验证):

# ✅ SAFE — explicit validation with WTForms or marshmallow
from marshmallow import Schema, fields, validate

class UserSchema(Schema):
    username = fields.Str(required=True, validate=validate.Length(min=3, max=50))
    age = fields.Int(validate=validate.Range(min=0, max=150))

# ❌ VULNERABLE — using request.args directly without validation
name = request.args.get("name")  # Could be anything
db.execute(text(f"SELECT * FROM users WHERE name = '{name}'"))

自动化扫描流程

SAST — Bandit
pip install bandit
bandit -r ./app -f json -o bandit_report.json

# Injection-specific test IDs:
# B608 — Hardcoded SQL expressions
# B602 — subprocess with shell=True
# B603 — subprocess without shell_injection check
# B605 — os.system call
# B606 — os.popen call
# B607 — partial executable path
# B701 — Jinja2 autoescape=False
DAST — OWASP ZAP
docker run -t owasp/zap2docker-stable zap-baseline.py \
  -t http://localhost:8000 \
  -r zap_report.html

# For active injection testing (more thorough but more aggressive):
docker run -t owasp/zap2docker-stable zap-full-scan.py \
  -t http://localhost:8000
组合流程(CI/CD):
# .github/workflows/security.yml
- name: Run Bandit SAST
  run: bandit -r ./app -t B608,B602,B603,B605,B606,B701 --exit-zero -f json -o bandit.json

- name: Upload results
  uses: github/codeql-action/upload-sarif@v2
  with:
    sarif_file: bandit.json

重要 CWE 参考

CWE名称主要风险
CWE-89SQL 注入数据库数据泄露/篡改
CWE-79XSS会话劫持、网络钓鱼
CWE-78OS 命令注入RCE、服务器接管
CWE-77命令注入通过 eval/exec 实现 RCE
CWE-94代码注入 / SSTI完整的 Python 执行
CWE-20输入验证不当通往其他所有注入类型的入口

LLM 提示词注入(2025 年新增)

2025 年的 OWASP 列表将 LLM 提示词注入列为相关类别。对于使用 AI API 的应用:

# ❌ VULNERABLE — user input directly in system prompt
system_prompt = f"You are a helpful assistant. Context: {user_provided_context}"

# ✅ SAFER — separate user content from system instructions
messages = [
    {"role": "system", "content": STATIC_SYSTEM_PROMPT},
    {"role": "user", "content": user_input}  # Never injected into system role
]

# Additional mitigations:
# - Input/output filtering for prompt injection patterns
# - Least-privilege tool use (don't give LLM access to sensitive ops)
# - Structured outputs (JSON schema) to limit instruction-following surface

快速参考:按攻击类型划分的严重程度

攻击严重程度利用难度典型影响
SSTI严重中等RCE
OS 命令注入严重中等RCE
SQL 注入高简单–中等数据泄露、绕过身份验证
XSS(存储型)高简单会话劫持
XSS(反射型)中中等网络钓鱼、凭据窃取
ORM 注入高中等数据暴露
提示词注入中–高简单绕过逻辑、数据外泄

参考资料

评论

支持 Markdown