安全测试相关

11 minute read

安全测试 完整系统学习大纲

本文面向测试工程师,按”合规与概念 → 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                     # 提高检测强度

防御:

  1. 预编译(参数化查询) —— 最有效
    // ✅ 正确:PreparedStatement
    String sql = "SELECT * FROM users WHERE username = ?";
    PreparedStatement ps = conn.prepareStatement(sql);
    ps.setString(1, username);
    
  2. ORM 框架(MyBatis 用 #{} 而非 ${})
  3. 输入校验(白名单、类型)
  4. 最小权限数据库账号
  5. 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 自动发请求 -->

测试方法:

  1. 抓一个敏感操作请求(改密码、转账、删除)
  2. 检查是否有 CSRF Token / 自定义 Header
  3. 构造表单在另一个页面提交,看是否成功
  4. 检查 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 安全测试左移建议

  1. 需求评审阶段就问:”这个功能涉及哪些敏感数据?谁能操作?”
  2. 测试用例里直接写安全用例,而不是等专项测试
  3. 建立团队安全测试用例库(越权、金额、并发等通用场景)
  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 安全》 中文经典书籍