Builds Postman test collections for structured API security testing covering OWASP Top 10 vulnerabilities like BOLA, auth bypass, injection, with multi-role environments, automated scripts, and Newman/ZAP CI/CD integration.
npx claudepluginhub killvxk/cybersecurity-skills-zhThis skill uses the workspace's default tool permissions.
- 构建覆盖 OWASP API 安全 Top 10 的可重复 API 安全测试套件
Performs API security testing with Postman targeting OWASP API Top 10 vulnerabilities including auth bypass, injection, and data exposure. Builds multi-role environments, test scripts, and integrates with ZAP/Newman for CI/CD.
Builds Postman collections to test OWASP API Security Top 10 vulnerabilities using multi-role environments, JavaScript scripts, OWASP ZAP proxy, and Newman for CI/CD automation.
Conducts security testing on REST, GraphQL, and gRPC APIs using OWASP API Top 10, Burp Suite, Postman, and scripts to identify auth, authorization, injection, and business logic vulnerabilities at all permission levels.
Share bugs, ideas, or general feedback.
不适用于 未经授权对生产 API 使用。Postman 安全测试涉及发送潜在恶意载荷。
npm install -g newman为多角色测试创建 Postman 环境:
// 环境:API 安全测试 - 普通用户
{
"values": [
{"key": "base_url", "value": "https://target-api.example.com/api/v1"},
{"key": "auth_token", "value": ""},
{"key": "user_email", "value": "regular@test.com"},
{"key": "user_password", "value": "TestPass123!"},
{"key": "user_id", "value": ""},
{"key": "other_user_id", "value": "1002"},
{"key": "admin_endpoint", "value": "/admin/users"},
{"key": "test_order_id", "value": ""},
{"key": "other_user_order_id", "value": "5003"}
]
}
用于自动认证的前置请求脚本:
// 集合级前置请求脚本,用于自动登录
if (!pm.environment.get("auth_token") || pm.environment.get("token_expired")) {
const loginRequest = {
url: pm.environment.get("base_url") + "/auth/login",
method: "POST",
header: {"Content-Type": "application/json"},
body: {
mode: "raw",
raw: JSON.stringify({
email: pm.environment.get("user_email"),
password: pm.environment.get("user_password")
})
}
};
pm.sendRequest(loginRequest, (err, res) => {
if (!err && res.code === 200) {
const token = res.json().access_token;
pm.environment.set("auth_token", token);
pm.environment.set("user_id", res.json().user.id);
}
});
}
// 测试:访问其他用户的个人资料(BOLA)
// 请求:GET {{base_url}}/users/{{other_user_id}}
// 认证:Bearer {{auth_token}}
// 测试脚本:
pm.test("BOLA:不能访问其他用户资料", function() {
pm.expect(pm.response.code).to.be.oneOf([401, 403]);
});
pm.test("BOLA:拒绝时无用户数据泄露", function() {
if (pm.response.code === 200) {
const body = pm.response.json();
pm.expect(body).to.not.have.property("email");
pm.expect(body).to.not.have.property("phone");
pm.expect(body).to.not.have.property("address");
// 如果返回了完整资料,标记为 BOLA 漏洞
console.error("BOLA 漏洞:返回了其他用户的完整资料");
}
});
// 测试:访问其他用户的订单
// 请求:GET {{base_url}}/orders/{{other_user_order_id}}
pm.test("BOLA:不能访问其他用户订单", function() {
pm.expect(pm.response.code).to.be.oneOf([401, 403, 404]);
});
// 测试:修改其他用户的资源
// 请求:PATCH {{base_url}}/users/{{other_user_id}}
// 请求体:{"name": "Hacked"}
pm.test("BOLA:不能修改其他用户资料", function() {
pm.expect(pm.response.code).to.be.oneOf([401, 403]);
});
// 测试:令牌验证
// 请求:GET {{base_url}}/users/me
// 认证:Bearer invalid_token_value
pm.test("认证:无效令牌被拒绝", function() {
pm.expect(pm.response.code).to.be.oneOf([401, 403]);
});
// 测试:过期令牌处理
// 请求:GET {{base_url}}/users/me
// 认证:Bearer {{expired_token}}
pm.test("认证:过期令牌被拒绝", function() {
pm.expect(pm.response.code).to.equal(401);
});
// 测试:缺少认证
// 请求:GET {{base_url}}/users/me
// 认证:无
pm.test("认证:未认证请求被拒绝", function() {
pm.expect(pm.response.code).to.equal(401);
});
// 测试:登录中的 SQL 注入
// 请求:POST {{base_url}}/auth/login
// 请求体:{"email": "' OR 1=1--", "password": "test"}
pm.test("认证:登录中的 SQL 注入被拒绝", function() {
pm.expect(pm.response.code).to.not.equal(200);
pm.expect(pm.response.text()).to.not.include("token");
});
// 测试:账号枚举
// 前置:使用有效邮箱+错误密码发送,然后使用无效邮箱+错误密码发送
pm.test("认证:无账号枚举", function() {
// 与存储的有效邮箱尝试响应进行比较
const validEmailResponse = pm.environment.get("valid_email_response");
const currentResponse = pm.response.text();
pm.expect(currentResponse).to.equal(validEmailResponse);
});
// 测试:过度数据暴露检查
// 请求:GET {{base_url}}/users/me
pm.test("数据暴露:响应中无敏感字段", function() {
const sensitiveFields = [
"password", "password_hash", "passwordHash",
"ssn", "social_security", "credit_card",
"api_key", "secret_key", "mfa_secret",
"refresh_token", "session_id"
];
const responseText = pm.response.text().toLowerCase();
sensitiveFields.forEach(field => {
pm.expect(responseText).to.not.include('"' + field + '"');
});
});
pm.test("数据暴露:安全响应头存在", function() {
pm.expect(pm.response.headers.has("X-Content-Type-Options")).to.be.true;
pm.expect(pm.response.headers.has("X-Frame-Options")).to.be.true;
pm.expect(pm.response.headers.get("X-Content-Type-Options")).to.equal("nosniff");
});
pm.test("数据暴露:无服务器信息泄露", function() {
pm.expect(pm.response.headers.has("Server")).to.be.false;
pm.expect(pm.response.headers.has("X-Powered-By")).to.be.false;
});
// 测试:BFLA - 管理员端点访问
// 请求:GET {{base_url}}{{admin_endpoint}}
// 认证:Bearer {{auth_token}}(普通用户)
pm.test("BFLA:普通用户不能访问管理员端点", function() {
pm.expect(pm.response.code).to.be.oneOf([401, 403]);
});
// 测试:BFLA - 管理员功能执行
// 请求:DELETE {{base_url}}/users/{{other_user_id}}
// 认证:Bearer {{auth_token}}(普通用户)
pm.test("BFLA:普通用户不能删除其他用户", function() {
pm.expect(pm.response.code).to.be.oneOf([401, 403]);
});
// 测试:通过资料更新进行批量赋值
// 请求:PUT {{base_url}}/users/me
// 请求体:{"name": "Test", "role": "admin", "is_admin": true}
pm.test("批量赋值:角色字段不被接受", function() {
if (pm.response.code === 200) {
const user = pm.response.json();
pm.expect(user.role).to.not.equal("admin");
pm.expect(user.is_admin).to.not.equal(true);
}
});
// 测试:限速执行
// 此测试应在高迭代次数的集合运行器中运行
pm.test("限速:超过限制时返回 429", function() {
// 此测试期望在多次迭代后触发限速
const iterationCount = pm.info.iteration;
if (iterationCount > 50) {
// 50 次迭代后应看到限速
if (pm.response.code === 429) {
pm.expect(pm.response.headers.has("Retry-After")).to.be.true;
console.log("在第 " + iterationCount + " 次迭代时触发限速");
}
}
});
// 测试:限速响应头存在
pm.test("限速:限速响应头存在", function() {
const hasRateHeaders = pm.response.headers.has("X-RateLimit-Limit") ||
pm.response.headers.has("X-Rate-Limit-Limit") ||
pm.response.headers.has("RateLimit-Limit");
pm.expect(hasRateHeaders).to.be.true;
});
# 通过 Newman CLI 运行安全测试集合
newman run "API-Security-Tests.postman_collection.json" \
--environment "Security-Test-Environment.postman_environment.json" \
--reporters cli,htmlextra,junit \
--reporter-htmlextra-export ./reports/security-test-report.html \
--reporter-junit-export ./reports/security-test-results.xml \
--iteration-count 1 \
--timeout-request 10000 \
--delay-request 100 \
--bail
# 使用不同用户角色运行
for role in "regular_user" "admin_user" "unauthenticated"; do
echo "使用角色测试:$role"
newman run "API-Security-Tests.postman_collection.json" \
--environment "Security-Test-${role}.postman_environment.json" \
--reporters cli,junit \
--reporter-junit-export "./reports/security-${role}.xml"
done
GitHub Actions 集成:
# .github/workflows/api-security-test.yml
name: API Security Tests
on:
pull_request:
paths: ['src/api/**', 'openapi.yaml']
jobs:
security-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm install -g newman newman-reporter-htmlextra
- name: Run API Security Tests
run: |
newman run tests/postman/api-security.json \
--environment tests/postman/env-staging.json \
--reporters cli,htmlextra,junit \
--reporter-htmlextra-export reports/security.html \
--reporter-junit-export reports/security.xml
- uses: actions/upload-artifact@v4
if: always()
with:
name: security-reports
path: reports/
| 术语 | 定义 |
|---|---|
| Postman 集合(Postman Collection) | 包含测试脚本的有组织 API 请求组,可共享、版本控制和自动执行 |
| Newman | Postman 的命令行伴侣工具,可在 CI/CD 流水线中运行集合并生成测试报告 |
| 前置请求脚本(Pre-request Script) | 在 Postman 请求前执行的 JavaScript 代码,用于动态认证和测试数据设置 |
| 测试脚本(Test Script) | 在 Postman 响应后执行的 JavaScript 代码,用于针对响应验证安全断言 |
| 集合运行器(Collection Runner) | Postman 功能,按顺序执行集合中所有请求,可配置迭代次数和延迟 |
| 环境变量(Environment Variables) | 限定在 Postman 环境范围内的键值对,用于针对不同目标、角色和配置参数化请求 |
场景背景:一个开发团队每两周发布 API 更新。他们需要一个自动化安全测试套件,在每次拉取请求时运行,以在合并前发现授权和认证回归问题。
方法:
常见陷阱:
## API 安全测试报告 - Postman/Newman
**集合**:API 安全测试 v2.3
**环境**:预发布 - 普通用户
**日期**:2024-12-15
**总请求数**:85
**总测试数**:234
**通过**:219
**失败**:15
### 失败测试摘要
| # | 请求 | 测试名称 | 严重性 |
|---|---------|-----------|----------|
| 1 | GET /users/1002 | BOLA:不能访问其他用户资料 | 严重 |
| 2 | GET /orders/5003 | BOLA:不能访问其他用户订单 | 严重 |
| 3 | GET /admin/users | BFLA:普通用户不能访问管理员端点 | 严重 |
| 4 | PUT /users/me | 批量赋值:角色字段不被接受 | 高 |
| 5 | GET /users/me | 数据暴露:响应中无敏感字段 | 高 |
| 6 | POST /auth/login | 认证:无账号枚举 | 中 |
| ... | ... | ... | ... |
### 建议
1. 修复 /users/{id} 和 /orders/{id} 的 BOLA——添加对象级授权检查
2. 修复 /admin/users 的 BFLA——执行基于角色的访问控制中间件
3. 修复 PUT /users/me 的批量赋值——实现字段允许列表
4. 从用户序列化中删除 password_hash 和 mfa_secret
5. 标准化登录错误消息以防止账号枚举