-- 普通认证逻辑漏洞 --
验证绕过/利用
验证形式
- 图形验证码:
生成图形的二进制数据(通常是base64加密后的)同时生成 跟验证码绑定的token 并返回(通过参数/Cookie),
验证时只有 提交token和 对应图形中的字符串 才可验证通过 - 滑块验证码:
生成 带缺口的背景图 滑块图, 同时生成 跟验证码绑定的token 并返回(通过参数/Cookie),
前端计算并提交 token 和 用户拖动滑块过程中采集位置、时间、行为特征(判断是否符合人类操作规律)等数据,
全部通过才可验证成功 - 手机/邮箱验证码:
向手机/邮箱发送短信, 并返回与该消息绑定的token(通过参数/Cookie),
验证时只有 提交token和 对应短信内容 才可验证通过 (注: 有时无token),
有时验证是和后续业务功能(如注册/重置密码)是用的同一个接口,
有时是验证接口验证通过后, 返回通过标识(Cookie/参数/认证头), 后续业务接口会验证该标识 - 密码验证
输入正确的账户与密码才可通过验证(账户可能是用Cookie标识, 或直接传参数)
有时验证是和后续业务功能(如重置密码)是用的同一个接口,
有时是验证接口验证通过后, 返回通过标识(Cookie/参数/认证头), 后续业务接口会验证该标识
图形验证码绕过
- 可复用: 认证错误/成功后token和验证码未失效, 所以可以复用
- 回显验证码内容: 生成验证码的接口会回显验证码内容
密码验证绕过
- 通过标识通用
情景: 验证接口验证通过后, 返回通过标识(Cookie/参数/认证头), 后续业务接口会验证该标识时
后续业务接口只验证 通过标识是否存在, 而不验证 通过标识是否来源于对应账户(即未与账户绑定),
导致后续业务接口 可以使用其它账户的 验证通过标识, 从而绕过验证 - 无效验证:
情景: 验证接口验证通过后, 才会调用实际的业务接口(如重置密码), 但实际业务接口可以直接调用而无需验证 - 爆破: 当站点没有限制必须使用复杂密码 且无最大错误次数时, 可通过暴力破解账户的密码
- 空密码登录: 由于密码校验存在漏洞, 可以通过空密码/0来进行登录
手机/邮箱验证码绕过
- token通用:
情景: 验证逻辑是-验证是和后续业务功能(如注册/重置密码)是用的同一个接口时,
接口只验证token是否与短信内容匹配, 而不验证token是否来源于对应手机/邮箱(即token未与手机/邮箱绑定),
从而可以利用其它手机/邮箱的短信内容和token 绕过验证 - 通过标识通用
情景: 验证接口验证通过后, 返回通过标识(Cookie/参数/认证头), 后续业务接口会验证该标识时
后续业务接口只验证 通过标识是否存在, 而不验证 通过标识是否来源于对应手机/邮箱(即未与手机/邮箱绑定),
导致后续业务接口 可以使用其它手机/邮箱的验证通过标识, 从而绕过验证 - 无效验证:
情景: 验证接口验证通过后, 才会调用实际的业务接口(如登录/注册), 但实际业务接口可以直接调用而无需验证 - 验证可爆破(未设置最大错误次数):
由于验证码验证时未设置最大错误次数/错误后不弃用, 且验证码简单(如四位数验证码), 所以可以爆破来猜解验证码 - 可发送多个目标
可同时选择多个目标发送验证码, 且此时可能会给二者发送同样的验证码, 从而绕过
常见格式: phone=13888888888,13999999999 phone=13888888888&13999999999 - 邮箱验证码发可猜解链接
对于发送的是链接的验证码, 通过用户点击链接来判定邮箱, 一般是通过get参数的值/复杂路由是否正确来判断,
若这个get参数/路由可猜解(如传送的是用户的uuid或者时间戳), 即可绕过邮箱检测 - 回显验证码内容: 发送验证码的接口会回显验证码内容
手机/邮箱短信轰炸
- 简介: 由于验证码可连续发送, 所以可以短信轰炸指定 电话/邮箱(每分钟15条以上为漏洞)
- 绕过:
高并发绕过: 通过高并发的方式, 使得一次性发送大量的短信绕过
杂字符绕过: 电话加上空格 @ 逗号 /r /n +86 86 086 0086 字母 0 00等进行绕过
大小写绕过: 对于邮箱, @后的内容可大小写,example@Qq.cOm
不同功能绕过: 可能不同功能的验证码CD不统一计算, 可通过改变 用于指定功能的参数的值/更换功能点 来绕过
删除cookie值绕过: 有些接口是根据Cookie来判断是否短时间内访问的, 通过删除cookie即可绕过
修改IP绕过: 有些接口是对当前IP进行显示, 通过使用代理池来绕过
登录
- 暴力破解: 当站点没有限制必须使用复杂密码时, 可通过暴力破解账户的密码
注: 若有图形/滑块验证码则看是否能绕过, 或者是不是先验证账号密码 再校验验证码
注: 若有做大错误次数, 则固定密码去爆破用户名 - 密码通过GET参数传输: 密码通过GET参数传输, 会被记录在日志中 且存在中间人攻击的风险
- 会话固定攻击
会话标识在登录后未更新, 而是更新会话标识对应的权限,
导致可以通过让受害者使用攻击者给予的会话标识来登录, 从而使用相同会话标识来 获取受害者权限 - 账户枚举: 由于账号存在与否响应不同, 导致可以判断哪些账号存在, 哪些不存在
- 空密码登录: 由于密码校验存在漏洞, 可以通过空密码/0来进行登录
注册
- 任意用户注册: 验证可绕过(比如手机/邮箱验证码可绕过), 或没有校验用户的真实信息(如只需要输入手机号/邮箱号而无需验证即可注册成功), 导致可以注册任意用户
- 覆盖注册: 可以注册已有账户(相同手机/邮箱/昵称), 从而可以覆盖原账户
注: 有些站点在点击注册按钮时, 可能会前端调用查询接口查询是否存在用户, 若存在则不调用注册接口, 但实际注册接口可以进行覆盖注册 - 账号枚举: 由于账号存在与否响应不同, 导致可以判断哪些账号存在, 哪些不存在
忘记密码
- 任意密码重置: 由于验证可绕过(比如手机/邮箱验证码可绕过, 旧密码验证可绕过), 导致可以重置任意账户
- 账户枚举: 由于账号存在与否响应不同, 导致可以判断哪些账号存在, 哪些不存在
-- 单点登录SSO --
简介
- 概念: 存在多个相互信任的应用系统中, 只需要认证一次, 就可以访问这些所有的应用系统
- 认证中心: 通常情况下单点登录存在一个认证中心
- 信任该认证中心的应用系统 会让用户 跳转到认证中心 进行认证(并携带类似redirect的get参数)
- 认证完成后再跳转到 原来的应用系统(即跳转回redirect指定的url)
- 实现-同域: 即当多个应用系统(包括认证中心)分别是 同一个主域名下的 不同子域名时
- 认证中心认证后 分发的Cookie的domain域属性 设置为主域名, 使得在访问 这些应用系统时 也会带上该Cookie
- 同时认证中心的Session 和这些信任的应用系统 进行共享, 从而实单点登录
- 实现-不同域: 同域也可使用
- 认证中心认证后 返回一个token(可能是Cookie, 也可能是其它类型的凭证), 携带该token跳转回原来的应用系统
- 认证中心存在认证token有效性的接口, 信任的应用系统接收token后, 携带token向该接口发起请求, 来验证token是否有效, 并获取token对应用户的信息
- 验证成功后, 应用系统将登录状态写入session并设置Cookie
-- 多因素认证MFA --
简介
- 概念: 为了提高登录的安全性, 要求用户进行两种及以上的认证才可完成登录
- 常见认证类型: 账户密码 手机/邮箱验证码OTP 安全问题答案 指纹/人脸/声纹 动态令牌TOTP(steam 腾讯云)
- 状态令牌: 通常情况下 多因素认证 会在因素一认证后 发放一个状态令牌, 用于代表因素一认证通过, 只有携带该状态令牌才可进行下一因素认证
多因素认证绕过
- 密码重置: 许多系统在密码重置后会自动登录, 若此时密码重置的认证比登录的认证还要简单, 则可通过密码重置绕过
防御: 1.密码重置不自动登录 2.密码重置认证设置的比登录难 - 状态令牌可混用:
当账号1的状态令牌在因素二认证时, 可以通过账号2携带该状态令牌来认证 从而成功登录时;
若登录上的是状态令牌 对应的账号, 则可绕过账号1的 因素二认证;
若登录上的是因素二认证 使用的账号, 则可绕过账号2的 因素一认证;
防御: 1.状态令牌不允许其它账号携带进行认证 2.在因素二认证时再进行一次因素一的认证
-- OAuth2 --
- 基础 -
简介
- 概念: OAuth是一种授权框架, 允许 网站/应用 申请 另一个网站/应用上用户 的有限访问权限
例子: 微信/QQ扫描第三方登录 - 认证流程(通用)
客户端请求授权: 客户端应用(如"百度") 向资源所有者(用户) 申请访问其在第三方平台(如"微信") 的特定资源(如用户头像、邮箱), 申请中需明确客户端身份、访问范围等信息
用户批准授权: 用户通过授权服务器(第三方平台的认证系统)的界面, 明确同意或拒绝客户端的访问请求, 若同意, 授权服务器会生成"授权证据"(如授权码/证书等) 并返回给客户端
客户端获取访问令牌: 客户端将用户的"授权证据"提交给授权服务器, 同时验证自身身份(如通过client_secret, 但若为公开客户端, 则无需提供client_secret), 授权服务器验证通过后, 发放访问令牌(Access Token)
客户端访问资源: 客户端携带访问令牌访问资源服务器(存储用户数据的服务器), 资源服务器验证令牌有效性/权限后, 返回相应数据 - 认证模式:
OAuth定义了多种授权类型, 其中 授权码模式 和 隐式授权类型(已过时, 设计初衷是用于纯前端页面) 最常用 - 机密客户端/公开客户端
授权码模式中可处理 机密客户端和公开客户端
公开客户端对比机密客户端的区别在于 其通常不可存储client_secret, 或存储可能会存在很大的泄露风险
公开客户端常见于 纯前端页面(无法存储client_secret) APP(因为安装包可被反编译, client_secret容易泄露)
授权码模式(机密客户端)
- 客户端请求授权: 客户端向授权服务器的
/authorization端点发送GET请求,
如/authorization?client_id=<客户端在授权服务器注册的唯一标识>&redirect_uri=<授权成功后跳转URL>&scope=<申请访问信息的范围>&state=<客户端生成的随机值(防CSRF)>&response_type=code(代表使用授权码模式) - 用户登录与授权: 授权服务器将用户重定向到登录页面, 用户输入第三方平台(如微信)的账号密码登录, 并在授权界面确认是否允许客户端访问请求的资源(如 “百度请求获取你的头像和昵称”)
- 授权服务器返回授权码: 用户同意授权后, 授权服务器将用户浏览器重定向到
redirect_uri指定的回调地址, 并在 URL中携带 授权码(code) 和 state参数, 通过用户携带访问的方式, 将授权码和state传给客户端 (此时客户端应该检测state是否与之前的相同从而防止CSRF) - 客户端用授权码换访问令牌: 客户端 向授权服务器的
/token端点发送 POST请求, 提交授权码、客户端身份凭证(client_id和client_secret,后者为客户端注册时生成的密钥), 请求换取访问令牌, 换取后授权码会立即失效
如POST请求/tokenclient_id=xxx&client_secret=xxx&redirect_uri=<跳转的url>&code=<授权码>&grant_type=authorization_code(代表使用授权码换访问令牌) - 授权服务器返回访问令牌: 响应返回access_token给客户端, 后端通过将access_token 放在Authorization头中可以向资源服务器申请资源 (整个过程用户无法得知access_token)
响应格式如{ "access_token": "xxx", "token_type": "Bearer", "expires_in": 3600, "scope": "openid profile" }
授权码模式(公开客户端)
- 客户端请求授权: 相同, 需多加两个参数
code_challenge=<PKCE挑战码,是对code_verifier哈希后的值>&code_challenge_method=S256(哈希算法) - 用户登录与授权: 相同
- 授权服务器返回授权码: 相同
- 客户端用授权码换访问令牌: 相同, 但无需提供client_secret参数, 需提供code_verifier参数, 授权服务器会校验 该参数值用code_challenge_method中的算法哈希后 与之前提交code_challenge是否相同
- 授权服务器返回访问令牌: 相同
隐式授权类型
- 客户端请求授权: 与授权码模式相同, response_type需改为token
- 用户登录与授权: 与授权码模式相同
- 授权服务器直接返回访问令牌: 用户同意授权后, 授权服务器直接返回令牌, 存储在用户的前端页面(一般存储在
localStorage/sessionStorage) - 前端提取令牌并访问资源: 通过前端脚本 从URL片段中提取访问令牌, 随后用户携带令牌(通过将access_token放在Authorization头)向资源服务器请求数据, 用户将数据发送给客户端
- 漏洞 -
授权码劫持
- 简介: 授权服务器漏洞, 当redirect_uri未校验时, 可通过修改伪造 客户端的网站来钓鱼获取授权码(redirect_uri就指向钓鱼网站), 或者直接发送带有恶意redirect_uri的链接让别人点击并授权 来获取授权码
- 绕过
///www.gh0st.com//.. ///www.gh0st.com//../ /https:/gh0st.com/ //www.gh0st.com//.. //www.gh0st.com
/www.gh0st.com //gh0st.com https://www.xxx.com/www.gh0st.com http://www.xxx.com.gh0st.com
http://gh0st.cn:80#@xxx.com http://www.xxx.com@gh0st.com http://www.xxx.com#gh0st.com
http://www.xxx.com?gh0st.com http://www.xxx.comgh0st.com http://www.xxx.comgh0st.com - 修复: 授权服务器 redirect_uri使用白名单进行匹配过滤
- 注: 这只能获取授权码, 授权码的进一步利用则 需要获取客户端的client_id/client_secret(机密客户端), 知道code_verifier(公开客户端)
CSRF绑定劫持
- 简介: 客户端漏洞, 对于类似绑定qq/微信的功能点, 当客户端不使用/校验state参数时, 此时攻击者可发送 带有自己的qq/微信授权码的 换取访问令牌的请求链接, 点击后受害者账号就会绑定攻击者QQ与微信
- 修复: 客户端 校验state参数是否与用户会话存储的state相同, 再进行绑定
- 注: 对于OAuth2, state参数是可选的, 但某些授权服务器会强制使用state参数, 否则会拒绝请求
隐式授权
- 简介:
客户端漏洞, 隐式授权已过时, 而且其设计初衷是用于 纯前端页面,
若用于带有后端的页面, 则客户端 要不让用户提交token到客户端(还不如用授权码),
要不让用户自行向授权服务器申请数据然后将数据提交给客户端(没法校验数据是否正确),
若token前端存储(localStorage/sessionStorage), 也可 XSS 脚本窃取 - 修复: 不使用隐式授权的方式, 改为授权码(公开客户端)的形式
其它
- 授权码重复使用: 授权服务器漏洞, 授权码应一次性有效且短期有效, 否则可能会因授权码泄露而导致用户信息泄露
- client_secret泄露: 客户端漏洞, 可伪造合法客户端, 用授权码向授权服务器请求access_token/refresh_token
- access_token泄露: 可访问授权服务器资源
- refresh_token泄露: 可重新申请access_token