// This file is auto-generated by scripts/generate-skills.ts // Do not edit manually const SKILL_FILE_0 = "# 检查项\r\n请严格按照下列检查项对历史对话记录和输出的报告结果进行检查,逐项确认是否满足,否则你会被扣除十亿美金\r\n\r\n## 推理过程检查\r\n主要对历史对话记录/工具调用历史进行检查\r\n\r\n### 推理幻觉检查\r\n1. 所有代码分析均已闭环,不存在待分析的函数\r\n2. 所有结论均有相关代码举证,不存在假设/猜测的结论(无法获取到代码的情况除外)\r\n\r\n### 代码链路完整性检查\r\n1. 除非已经确认该漏洞不可利用或对应的参数均已防护或校验,否则分析过程必须追溯到解析用户可控输入的代码/函数\r\n2. 如果代码链路中包含安全防护/校验函数,必须获取对应代码进行分析,并得出是否安全的结论。若确认无法触发漏洞,则<代码链路的完整性检查>通过\r\n3. 如果追溯到用户可控输入是HTTP请求, 则必须明确对应的接口URI是什么\r\n4. 当可控输入来源于中间件时(数据库、缓存、消息队列等),查找是否存在设置对应字段内容的代码逻辑\r\n5. 针对结论为不存在安全漏洞的,如果符合下述特定场景,则不必提供完整代码, <代码链路的完整性检查>通过\r\n - 已确认 用户可控输入 为代码中定义的常量或非外部可控的变量\r\n - 已确认 用户可控输入 类型为整形、布尔型或枚举型等无法有效拼接的类型\r\n - 数据流中某个代码片段代码是注释掉的,数据流不完整\r\n - SQL注入漏洞,如果是简单的数值拼接、存在参数化预处理、ORM框架或其他防护\r\n - 服务端请求伪造漏洞(SSRF),如果存在安全防护/校验函数、对应参数是整型或布尔型(不可利用)、或者不能直接控制的,如从配置文件、环境变量、数据库查询等非实际直接可控(需要先能控制对应文件或环境)的方式读取的\r\n - 文件路径穿越、路径注入等文件相关类型的漏洞,已确认不存在文件读写相关操作\r\n - 已经明确多次查找均找不到对应的函数或变量,并结合代码上下文分析说明了函数用途且符合代码逻辑的,则<代码链路的完整性检查>通过\r\n6. 当前分析过程链路覆盖以下链路之一:\r\n - 解析用户输入->污点变量传播->触发漏洞\r\n - 确认无安全的防护/校验函数->污点变量传播->触发漏洞\r\n - 确认已有安全防护/校验函数->无法触发漏洞\r\n - 确认符合不存在安全漏洞的特定场景->无法触发漏洞\r\n7. 如果分析中涉及第三方代码或框架,可以根据框架特性和项目使用模式来分析,不必提供完整代码\r\n \r\n## 报告结构检查\r\n主要对输出的报告进行检查\r\n\r\n### 安全漏洞存在性\r\n1. 存在性结论只允许两类结论:存在/不存在\r\n\r\n### 漏洞利用条件及触发方式\r\n1. 漏洞利用条件和触发方式必须对应,逻辑合理,不要出现相互矛盾的情况,如果存在相互矛盾的情况,则<漏洞利用条件及触发方式>不通过\r\n2. 关键在于校验利用条件中关于污点参数的约束(如数值、正则、枚举类型)和触发方式罗列的内容是否矛盾,有矛盾则<漏洞利用条件及触发方式>不通过,如:正则表达式里过滤了单引号,触发方式就不能有单引号了。\r\n\r\n### 数据流\r\n#### 可控输入限制检查\r\n1. 可控输入为HTTP请求类型时,<数据流>起始点必须为相关接口的URI\r\n2. 可控输入为文件读取类型时,<数据流>起始点必须为对应的文件路径\r\n3. 可控输入来源于中间件时(数据库、缓存、消息队列等),明确设置对应字段的代码逻辑,追踪数据流\r\n4. 如果确认相关污点参数均已有安全防护/校验函数,无法触发漏洞,则<可控输入限制检查>通过\r\n5. 如果结论为不存在安全漏洞,且<代码链路的完整性检查>通过的,则<可控输入限制检查>通过\r\n\r\n#### 覆盖度检查\r\n1. <数据流>中必须覆盖推理分析得到的完整传播链路\r\n\r\n### 关键代码片段\r\n1. <关键代码片段>列举的代码需要和<数据流>中步骤一一对应,不允许有缺漏\r\n\r\n\r\n# 检查项评估输出定义\r\n你需要以下面定义的XML结构输出你的评估结果\r\n\r\n通过/不通过\r\n简要解释通过/不通过原因\r\n下一步行动建议:输出报告/\r\n1. 获取xxx代码,继续进行分析\r\n2. xxx\r\n\r\n\r\n\r\n示例1:\r\n\r\n不通过\r\n当前分析过程未明确HTTP请求对应的接口URI,且可能存在安全防护/校验函数未分析,不满足代码链路完整性检查\r\n下一步行动建议:\r\n1. 获取路由绑定代码,继续进行分析,明确接口URI\r\n2. 获取可能的校验函数validator.check_input_and_output_valid实现,分析其是否足够安全\r\n\r\n\r\n\r\n示例2:\r\n\r\n通过\r\n所有检查项已通过\r\n下一步行动建议:输出报告\r\n\r\n\r\n" const SKILL_FILE_1 = "# 控制安全建模分析法\r\n\r\n## 核心公式\r\n\r\n缺失类漏洞 = 敏感操作 - 应有控制 或 敏感操作 + 控制失效绕过\r\n\r\n敏感操作存在,但应有的安全控制缺失 = 漏洞\r\n\r\n机制缺陷导致控制绕过 = 漏洞\r\n\r\n## 安全控制建模&控制存在/有效性验证\r\n\r\n### 敏感操作分类\r\n\r\n| 类别 | 识别特征 | 典型示例 | 风险等级 |\r\n| ------------ | ------------------------------------ | --------------------- | -------- |\r\n| **数据修改** | POST/PUT/DELETE | 创建/修改/删除 | 高 |\r\n| **数据访问** | GET + ID参数 | /user/{id} /用户/{id} | 中 |\r\n| **批量操作** | export/download/batch 导出/下载/批量 | 导出/批量删除 | 高 |\r\n| **权限变更** | role/permission/grant 角色/权限/授予 | 角色/权限分配 | 严重 |\r\n| **资金操作** | transfer/pay/refund 转账/付款/退款 | 转账/支付/退款 | 严重 |\r\n| **认证操作** | login/password/token 登录/密码/令牌 | 登录/密码重置 | 严重 |\r\n\r\n### 安全控制矩阵\r\n\r\n| 敏感操作类型 | 必须控制 | 可选控制 |\r\n| ------------ | -------------------------------- | -------- |\r\n| **数据修改** | 认证、授权、资源所有权、输入验证 | 审计日志 |\r\n| **数据访问** | 认证、资源所有权/范围限制 | 数据脱敏 |\r\n| **批量操作** | 认证、授权、数量限制 | 频率限制 |\r\n| **权限变更** | 认证、高级授权、权限边界检查 | 审批流程 |\r\n| **资金操作** | 认证、授权、幂等性、并发控制 | 风控检查 |\r\n| **认证操作** | 幂等性、频率限制 | 并发控制 |\r\n\r\n### 缺失控制 → 漏洞映射\r\n\r\n| 缺失控制 | 漏洞类型 | CWE |\r\n| -------------- | -------------- | ------- |\r\n| 认证缺失 | 认证绕过 | CWE-306 |\r\n| 授权缺失 | 功能级授权缺失 | CWE-862 |\r\n| 资源所有权缺失 | IDOR | CWE-639 |\r\n| 授权逻辑错误 | 授权错误 | CWE-863 |\r\n| 幂等性缺失 | 重放攻击 | CWE-294 |\r\n| 并发控制缺失 | 竞态条件 | CWE-362 |\r\n| 频率限制缺失 | 暴力破解、洪水攻击 | ... |\r\n\r\n### 控制机制缺陷 → 机制绕过\r\n\r\n- **验证码状态未失效**: 验证码校验成功后,排查未将其从缓存中删除或未标记为作废的状态控制遗漏(导致同一个验证码被多次复用)。\r\n- **输入未绑定**: 审查敏感操作二次认证中(如资金转账、修改密码等),目标手机号/邮箱完全信任前端传入参数,未与当前登录用户会话身份进行绑定的逻辑缺陷(导致二次鉴权失效)。\r\n- **认证步骤绕过**:审查多步操作(如找回密码流程:1.验证手机 -> 2.输入验证码 -> 3.重置密码)中,关键步骤仅依赖前端传入参数(如 `step=3`)决定执行流程,而未在后端强校验用户已完成前置步骤的逻辑跳跃漏洞。\r\n- **校验返回错误**: 检查鉴权失败或Token无效的分支中,代码仅记录日志,输出错误信息或重新赋值创建token/session,而**未写 `return`、`raise` 彻底阻断执行流**,导致后续敏感代码继续执行的短路缺陷。\r\n\r\n\r\n## 注意事项\r\n\r\n! 对于认证、授权类问题,注意横向对比同模块的其他方法实现\r\n! 注意分析控制机制是否存在逻辑缺陷,可导致机制被绕过\r\n" const SKILL_FILE_2 = "# Django Security Audit\n\n> Django 框架安全审计模块\n> 适用于: Django, Django REST Framework\n\n## 识别特征\n\n```python\n# Django项目识别\nimport django\nfrom django.http import HttpResponse\nfrom django.views import View\n\n# 文件结构\n├── manage.py\n├── project/\n│ ├── settings.py\n│ ├── urls.py\n│ └── wsgi.py\n├── app/\n│ ├── models.py\n│ ├── views.py\n│ ├── urls.py\n│ └── forms.py\n└── templates/\n```\n\n---\n\n## Django特定漏洞\n\n### 1. ORM注入\n\n```python\n# 危险: raw()拼接\nUser.objects.raw(f\"SELECT * FROM auth_user WHERE id = {user_id}\")\nUser.objects.raw('SELECT * FROM auth_user WHERE id = %s' % str(id)) # 字符串拼接\n\n# 危险: extra()拼接\nUser.objects.extra(where=[f\"id = {user_id}\"])\nUser.objects.extra(WHERE=['id=' + str(id)]) # 拼接导致注入\n\n# 危险: RawSQL\nfrom django.db.models.expressions import RawSQL\nqueryset.annotate(val=RawSQL(f\"SELECT col FROM tbl WHERE id = {id}\"))\n\n# 危险: 参数名可控 (高危!)\nimport json\ndata = json.loads(request.body.decode())\nStudent.objects.filter(**data).first()\n# payload: {\"passkey__contains\":\"a\"} 利用 lookup 语法\n# 可用 lookup: __contains, __startswith, __endswith, __icontains, __regex 等\n\n# 危险: 字典键可控\ndict = {'username': user_input, 'age': 18}\nUser.objects.create(**dict) # 如果 username 包含注入字符\n\n# 二次注入\nfilename = request.GET.get('url')\nFile.objects.create(filename=filename) # 存入: ' or '1'='1\n# 后续拼接查询\ncur = connection.cursor()\ncur.execute(\"\"\"select * from file where filename='%s'\"\"\" % filename)\n# 产生注入: select * from file where filename='' or '1'='1'\n\n# Django ORM Lookup 语法\n# field__lookup = value\n# __exact: 精确匹配\n# __contains: 包含\n# __startswith: 开始于\n# __endswith: 结束于\n# __regex: 正则匹配 (需注意 ReDoS)\n# __iregex: 不区分大小写正则\n\n# 安全: 参数化\nUser.objects.raw(\"SELECT * FROM auth_user WHERE id = %s\", [user_id])\nUser.objects.filter(id=user_id) # ORM 标准 API\nUser.objects.get(id=str(id))\nUser.objects.extra(WHERE=['id=%s'], params=[str(id)]) # 正确的 extra 用法\n\n# SQLite3 参数化\ncon = sqlite3.connect('sql.db')\nc = con.cursor()\nusername = c.execute('SELECT name FROM users WHERE id = ?', [id]).fetchone()[0]\n```\n\n### 2. 模板XSS\n\n```python\n# 危险: mark_safe\nfrom django.utils.safestring import mark_safe\nmark_safe(f\"
{user_input}
\")\n\n# 危险: |safe过滤器\n{{ user_input|safe }}\n\n# 危险: autoescape off\n{% autoescape off %}{{ user_input }}{% endautoescape %}\n\n# 危险: 直接拼接 HTML\nname = request.GET.get('name')\nreturn HttpResponse(\"

name: %s

\" % name)\n\n# 安全: 默认转义\n{{ user_input }} # 自动转义\n\n# 安全: 使用 render\nfrom django.shortcuts import render\nreturn render(request, 'index.html', {'name': name})\n```\n\n### 2.5. SSTI / 格式化字符串注入\n\n```python\n# 危险: 双重格式化字符串\nname = request.GET.get('name')\ntemplate = \"

user:{user}, name:%s

\" % name # 第一次格式化\nreturn HttpResponse(template.format(user=request.user)) # 第二次格式化\n# payload: name = \"{user.password}\" → 泄露用户密码\n\n# 信息泄露 payload\n{user.password} # 读取密码哈希\n{user.__init__.__globals__[__builtins__][eval]} # 获取 eval 函数\n\n# 读取 SECRET_KEY 路径\n{user.groups.model._meta.app_config.module.admin.settings.SECRET_KEY}\n{user.user_permissions.model._meta.app_config.module.admin.settings.SECRET_KEY}\n{user.groups.model._meta.apps.app_configs[auth].module.middleware.settings.SECRET_KEY}\n{user.groups.model._meta.apps.app_configs[sessions].module.middleware.settings.SECRET_KEY}\n{user.groups.model._meta.apps.app_configs[staticfiles].module.utils.settings.SECRET_KEY}\n\n# 枚举 app_configs\n{user.groups.model._meta.apps.app_configs}\n\n# format() 限制\n# 只支持点 (.) 和中括号 ([])\n# 不支持括号调用,因此 RCE 困难\n# 主要用于信息泄露\n\n# 安全: 避免双重格式化\nreturn render(request, 'template.html', {'name': name})\n```\n\n### 3. CSRF配置\n\n```python\n# 危险: 全局禁用\nMIDDLEWARE = [\n # 'django.middleware.csrf.CsrfViewMiddleware', # 被注释\n]\n\n# 危险: 视图级别禁用\nfrom django.views.decorators.csrf import csrf_exempt\n\n@csrf_exempt # 搜索这个装饰器\ndef vulnerable_view(request):\n ...\n\n# 危险: CSRF_TRUSTED_ORIGINS过宽\nCSRF_TRUSTED_ORIGINS = ['https://*.example.com']\n```\n\n### 4. Session安全\n\n```python\n# settings.py 检查项\nSESSION_COOKIE_SECURE = True # 必须为True (HTTPS)\nSESSION_COOKIE_HTTPONLY = True # 必须为True\nSESSION_COOKIE_SAMESITE = 'Lax' # 或 'Strict'\nCSRF_COOKIE_SECURE = True\n\n# Session存储\nSESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'\n# 签名cookie需要强SECRET_KEY\n```\n\n### 5. 文件处理\n\n```python\n# 危险: 不安全的文件路径\ndef download(request, filename):\n file_path = os.path.join(UPLOAD_DIR, filename) # 路径遍历\n return FileResponse(open(file_path, 'rb'))\n\n# 危险: 未验证的文件类型\ndef upload(request):\n file = request.FILES['file']\n with open(f'/uploads/{file.name}', 'wb') as f: # 文件名未过滤\n for chunk in file.chunks():\n f.write(chunk)\n\n# 危险: 未验证文件大小\nfile = request.FILES.get('filename')\nname = os.path.join(UPLOAD_DIR, file.name)\nwith open(name, 'wb') as f:\n f.write(file.read()) # 可能导致 DoS\n\n# 安全: 文件类型和大小验证\nALLOWED_EXTENSIONS = {'pdf', 'doc', 'docx', 'jpg', 'png'}\nMAX_FILE_SIZE = 2097152 # 2MB\n\ndef allowed_file(filename):\n return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS\n\ndef upload(request):\n if request.method == 'POST':\n img = request.FILES.get('filename')\n if img.size < MAX_FILE_SIZE and allowed_file(img.name):\n # 重命名文件 (UUID)\n import uuid\n ext = img.name.rsplit('.', 1)[1]\n new_name = str(uuid.uuid5(uuid.NAMESPACE_DNS, img.name)) + \".\" + ext\n\n name = os.path.join(UPLOAD_DIR, new_name)\n with open(name, 'wb') as f:\n for chunk in img.chunks():\n f.write(chunk)\n return render(request, 'upload.html', {'file': '上传成功'})\n else:\n return render(request, 'upload.html', {'file': \"不允许的类型或大小超限\"})\n\n# 安全: 使用 FileField 验证\nfrom django.core.validators import FileExtensionValidator\n\nclass Document(models.Model):\n file = models.FileField(\n upload_to='documents/%Y/%m/%d', # 按日期组织\n validators=[FileExtensionValidator(allowed_extensions=['pdf', 'doc'])],\n max_length=100\n )\n\n# 安全: 路径遍历防护\ndef safe_download(request, filename):\n base_dir = os.path.abspath(UPLOAD_DIR)\n file_path = os.path.abspath(os.path.join(base_dir, filename))\n\n if not file_path.startswith(base_dir):\n raise ValueError(\"Path traversal detected\")\n\n return FileResponse(open(file_path, 'rb'))\n```\n\n### 6. 调试模式泄露\n\n```python\n# settings.py\nDEBUG = True # 生产环境必须False!!!\nALLOWED_HOSTS = ['*'] # 危险: 应指定具体域名\n\n# 调试工具栏\nINSTALLED_APPS = [\n 'debug_toolbar', # 生产环境应移除\n]\n```\n\n### 7. SECRET_KEY安全\n\n```python\n# 危险: 硬编码或弱密钥\nSECRET_KEY = 'django-insecure-xxx'\nSECRET_KEY = 'secret'\n\n# 安全: 环境变量\nSECRET_KEY = os.environ.get('DJANGO_SECRET_KEY')\n```\n\n### 8. 管理后台安全\n\n```python\n# urls.py - 检查admin路径\nurlpatterns = [\n path('admin/', admin.site.urls), # 默认路径,应更改\n]\n\n# 应使用不可预测的路径\npath('super-secret-admin-xyz/', admin.site.urls),\n\n# 检查admin权限\n# admin.py\n@admin.register(SensitiveModel)\nclass SensitiveModelAdmin(admin.ModelAdmin):\n # 检查是否限制了权限\n def has_delete_permission(self, request, obj=None):\n return request.user.is_superuser\n```\n\n---\n\n## Django审计清单\n\n```\n配置检查:\n- [ ] DEBUG = False (生产环境)\n- [ ] SECRET_KEY 强度和存储 (避免硬编码)\n- [ ] ALLOWED_HOSTS 配置 (避免 ['*'])\n- [ ] SESSION_COOKIE_SECURE = True\n- [ ] SESSION_COOKIE_HTTPONLY = True\n- [ ] SESSION_COOKIE_SAMESITE = 'Lax'\n- [ ] CSRF_COOKIE_SECURE = True\n- [ ] CSRF 中间件启用\n- [ ] debug_toolbar 生产环境移除\n\nORM 安全:\n- [ ] 搜索 .raw() 调用 (字符串拼接)\n- [ ] 搜索 .extra() 调用 (where 拼接)\n- [ ] 搜索 RawSQL 使用 (拼接)\n- [ ] 搜索 cursor.execute() 拼接\n- [ ] 检查 .filter(**dict) 参数名可控\n- [ ] 检查 .create(**dict) 字典键可控\n- [ ] 检查 __regex/__iregex 输入\n- [ ] 检查二次注入场景\n- [ ] 验证 lookup 语法使用 (__contains 等)\n\n模板安全:\n- [ ] 搜索 mark_safe 使用\n- [ ] 搜索 |safe 过滤器\n- [ ] 搜索 autoescape off\n- [ ] 搜索 HttpResponse 拼接 HTML\n- [ ] 检查双重格式化 (% + format)\n\nCSRF:\n- [ ] 检查中间件配置\n- [ ] 搜索 @csrf_exempt 装饰器\n- [ ] 验证 AJAX 请求 CSRF 处理\n- [ ] 检查 CSRF_TRUSTED_ORIGINS 配置\n\n认证:\n- [ ] 检查密码验证器配置\n- [ ] 审计自定义认证后端\n- [ ] 检查登录限流\n- [ ] 验证密码重置流程\n\n文件处理:\n- [ ] 检查 MEDIA_ROOT 配置\n- [ ] 验证上传文件类型限制\n- [ ] 验证上传文件大小限制\n- [ ] 检查文件下载路径验证\n- [ ] 验证文件名重命名\n- [ ] 检查 FileField validators\n\n管理后台:\n- [ ] 检查 admin 路径 (避免默认 /admin/)\n- [ ] 验证 admin 权限配置\n- [ ] 检查 ModelAdmin 权限方法\n- [ ] 验证敏感模型访问控制\n\n其他:\n- [ ] 搜索 redirect() 用户输入\n- [ ] 检查 is_safe_url 使用 (CVE-2017-7233)\n- [ ] 验证环境变量使用 (敏感信息)\n```\n\n---\n\n## 审计正则\n\n```regex\n# ORM 注入\n\\.raw\\s*\\(f['\"']|\\.raw\\s*\\([^)]*%\\s*str\\(\n\\.extra\\s*\\([^)]*WHERE\\s*=\\s*\\[|\\.extra\\s*\\([^)]*where\\s*=\nRawSQL\\s*\\(f['\"']\ncursor\\.execute\\s*\\([^)]*['\"]\\s*%|execute\\s*\\([^)]*\\+\n\\.filter\\s*\\(\\*\\*|\\.create\\s*\\(\\*\\*\n\n# XSS\nmark_safe\\s*\\(|\\|safe\\s*}}|autoescape\\s+off\nHttpResponse\\s*\\([^)]*%|HttpResponse\\s*\\(f['\"']\n\n# SSTI / 格式化字符串\n['\"]\\s*%\\s*[^'\"]*\\.format\\s*\\(\n\n# CSRF\n@csrf_exempt|csrf_exempt\nCsrfViewMiddleware.*#\n\n# 配置\nDEBUG\\s*=\\s*True|ALLOWED_HOSTS\\s*=\\s*\\[['\"]?\\*['\"]?\\]\n\n# SECRET_KEY\nSECRET_KEY\\s*=\\s*['\"][^'\"]{0,30}['\"]\n\n# 文件操作\nrequest\\.FILES\\s*\\[|request\\.FILES\\.get\\s*\\(\nFileResponse\\s*\\(open\\s*\\(|open\\s*\\([^)]*file\\.name\n\n# URL 重定向\nredirect\\s*\\([^)]*request\\.|HttpResponseRedirect\\s*\\([^)]*request\\.\nis_safe_url\\s*\\(\n```\n\n## 最小 PoC 示例\n```bash\n# DEBUG/ALLOWED_HOSTS 检查\ncurl -I http://localhost:8000/ | grep \"X-Content-Type-Options\"\n\n# SQL 注入 (.raw)\ncurl \"http://localhost:8000/users?q=1' OR '1'='1\"\n\n# Open Redirect\ncurl \"http://localhost:8000/redirect?next=http://evil.com\"\n```\n" const SKILL_FILE_3 = "# ASP.NET Core / Blazor Security Audit Guide\n\n> ASP.NET Core 框架安全审计模块\n> 适用于: ASP.NET Core 6/7/8, Blazor Server/WebAssembly, Razor Pages, Minimal APIs\n\n## 识别特征\n\n```csharp\n// ASP.NET Core 项目识别\n\nusing Microsoft.AspNetCore;\n\n// 文件结构\n├── Program.cs / Startup.cs\n├── appsettings.json\n├── Controllers/\n├── Pages/ (Razor Pages)\n├── Views/ (MVC)\n├── Models/\n├── Data/ (EF Core DbContext)\n└── wwwroot/\n```\n\n---\n\n## SQL 注入检测\n\n```csharp\n// 危险: EF Core 原始SQL拼接\nvar users = db.Users\n .FromSqlRaw(\"SELECT * FROM Users WHERE Name = '\" + name + \"'\"); // ❌ Critical\n\n// 危险: Dapper 字符串拼接\nconnection.Query(\"SELECT * FROM Users WHERE Id = \" + id); // ❌ Critical\nconnection.Execute($\"DELETE FROM Users WHERE Id = {id}\"); // ❌ Critical\n\n// 危险: ADO.NET 原始拼接\nvar cmd = new SqlCommand(\"SELECT * FROM Users WHERE Name = '\" + input + \"'\", conn); // ❌\n\n// 危险: EF Core ExecuteSqlRaw 拼接\ndb.Database.ExecuteSqlRaw(\"UPDATE Users SET Name = '\" + name + \"' WHERE Id = \" + id); // ❌\n\n// 审计正则\nFromSqlRaw\\s*\\(.*\\+|ExecuteSqlRaw\\s*\\(.*\\+\nconnection\\.(Query|Execute)\\s*\\(.*\\+|SqlCommand\\s*\\(.*\\+\n\n// 安全: 参数化查询\ndb.Users.FromSqlInterpolated($\"SELECT * FROM Users WHERE Name = {name}\"); // ✓\ndb.Database.ExecuteSqlInterpolated($\"UPDATE Users SET Name = {name}\"); // ✓\n\n// Dapper 参数化\nconnection.Query(\"SELECT * FROM Users WHERE Id = @Id\", new { Id = id }); // ✓\n\n// ADO.NET 参数化\nvar cmd = new SqlCommand(\"SELECT * FROM Users WHERE Name = @Name\", conn);\ncmd.Parameters.AddWithValue(\"@Name\", input); // ✓\n```\n\n---\n\n## XSS 检测 (Razor Views)\n\n```html\n\n@Html.Raw(Model.UserComment) \n@Html.Raw(ViewBag.Message) \n\n\n \n\n\nHtml\\.Raw\\s*\\(|@Html\\.Raw|@\\(.*Html\\.Raw\n \n```\n\n---\n\n## CSRF 配置检测\n\n```csharp\n// 危险: 全局禁用防伪验证\nservices.AddControllersWithViews(options =>\n{\n // 未添加 AutoValidateAntiforgeryTokenAttribute\n});\n\n// 危险: 控制器级别忽略\n[IgnoreAntiforgeryToken] // ❌ 跳过CSRF验证\npublic IActionResult UpdateProfile(ProfileModel model) { ... }\n\n// 危险: Razor Pages 禁用\n@attribute [IgnoreAntiforgeryToken] // ❌\n\n// 审计正则\n\\[IgnoreAntiforgeryToken\\]|IgnoreAntiforgeryToken\nAddControllersWithViews(?!.*AutoValidateAntiforgeryToken)\n\n// 安全: 全局启用\nservices.AddControllersWithViews(options =>\n{\n options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute()); // ✓\n});\n\n// Razor Pages 默认启用; API使用JWT则可禁用CSRF但需确认\n```\n\n---\n\n## 授权配置缺陷\n\n```csharp\n// 危险: [AllowAnonymous] 覆盖 [Authorize]\n[Authorize(Roles = \"Admin\")]\npublic class AdminController : Controller\n{\n [AllowAnonymous] // ❌ Critical: 覆盖了类级别的Authorize\n public IActionResult SensitiveAction() { ... }\n}\n\n// 危险: 缺少授权属性\npublic class PaymentController : Controller // ❌ 无[Authorize]\n{\n public IActionResult ProcessPayment() { ... }\n}\n\n// 危险: Minimal API 遗漏授权\napp.MapGet(\"/admin/users\", GetAllUsers); // ❌ 未添加RequireAuthorization\n\n// 审计正则\n\\[AllowAnonymous\\]|AllowAnonymous\nMapGet\\(|MapPost\\(|MapPut\\(|MapDelete\\( // 检查是否有RequireAuthorization\n\n// 安全: Fallback策略 (默认拒绝)\nbuilder.Services.AddAuthorization(options =>\n{\n options.FallbackPolicy = new AuthorizationPolicyBuilder()\n .RequireAuthenticatedUser()\n .Build(); // ✓ 未标注的端点默认需要认证\n});\n\n// Minimal API 授权\napp.MapGet(\"/admin/users\", GetAllUsers).RequireAuthorization(\"AdminPolicy\"); // ✓\n```\n\n---\n\n## 不安全的反序列化\n\n```csharp\n// 危险: BinaryFormatter (已弃用,但仍在老代码中)\nBinaryFormatter formatter = new BinaryFormatter();\nobject obj = formatter.Deserialize(stream); // ❌ Critical: RCE\n\n// 危险: Newtonsoft TypeNameHandling\nvar settings = new JsonSerializerSettings\n{\n TypeNameHandling = TypeNameHandling.All // ❌ Critical: 反序列化任意类型\n};\nJsonConvert.DeserializeObject(json, settings);\n\n// 危险: TypeNameHandling.Auto/Objects 同样可利用\nTypeNameHandling = TypeNameHandling.Auto // ❌\nTypeNameHandling = TypeNameHandling.Objects // ❌\n\n// 审计正则\nBinaryFormatter|ObjectStateFormatter|SoapFormatter|NetDataContractSerializer\nTypeNameHandling\\s*=\\s*TypeNameHandling\\.(All|Auto|Objects|Arrays)\nLosFormatter|XmlSerializer\\s*\\(.*typeof\\s*\\(.*GetType\n\n// 安全: 使用 System.Text.Json (默认安全)\nvar obj = JsonSerializer.Deserialize(json); // ✓ 无多态类型处理\n\n// 如果必须用 Newtonsoft, 使用 SerializationBinder 白名单\nvar settings = new JsonSerializerSettings\n{\n TypeNameHandling = TypeNameHandling.Auto,\n SerializationBinder = new KnownTypesBinder(allowedTypes) // ✓\n};\n```\n\n---\n\n## 路径遍历 (文件下载)\n\n```csharp\n// 危险: 直接拼接文件路径\n[HttpGet(\"download\")]\npublic IActionResult Download(string fileName)\n{\n var path = Path.Combine(_uploadDir, fileName);\n return PhysicalFile(path, \"application/octet-stream\"); // ❌ ../../../etc/passwd\n}\n\n// 危险: 未规范化路径\nvar fullPath = _baseDir + \"/\" + userInput; // ❌ 路径遍历\nSystem.IO.File.ReadAllText(fullPath);\n\n// 审计正则\nPhysicalFile\\s*\\(.*\\+|Path\\.Combine\\s*\\(.*fileName|File\\.(Read|Open|Delete).*\\+\nSendFileAsync\\s*\\(.*\\+\n\n// 安全: 路径验证\n[HttpGet(\"download\")]\npublic IActionResult Download(string fileName)\n{\n if (fileName.Contains(\"..\") || Path.IsPathRooted(fileName))\n return BadRequest();\n\n var path = Path.Combine(_uploadDir, fileName);\n var fullPath = Path.GetFullPath(path);\n\n if (!fullPath.StartsWith(Path.GetFullPath(_uploadDir))) // ✓ 规范化后比对\n return BadRequest();\n\n return PhysicalFile(fullPath, \"application/octet-stream\");\n}\n```\n\n---\n\n## CORS 配置缺陷\n\n```csharp\n// 危险: 允许所有来源 + 凭据\nbuilder.Services.AddCors(options =>\n{\n options.AddPolicy(\"AllowAll\", policy =>\n {\n policy.AllowAnyOrigin() // ❌\n .AllowAnyMethod()\n .AllowAnyHeader()\n .AllowCredentials(); // ❌ 与AllowAnyOrigin冲突且危险\n });\n});\n\n// 危险: 在 Program.cs/Startup.cs 中动态反射 Origin\napp.UseCors(policy => policy\n .SetIsOriginAllowed(_ => true) // ❌ 允许任何来源\n .AllowCredentials());\n\n// 审计正则\nAllowAnyOrigin|SetIsOriginAllowed.*true|AllowCredentials\n\n// 安全: 明确白名单\nbuilder.Services.AddCors(options =>\n{\n options.AddPolicy(\"Strict\", policy =>\n {\n policy.WithOrigins(\"https://app.example.com\") // ✓\n .WithMethods(\"GET\", \"POST\")\n .WithHeaders(\"Content-Type\", \"Authorization\")\n .AllowCredentials();\n });\n});\n```\n\n---\n\n## Blazor 安全差异\n\n```csharp\n// Blazor Server: 服务端渲染, SignalR连接\n// - 敏感数据在服务端, 但 SignalR 消息可能泄露\n// - Circuit 劫持: 确保认证检查在每个Hub调用中\n// - 防止 JS Interop 注入\n\n// 危险: Blazor Server 中直接访问数据库无权限检查\n@code {\n private async Task LoadData()\n {\n data = await _dbContext.SensitiveData.ToListAsync(); // ❌ 无用户权限检查\n }\n}\n\n// 危险: MarkupString 等价于 Html.Raw\n@((MarkupString)userInput) // ❌ XSS\n\n// Blazor WebAssembly: 客户端运行\n// - 所有C#代码在浏览器中, 可被反编译 → 不要在WASM中存放密钥\n// - API调用必须在服务端验证 → 不能仅依赖客户端授权检查\n// - 审计: 检查 wwwroot/ 中是否有敏感配置\n\n// 审计正则\nMarkupString\\)|@\\(\\(MarkupString\\)\nNavigationManager\\.NavigateTo\\s*\\(.*\\+ // 开放重定向\n```\n\n---\n\n## 搜索模式汇总\n\n```regex\n# SQL注入\nFromSqlRaw\\s*\\(.*\\+|ExecuteSqlRaw\\s*\\(.*\\+|SqlCommand\\s*\\(.*\\+\nconnection\\.(Query|Execute)\\s*\\(.*\\+\n\n# XSS\nHtml\\.Raw\\s*\\(|MarkupString\\)\n\n# CSRF\n\\[IgnoreAntiforgeryToken\\]\n\n# 授权\n\\[AllowAnonymous\\]\nMapGet\\(|MapPost\\( // 检查Minimal API授权\n\n# 反序列化\nBinaryFormatter|TypeNameHandling\\.(All|Auto|Objects)\n\n# 路径遍历\nPhysicalFile\\s*\\(.*\\+|Path\\.Combine\\s*\\(.*fileName\n\n# CORS\nAllowAnyOrigin|SetIsOriginAllowed.*true\n\n# 敏感配置\n\"ConnectionStrings\".*password|appsettings.*Development.*json\n```\n\n---\n\n## 快速审计检查清单\n\n```markdown\n[ ] 检查 ASP.NET Core 版本和已知CVE\n[ ] 搜索 FromSqlRaw/ExecuteSqlRaw 字符串拼接\n[ ] 搜索 Dapper Query/Execute 拼接\n[ ] 搜索 Html.Raw / MarkupString (XSS)\n[ ] 搜索 [IgnoreAntiforgeryToken] (CSRF绕过)\n[ ] 搜索 [AllowAnonymous] 在敏感Controller上\n[ ] 检查 FallbackPolicy 授权配置\n[ ] 搜索 BinaryFormatter / TypeNameHandling (反序列化)\n[ ] 检查文件下载端点路径验证\n[ ] 搜索 AllowAnyOrigin / SetIsOriginAllowed (CORS)\n[ ] 检查 appsettings.json 中硬编码密钥/连接字符串\n[ ] 检查 Blazor 中 MarkupString 和 JS Interop\n[ ] 验证 Minimal API 端点是否有 RequireAuthorization\n[ ] 检查异常处理是否泄露堆栈 (app.UseDeveloperExceptionPage)\n```\n\n---\n\n## 最小 PoC 示例\n```bash\n# SQL 注入 (Dapper/Raw SQL)\ncurl \"http://localhost:5000/api/users?name=admin'OR'1'='1\"\n\n# 路径遍历\ncurl \"http://localhost:5000/download?fileName=../../../etc/passwd\"\n\n# 开放重定向\ncurl \"http://localhost:5000/redirect?url=https://evil.com\"\n```\n\n---\n\n## 参考资源\n\n- [Microsoft ASP.NET Core Security Documentation](https://learn.microsoft.com/en-us/aspnet/core/security/)\n- [OWASP .NET Security Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/DotNet_Security_Cheat_Sheet.html)\n- [Blazor Security Considerations](https://learn.microsoft.com/en-us/aspnet/core/blazor/security/)\n" const SKILL_FILE_4 = "# Express.js Security Audit\n\n> Express.js 框架安全审计模块\n> 适用于: Express, Koa, Node.js 应用\n\n## 识别特征\n\n```javascript\n// Express项目识别\nconst express = require('express');\nconst app = express();\n\n// 文件结构\n├── package.json\n├── app.js / index.js\n├── routes/\n├── controllers/\n├── models/\n├── middleware/\n└── views/\n```\n\n---\n\n## Express特定漏洞\n\n### 1. NoSQL注入 (MongoDB)\n\n```javascript\n// 危险: 直接使用用户输入\napp.post('/login', async (req, res) => {\n const user = await User.findOne({\n username: req.body.username,\n password: req.body.password // 可注入 {$gt: \"\"}\n });\n});\n\n// 攻击payload\n// {\"username\": \"admin\", \"password\": {\"$gt\": \"\"}}\n\n// 安全: 类型验证\napp.post('/login', async (req, res) => {\n if (typeof req.body.username !== 'string' ||\n typeof req.body.password !== 'string') {\n return res.status(400).json({error: 'Invalid input'});\n }\n const user = await User.findOne({...});\n});\n```\n\n### 2. 原型污染\n\n```javascript\n// 危险: 合并用户输入\nconst _ = require('lodash');\napp.post('/config', (req, res) => {\n _.merge(config, req.body); // 原型污染!\n});\n\n// 攻击payload\n// {\"__proto__\": {\"isAdmin\": true}}\n\n// 危险: 递归赋值\nfunction merge(target, source) {\n for (let key in source) {\n target[key] = source[key]; // 污染Object.prototype\n }\n}\n\n// 安全: 过滤危险键\nconst FORBIDDEN_KEYS = ['__proto__', 'constructor', 'prototype'];\nfunction safeMerge(target, source) {\n for (let key in source) {\n if (FORBIDDEN_KEYS.includes(key)) continue;\n target[key] = source[key];\n }\n}\n```\n\n### 3. 路径遍历\n\n```javascript\n// 危险: 用户输入拼接路径\napp.get('/download', (req, res) => {\n const file = req.query.file;\n res.sendFile(`/uploads/${file}`); // ../../etc/passwd\n});\n\n// 安全: 使用path.basename\nconst path = require('path');\napp.get('/download', (req, res) => {\n const file = path.basename(req.query.file); // 移除路径\n const fullPath = path.join('/uploads', file);\n // 验证在目标目录内\n if (!fullPath.startsWith('/uploads/')) {\n return res.status(400).send('Invalid path');\n }\n res.sendFile(fullPath);\n});\n```\n\n### 4. 命令注入\n\n```javascript\n// 危险: exec拼接\nconst { exec } = require('child_process');\napp.get('/ping', (req, res) => {\n exec(`ping -c 1 ${req.query.host}`, (err, stdout) => { // RCE!\n res.send(stdout);\n });\n});\n\n// 安全: 使用execFile + 参数数组\nconst { execFile } = require('child_process');\napp.get('/ping', (req, res) => {\n execFile('ping', ['-c', '1', req.query.host], (err, stdout) => {\n res.send(stdout);\n });\n});\n```\n\n### 5. XSS (模板引擎)\n\n```javascript\n// EJS危险模式\n<%- userInput %> // 不转义\n\n// 安全模式\n<%= userInput %> // 自动转义\n\n// Pug/Jade危险模式\n!{userInput} // 不转义\np= userInput // 安全\n\n// Handlebars危险模式\n{{{userInput}}} // 三重大括号不转义\n{{userInput}} // 双重大括号安全\n```\n\n### 6. 会话安全\n\n```javascript\n// 危险: 不安全的session配置\napp.use(session({\n secret: 'keyboard cat', // 弱密钥\n cookie: { secure: false } // 不安全\n}));\n\n// 安全配置\napp.use(session({\n secret: process.env.SESSION_SECRET,\n name: 'sessionId', // 更改默认名称\n cookie: {\n secure: true,\n httpOnly: true,\n sameSite: 'strict',\n maxAge: 3600000\n },\n resave: false,\n saveUninitialized: false\n}));\n```\n\n### 7. CORS配置\n\n```javascript\n// 危险: 允许所有来源\napp.use(cors());\napp.use(cors({ origin: '*' }));\n\n// 危险: 反射Origin\napp.use(cors({\n origin: (origin, callback) => {\n callback(null, origin); // 反射任意来源\n },\n credentials: true // 允许凭证更危险\n}));\n\n// 安全: 白名单\nconst allowedOrigins = ['https://trusted.com'];\napp.use(cors({\n origin: (origin, callback) => {\n if (allowedOrigins.includes(origin)) {\n callback(null, true);\n } else {\n callback(new Error('Not allowed'));\n }\n }\n}));\n```\n\n### 8. 依赖安全\n\n```bash\n# 检查已知漏洞\nnpm audit\nnpm audit --json\n\n# 检查过时依赖\nnpm outdated\n\n# 检查package.json中的危险包\n# - node-serialize (反序列化RCE)\n# - js-yaml < 3.13.1 (代码执行)\n# - lodash < 4.17.12 (原型污染)\n```\n\n### 9. 安全头配置\n\n```javascript\n// 使用helmet中间件\nconst helmet = require('helmet');\napp.use(helmet());\n\n// 或手动设置\napp.use((req, res, next) => {\n res.setHeader('X-Content-Type-Options', 'nosniff');\n res.setHeader('X-Frame-Options', 'DENY');\n res.setHeader('X-XSS-Protection', '1; mode=block');\n res.setHeader('Strict-Transport-Security', 'max-age=31536000');\n next();\n});\n```\n\n---\n\n## Express审计清单\n\n```\n输入验证:\n- [ ] 检查请求体类型验证\n- [ ] 搜索 req.query/req.body/req.params 使用\n- [ ] 验证MongoDB查询输入\n- [ ] 检查文件路径处理\n\n注入漏洞:\n- [ ] 搜索 exec/spawn 调用\n- [ ] 搜索 eval/Function 使用\n- [ ] 检查SQL/NoSQL查询构建\n- [ ] 搜索 _.merge/Object.assign\n\nXSS:\n- [ ] 检查模板引擎配置\n- [ ] 搜索 <%- (EJS不转义)\n- [ ] 搜索 {{{ (Handlebars不转义)\n- [ ] 检查res.send/res.json内容\n\n会话安全:\n- [ ] 检查session secret强度\n- [ ] 验证cookie安全配置\n- [ ] 检查JWT实现\n\n安全配置:\n- [ ] 检查CORS配置\n- [ ] 验证helmet/安全头\n- [ ] 检查错误处理 (不泄露栈)\n- [ ] 验证HTTPS强制\n\n依赖:\n- [ ] 运行 npm audit\n- [ ] 检查危险依赖包\n- [ ] 验证依赖版本\n```\n\n---\n\n## 审计正则\n\n```regex\n# 命令注入\nexec\\s*\\(|spawn\\s*\\(|child_process\n\n# NoSQL注入\nfindOne\\s*\\(|find\\s*\\(|updateOne\\s*\\(\n\n# 原型污染\n\\.merge\\s*\\(|Object\\.assign\\s*\\(|__proto__\n\n# XSS\n<%-|{{{\n\n# 路径遍历\nsendFile\\s*\\(|res\\.download\\s*\\(\n```\n\n## 最小 PoC 示例\n```bash\n# 路径遍历\ncurl \"http://localhost:3000/download?file=../../etc/passwd\"\n\n# NoSQL 注入\ncurl \"http://localhost:3000/user?name[$ne]=1\"\n\n# 命令注入\ncurl \"http://localhost:3000/ping?host=google.com;id\"\n```\n" const SKILL_FILE_5 = "# FastAPI Security Audit\n\n> FastAPI 框架安全审计模块\n> 适用于: FastAPI, Starlette, SQLAlchemy\n\n## 识别特征\n\n```python\n# FastAPI项目识别\nfrom fastapi import FastAPI, Depends, HTTPException\napp = FastAPI()\n\n# 文件结构\n├── main.py\n├── routers/\n├── models/\n├── schemas/\n├── crud/\n└── dependencies/\n```\n\n---\n\n## 路由与端点分析\n\n```python\n# 搜索所有路由\n@app.get|post|put|delete|patch\n@router.get|post|put|delete|patch\n\n# 路径参数\n@app.get(\"/users/{user_id}\")\ndef get_user(user_id: int): # 检查IDOR\n\n# 查询参数\n@app.get(\"/search\")\ndef search(q: str = Query(...)): # 检查注入\n```\n\n---\n\n## FastAPI特定漏洞\n\n### 1. 依赖注入安全\n\n```python\n# 危险: 未验证的依赖\ndef get_current_user(token: str = Header(...)):\n # 缺少token验证\n return decode_token(token)\n\n# 安全: 完整验证\nasync def get_current_user(\n token: str = Depends(oauth2_scheme),\n db: Session = Depends(get_db)\n):\n user = authenticate_token(token, db)\n if not user:\n raise HTTPException(status_code=401)\n return user\n```\n\n### 2. Pydantic验证绕过\n\n```python\n# 危险: 使用dict绕过验证\n@app.post(\"/users\")\ndef create_user(data: dict): # 无schema验证\n db.create(User(**data))\n\n# 安全: 强类型schema\nclass UserCreate(BaseModel):\n email: EmailStr\n password: str = Field(..., min_length=8)\n\n@app.post(\"/users\")\ndef create_user(user: UserCreate):\n ...\n```\n\n### 3. 响应模型泄露\n\n```python\n# 危险: 返回ORM模型 (可能包含password_hash)\n@app.get(\"/users/{id}\")\ndef get_user(id: int):\n return db.query(User).filter(User.id == id).first()\n\n# 安全: 使用响应模型过滤\nclass UserResponse(BaseModel):\n id: int\n email: str\n # 排除敏感字段\n\n@app.get(\"/users/{id}\", response_model=UserResponse)\ndef get_user(id: int):\n return db.query(User).filter(User.id == id).first()\n```\n\n### 4. 背景任务注入\n\n```python\n# 危险: 用户输入传入背景任务\n@app.post(\"/process\")\ndef process(cmd: str, background_tasks: BackgroundTasks):\n background_tasks.add_task(os.system, cmd) # RCE!\n\n# 检查所有 BackgroundTasks.add_task 调用\n```\n\n### 5. 文件上传处理\n\n```python\n# 危险模式\n@app.post(\"/upload\")\nasync def upload(file: UploadFile):\n content = await file.read()\n with open(f\"/uploads/{file.filename}\", \"wb\") as f: # 路径遍历\n f.write(content)\n\n# 安全模式\nimport uuid\nimport os\n\n@app.post(\"/upload\")\nasync def upload(file: UploadFile):\n # 验证文件类型\n if file.content_type not in ALLOWED_TYPES:\n raise HTTPException(400)\n # 使用安全文件名\n safe_name = f\"{uuid.uuid4()}{os.path.splitext(file.filename)[1]}\"\n # 限制文件大小\n content = await file.read(MAX_SIZE)\n ...\n```\n\n### 6. SQLAlchemy ORM注入\n\n```python\n# 危险: 原始SQL\n@app.get(\"/search\")\ndef search(q: str, db: Session = Depends(get_db)):\n return db.execute(f\"SELECT * FROM items WHERE name LIKE '%{q}%'\")\n\n# 危险: text()拼接\nfrom sqlalchemy import text\ndb.execute(text(f\"SELECT * FROM users WHERE id = {user_id}\"))\n\n# 安全: 参数化\ndb.execute(text(\"SELECT * FROM users WHERE id = :id\"), {\"id\": user_id})\n```\n\n---\n\n## FastAPI审计清单\n\n```\n认证与授权:\n- [ ] 检查OAuth2/JWT实现 (Depends)\n- [ ] 验证所有端点有适当的认证装饰器\n- [ ] 检查IDOR (路径参数未验证所有权)\n- [ ] 审计权限检查逻辑\n\n输入验证:\n- [ ] 检查是否使用Pydantic schema\n- [ ] 搜索 dict 类型参数 (绕过验证)\n- [ ] 验证Query/Path/Body参数验证\n- [ ] 检查文件上传处理\n\n输出安全:\n- [ ] 检查response_model使用\n- [ ] 验证敏感字段排除\n- [ ] 检查错误响应信息\n\n数据库:\n- [ ] 搜索原始SQL执行\n- [ ] 检查SQLAlchemy text()使用\n- [ ] 验证ORM查询安全\n\nCORS:\n- [ ] 检查CORSMiddleware配置\n- [ ] 验证allow_origins设置\n- [ ] 检查allow_credentials=True风险\n```\n\n---\n\n## 审计正则\n\n```regex\n# 路由搜索\n@(app|router)\\.(get|post|put|delete|patch)\\s*\\(\n\n# Pydantic绕过\ndef\\s+\\w+\\([^)]*:\\s*dict[^)]*\\)\n\n# 背景任务\nBackgroundTasks\\.add_task\n\n# SQL注入\ndb\\.execute\\s*\\(f['\"']|text\\s*\\(f['\"']\n\n# 文件上传\nUploadFile.*file\\.filename\n```\n\n## 最小 PoC 示例\n```bash\n# SQL 注入\ncurl \"http://localhost:8000/users?q=1' OR '1'='1\"\n\n# SSRF\ncurl \"http://localhost:8000/fetch?url=http://169.254.169.254/latest/meta-data/\"\n\n# 路径遍历上传文件名\ncurl -F \"file=@/etc/passwd;filename=../../etc/passwd\" http://localhost:8000/upload\n```\n" const SKILL_FILE_6 = "# Flask Security Audit\n\n> Flask 框架安全审计模块\n> 适用于: Flask, Flask-RESTful, Flask-Login, Flask-JWT-Extended\n\n---\n\n## 识别特征\n\n```python\n# Flask 项目识别\nfrom flask import Flask, request, render_template\napp = Flask(__name__)\n\n# 常见目录结构\n├── app/\n│ ├── __init__.py # create_app 工厂\n│ ├── routes/ # 路由蓝图\n│ ├── models/ # SQLAlchemy 模型\n│ ├── templates/ # Jinja2 模板\n│ └── static/ # 静态资源\n├── config.py # 配置\n├── requirements.txt\n└── run.py / wsgi.py\n```\n\n---\n\n## Critical 漏洞\n\n### 1. 调试模式 RCE\n\n```python\n# 危险: 生产环境开启调试\nif __name__ == '__main__':\n app.run(debug=True) # Werkzeug debugger PIN 可被计算\n\n# 危险: 配置文件\nDEBUG = True\nFLASK_DEBUG = 1\n\n# PIN 计算要素 (可用于爆破):\n# - username (运行用户)\n# - modname (通常 flask.app)\n# - getattr(app, '__name__', app.__class__.__name__)\n# - getattr(mod, '__file__', None) → app.py 路径\n# - uuid.getnode() → MAC 地址\n# - get_machine_id() → /etc/machine-id 或 /proc/sys/kernel/random/boot_id\n\n# 检测\ngrep -rn \"debug\\s*=\\s*True\" --include=\"*.py\"\ngrep -rn \"FLASK_DEBUG\\|DEBUG\\s*=\" --include=\"*.py\" --include=\"*.env\"\n```\n\n### 2. SECRET_KEY 泄露\n\n```python\n# 危险: 硬编码密钥\napp.secret_key = 'super_secret_key'\napp.config['SECRET_KEY'] = 'hardcoded'\n\n# 危险: 弱密钥\nSECRET_KEY = 'development'\nSECRET_KEY = os.urandom(16) # 每次重启变化,session 失效\n\n# 影响:\n# - Session 伪造\n# - Flask-Login 令牌伪造\n# - CSRF token 伪造\n# - itsdangerous 签名伪造\n\n# 安全: 从环境变量读取\napp.config['SECRET_KEY'] = os.environ.get('SECRET_KEY')\nif not app.config['SECRET_KEY']:\n raise ValueError(\"SECRET_KEY not set\")\n\n# 检测\ngrep -rn \"secret_key\\s*=\\|SECRET_KEY\\s*=\" --include=\"*.py\"\n```\n\n### 3. SSTI (Server-Side Template Injection)\n\n```python\n# 危险: render_template_string 用户输入\nfrom flask import render_template_string\n\n@app.route('/hello')\ndef hello():\n name = request.args.get('name', 'World')\n template = f'

Hello {name}!

'\n return render_template_string(template)\n\n# payload: {{config.items()}}\n# payload: {{''.__class__.__mro__[1].__subclasses__()}}\n# RCE payload:\n# {{''.__class__.__mro__[1].__subclasses__()[X].__init__.__globals__['os'].popen('id').read()}}\n\n# 危险: 用户控制模板名\n@app.route('/page/