2. OpenAPI规范基础回顾:OpenAPI 3.0/3.1核心结构、路径、方法、参数、请求体、响应体
在开始审计基线之前,必须牢固掌握OpenAPI规范的核心结构。无论是3.0还是3.1版本,其文档根对象均由几个顶级字段构成,这些字段定义了API的元信息、路径、组件和安全性。审计人员需要能够快速定位这些字段,并理解它们之间的依赖关系。
2.1 核心文档结构
一个合法的OpenAPI文档必须包含openapi版本声明、info元信息以及至少一个paths路径条目。下表列出了3.0和3.1版本中顶级字段的差异与共性:
| 字段 | 3.0.x | 3.1.x | 审计关注点 |
|---|---|---|---|
| openapi | 必填,如"3.0.3" | 必填,如"3.1.0" | 版本号决定JSON Schema版本(3.0用draft-07,3.1用2020-12) |
| info | 必填,含title/version | 必填,含title/version | version字段是否与实际部署版本一致 |
| paths | 必填,至少一个路径 | 必填,至少一个路径 | 路径是否暴露了未预期的端点 |
| components | 可选,可复用对象 | 可选,可复用对象 | 是否引用了未定义的组件 |
| webhooks | 不支持 | 新增,回调定义 | 回调URL是否经过验证 |
| jsonSchemaDialect | 不支持 | 可选,指定Schema方言 | 是否使用了不兼容的Schema关键字 |
审计提示: 3.1版本对nullable字段的处理与3.0不同。3.0使用"nullable": true,而3.1推荐使用"type": ["string", "null"]。审计时需检查是否混用了两种写法。
2.2 路径与HTTP方法
paths对象是API的端点清单。每个路径键(如/users/{userId})下包含一个或多个HTTP方法对象(get、post、put、delete、patch等)。审计时需检查路径参数是否在parameters中正确定义,以及是否使用了summary和operationId来唯一标识操作。
paths:
/users/{userId}:
get:
summary: 获取用户信息
operationId: getUserById
parameters:
- name: userId
in: path
required: true
schema:
type: integer
responses:
'200':
description: 成功返回用户对象
content:
application/json:
schema:
$ref: '#/components/schemas/User'
post:
summary: 创建新用户
operationId: createUser
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateUserRequest'
responses:
'201':
description: 用户创建成功
审计要点: 检查operationId是否全局唯一。重复的operationId会导致代码生成工具冲突,且可能隐藏安全审计中的操作追踪漏洞。
2.3 参数类型与位置
OpenAPI定义了四种参数位置(in字段):path、query、header、cookie。每种位置的安全含义不同。例如,path参数通常用于资源标识,query参数用于过滤或分页,header参数常用于传递认证令牌。
| 参数位置 | 示例 | 常见安全风险 | 审计检查项 |
|---|---|---|---|
| path | /users/{id} |
IDOR(水平越权) | 是否对路径参数做了权限校验 |
| query | ?page=1&limit=10 |
SQL注入、批量数据泄露 | 是否限制了limit最大值 |
| header | Authorization: Bearer xxx |
令牌泄露、未加密传输 | 是否要求HTTPS;是否定义了security方案 |
| cookie | sessionId=abc123 |
CSRF、会话固定 | 是否设置了HttpOnly和SameSite |
2.4 请求体(Request Body)
请求体仅在POST、PUT、PATCH等方法中使用。审计时重点关注required字段和content类型。如果API接受application/json,则必须检查Schema定义是否严格限制了字段类型和格式。
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- username
- email
properties:
username:
type: string
minLength: 3
maxLength: 50
email:
type: string
format: email
role:
type: string
enum: [admin, user, guest]
安全警告: 如果requestBody的Schema中使用了"additionalProperties": true(或未显式设置为false),攻击者可能注入未预期的字段。审计时应要求所有请求体Schema显式设置additionalProperties: false,除非有明确业务需求。
2.5 响应体(Responses)
每个HTTP方法必须至少定义一个响应(通常为200或201)。响应体通过content字段描述,与请求体结构类似。审计时需检查是否覆盖了错误状态码(如400、401、403、500),以及错误响应中是否泄露了堆栈信息。
responses:
'200':
description: 成功响应
content:
application/json:
schema:
type: object
properties:
data:
$ref: '#/components/schemas/User'
meta:
type: object
properties:
requestId:
type: string
'400':
description: 请求参数错误
content:
application/json:
schema:
type: object
properties:
error:
type: string
code:
type: integer
'500':
description: 服务器内部错误
# 注意:生产环境不应返回详细错误信息
2.6 核心结构关系图
下图展示了OpenAPI文档中顶级字段与路径、方法、参数、请求体、响应体之间的层级关系。审计人员应能根据此图快速定位每个安全要素在文档中的位置。
2.7 组件复用与引用
components对象是提升文档可维护性和审计效率的关键。通过$ref引用,可以避免在多个路径中重复定义相同的Schema。审计时需检查$ref路径是否正确,以及被引用的组件是否确实存在。
components:
schemas:
User:
type: object
properties:
id:
type: integer
username:
type: string
email:
type: string
format: email
ErrorResponse:
type: object
properties:
error:
type: string
code:
type: integer
securitySchemes:
BearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
审计技巧: 使用$ref时,注意不要形成循环引用(如A引用B,B又引用A)。大多数OpenAPI解析器会因此报错,但某些宽松的实现可能静默失败,导致安全策略被绕过。
2.8 版本差异速查表
审计过程中经常需要区分3.0和3.1的语法差异。下表列出了审计人员必须掌握的关键差异点:
| 特性 | OpenAPI 3.0 | OpenAPI 3.1 | 审计影响 |
|---|---|---|---|
| JSON Schema版本 | draft-07 | 2020-12 | 3.1支持if/then/else、unevaluatedProperties等新关键字 |
| nullable | "nullable": true |
使用"type": ["string", "null"] |
3.0的nullable在3.1中已废弃 |
| examples | 支持example和examples |
支持example和examples |
3.1的examples遵循JSON Schema规范 |
| webhooks | 不支持 | 新增顶级字段 | 需检查webhook回调URL是否经过验证 |
| 路径参数默认值 | 通过schema.default设置 |
通过schema.default设置 |
无差异,但需注意默认值是否安全 |