Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [Ajax][PHP] Bezpieczeństwo skryptów
Forum PHP.pl > Inne > Oceny
Quantum
Witam, od jakiegoś czasu zacząłem stosować AJAX'a w swoich projektach.
Chciałbym zabezpieczyć plik PHP w ten sposób, aby zwracał dane tylko dla mojego skryptu, a po wejściu do tego pliku z zewnątrz (np: http://snifferwebpage.awardspace.biz/data.php) zwracał błąd.
Napisałem małe zabezpieczenie, ale chciałbym, żeby ktoś z Was je przetestował smile.gif
BTW. sam próbowałem je ominąć, przy wykorzystaniu cURL'a na innym serwerze, ale się nie udało.

Link: http://snifferwebpage.awardspace.biz/

Pozdrawiam, sniff smile.gif
zegarek84
tzn. co jest zabezpieczone?? - a jeśli tak miało być to gratuluję winksmiley.jpg - wchodzę na link niżej do strony głównej i nic mi się nie wyświetla dodatkowego jak klikam pierwszy czy drugi buton - a że jestem już wstawiony po kilku głębszych to kodu nie analizuję ;p - ale zanim przeczytałem do końca temat miałem tylko proponować jak to zabezpieczyć jednocześnie nadmieniając, że danych ajax/js nie da się zabezpieczyć w pełni!!!! - ale Tobie widzę się to udało gdyz danych nie mogę pobrać winksmiley.jpg - sorki za ten czarny chumor ale drinken drinken - szczerze nawet nie wiem co ma się pobrać winksmiley.jpg a takie aplikacje po stronie klijenta nigdy nie zabezpieczysz na 100% - jedynie możesz filtrować co najwyżej tych co zauważysz, że nadużywają pewnej funkcjonalności - lub nie wiem jak często aplikacja ma pobierać dane ale jesli nie aż tak często to coś w stylu zabezpieczenia przed floodowaniem możesz urzyć winksmiley.jpg

i napisz co tam miało sie wyświetlić ;p winksmiley.jpg
Quantum
Jak widzisz po wciśnięciu przycisku "pobierz dane1" lub "pobierz dane2", ajax wysyła żądanie do pliku data.php o zwrot danych, w tym przypadku dane1 = 'to są dane 1', dane2 = 'to są dane 2' biggrin.gif
Ten skrypt ma za zadanie blokować wyświetlenie tych danych przez inne skrypty napisane przez osoby z zewnątrz.

BTW. Jak to mówią, "Nie chwal dnia przed zachodem słońca" tongue.gif Jak znam życie, znajdzie się ktoś kto to ominie.
marcio
Z tego co widzialem za pomoca firebug'a i livehttpheaders to zmieniajac naglowki moze dalbym rade cos zdzialac ale najpierw musialbym pokombinowac z curlem by zobaczyc jak skrypt sie zachowuje jak bede mial troche czasu to cos pokombinuje tongue.gif
Fishu
Ostatnio też myślałem, o bezpieczeństwie takich skryptów, a tu taki temacik smile.gif No na początek widać, że zabezpieczenie działa. Tylko jest taki mały problemik. Zrobiłeś w pliku php warunek sprawdzający url ? Bo wpisując przykładowo http://snifferwebpage.awardspace.biz/?var=test nic nie wypisuje ;p
Quantum
Cytat
Ostatnio też myślałem, o bezpieczeństwie takich skryptów, a tu taki temacik smile.gif No na początek widać, że zabezpieczenie działa. Tylko jest taki mały problemik. Zrobiłeś w pliku php warunek sprawdzający url ? Bo wpisując przykładowo http://snifferwebpage.awardspace.biz/?var=test nic nie wypisuje ;p


Błąd w skrypcie tongue.gif Poprawione smile.gif
zegarek84
hehe - masz tam jakieś zabezpieczenie przed floodowaniem czy tylko skrypt nie wyrobił przy pętli 100?? - co drugie średnio 50% wyskoczyły błędy - ale dane bez problemu się pobierają - swoją drogą coś jest nie tak bo i w przeglądarce jak za często i za szybko klikałem te przyciski to się wykolejało i potem nie zmieeee^^ - pozatym do zapytań ajax'owych mógłbyś dorzucić jakąś pamięć - pomysł na zabezpieczenie fajny - np to z liczbą znaków

w sumie to mógłbyś pobrać przez takie pseudo zabezpieczenie dopiero główniejszy skrypt co tym by się zajmował jakiś trudniejszy - no hoć jak się nagłówki sprawdzi to pod wszystko da się podszyć - ps. do czego jest to xmlhttp.setRequestHeader("Connection", "close");questionmark.gif - tzn podejrzewałem ale nagłówki były wysłąne w przeglądarce i tak:
Connection: keep-alive
Keep-Alive: 300


w każdym bądź razie jeśli logowałęś ilość zapytań z jednego ip to weisz że to nie zabezpieczenie dla kogoś kto coś trochu pisze - ale lepszy rydz jak nic winksmiley.jpg - swoją drogą już myślałem że jednak coś konkretnego jest z tym zabezpieczeniem bo jest weekend i dzisiaj też trochu chlupnąłem ale jak się okazało katalog dla skryptu nie miał praw zapisu i ja na fazie patrzałem gdzie literówkę zrobiłem

ale przyznaję, że dosyć ciekawy pomysł na zabezpieczenie winksmiley.jpg - zapamiętam - moze trochu zmodyfikuję i pewnie wykożystam w przyszłości winksmiley.jpg

oki - jest to przydługawe bo mi się teraz myśleć nie chciało to tylko funkcje kopiowałem i modyfikowałem ale jeśli miałbyś nie wierzyć [wiem - brzydki kod ale co chcesz od kogoś co jest na fazie - skopiowałem tylko fragment z kodu co po pijanemu analizowałem serwisz podbij )
Kod
<?php


// strona
function strona($url){
$ch = curl_init();curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
$headers = array(    'Keep-Alive: 300',
            'Accept-Language: pl,en-us;q=0.7,en;q=0.3',
            'Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7',
            
            
            'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'
            
            );
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.5) Gecko/2008121300 SUSE/3.0.5-0.1 Firefox/3.0.5');


curl_setopt($ch, CURLOPT_HEADER, 0);
// gzip
curl_setopt($ch, CURLOPT_ENCODING, 'gzip');
// deflate
curl_setopt($ch, CURLOPT_ENCODING, 'deflate');
// gzip, deflate
curl_setopt($ch, CURLOPT_ENCODING, '');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

curl_setopt($ch, CURLOPT_COOKIEFILE, dirname(__FILE__) . '/cookies.txt');
curl_setopt($ch, CURLOPT_COOKIEJAR, dirname(__FILE__) . '/cookies.txt');
$tresc=curl_exec($ch); if(curl_errno($ch)){echo 'Błąd #'.curl_errno($ch).': '.curl_error($ch);}
curl_close($ch);
return $tresc;
unset($tresc);
};



// reqID
function reqID($url){
$ch = curl_init();curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
$headers = array(    'Host: snifferwebpage.awardspace.biz',
            'Keep-Alive: 300',
            'Accept-Language: pl,en-us;q=0.7,en;q=0.3',
            'Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7',
            
            'POST /data.php HTTP/1.1',
            'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
            'Content-Type: application/x-www-form-urlencoded',
            'Content-Length: 9',
            'Keep-Alive: 300',
            'Cache-Control: no-cache',
            'Pragma: no-cache',
            'Connection: keep-alive'
            );
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.5) Gecko/2008121300 SUSE/3.0.5-0.1 Firefox/3.0.5');
curl_setopt($ch, CURLOPT_POST, 1);//przesylamy metodą post
curl_setopt($ch, CURLOPT_POSTFIELDS, 'reqID=get'); //dane do wyslania
curl_setopt($ch, CURLOPT_REFERER, 'http://snifferwebpage.awardspace.biz/');
curl_setopt($ch, CURLOPT_FORBID_REUSE, true);

curl_setopt($ch, CURLOPT_HEADER, 0);
// gzip
curl_setopt($ch, CURLOPT_ENCODING, 'gzip');
// deflate
curl_setopt($ch, CURLOPT_ENCODING, 'deflate');
// gzip, deflate
curl_setopt($ch, CURLOPT_ENCODING, '');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

curl_setopt($ch, CURLOPT_COOKIEFILE, dirname(__FILE__) . '/cookies.txt');
curl_setopt($ch, CURLOPT_COOKIEJAR, dirname(__FILE__) . '/cookies.txt');
$tresc=curl_exec($ch); if(curl_errno($ch)){echo 'Błąd #'.curl_errno($ch).': '.curl_error($ch);}
curl_close($ch);
return $tresc;
unset($tresc);
};





// dane
function dane($ktore,$url){
$ch = curl_init();curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
$headers = array(    'Host: snifferwebpage.awardspace.biz',
            'Keep-Alive: 300',
            'Accept-Language: pl,en-us;q=0.7,en;q=0.3',
            'Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7',
            
            'POST /data.php HTTP/1.1',
            'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
            'Content-Type: application/x-www-form-urlencoded',
            'Keep-Alive: 300',
            'Cache-Control: no-cache',
            'Pragma: no-cache',
            'Connection: keep-alive',
            'Content-Length: 44'
            );
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.5) Gecko/2008121300 SUSE/3.0.5-0.1 Firefox/3.0.5');
curl_setopt($ch, CURLOPT_POST, 1);//przesylamy metodą post
curl_setopt($ch, CURLOPT_POSTFIELDS, 'dane='.$ktore.'&sess='.reqID($url)); //dane do wyslania
curl_setopt($ch, CURLOPT_REFERER, 'http://snifferwebpage.awardspace.biz/');

curl_setopt($ch, CURLOPT_HEADER, 0);
// gzip
curl_setopt($ch, CURLOPT_ENCODING, 'gzip');
// deflate
curl_setopt($ch, CURLOPT_ENCODING, 'deflate');
// gzip, deflate
curl_setopt($ch, CURLOPT_ENCODING, '');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

curl_setopt($ch, CURLOPT_COOKIEFILE, dirname(__FILE__) . '/cookies.txt');
curl_setopt($ch, CURLOPT_COOKIEJAR, dirname(__FILE__) . '/cookies.txt');
$tresc=curl_exec($ch); if(curl_errno($ch)){echo 'Błąd #'.curl_errno($ch).': '.curl_error($ch);}
curl_close($ch);
return $tresc;
unset($tresc);
};

strona('http://snifferwebpage.awardspace.biz/');
// echo '<pre>'.reqID('http://snifferwebpage.awardspace.biz/data.php').'</pre>';
for ($i=1;$i<7;++$i){$ktore=($i%2)+1;
echo $i.' : '.dane($ktore,'http://snifferwebpage.awardspace.biz/data.php').'<br/>';}

?>


ps. co niektórzy boty piszą też w js jako userscript i parametry do serwera swojego przekazują - a więc to co na stronie wtedy jest jak na talerzu podane winksmiley.jpg - tyle, że musi mieć przeglądarkę włączoną ^^
Quantum
Cytat
hehe - masz tam jakieś zabezpieczenie przed floodowaniem czy tylko skrypt nie wyrobił przy pętli 100?? - co drugie średnio 50% wyskoczyły błędy - ale dane bez problemu się pobierają - swoją drogą coś jest nie tak bo i w przeglądarce jak za często i za szybko klikałem te przyciski to się wykolejało i potem nie zmieeee^^


Ten serwer jest darmowy, a darmowy znaczy wolny jak.. tongue.gif Dlatego wykłada się na zbyt częstych requestach. Przymierzam się teraz do wykupienia serwera na hostnine.com pod linuxem, mają dość ciekawą ofertę.

Cytat
oki - jest to przydługawe bo mi się teraz myśleć nie chciało to tylko funkcje kopiowałem i modyfikowałem ale jeśli miałbyś nie wierzyć [wiem - brzydki kod ale co chcesz od kogoś co jest na fazie - skopiowałem tylko fragment z kodu co po pijanemu analizowałem serwisz podbij )


Twój kod w porównaniu do mojego jest wyjątkowo przejrzysty i zrozumiały tongue.gif

A wracając do sprawy, skopiowałem twój kod, wrzuciłem na inny serwer wspierający cURL, lecz po odpaleniu uzyskałem taki efekt :

Kod
1 : Błąd 403 ! Dostęp zabroniony !
        
  2 : Błąd 403 ! Dostęp zabroniony !
        
  3 : Błąd 403 ! Dostęp zabroniony !
        
  4 : Błąd 403 ! Dostęp zabroniony !
        
  5 : Błąd 403 ! Dostęp zabroniony !
        
  6 : Błąd 403 ! Dostęp zabroniony !

Mógłbyś mi wytłumaczyć co jest nie tak? biggrin.gif A i czy jest jakiś sposób, żeby pobieranie naszego "sessid" nie kończyło się na wysłaniu do serwera metodą POST reqID=get ? bo jak widać sesji użyć nie można bo właśnie mamy ją pobrać tongue.gif

BTW. Pracuję już nad nowym zabezpieczeniem, bo moja strona, która ma za jakieś 2 miesiące powstać musi przetrwać nawet atak nuklearny tongue.gif
zegarek84
a dałeś w katalogu uprawnienia do zapisu skryptom?? - na localhoście to hula bez problemu winksmiley.jpg

i przecież chyba sprawdzasz też cookies??

i nie da się tego w pełni zabezpieczyć (tzn możesz dorzucić logowanie ale logowanie akurat tutaj do skryptu jest chyba odrazu po wejściu na stronę?? - to cookies?? - przynajmniej odrazu tą drogą szłem)...

można jeszcze na kilka sposobów jedynie utrudnić algorytm tej sesji czy jak to jest - np. sam pomysl z długością ciągu jest niezły - ale skoro już jest ten mechanizm to dlaczego stała długość ciągu?? - czy sesja nie może mieć różnej długości?? - akurat ta moim zdaniem może....

Cytat
A i czy jest jakiś sposób, żeby pobieranie naszego "sessid" nie kończyło się na wysłaniu do serwera metodą POST reqID=get ?

taki może trochę głupi pomysł ale można by obmysleć jakiś algorytm matematyczny przeliczający sesję z cookies do jakiejś cyfry matematycznej i zamiast tego reqID=get dać reqID=[fragment cookies] - dzięki czemu każda nowo otwarta strona miała by inny request - ale to wiadomo, ze jesli kod js bedzie czytelny i oczywisty to i to zabezpieczenie będzie łatwo obejść....

to co chcesz wyświetlić nie da się ukryć po prostu przed światem - co innego z bezpieczeństwem że ktoś ci psikusa zrobi - ale ukraść dane zawsze może ktoś co trochu wie winksmiley.jpg
Quantum
W 1 wersji było coś takiego, że dla reqID, generowało 3 zmienne, ich suma nie mogła przekroczyć sumy liczb odpowiedników znaków unicode wylosowanego ciągu znaków, niestety nie mam już tego skryptu, ale nie chcę mi się już go na nowo pisać tongue.gif
Stwierdziłem, że jest to w sumie bezsensowne rozwiązanie można to zrobić w php przy użyciu chr(), ord() i odwołać sie cURL'em jak to wcześniej zrobiłeś.

Mój nowy pomysł to:

1. Zamiast: sess = [hash], będzie: [losowy ciag znakow zakodowany w md5] = [hash].
2. Losowy identyfikator dla diva lub pola input, w którym zapisywana jest aktualna sesja.
3. Sesja wywoływana co ustalony okres czasu, przez setInterval.

Co o tym myślisz ? winksmiley.jpg
zegarek84
wszystko ok i już trudniej - ale jak już napisałem gożej jak ktoś załapie co z czego się bierze bo jednak dane początkowe są na stronie - tyle tylko że taki gościu jak już pisałem nie zhakuje innych kont a jedynie się zaloguje i na inny serwis walnie wiadomości automatycznie - jedyne co możesz zrobić to spróbować wymyślić jak najtrudniejszy algorytm (co nie zmieni faktu, że i tak dane bez js będzie się dało pobrać) - jednak też nad sposobem za bardzo nie myśl bo czasem tak można zakrecić algorytm że nie zauważy sie iż dużo krótszą drogą można go obejść...

no i jak pisałem kod js końcowy niech już będzie trochu sieczką i nie oczywiste nazwy zmiennych - ale to kod końcowy - jednak czytelny też sobie zostaw w archiwum winksmiley.jpg
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.