Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [AJAX] Zabezpieczenie przed wywołaniem spoza aplikacji
Forum PHP.pl > Forum > XML, AJAX
nu_moon
Witam!

Zrobilem sobie calkiem fajna aplikacje na bazie Ajaxa i wszystko pieknie dziala.
Zaczalem tez na sile starac sie zepsuc aplikacje od strony uzytkownika, zanim wystawie ja publicznie smile.gif

Jedna rzecz (w sumie kosmetyczna) - czy mozna w jakis sposob zabezpieczyc strony wywolywane za pomoca ajaxa ?
Tzn chodzi o to ze np. majac pliki ktore za jego pomoca sa pobierane (np. zanjduja sie w katalogu ax/skrypt.php), zostana wywolane bezposrednio z pzregladarki produkuja dosc nie-ladny stzrep HTML'a lub tekstu.

Da sie to w jakis sposob zabezpieczyc ?
Od strony serwera nie bardzo chyba jest taka mozliwosc, bo żądanie przychodzi z IP klienta.
Od strony aplikacji - hm jedyne co mi przyszlo do glowy to inicjowac zmienna sesyjna po wejsciu na strone w sposob "normalny" i wypluwac output w zaleznosci czy jest ona juz ustawiona czy nie...

Jakies inne roziwzania ? czy moze sobie odpuscic ?
nospor
Pytanie podstawowe: po co? Co cie obchodzi ze jakis losiek podejrzy adres ajaxa i wpisze go recznie do przegladarki? Dostanie cos, brzydkie nie brzydkie, ale co cie to obchodzi?
Ja tez namietnie uzywam ajaxa i jesli jakis adres moze wykonac ajax to i na upartego mozna go wykonac bezposrednio w przegladarce. No to co smile.gif

edit:
zeby nie bylo ze pisze nia na temato to jeszcze dopisze:
Cytat
Od strony aplikacji - hm jedyne co mi przyszlo do glowy to inicjowac zmienna sesyjna po wejsciu na strone w sposob "normalny" i wypluwac output w zaleznosci czy jest ona juz ustawiona czy nie...

To nic nie da. Wejde na strone, sesja zostanie ustawiona, i teraz sobie twoj link z palca wpisze w przegladarke i juz mam dostep.
Sabistik
Tak jak napisał nospor nie ma po co. Możesz jednak sprawdzać nagłówki przychodzących żądań czy jest to xmlhttprequest, jeśli nie to exit(). Oczywiście to nie jest nie wiadomo jaki problem ustawić taki nagłówek ręcznie.
piotrf
Metoda isXmlHttpRequest sprawdza czy "żądanie jest ajaxowe"

Kod
    public function getHeader($header)
    {
        if (empty($header)) {
            require_once 'Zend/Controller/Request/Exception.php';
            throw new Zend_Controller_Request_Exception('Error');
        }

        $temp = 'HTTP_' . strtoupper(str_replace('-', '_', $header));
        if (!empty($_SERVER[$temp])) {
            return $_SERVER[$temp];
        }

        if (function_exists('apache_request_headers')) {
            $headers = apache_request_headers();
            if (!empty($headers[$header])) {
                return $headers[$header];
            }
        }

        return false;
    }

    public function isXmlHttpRequest()
    {
        return ($this->getHeader('X_REQUESTED_WITH') == 'XMLHttpRequest');
    }
pp-layouts
Trochę nie w czas, ale jakby kto do wątku wrócił...

Przed chwilą robiłem coś takiego u siebie. Proste do bólu, a na pytanie "po co zabezpieczać": nie trzeba być geniuszem, żeby się domyśleć, że można mieć np. prywatną, kupioną bazę danych, której nie chce się udostępniać wszystkim jak leci. Przecież napisać skrypt który wyciąga całą bazę z czyjegoś niezabezpieczonego AJAXA jest barszczowo łatwo.

Temat był wiele razy opisywany na tym forum ale podsumuję wrzucając moje krótkie i banalnie proste rozwiązanie:

W skrypcie głównym wrzucamy coś takiego:

Kod
  session_start();
  $_SESSION['_' . session_id()] = null; // wysyłamy unikalny klucz w sesji


W skrypcie wywoływanym AJAX-em coś takiego:

Kod
  if ($_SERVER['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest') { // wywołanie AJAXEM?
    session_start();
    $acc = array_key_exists('_' . session_id(), $_SESSION); // kluczyk jest?
  }
  if (!$acc) {
    header('HTTP/1.1 403 Forbidden'); // grzeczny header dla botów
    exit('Akwizytorom dziękujemy!'); // przyjazny komunikat dla nieproszonych gości
  }


I pozamiatane. Musisz zhackować mechanizm sesji w PHP żeby to obejść. Zaletą tego rozwiązania jest, oprócz absolutnie minimalnego obciążenia serwera, że klucz przesyłany w sesji jest unikalny, tzn nie ma żadnej możliwości, żeby nadpisał jakąkolwiek inną zmienną sesyjną. Dodatkowo jego wartość jest nieistotna. Ustawiłem ją dodatkowo na null, żeby łatwiej ją było ignorować w funkcjach operujących na całej tablicy $_POST.

Quantum
a co się stanie jeżeli odpalę główny skrypt przez cURL, ciastko zapisze, później odwołam się do skryptu AJAX-a dodatkowo przesyłając nagłówek HTTP_X_REQUESTED_WITH jako XMLHttpRequest + ciacho z ID sesji ? winksmiley.jpg
Istalacar
pp-layouts: zamiast bawić się w wysyłanie id sesji i zmienianie jej co chwilę raczej wprowadził bym zabezpieczenie przed odczytaniem więcej niż X wpisów z bazy w ciągu danego czasu, dla danego IP. Twoje zabezpieczenie odstraszy dzieciaki, ale pokonanie go to kwestia kilku więcej linijek kodu.
pp-layouts
Mistrzu, proszę Cię, powiedz mi, jak to złamać? Jeśli to złamiesz, masz złamane wszelkiej maści strony php z logowaniem oparte na sesjach. Hm, pehapowcy się raczej nie zajmują włamami a raczej zabezpieczaniem, więc możesz mechanizm zdradzić, to pomogłoby wielu ludziom poprawić swoje zabezpieczenia.

A propos zabezpieczania limitem na odczyty z bazy, w ten sposób mógłbym strzelić sobie samobója, bo wyobraź sobie "wykop efekt" na mojej aplikacji. Trochę rzeczywistego ruchu i leży. Tym bardziej, że to w końcu AJAX, czyli odpala się w momencie kiedy ktoś w aplikacji wpisuje ostatnią literę kodu.

Ostatnia sprawa, dlaczego mówisz o zmienianiu sesji? Sesja jest jedna, bezczasowa, czyli ważna do zamknięcia przeglądarki. Utworzona w najprostszy możliwy sposób. W tej samej sesji trzymam też cały stan aplikacji, czyli aktualnie wybrane opcje, zakładki, podstrony, okienka i takie tam.

Przy okazji przyłapałem się na błędzie, mój przykładowy kod nie będzie działał. W częsci wywoływanej z AJAX-a należy dodać przed session_start() jeszcze session_id($_COOKIE['SESSION_NAME']). W sumie nie wiem czemu przedwczoraj mi to śmigało, a dzisiaj już nie. W każdym razie po tej przeróbce działa.

Co do łamania, próbowałem na swoim serwerze, w innym katalogu odpalić skrypt, w którym próbowałem rozpocząć sesję z przechwyconym ID. Nie działał. Więc nie mam pomysłu, jak możnaby to obejść.

nospor
Cytat
Proste do bólu, a na pytanie "po co zabezpieczać": nie trzeba być geniuszem, żeby się domyśleć, że można mieć np. prywatną, kupioną bazę danych, której nie chce się udostępniać wszystkim jak leci.
Ale slyszales o czyms takim jak autoryzacja? Jak ktos sie zaloguje to co za roznica czy pobierze dane ajaxem czy bezposrednio. smile.gif
pp-layouts
Hm, baza ma być dostępna bez logowania. Takie jest założenie. To jest formularz dla klienta który nie musi się jeszcze w tym momencie logować. Baza uzupełnia dane, które klient wpisuje. Dane są ogólnie jawne, ale nie chcę wystawiać interfejsu do całej tabeli, żeby sobie ktoś tego zwyczajnie nie skopiował. Albo nie podłączył się do tego swoim skryptem.

Powiedzmy że masz bazę "książka telefoniczna". Każdy klient, bez logowania może sobie sprawdzić numer. Ale nie chcemy, żeby ktokolwiek zgrywał sobie całą książkę, ani też nie chcemy żeby ktoś zrobił sobie taką książkę na swojej stronie, używając naszej bazy. Jeśli mam zabezpieczenie sesją, to tak długo dopóki ktoś nie złamie mechanizmu zabezpieczenia sesji php i nie przejmie sesji - nie jest w stanie nic wyciągnąć zewnętrznym skryptem.

W wielu poważnych aplikacjach webowych znalazłem dziury pozwalające na podkradanie danych z niepublicznych baz. Niektóre były tak przyjazne, że pozwalały na proste zapytanie via get zwracając xml. W mojej aplikacji ten numer nie przejdzie.

nospor
no i ok, mozna dodac te proste i banalne zabezpieczenia na ajaxa co ty dales, ale to jest nadal proste i banalne zabezpieczenie, które jest do obejscia. przyklad dostales pare postow wczesniej. smile.gif
seth-kk
Cytat(nospor @ 9.09.2009, 11:20:49 ) *
...ale to jest nadal proste i banalne zabezpieczenie, które jest do obejscia...

a czy http pozwala na budowanie bezpiecznych rozwiazan?
jak dla mnie takie zabezpieczenia maja troche sensu (a przynajmniej dopuki dane warte sa protekcji) gdyz zawezaja grono potencjalnych interesantow, ale gdyby zamiast przesylac ciagle ten sam klucz modyfikowac go dla kazdego requesta...
nospor
Cytat
jak dla mnie takie zabezpieczenia maja troche sensu (a przynajmniej dopuki dane warte sa protekcji)
ale jaka protekcja? Sek w tym ze to zabezpieczenie to zadna protekcja...
Uchroni jedynie przed lamerem co bedzie chciał dla hecy wpisac w pasku przeglądarki to co wysyla ajax i to tyle z zabezpieczen.
Jak bedzie chciał wykraść "hakier", ktoremu te dane będą potrzebne to obejdzie to w 5 minut.
seth-kk
hmm jednorazowy klucz powinien wydluzyc te przyslowiowe 5 min i wyeliminowac ludzi ktorzy podpisuja sie pod 'posklejanymi kawalkami kodu'
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.