Skip to content
KitploitKITPLOIT
OutilsExploitsBlog
Log in
Soumettre
OutilsExploitsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

FluxContactConfidentialité© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
pasteguard-PoC — PoC — abus de proxy cross-origin des clés API de fournisseur configurées dans PasteGuard (GHSA-q94x-p9rc-q89f, CVE-2026-86998, CVSS 7.6). | Kitploit
Outils/GitHubGitHub/squeeze440/pasteguard-poc
Analyse des VulnérabilitésExploitationSécurité WebTests d'IntrusionArticles et RechercheSécurité des API
GitHubsqueeze440/pasteguard-poc

pasteguard-PoC

PoC — abus de proxy cross-origin des clés API de fournisseur configurées dans PasteGuard (GHSA-q94x-p9rc-q89f, CVE-2026-86998, CVSS 7.6).

Voir le dépôt
33il y a 1 moisPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

PasteGuard : avis de sécurité

Statut CVE : demandé, en attente d'attribution. Cette découverte est publiée sous GHSA-q94x-p9rc-q89f. Lors de l'attribution de la CVE, ce dépôt sera renommé CVE-YYYY-NNNNN-pasteguard-PoC et cette bannière sera remplacée par le lien CVE.

ChercheurDostxodjayev Abdullox (@squeeze440)
AvisGHSA-q94x-p9rc-q89f
CVSS 3.17.6 (Élevé)
FaiblesseCWE-352, CWE-942

Résumé : L'absence de protection CORS/CSRF sur les routes du proxy LLM dans PasteGuard 0.9.1 permet à un attaquant distant (tout site web visité par le navigateur de l'opérateur, ou tout hôte du réseau local) de déclencher des requêtes authentifiées vers l'API OpenAI/Anthropic configurée par l'opérateur en utilisant la clé API de repli côté serveur de PasteGuard, et de lire la réponse, via un fetch() cross-origin vers /openai/v1/chat/completions (et la route sœur /anthropic/v1/messages).

Produit : PasteGuard (github.com/sgasser/pasteguard)

Version testée : commit 100718191499c52934f3b2ccca72ca16373fb765 (2026-07-30), version package.json 0.9.1

CVSS v3.1 estimé : CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:H — 7.6 (Élevé)

  • UI:R — l'opérateur doit avoir son navigateur ouvert sur une page (n'importe quelle page, sur n'importe quel site) pendant que PasteGuard est en cours d'exécution ; aucune autre interaction n'est nécessaire.
  • C:L / I:L — le JS de l'attaquant ne lit que la réponse à sa propre invite choisie par l'attaquant (pas les conversations/données du tableau de bord précédentes de l'opérateur, qui sont correctement exclues du CORS), mais cela confirme/utilise tout de même un compte actif et financé et pollue la piste d'utilisation/audit du compte sous l'identité de l'opérateur.
  • A:H — l'impact réaliste et non borné : une page attaquante peut boucler cette requête indéfiniment, générant une utilisation réellement facturée sur le compte/quota du fournisseur de l'opérateur (épuisement financier, épuisement possible des limites de débit ou signalements d'abus côté fournisseur) sans limitation de débit ni vérification d'origine pour l'arrêter.
  • S:U — l'impact reste dans la même frontière de confiance (c'est le propre identifiant configuré du proxy qui est utilisé) ; aucune autorité de sécurité distincte n'est franchie.

Détails :

La couche HTTP de PasteGuard applique une politique CORS permissive avec joker à toutes les routes sauf le tableau de bord :

  • src/index.ts:40-45 — const corsMiddleware = cors(); (le cors() de Hono sans options par défaut à Access-Control-Allow-Origin: *) est appliqué via app.use("*", ...) à tout, avec une exception explicite uniquement pour /dashboard et /dashboard/*. Le commentaire juste au-dessus (src/index.ts:34-39) montre que l'auteur a raisonné soigneusement sur l'exposition CORS du tableau de bord mais n'a pas étendu le même raisonnement aux routes du proxy en dessous.
  • src/config.ts:153 — host: z.string().default("0.0.0.0"), confirmé en direct dans config.example.yaml:13. Le proxy écoute sur toutes les interfaces par défaut, pas seulement sur loopback, donc il est également accessible depuis le LAN, pas uniquement depuis le navigateur de l'opérateur.
  • src/providers/openai/client.ts:48-53 :
    // Use client's auth header if provided, otherwise fall back to config
    if (authHeader) {
      headers.Authorization = authHeader;
    } else if (config.api_key) {
      headers.Authorization = `Bearer ${config.api_key}`;
    }
    
    Si la requête entrante ne porte pas d'en-tête Authorization, PasteGuard attache silencieusement sa propre providers.openai.api_key détenue côté serveur à la requête sortante. config.example.yaml:22-24 documente cela comme une fonctionnalité de commodité intentionnelle (« Repli optionnel si le client n'envoie pas d'en-tête d'authentification ») pour le cas d'usage « Apps & APIs ».
  • src/providers/anthropic/client.ts:37-61 implémente le même schéma de repli pour /anthropic/v1/messages (repli x-api-key/Authorization vers config.api_key) — confirmé comme une instance sœur de la même cause racine, non revérifié indépendamment de bout en bout (voir la portée du PoC ci-dessous).

Parce que la politique CORS avec joker se trouve devant des routes qui détiennent cet identifiant de repli, n'importe quelle origine peut (1) faire envoyer par le navigateur la requête sans en-tête Authorization, ce qui amène le serveur à attacher sa propre clé API réelle, et (2) lire la réponse JSON, puisque Access-Control-Allow-Origin: * est présent. Aucune vérification Origin/Referer ni jeton CSRF ne protège ces routes.

Preuve de concept (confirmée dynamiquement, pas seulement tracée statiquement) :

  1. config.yaml configuré avec providers.openai.base_url: http://127.0.0.1:9091 (upstream simulé) et providers.openai.api_key: "sk-VICTIM-SECRET-DO-NOT-LEAK-12345", pii_detection.enabled: false (détecteur simulé /health uniquement, pour éviter d'avoir besoin du service complet du modèle GLiNER), secrets_detection.enabled: false. PasteGuard démarré avec bun run src/index.ts, /health confirmé → 200.
  2. Un upstream simulé (mock_upstream.py) démarré sur 127.0.0.1:9091 qui journalise tout en-tête Authorization qu'il reçoit.
  3. Une véritable page attaquante servie depuis une origine réellement distincte, http://127.0.0.2:8001/attack.html (IP loopback littérale différente, selon les règles d'isolation de site de Chrome — pas un test same-origin localhost), via python3 -m http.server 8001 --bind 127.0.0.2. La seule action de la page au chargement :
    fetch("http://127.0.0.1:3000/openai/v1/chat/completions", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ model: "gpt-4o-mini", messages: [{ role: "user", content: "cross-origin drive-by call, attacker supplied NO api key" }] })
    }).then(r => r.json()).then(data => { /* render on page */ });
    
  4. Une véritable instance Chrome (Chrome DevTools Protocol) pilotée vers http://127.0.0.2:8001/attack.html. Confirmé via l'inspection réseau de DevTools :
    • Requête : origin: http://127.0.0.2:8001, sec-fetch-site: cross-site, aucun en-tête Authorization envoyé par la page attaquante.
    • Réponse : access-control-allow-origin: *, HTTP 200, corps JSON entièrement lisible par le JS de la page attaquante.
    • Page rendue : « CROSS-ORIGIN READ SUCCEEDED. Response body visible to attacker JS: ... » — capture d'écran : ../evidence/cross_origin_csrf_success.png.
    • Journal de l'upstream simulé pour cette requête exacte : RECEIVED AUTH HEADER: Bearer sk-VICTIM-SECRET-DO-NOT-LEAK-12345 — prouvant que PasteGuard a attaché la clé réelle configurée de l'opérateur côté serveur, sans que la page attaquante ne l'ait jamais connue ni fournie.

Preuves brutes : ~/engagements/pasteguard/evidence/cross_origin_csrf_success.png, ~/engagements/pasteguard/evidence/mock_upstream_log.txt.

La route /anthropic/v1/messages a été confirmée statiquement (fichier:ligne ci-dessus) comme partageant le même schéma de repli + CORS avec joker, mais n'a pas été relancée séparément via le PoC navigateur en direct, dans l'intérêt de la profondeur plutôt que de l'étendue / de la règle des 5 minutes de la session, une fois la cause racine déjà confirmée sur /openai.

Télécharger l’outil