用途
本技能用于检测、分析和修复 OWASP A10:2025「异常条件处理不当」(Mishandling of Exceptional Conditions),主要面向 Python Web 应用,覆盖 FastAPI 与 Flask 两个框架。该类别是 2025 年新增分类,取代了 SSRF(后者被并入 A01)。它包含 24 个 CWE,共记录 769,581 次出现。其针对的是那些未能预防、检测和响应异常情况的程序,这类问题会导致崩溃、意外行为、信息泄露以及可被利用的状态。
主要能力
技能围绕以下弱点与风险展开:
- 错误处理不当:未处理的异常会使应用崩溃或暴露内部信息。
- 失败开放(CWE-636):认证/授权检查在抛出异常时反而通过。
- 错误消息中的敏感数据(CWE-209):堆栈跟踪、数据库细节、文件路径泄露给客户端。
- 未捕获异常(CWE-248):没有全局安全网,导致带调试输出的 500 响应。
- 异常路径中的资源耗尽:数据库连接、文件句柄在出错时从未关闭。
- 状态损坏:异常时部分事务被提交。
- NULL 指针 / None 解引用(CWE-476):在访问属性前缺少对 None 的防护。
- 缺少默认分支(CWE-754):if/elif 链没有 else;match 没有通配分支。
- 错误恢复中的竞态条件:清理逻辑本身可能被中断。
预防原则
- 在错误发生处捕获:在能够处理它的函数处捕获,而不是向上三层。
- 失败关闭:当认证/授权逻辑抛出异常时,拒绝访问,绝不放行。
- 完整回滚:部分数据库事务必须回滚,绝不提交。
- 用户消息与技术细节分离:在服务端记录堆栈跟踪,向客户端返回安全、通用的消息。
- 全局异常处理器作为安全网:每个应用都需要一个,但它不能替代本地处理。
- 限流与配额:防止异常情况(如资源耗尽)被有意触发。
使用方式
FastAPI 测试清单
-
全局异常处理器:注册
@app.exception_handler(Exception),记录日志并返回通用 500 消息。若缺失则标记。FastAPI 默认 500 响应在开发模式下可能包含 traceback。 -
失败关闭的认证中间件(CWE-636):在中间件中,若
verify_token抛异常,BAD 写法是except Exception: pass(失败开放),GOOD 写法是记录警告并返回 401(失败关闭)。 -
自定义 HTTP 错误响应(CWE-756 / CWE-209):为 404、422 等常见错误码注册处理器,返回通用消息。标记任何在响应体中返回
str(exc)、repr(exc)或traceback.format_exc()的处理器。 -
异常路径中的资源清理:BAD 写法是
conn = db.connect()后直接执行查询,异常时连接永不关闭;GOOD 写法是使用with db.connect() as conn:上下文管理器保证清理。扫描不在with块或try/finally中的db.connect()、open(file)、socket.socket()。 -
SQLAlchemy 事务回滚:BAD 写法是
session.add(obj)后执行风险操作再session.commit(),异常时部分写入被提交;GOOD 写法是在try中提交,在except中session.rollback()并重新抛出。标记任何未在 except 分支中配对session.rollback()的session.commit()。
Flask 测试清单
-
全局异常处理器:注册
@app.errorhandler(Exception),记录日志并返回通用 500。同时注册 404、500 等具体处理器。 -
Flask 调试模式(同时属于 A02 + A10 问题):
debug=True或FLASK_DEBUG=1会启用 Werkzeug 交互式调试器,向浏览器暴露完整 traceback,并允许通过调试器控制台执行任意代码。若在生产配置或环境变量中发现,立即标记。 -
request.args.get()静默返回 None:BAD 写法是直接使用可能为 None 的user_id查询,导致错误查询;GOOD 写法是显式校验,若为 None 则abort(400)。FastAPI 的 Pydantic 模型可自动防止此问题,Flask 需要手动防护。 -
失败关闭的
before_request钩子:BAD 写法是在认证检查中except: pass,绕过保护;GOOD 写法是记录警告并abort(401)。
自动化扫描方法
静态分析(Bandit):
bandit -r . -t B110,B112 # try-except-pass and try-except-continue
bandit -r . --severity-level medium
关键 Bandit 测试 ID:B110(try/except pass,吞掉异常)、B112(try/except continue,循环中吞掉异常)。
模式搜索(grep / ripgrep):
# Fail-open patterns
rg "except.*:\s*(pass|continue|return True)" --type py
# Stack traces leaking to response
rg "traceback\.format_exc\(\)|str\(exc\)|repr\(exc\)" --type py
# Missing context managers
rg "open\(|\.connect\(\)" --type py # review each hit for 'with'
# Missing rollback
rg "session\.commit\(\)" --type py # check each for paired rollback
运行时 / DAST:触发故意的 404、500 和校验错误(FastAPI 上为 422);检查 HTTP 响应中是否出现文件路径、堆栈帧、SQL 查询字符串、异常类名;发送格式错误的 Authorization 头探测中间件,验证响应是 401 而非 200。
关键 CWE(A10:2025)
- CWE-209 错误消息中的敏感信息:Python 表现为 JSON 响应中的
str(exc)、调试 traceback。 - CWE-248 未捕获异常:无全局处理器;未处理的 raise 使应用崩溃。
- CWE-636 失败开放:认证检查中的
except: pass。 - CWE-703 异常条件处理不当:宽泛的 except 隐藏错误。
- CWE-754 异常条件检查不当:对外部输入缺少 None/空值检查。
- CWE-476 NULL 指针解引用:对可能为 None 的对象访问属性。
- CWE-756 缺少自定义错误页:带调试信息的默认框架错误页。
适用场景
适用于对 FastAPI 或 Flask 编写的 Python Web 应用进行安全审计、代码审查、静态扫描与运行时测试,尤其关注认证/授权逻辑、错误响应、事务处理、资源管理与调试配置。
限制
技能内容仅覆盖 FastAPI 与 Flask 的 Python 场景,未提供其他语言或框架的指导。资料未说明该技能的安装方式、收费模式、价格或平台信息,这些事实暂未提供。