安全测试相关
安全测试 完整系统学习大纲
本文面向测试工程师,按”合规与概念 → OWASP Top 10 → 各类漏洞 → 工具 → 流程实战 → 体系”的顺序组织,由浅入深。 功能测试保证”做对了”,安全测试保证”没做错”——一个能下单的系统如果可以改金额、能看别人订单,功能再完美也是失败的。安全测试不需要你成为黑客,但要能发现常见的、高危的、业务相关的安全问题。
⚠️ 合规声明(务必先读):本文所有测试方法仅限在你有明确授权的测试环境、自己搭建的实验环境或公司正式立项的安全测试项目中使用。未经授权对他人系统进行测试,违反《网络安全法》《刑法》第 285/286 条(非法侵入/破坏计算机信息系统罪),属于违法行为。测试工程师的价值在于发现并推动修复,而非利用漏洞。
一、安全测试概述
1.1 什么是安全测试?
- 定义:以发现系统安全隐患为目标的测试活动,验证系统在机密性、完整性、可用性(CIA 三要素)上的防护能力。
- 核心问题:
- 能访问不该访问的数据吗?(机密性)
- 能篡改不该篡改的内容吗?(完整性)
- 能让服务不可用吗?(可用性)
1.2 安全测试 vs 渗透测试 vs 漏洞扫描
| 类型 | 执行者 | 深度 | 特点 |
|---|---|---|---|
| 安全测试 | 测试工程师 | 中等 | 融入日常测试流程,覆盖常见漏洞 + 业务逻辑安全 |
| 渗透测试 | 安全工程师/白帽子 | 深入 | 模拟真实攻击,追求”拿下权限”,产出渗透报告 |
| 漏洞扫描 | 自动化工具 | 浅 | 批量扫描已知特征,误报率高,需人工验证 |
| 代码审计 | 开发/安全 | 深入 | 白盒,直接看源码找问题 |
💡 测试工程师的定位:不必追求 0day 和高深利用链,重点是把 OWASP Top 10 常见漏洞 + 业务逻辑漏洞覆盖住,把明显的高危问题拦在上线前。
1.3 安全测试的分类
安全测试
├── Web 安全 注入、XSS、CSRF、越权、SSRF…
├── 接口安全 鉴权、参数校验、签名、重放、频控
├── 业务安全 金额篡改、库存、优惠券、并发(逻辑漏洞)
├── 移动安全 本地存储、组件导出、日志泄露、反编译
├── 数据安全 敏感信息、加密存储、脱敏、传输
├── 认证安全 弱口令、暴力破解、会话管理、验证码
├── 配置安全 默认口令、目录列表、错误信息、组件版本
└── 基础设施 端口、中间件、服务器、依赖组件漏洞
1.4 安全测试在开发流程中的位置
需求阶段 → 设计阶段 → 编码阶段 → 测试阶段 → 上线 → 运营
│ │ │ │ │ │
安全需求 威胁建模 代码审计 安全测试 安全配置 监控/应急响应
SAST/DAST ★ 本文重点 基线检查 定期渗透
安全左移:越早发现,修复成本越低。需求阶段的安全评审 > 上线后的渗透测试。
1.5 相关法律法规与标准
| 法规/标准 | 要点 |
|---|---|
| 《网络安全法》 | 网络运营者安全保护义务,不得非法侵入他人网络 |
| 《数据安全法》 | 数据分类分级、重要数据保护 |
| 《个人信息保护法》 | 个人信息收集需告知同意、最小必要、不得泄露 |
| 《等保 2.0》(GB/T 22239-2019) | 五级安全保护能力要求,定级备案与测评 |
| 《刑法》285/286 条 | 未授权侵入/破坏计算机信息系统属犯罪 |
| GDPR | 欧盟数据保护(涉欧业务) |
| PCI DSS | 支付卡行业数据安全标准(涉及支付) |
这些法规是测试同学在合规性测试中的依据:比如”用户注销后必须删除个人信息”(个保法)、”密码不能明文存储”(等保)。
二、OWASP Top 10(核心框架)
2.1 OWASP 简介
OWASP(Open Web Application Security Project)是开放的 Web 安全组织,其 OWASP Top 10 是业界公认的”十大 Web 安全风险”清单,每 3~4 年更新一次,是安全测试的标准检查单。
2.2 2021 版 Top 10
| 编号 | 风险 | 一句话理解 |
|---|---|---|
| A01 | 失效的访问控制 | 能看/改不该看的数据(越权) |
| A02 | 加密机制失效 | 明文传输/存储敏感数据 |
| A03 | 注入 | SQL、命令、XSS 等把输入当代码执行 |
| A04 | 不安全设计 | 设计阶段就埋下的缺陷(如验证码可绕过) |
| A05 | 安全配置错误 | 默认口令、目录列表、详细错误信息 |
| A06 | 易受攻击和过时的组件 | 用了有已知漏洞的老版本框架 |
| A07 | 身份识别和身份验证错误 | 弱口令、可被爆破、会话管理不当 |
| A08 | 软件和数据完整性故障 | 不安全的反序列化、未校验的更新 |
| A09 | 安全日志记录和监控失败 | 没有审计日志,被入侵了不知道 |
| A10 | 服务端请求伪造(SSRF) | 诱导服务器去访问内网 |
2.3 A01 失效的访问控制(越权,最高频)
原理:服务端只验证了”是否登录”,没验证”是否有权操作这份数据”。
| 类型 | 说明 | 示例 |
|---|---|---|
| 水平越权 | 访问同级别其他用户的数据 ★最常见 | 用户 A 改 ID 看到用户 B 的订单 |
| 垂直越权 | 低权限用户执行高权限操作 | 普通用户访问 /admin/deleteUser |
| 未授权访问 | 完全不登录就能访问 | 直接访问后台 URL |
测试方法(抓包改参数):
1. 用户 A 登录,查看自己的订单:GET /api/orders/10001
2. 抓包把 10001 改成 10002(用户 B 的订单)
3. 若能返回用户 B 的订单数据 → 水平越权漏洞(高危)
同理测试:
□ 改 URL 中的 ID(/user/1 → /user/2)
□ 改请求体中的 userId
□ 改 Cookie / Token 里的用户标识
□ 用 A 的 token 访问 B 的资源
□ 直接访问管理端接口(普通用户 token)
□ 修改订单归属 userId 后再提交
防御:每个接口都做数据与用户的归属校验;用不可预测的资源 ID(UUID);统一鉴权中间件;默认拒绝。
2.4 A02 加密机制失效
| 问题 | 测试点 |
|---|---|
| 明文传输 | 是否还有 HTTP 接口?抓包看是否明文 |
| 弱算法 | 是否用 MD5/SHA1 存密码?DES/RC4 加密? |
| 密钥硬编码 | 前端 JS / App 里是否有 AK/SK、密钥 |
| 敏感数据明文存储 | 数据库里密码是否明文?日志里有身份证吗? |
| 证书问题 | HTTPS 证书是否有效、是否校验主机名 |
# 检查是否明文传输(配合抓包工具,见抓包工具篇)
curl -v http://api.example.com/login # 看是否有 HTTP(非 HTTPS)接口
# 检查证书
openssl s_client -connect example.com:443
💡 测试要点:密码必须加盐哈希(bcrypt/scrypt/Argon2/PBKDF2),绝不能 MD5 直接存;传输层必须 HTTPS;敏感字段(身份证、银行卡)存储需加密或脱敏。
2.5 A03 注入(详见第三章)
输入被当作代码执行。包括 SQL 注入、命令注入、XSS、LDAP 注入、表达式注入等。
2.6 A05 安全配置错误(最容易发现)
| 检查项 | 测试方法 |
|---|---|
| 默认口令 | 尝试 admin/admin、root/123456、tomcat/tomcat |
| 目录列表 | 访问 /static/、/upload/ 看是否列出文件 |
| 详细错误信息 | 触发异常,看是否暴露堆栈、SQL、路径 |
| 后台暴露 | /admin、/phpmyadmin、/actuator、/druid 是否可直接访问 |
| 调试开关 | 生产是否开了 debug、Swagger、Spring Boot Actuator |
| 备份文件 | 是否存在 xxx.bak、xxx.zip、/WEB-INF/ |
| HTTP 头 | 是否缺失 X-Content-Type-Options、X-Frame-Options 等 |
# Spring Boot Actuator 未授权访问(常见高危)
curl http://example.com/actuator/env # 可能泄露数据库密码、密钥
curl http://example.com/actuator/heapdump # 堆转储,含敏感信息
# 常见后台/管理路径探测
/admin /manage /login /console /swagger-ui.html /druid /solr /zabbix
2.7 A06 易受攻击和过时的组件
# 前端依赖
npm audit
# Java 依赖
mvn dependency-check:check # OWASP Dependency-Check
# Python 依赖
pip-audit
# 通用
snyk test
测试点:定期扫描依赖清单,关注 Log4j2(CVE-2021-44228)、Fastjson、Struts2、Shiro 等高频被利用组件的版本。
2.8 A07 身份识别和身份验证错误
详见第四章。包括弱口令、可被爆破、会话固定、Token 不过期等。
2.9 A09 日志与监控缺失
测试点(常被忽略但很重要):
- 登录失败是否有日志记录
- 敏感操作(改密码、改绑手机、提现)是否有审计日志
- 日志中是否泄露敏感信息(密码、token、身份证)——这本身是漏洞
- 是否有异常登录告警
- 日志是否有防篡改保护
💡 移动端:
adb logcat检查日志是否打印密码、token、身份证号(见 ADB与移动端专项)。
2.10 A10 SSRF(服务端请求伪造)
原理:服务端提供了”让服务器去请求某个 URL”的功能(如图片抓取、Webhook、转码),攻击者借此让服务器访问内网。
测试 payload(授权环境):
功能点:用户传入 URL,服务端去下载
尝试:
http://127.0.0.1:8080/admin 访问本机服务
http://169.254.169.254/ 云厂商元数据(可拿 AK/SK)
http://192.168.1.1/ 内网路由器
file:///etc/passwd 读本地文件
dict:// / gopher:// / ldap:// 其他协议
http://example.com@127.0.0.1/ URL 解析绕过
短链接 / DNS rebinding 绕过黑名单
防御:白名单域名、禁止内网 IP、统一解析后校验、禁用危险协议、限制端口
三、注入类漏洞(重点)
3.1 SQL 注入
原理:用户输入被拼接到 SQL 语句中,改变了 SQL 的语义。
-- 有漏洞的代码(拼接)
SELECT * FROM users WHERE username = '" + input + "' AND password = '...'
-- 输入 admin' --
-- 实际执行:
SELECT * FROM users WHERE username = 'admin' --' AND password = '...'
-- ↑ 后面被注释掉,绕过密码登录
分类:
| 类型 | 特征 | 检测难度 |
|---|---|---|
| 数字/字符型 | '、" 闭合 |
容易 |
| 布尔盲注 | 页面只有真/假两种状态 | 中 |
| 时间盲注 | 用 sleep() 通过响应时间判断 |
中 |
| 报错注入 | 通过数据库报错回显数据 | 容易 |
| 联合查询(UNION) | 用 UNION 拼出数据 | 容易 |
| 堆叠查询 | 用 ; 执行多条语句 |
支持时危害大 |
测试 Payload(授权环境):
基础探测:
' 看是否报错
' or '1'='1
' or 1=1 --
" or "a"="a
admin' --
admin' #
数字型:
1 and 1=1 / 1 and 1=2 对比差异
1' and '1'='1
判断列数(UNION):
' order by 3 --
' union select null,null,null --
时间盲注:
' and sleep(3) --
1; waitfor delay '0:0:3' --
报错注入:
' and updatexml(1,concat(0x7e,version()),1) --
' and extractvalue(1,concat(0x7e,database())) --
测试步骤:
1. 找输入点:URL 参数、表单、Cookie、Header、JSON 字段、搜索框
2. 加单引号测试:' → 看是否报数据库错误
3. and 1=1 / and 1=2 → 看响应是否有差异
4. 确认类型(字符/数字/盲注)
5. 用 sqlmap 验证(仅限于授权环境)
6. 记录并报告
# sqlmap(授权环境使用)
sqlmap -u "http://test.com/page?id=1" --batch
sqlmap -u "http://test.com/page?id=1" --dbs # 列出数据库
sqlmap -u "http://test.com/page?id=1" -D dbname --tables
sqlmap -r request.txt # 从抓包文件
sqlmap -u "..." --forms # 自动测表单
sqlmap -u "..." --level=3 --risk=2 # 提高检测强度
防御:
- 预编译(参数化查询) —— 最有效
// ✅ 正确:PreparedStatement String sql = "SELECT * FROM users WHERE username = ?"; PreparedStatement ps = conn.prepareStatement(sql); ps.setString(1, username); - ORM 框架(MyBatis 用
#{}而非${}) - 输入校验(白名单、类型)
- 最小权限数据库账号
- WAF(辅助,不能替代代码修复)
💡 MyBatis 经典坑:
${}是字符串拼接(有注入风险),#{}才是预编译。测试时可以直接在代码里搜${快速定位风险点。
3.2 XSS(跨站脚本)
原理:恶意脚本被注入到页面,在其他用户浏览器中执行。
| 类型 | 说明 | 场景 |
|---|---|---|
| 反射型 | 脚本在 URL 中,服务器原样返回 | 搜索框、错误提示 |
| 存储型 ★危害最大 | 脚本存入数据库,所有访问者都会中招 | 评论、昵称、留言 |
| DOM 型 | 前端 JS 操作 DOM 时触发,不经过服务端 | 前端路由、innerHTML |
测试 Payload:
<script>alert(1)</script>
<img src=x onerror=alert(1)>
<svg onload=alert(1)>
<body onload=alert(1)>
"><script>alert(1)</script>
javascript:alert(1)
'"><img src=1 onerror=alert(document.cookie)>
测试点:
- 所有用户输入回显的地方:昵称、评论、搜索结果、URL 参数、表单回显
- 富文本编辑器(最容易出存储型 XSS)
- 文件上传的文件名、SVG/HTML 文件
- Markdown 编辑器
- 输入框是否做了输出编码(不是只做输入过滤)
防御:
- 输出编码(HTML Entity 编码)——根本解法
- CSP(内容安全策略)
- HttpOnly Cookie(防止 JS 窃取 Cookie)
- 富文本用白名单过滤(如 DOMPurify)
3.3 命令注入
场景:服务端调用系统命令,参数来自用户输入(如 ping、文件转换)
测试 payload:
127.0.0.1; cat /etc/passwd
127.0.0.1 && whoami
127.0.0.1 | id
$(whoami)
`whoami`
127.0.0.1 %0a id (换行注入)
防御:避免拼接系统命令;用参数数组;白名单校验输入;最小权限运行
3.4 文件上传漏洞(高危)
| 测试点 | 方法 |
|---|---|
| 上传可执行文件 | 传 .jsp/.php webshell,看是否能访问执行 |
| 绕过前端校验 | 抓包改 Content-Type、改文件后缀 |
| 绕过黑名单 | .php5、.phtml、.php.jpg、大小写 .PHP、双后缀 |
| 文件内容检查 | 图片马(正常图片尾部追加恶意代码) |
| 路径穿越 | 文件名用 ../../shell.jsp |
| 解析漏洞 | 利用中间件解析特性(IIS/Nginx/Apache) |
| 大小限制 | 传超大文件看是否导致拒绝服务 |
防御:
- 白名单后缀 + MIME 校验
- 重命名文件(随机名,不让用户控制)
- 存储在非 Web 目录 / 独立对象存储
- 禁止执行权限
- 图片二次渲染/压缩
3.5 XXE(XML 外部实体注入)
<!-- 恶意 XML -->
<?xml version="1.0"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<data>&xxe;</data>
测试点:接口是否接受 XML 输入(如 SOAP、SVG 上传、Excel 导入)→ 尝试上述 payload 看是否读取到文件内容。
防御:禁用外部实体解析(setFeature("http://apache.org/xml/features/disallow-doctype-decl", true))。
四、认证与会话安全
4.1 身份认证测试点
| 测试项 | 方法 | 风险等级 |
|---|---|---|
| 弱口令 | 尝试常见密码(123456、admin、手机号后 6 位) | 高 |
| 暴力破解 | 连续错误登录 20 次,看是否锁定/验证码 | 高 |
| 验证码可绕过 | 删除验证码参数、用同一验证码重放、验证码在响应中返回 | 高 |
| 密码明文传输 | 抓包看密码是否加密 | 高 |
| 密码策略 | 是否允许 6 位纯数字弱密码 | 中 |
| 用户名枚举 | 不同用户名返回不同提示(”用户不存在”/”密码错误”) | 中 |
| 默认账号 | 是否存在 admin/admin、测试账号未删 |
高 |
暴力破解测试(授权环境):
1. 抓登录请求到 Burp Intruder
2. 密码字段加载字典,连续请求 50 次
3. 观察:
□ 是否一直能请求(无锁定)→ 高危
□ 是否出现验证码
□ 是否有 IP 限制
□ 响应时间是否异常(可用于用户枚举)
4.2 会话管理
| 测试项 | 方法 |
|---|---|
| 会话超时 | 登录后 30 分钟不操作,再用旧 token 请求是否还有效 |
| 登出失效 | 退出登录后,用旧 token 请求是否仍能访问(应失效) |
| 会话固定 | 登录前后 SessionID 是否变化(应变化) |
| Token 可预测 | 检查 token 是否有规律、是否含用户信息(base64 解码看看) |
| 并发登录 | 同一账号多处登录,是否挤下线 |
| Token 传输 | 是否在 URL 中传 token(会被日志记录) |
| Cookie 属性 | 是否设置 HttpOnly、Secure、SameSite |
# 检查 Cookie 安全属性
curl -I https://example.com | grep -i set-cookie
# 应包含:HttpOnly; Secure; SameSite=Lax/Strict
4.3 JWT 安全
JWT 结构:header.payload.signature(base64 编码,用 . 分隔)
在线解码:jwt.io
测试点:
□ alg 是否为 none(可伪造签名) → 高危
□ 是否用了弱密钥(可被爆破)
□ 是否校验 exp 过期时间
□ payload 里是否含敏感信息(base64 只是编码不是加密!)
□ 是否支持密钥混淆攻击(RS256 → HS256)
□ 登出后 token 是否失效(JWT 无状态,需黑名单机制)
4.4 密码找回与多因素
密码找回逻辑漏洞(经典):
- 验证码在响应包中返回(最高频)
- 验证码 4 位纯数字且无次数限制 → 可爆破
- 改
userId/手机号参数,用自己收到的验证码改别人的密码 - 跳过验证步骤直接访问重置页
- 验证码不过期 / 可重复使用
五、业务逻辑安全(测试工程师的主战场)
逻辑漏洞扫描器扫不出来,只能靠人理解业务。这是测试同学相对安全工程师的独特优势。
5.1 经典逻辑漏洞清单
| 漏洞 | 场景 | 测试方法 |
|---|---|---|
| 金额篡改 ★ | 下单时改商品价格/数量 | 抓包改 price、amount,看服务端是否重新计算 |
| 数量负数 | 购买数量填 -1 | 看是否能”刷”出余额 |
| 库存绕过 | 并发下单 | 多线程同时下单,看是否超卖 |
| 优惠券复用 | 同一券多次使用 | 重放请求,看是否有幂等校验 |
| 重复提交 | 快速点两次下单 | 看是否产生两笔订单 |
| 短信轰炸 | 反复请求验证码 | 看是否有频率限制(会浪费公司资费) |
| 任意用户注册 | 用他人手机号注册 | 看是否校验短信归属 |
| 越权查看订单 | 改订单 ID | 见 2.3 越权 |
| 提现/积分刷取 | 并发提现 | 看余额并发扣减是否安全 |
| 退款金额篡改 | 改退款金额 > 实付 | 看是否校验 |
| 订单状态绕过 | 未支付直接改状态为已完成 | 看状态机是否服务端控制 |
5.2 金额篡改测试(最经典的案例)
正常流程:
客户端提交:{productId: 1001, qty: 1}
服务端:查库取单价 → 计算总价 → 下单
有漏洞的流程:
客户端提交:{productId: 1001, qty: 1, price: 0.01}
服务端:直接用了客户端传的 price → 1 分钱买手机
测试方法:
1. 抓下单请求
2. 修改 price / amount / totalFee 等字段为极小值
3. 提交,看订单金额是否跟着变
4. 同样测:负数、超大数、小数点后多位
5. 观察服务端是否重新计算
判定:只要服务端信任客户端传的价格 → 高危漏洞
💡 重要原则:前端的任何校验都可以被绕过,服务端必须二次校验。价格、库存、权限、状态,一切以服务端为准。这是安全测试最核心的一条。
5.3 并发/竞态条件测试
# 并发下单测试(授权环境)
import threading
import requests
URL = "https://test.example.com/api/order/create"
TOKEN = "xxx"
def create_order():
r = requests.post(URL, json={"productId": 1001, "qty": 1},
headers={"Authorization": f"Bearer {TOKEN}"}, timeout=10)
return r.status_code, r.text[:100]
# 库存只有 1 件,同时发 20 个请求
results = []
threads = [threading.Thread(target=lambda: results.append(create_order()))
for _ in range(20)]
[t.start() for t in threads]
[t.join() for t in threads]
success = sum(1 for code, _ in results if code == 200)
print(f"成功下单数: {success}")
# 若 success > 库存数量 → 超卖漏洞(库存未加锁)
其他并发测试点:
- 并发领取优惠券(一人领多张)
- 并发提现(余额扣减不安全)
- 并发点赞/投票(刷量)
- 并发注册(同一手机号注册多个账号)
5.4 重复提交与幂等
测试方法:
1. 抓一个创建类请求(下单、评论、领券)
2. 连续重放 5 次(Burp Repeater 或脚本)
3. 观察是否产生 5 条记录
防御:幂等设计(唯一请求号/token)、数据库唯一索引、分布式锁
六、敏感信息与数据安全
6.1 传输安全
- 全站 HTTPS(无 HTTP 明文接口)
- 无混合内容(HTTPS 页面加载 HTTP 资源)
- 证书有效、未过期、域名匹配
- HSTS 头配置
- 敏感接口(登录、支付)是否额外加密
6.2 敏感信息泄露检查清单
| 位置 | 检查内容 |
|---|---|
| 响应数据 | 是否返回多余字段(身份证、密码、内部 ID、手机号未脱敏) |
| 错误信息 | 是否暴露堆栈、SQL 语句、服务器路径、版本号 |
| 前端源码 | 注释里的测试账号、API Key、内网地址 |
| 日志文件 | 是否打印密码、token、身份证 |
| 备份文件 | 是否存在 .bak、.sql、.git 目录可下载 |
| 抓包数据 | 明文传输的敏感字段 |
| 第三方 | 是否把用户数据传给未授权的第三方 SDK |
# 检查是否泄露 .git 目录(可直接下载源码!)
curl -I http://example.com/.git/config
# 常见信息泄露路径
/.git/config /.svn/ /.env /backup.sql /www.zip
/WEB-INF/ /phpinfo.php /server-status
6.3 数据脱敏规范
| 数据类型 | 脱敏要求 |
|---|---|
| 手机号 | 138****1234 |
| 身份证 | 3301**********1234 |
| 银行卡 | **** **** **** 1234 |
| 姓名 | 张** |
| 地址 | 只显示到区县 |
| 密码/密钥 | 任何情况下都不应返回 |
💡 测试要点:列表页、导出功能、日志、第三方接口调用,都要检查脱敏。特别是导出 Excel 功能,经常导出完整未脱敏数据。
6.4 密码存储
❌ 错误做法:
MD5(password) 彩虹表可破
MD5(password + 固定盐) 盐硬编码在代码里等于没有
SHA1(password) 已被攻破
明文存储 最严重
✅ 正确做法:
bcrypt / scrypt / Argon2 / PBKDF2
每个用户独立随机盐,加盐慢哈希
测试点:数据库中查看密码字段,若为 32 位字符串很可能是 MD5,需确认算法
七、其他 Web 漏洞
7.1 CSRF(跨站请求伪造)
原理:攻击者诱导已登录用户访问恶意页面,以用户名义发起请求(如转账)。
<!-- 恶意页面(示例) -->
<img src="https://bank.com/transfer?to=attacker&amount=10000">
<!-- 用户访问该页面时,浏览器带着 bank.com 的 Cookie 自动发请求 -->
测试方法:
- 抓一个敏感操作请求(改密码、转账、删除)
- 检查是否有 CSRF Token / 自定义 Header
- 构造表单在另一个页面提交,看是否成功
- 检查 Cookie 的
SameSite属性
防御:CSRF Token、SameSite Cookie、验证 Referer/Origin、关键操作二次验证(短信/密码)。
7.2 目录遍历 / 文件包含
测试 payload:
../../../../etc/passwd
..%2f..%2f..%2fetc%2fpasswd URL 编码绕过
....//....//etc/passwd 双写绕过
file=../../config/database.yml
测试点:文件下载、图片查看、模板加载功能的参数
防御:白名单、路径规范化后校验、禁止 .. 、使用文件 ID 而非路径
7.3 其他漏洞速查
| 漏洞 | 要点 |
|---|---|
| 开放重定向 | ?redirect=http://evil.com 未校验白名单,用于钓鱼 |
| CORS 配置不当 | Access-Control-Allow-Origin: * 且带凭证 |
| 点击劫持 | 缺少 X-Frame-Options / CSP frame-ancestors |
| HTTP 方法滥用 | 是否允许 PUT/DELETE/TRACE(TRACE 可致 XST) |
| 不安全的反序列化 | 接受序列化对象输入(Java/Python pickle/PHP) |
| CRLF 注入 | 输入包含 %0d%0a 注入响应头 |
| Host 头攻击 | 密码重置链接使用 Host 头导致可劫持 |
| 条件竞争 | 见 5.3 |
八、移动端安全
配合 ADB 工具使用,详见 ADB与移动端专项。
| 测试项 | 方法 |
|---|---|
| 本地存储 | 检查 SharedPreferences/SQLite/沙盒文件是否有明文密码、token |
| 日志泄露 | adb logcat 查是否打印敏感信息 |
| 组件导出 | dumpsys package 看 exported=true 的组件是否可被恶意调用 |
| 证书校验 | 是否校验 HTTPS 证书;是否有 SSL Pinning |
| 反编译 | apktool/jadx 反编译,看代码是否混淆、有无硬编码密钥 |
| 权限 | 是否过度申请权限;权限关闭是否崩溃 |
| root/越狱检测 | 是否有检测与提示 |
| 二次打包 | 应用是否有签名校验、防篡改 |
| 剪贴板 | 是否读取剪贴板敏感信息 |
| 截屏 | 支付/密码页面是否可被截屏(金融 App 需防护) |
# 组件导出检查
adb shell dumpsys package com.example.app | grep -i "exported"
# 本地存储检查(需 debug 包或 root)
adb shell run-as com.example.app ls /data/data/com.example.app/shared_prefs/
adb shell run-as com.example.app cat /data/data/com.example.app/databases/*.db
# 日志敏感信息检查
adb logcat | grep -iE "password|token|身份证|phone|cardNo"
九、接口安全测试
| 测试项 | 方法 |
|---|---|
| 鉴权 | 不带 token / 带过期 token / 带他人 token 访问 |
| 参数校验 | 类型、长度、范围、特殊字符;服务端是否二次校验 |
| 签名机制 | 改参数后签名是否校验;时间戳是否过期校验 |
| 重放攻击 | 抓包重复发送同一请求,看是否生效(需 timestamp+nonce) |
| 频控 | 1 分钟内请求 100 次,看是否限流 |
| 脱敏 | 返回字段是否脱敏 |
| 批量遍历 | 遍历 ID 拉取全量数据(拖库风险) |
| 越权 | 见 2.3 |
# 接口安全测试脚本示例(授权环境)
import requests
BASE = "https://test.example.com"
TOKEN = "user_a_token"
def test_no_auth():
"""不带 token 应被拒绝"""
r = requests.get(f"{BASE}/api/orders", timeout=5)
assert r.status_code in (401, 403), f"未鉴权却可访问: {r.status_code}"
def test_expired_token():
"""过期 token 应被拒绝"""
r = requests.get(f"{BASE}/api/orders",
headers={"Authorization": "Bearer expired_token"}, timeout=5)
assert r.status_code in (401, 403)
def test_horizontal_privilege():
"""水平越权:用 A 的 token 访问 B 的订单"""
r = requests.get(f"{BASE}/api/orders/88888", # B 的订单 ID
headers={"Authorization": f"Bearer {TOKEN}"}, timeout=5)
# 应返回 403/404,而不是 B 的数据
assert r.status_code in (403, 404), f"疑似越权,返回: {r.text[:200]}"
def test_id_enumeration():
"""遍历 ID,检查是否可批量拉取他人数据"""
leaked = 0
for oid in range(10000, 10050):
r = requests.get(f"{BASE}/api/orders/{oid}",
headers={"Authorization": f"Bearer {TOKEN}"}, timeout=5)
if r.status_code == 200:
leaked += 1
print(f"可访问订单数: {leaked}")
assert leaked <= 5, f"疑似越权遍历,可访问 {leaked} 条他人数据"
def test_replay():
"""重放攻击:同一请求重发 3 次"""
payload = {"productId": 1001, "qty": 1}
headers = {"Authorization": f"Bearer {TOKEN}"}
codes = []
for _ in range(3):
r = requests.post(f"{BASE}/api/order/create", json=payload,
headers=headers, timeout=5)
codes.append(r.status_code)
print("重放结果:", codes)
# 幂等接口第二次应返回错误或同一订单
十、安全测试工具
10.1 工具对比
| 工具 | 类型 | 免费 | 用途 | 推荐度 |
|---|---|---|---|---|
| Burp Suite | 综合平台 | 社区版 | 抓包改包、扫描、爆破 | ★★★★★ |
| OWASP ZAP | 综合扫描 | ✅ | 自动扫描、被动代理 | ★★★★ |
| sqlmap | 专项 | ✅ | SQL 注入检测 | ★★★★★ |
| Nmap | 端口扫描 | ✅ | 端口/服务探测 | ★★★★ |
| Postman/Charles | 抓包 | ✅ | 接口调试改参 | ★★★★ |
| Nikto | Web 扫描 | ✅ | 服务器漏洞扫描 | ★★★ |
| ffuf / dirb | 目录爆破 | ✅ | 路径/目录发现 | ★★★★ |
| MobSF | 移动安全 | ✅ | APK/IPA 静态动态分析 | ★★★★ |
| Dependency-Check / Snyk | 依赖扫描 | 部分 | 组件漏洞 | ★★★★ |
| Hydra | 爆破 | ✅ | 弱口令检测 | ★★★ |
10.2 Burp Suite 核心模块
| 模块 | 用途 | 测试常用 |
|---|---|---|
| Proxy | 拦截/查看/修改 HTTP(S) 流量 | 抓包改参数(改金额、改 ID) |
| Repeater | 手动重放单个请求 | ★ 最常用,改包重发 |
| Intruder | 自动化爆破/枚举 | 弱口令、验证码爆破、ID 遍历 |
| Scanner | 自动漏洞扫描 | 社区版有限(Pro 版强) |
| Decoder | 编码解码 | base64、URL、JWT 解码 |
| Comparer | 对比响应差异 | 判断注入是否生效 |
Burp 使用流程:
1. 浏览器/手机 设置代理指向 Burp(默认 127.0.0.1:8080)
2. 安装 Burp CA 证书(抓 HTTPS)
3. Proxy → Intercept 开启拦截
4. 触发业务操作 → 请求被拦住
5. 右键 Send to Repeater
6. 在 Repeater 里改参数 → Send → 观察响应
7. 需要批量时 Send to Intruder
10.3 OWASP ZAP(免费首选)
# 快速扫描
zap-cli quick-scan --self-contained --start-options '-config api.disablekey=true' http://test.example.com
# Baseline 扫描(CI 集成常用)
docker run -t owasp/zap2docker-stable zap-baseline.py -t http://test.example.com
10.4 Nmap 端口扫描
nmap -sV -p 1-65535 192.168.1.100 # 全端口 + 服务版本
nmap -A 192.168.1.100 # 全面检测
nmap --script vuln 192.168.1.100 # 漏洞脚本扫描
10.5 目录/路径爆破
ffuf -u http://test.com/FUZZ -w /usr/share/wordlists/dirb/common.txt
dirb http://test.com
gobuster dir -u http://test.com -w wordlist.txt
10.6 移动端分析
# MobSF(Docker 一键)
docker run -it --rm -p 8000:8000 opensecurity/mobile-security-framework-mobsf
# APK 反编译
apktool d app.apk -o out/
jadx-gui app.apk # 看 Java 源码
# 检查硬编码密钥
grep -rE "AKIA[0-9A-Z]{16}|api[_-]?key|secret" out/
十一、安全测试流程与实战
11.1 标准流程
1. 授权与范围确认 ★
□ 书面授权,明确测试范围、时间、禁止事项
□ 确认测试环境(绝不在生产直接测!)
2. 信息收集
□ 资产梳理:域名、IP、接口、App
□ 技术栈识别:框架、中间件、组件版本
□ 接口清单:Swagger/抓包
3. 威胁建模
□ 识别资产、入口、信任边界
□ 排优先级:哪些功能出问题最严重(支付、用户数据、权限)
4. 漏洞扫描
□ 自动化工具:ZAP/Nikto/依赖扫描
□ 过滤误报
5. 手工验证(核心)
□ OWASP Top 10 逐项过
□ 业务逻辑安全(越权、金额、并发)
□ 用 Burp Repeater 逐个验证
6. 报告与复测
□ 写报告:漏洞描述 + 复现步骤 + 危害 + 修复建议
□ 开发修复后回归复测
□ 关闭漏洞
11.2 安全测试用例模板
| 字段 | 内容 |
|---|---|
| 用例编号 | SEC-LOGIN-001 |
| 用例名称 | 登录接口暴力破解防护 |
| 前置条件 | 已授权测试环境,有效用户名 |
| 测试步骤 | 1. 抓登录请求 2. 用 Burp Intruder 加载密码字典 3. 连续请求 50 次 |
| 预期结果 | 第 5 次失败后触发验证码/锁定,或 IP 限流 |
| 实际结果 | 50 次全部可请求,仅返回”密码错误” |
| 风险等级 | 高危 |
| 修复建议 | 增加失败次数锁定、验证码、IP 限流、登录告警 |
11.3 漏洞等级评定
| 等级 | 判定标准 | 示例 |
|---|---|---|
| 严重 Critical | 可直接获取系统权限/大量数据 | 远程代码执行、拖库 |
| 高危 High | 可导致重要数据泄露或资金损失 | 越权查看他人订单、金额篡改、SQL 注入 |
| 中危 Medium | 有限影响,需一定条件 | 存储型 XSS、CSRF(需交互)、弱口令策略 |
| 低危 Low | 影响很小 | 缺少安全响应头、版本号泄露、目录列表(无敏感文件) |
| 信息 Info | 不构成直接风险 | 技术栈信息、注释信息 |
CVSS 评分(0~10 分)是通用量化标准,可借助 CVSS 计算器 评定。
11.4 安全测试报告结构
1. 概述(测试范围、时间、方法、人员)
2. 风险摘要(按等级统计:严重 x / 高危 x / 中危 x / 低危 x)
3. 漏洞详情(每个漏洞)
□ 名称与等级
□ 影响范围(URL/接口/功能)
□ 详细描述
□ 复现步骤(含请求包截图)
□ 危害分析(能造成什么后果)
□ 修复建议(具体到代码层面)
4. 总体安全评估与改进建议
5. 附录(工具、字典、参考资料)
💡 写好报告的关键:复现步骤要让开发照着做就能看到问题,危害分析要说清”能造成什么业务损失”,修复建议要具体到怎么做(不要只写”加强校验”)。
十二、SDL 与 DevSecOps
12.1 安全开发生命周期(SDL)
培训 → 需求分析(安全需求)→ 设计(威胁建模)→ 实现(安全编码规范)
→ 验证(安全测试 ★)→ 发布(安全配置)→ 响应(应急响应)
12.2 三类自动化安全测试
| 类型 | 全称 | 阶段 | 特点 |
|---|---|---|---|
| SAST | 静态应用安全测试 | 编码期 | 扫源码,无需运行(SonarQube、Checkmarx) |
| DAST | 动态应用安全测试 | 测试期 | 扫运行中的应用(ZAP、Burp Scanner) |
| IAST | 交互式安全测试 | 测试期 | 插桩,结合两者优点 |
| SCA | 软件成分分析 | 依赖期 | 组件依赖漏洞(Snyk、Dependency-Check) |
12.3 CI 中集成安全检查
# GitLab CI 示例
stages:
- test
- security
dependency_scan:
stage: security
script:
- npm audit --audit-level=high
- snyk test --severity-threshold=high
dast_scan:
stage: security
script:
- docker run owasp/zap2docker-stable zap-baseline.py -t $TEST_URL
💡 把安全扫描接进流水线,实现”每次提交自动查依赖漏洞 + 每次部署自动扫一遍”——这是安全左移的落地方式。
12.4 安全测试左移建议
- 需求评审阶段就问:”这个功能涉及哪些敏感数据?谁能操作?”
- 测试用例里直接写安全用例,而不是等专项测试
- 建立团队安全测试用例库(越权、金额、并发等通用场景)
- 定期做安全培训与漏洞复盘
十三、常见问题速查
| 问题 | 说明 |
|---|---|
| 扫描器报了一堆问题怎么办 | 先人工验证,过滤误报,再提交 |
| 分不清是不是漏洞 | 看”是否造成了实际危害”(数据泄露/资金损失/权限提升) |
| 开发说”这是设计如此” | 让他说明设计依据,确认是否有补偿控制(如频控、审计) |
| 生产环境能不能测 | 绝对不行,除非有正式授权的渗透项目 |
| 发现漏洞要不要公开 | 走内部流程,禁止对外披露;遵守漏洞披露规范 |
| 没有安全工具怎么办 | Postman/Charles + curl 也能做大部分手工验证 |
| 逻辑漏洞怎么测 | 靠理解业务 + 抓包改参 + 并发,扫描器无效 |
| 测出漏洞开发不认 | 提供可复现的请求包截图 + 危害说明 + 参考 OWASP |
十四、学习资源
| 资源 | 说明 |
|---|---|
| OWASP Top 10 官方 | 权威清单,必读 |
| OWASP Testing Guide | 完整的 Web 安全测试方法论 |
| OWASP Cheat Sheet Series | 各类漏洞的防御速查 |
| PortSwigger Web Security Academy | 免费交互式实验,Burp 官方出品,强烈推荐 |
| PayloadsAllTheThings | Payload 大全 |
| HackTricks | 渗透测试知识库 |
| sqlmap 文档 | SQL 注入工具 |
| Burp Suite 官方文档 | 工具使用 |
| CVSS 计算器 | 漏洞定级 |
| DVWA / WebGoat / Juice Shop | 故意留有漏洞的练习靶场,安全学习必练 |
| 《Web 安全深度剖析》《白帽子讲 Web 安全》 | 中文经典书籍 |