Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Bezpieczeństwo skryptów PHP
Forum PHP.pl > Forum > PHP
Stron: 1, 2, 3, 4, 5, 6, 7
hind
regułka w mod_rewrite żeby wszystko przekierowywało na (np.) index.php a w nim readfile() (+ inne śmiecie do wyświetlania mime)
bełdzio
tyle, że samym readfile też można sporo namieszać smile.gif tak więc też trzeba zrobić to z głową
hind
Owszem, może ale wystarczy dodać sprawdzanie nazwy pliku/katalogu i po problemie. Lub też mieć nazwy plików w bazie a w tedy odwoływać się do plików poprzez id.
i najważniejsze, katalog z plikami nie dostępny z zewnątrz.

przy złej implementacji "najwyżej" ktoś pobierze spobie konfigurację do bazy danych i parę innych plików/danych smile.gif
Spawnm
Hey,
co to za rodzaj ataku że komuś się dolepia do strony:
/strona.php?page=php://input
Z logów mi wynika że od pewnego czasu ktoś mnie ciągle tym częstuje ...
hind
zobacz sobie raw post data, php://input zawiera niesparsowane dane przesłane na serwer poprzez post
Spawnm
hey,
powiedzcie jak się zabezpieczacie przed atakami na usera typu [img=mojastrona.pl/ct/act?delete=id_czegos_danego_usera ?
Niby powinno wystarczyć danie w bootstrapie takiego kodu:
  1. if($_GET){
  2. //czy jest ref ?
  3. if(isset($_GET['delete']) && !isset($_SERVER['HTTP_REFERER'])){
  4. }
  5.  
  6. //czy ref to nasza strona ?
  7. if(isset($_GET['delete'])){
  8. $host = parse_url($_SERVER['HTTP_REFERER']);
  9. $host = $host['host'];
  10. $local = $_SERVER['HTTP_HOST'];
  11. if($host !== $local ){
  12. }
  13. }
  14. }

Ale czy to aby na 100% zapewni nam bezpieczeństwo?
Co jeszcze dajecie aby czuć się bezpieczniej?
Crozin
A co jeśli wyłączę sobie wysyłanie nagłówka REFERER?

1. Akcje dodaj, usuń, edytuj, przenieś itp. powinny być wykonywane metodą POST.
2. Niezależnie od metody używaj jednorazowego, unikalnego tokenu.
3. CSRF.
wookieb
1) Wysłanie postem
2) Wymagany dodatkowy losowy klucz w parametrze $_GET (generowany na stronie poprzedniej i np zapisywany w sesji)
3) Przy bardzo wrażliwych danych ponowne zalogowanie
4) To z refererem też jest niegłupie
batman
1. Wysyłaj dane postem (słabe zabezpieczenie).
2. Operacje mogące spowodować jakiekolwiek szkody - weryfikacja przy pomocy tokena.
3. Operacje mogące spowodować duże szkody - wymaganie podania hasła.
Chillout
A czy nie dałoby radę zabezpieczyć plików przed potencjalnym hax0rem w .htaccess? coś typu Disallow from all i dać sobie dostęp tylko do plików na IP które mogą zaszkodzić stronie tongue.gif w sumie zabezpieczaniu jestem na początkowym stanie, ale ostatnio sprawdzałem u kumpla czy może wbić w dany plik i wyskoczyło mu że nie ma dostępu :]. Fakt że hax0r będzie szukał głębiej, nie mniej jednak i tak to jest jakieś zabezpieczenie już.
pyro
Cytat(Chillout @ 25.01.2011, 00:57:39 ) *
A czy nie dałoby radę zabezpieczyć plików przed potencjalnym hax0rem w .htaccess? coś typu Disallow from all i dać sobie dostęp tylko do plików na IP które mogą zaszkodzić stronie tongue.gif w sumie zabezpieczaniu jestem na początkowym stanie, ale ostatnio sprawdzałem u kumpla czy może wbić w dany plik i wyskoczyło mu że nie ma dostępu :]. Fakt że hax0r będzie szukał głębiej, nie mniej jednak i tak to jest jakieś zabezpieczenie już.


A nie lepiej się po prostu normalnie zabezpieczyć sprawdzonymi sposobami? Szczerze nie rozumiem po co ludzie tak kombinują.

(A tak nawiasem to o czym Ty piszesz jest zupełnie bez sensu na stronę www)
ZuyPan
Tak sobie czytam i czytam ten temat i doszedłem to następujących wniosków:

* Jeśli już robić wczytywanie podstron za pomocą include to owe podstrony muszą być w osobnym katalogu:
  1. if(is_file('/katalog/'.$_GET[strona].'.php')){
  2. include ('/katalog/'.$_GET[strona].'.php');
  3. }


* Zawsze filtruje się wszystkie tablice $_GET, $_POST, $_SESSION, $_COOKIE

* Jeśli coś ma być int to dajemy
if(is_int($_GET['liczba'])){
$liczba = $_GET['liczba'];
}

* Jeśli coś jest tekstem to robimy:
$tekst = mysql_real_escape_string($_POST['tekst'];

* Sprawdzamy długość wpisanych danych

* jeśli coś ma być emailem to sprawdzamy poprawność tego co zostało wpisane.

Czy tych kilka zabezpieczeń jest skutecznych? Może ja coś źle rozumiem. I takie pytanie: jeśli tekst filtruje mysql_real_escape_string to nie muszę używać addslashes, htmlspecialchars itd? Ta funkcja chyba mnie odpowiednio zabezpiecza?
erix
A może by tak przeczytać CAŁY temat i nie siać herezji, zwłaszcza z bezpośrednim wstawianiem wartości z tablicy $_GET?
ZuyPan
Przeczytałem cały temat, ale uwierz mi - te wasze małe "sprzeczki" gdzie ktoś mówi, że bredzicie a potem Wy staracie się udowodnić coś manualem... Z tego tematu stał się śmietnik a nie poradnik. Ktoś taki jak ja wchodzi, czyta i ma jeszcze większy mętlik bo ktoś powiedział o czymś tak a jeszcze inny inaczej. Tylko któraś z tych opinii jest słuszna a któraś błędna. To może warto by było zostawić tylko te słuszne? Temat zmniejszył by się o co najmniej kilka stron. Tylko komu by się chciało....
pyro
Cytat(ZuyPan @ 26.07.2011, 12:26:47 ) *
Tak sobie czytam i czytam ten temat i doszedłem to następujących wniosków:

* Jeśli już robić wczytywanie podstron za pomocą include to owe podstrony muszą być w osobnym katalogu:
  1. if(is_file('/katalog/'.$_GET[strona].'.php')){
  2. include ('/katalog/'.$_GET[strona].'.php');
  3. }


Jeśli chcesz, żeby ktoś włamał Ci się na stronę to tak.

Cytat(ZuyPan @ 26.07.2011, 12:26:47 ) *
* Zawsze filtruje się wszystkie tablice $_GET, $_POST, $_SESSION, $_COOKIE


Nie. Nie zawsze. Według potrzeb.

Cytat(ZuyPan @ 26.07.2011, 12:26:47 ) *
* Jeśli coś ma być int to dajemy
if(is_int($_GET['liczba'])){
$liczba = $_GET['liczba'];
}


Lub po prostu:
  1. $liczba = (int)$_GET['liczba'];


Cytat(ZuyPan @ 26.07.2011, 12:26:47 ) *
* Jeśli coś jest tekstem to robimy:
$tekst = mysql_real_escape_string($_POST['tekst'];


Też w zależności od sytuacji.

Cytat(ZuyPan @ 26.07.2011, 12:26:47 ) *
* Sprawdzamy długość wpisanych danych


To nie jest warunek, ale dobrze to robić.

Cytat(ZuyPan @ 26.07.2011, 12:26:47 ) *
* jeśli coś ma być emailem to sprawdzamy poprawność tego co zostało wpisane.


Jak prawie wszędzie...

Cytat(ZuyPan @ 26.07.2011, 12:26:47 ) *
I takie pytanie: jeśli tekst filtruje mysql_real_escape_string to nie muszę używać addslashes, htmlspecialchars itd?


A może przeczytaj co robi ta i pozostałe wymienione funkcje...
evilpr0
A ja mam takie pytanko, co z takim kodem?

  1. if($_GET['akcja'] == "uzytkownicy") {
  2. include('uzytkownicy.php');
  3. }


Czy taki kod również jest niebezpieczny?
foxmark
Cytat(Speedy @ 5.05.2005, 17:06:27 ) *
To ja dodam od siebie jeszcze, że niektóre osoby pisząc aplikacje internetowe, stosują coś takiego jak przechowywanie poufnych danych o userze (po zalogowaniu) w pliku cookie. Taki potencjalny H4X0R może sobie potem swobodnie przeglądać zawartość tych plików i dowolnie je modyfikować. Najgorzej jest wtedy, gdy w takim pliku przechowywana jest wartość zmiennej odpowiedzialna np. za uprawnienia administratora... Wtedy wystarczy ją odpowiednio podmienić i śmiga wink.gif .
Rozwiązaniem są sesje, które przechowują dane na serwerze.

Pozdrawiam.



Witam,

Dwa pytania.

Pyt. 1: Jestem w poczatkowej fazie projektu i zastanawiam sie nad mozliwymi rozwiazaniami kontroli praw uzytkownikow.
To moj pierwszy projekt w ktorym musze identyfikowac uzytkownika i dodatkowo nadac mu prawa do robienia tego czy tamtego.
Po autoryzacji uzytkownika sprawdzam w DB czy i do jakiej grupy nalezy dany uzytkownik (uzywam LDAP do autentyfikacji uzytkowniak wiec ten problem mi odpada bo ta czesc jest wymuszana zasadami bezpieczenstwa w sieci lokalnej i musze wspolpracowac z administratorem sieci odnosnie autentyfikacji). Moje pytanie jest nastepujace:
Czy ktos moze podac mi przyklady tego jak nalezy konstruowac logike takiej strony. jak sprawdzac czy dana grupa moze uzywac danej finkcji
lub miec dostep do danego linku itp? Jakie rozwiazanie jest najbardziej dynamiczne i efektywne.
Moze ktos zna inne rozwiazania nie bazujace na grupach (np. przywileje do wykonywania dannych czynnosci)
Mysle np. o tym jak w jednym pliku (np. menu.php) zawierac informacje dla wszystkich grup ale podaczas includowania pliku wyswietlcic tylko
linki dla danej grupy uzytkownikow (i/lub linki dla grup ponizej danego lewelu) tzn. ze adminstrator zobaczy wszystkie linki trenerow, userow itp
a trener zobaczy link trenerow i usera ale nie administratorow.

Pyt. 2: Chcialbym w sesji zapisac informacje o nazwie uzytkownika i jego grupie (Admin, user itp) czy istnieje mozliwosc ze znajac
nazwe zmiennej mozna zewnatrznie podmieniac jej wartosc - czyli np.
  1.  
  2. $_SESSION['user'] = costam;
  3. $_SESSION['ugroupID'] = costam;


i przypisac im inne wartosci jesli tak jak moge sie przed tym zabezpieczyc?
Nie obawiam sie problemow z loginem bo pracuje w sieci lokalnej dostepnej tylko w jednym budynku
Uzywam LDAP do autoryzacji uzytkownika ale boje sie ze zwyczjany uzytkownik moze chciac podmienic swoje prawa i dac sobie
uprawnienia administratora po tym jak przypisze sesji jego uprawniania

Pozdrawiam!
adam882
@evilpr0
Twój kod jest OK
Orzeszekk
A co jezeli includujemy pliki bezposrednio uzywajac wartosci get, i pliki includowane znajduja sie w oddzielnym katalogu, ale ktos bedzie sprytny i poda nam w GET sciezke /../../costamcostam.php? /.. - powinno nas przeniesc do katalogu niżej.

Jesli juz ktos koniecznie chce brac bezposrednio z GET to musi regexpem wykasowac te znaki z parametru.

Ja tam jestem zwolennikiem białej listy: kazda klasa ktora includuje pliki / uruchamia metody w php funkcją call() biorąc jako parametr parametr z $_GET, korzysta z białej listy (listy dozwolonych wartosci parametru). Taką listę mozna sobie bardzo szybko utworzyc za pomocą array('parametr_1','parametr_2')... a sprawdzic poprawnosc za pomocą

$naszParametr = htmlspecialchars($_GET['param']);
if (!(in_array($naszParametr, $tablicaDozwolonychWartosci))
{
/* Parametr nieprawidlowy, nie znaleziono na liscie, ustawiamy mu tutaj wartosc domyslna lub zatrzymujemy program */
}
/* od tego momentu mozemy uwazac wartosc w $naszParametr za poprawną */
include($naszParametr) / call($naszParametr);


itd itp tongue.gif
biała lista jest znacznie bezpieczniejsza od czarnej listy czy w ogole niesprawdzania poprawnosci bo chroni cie tez przed tym czego nie możesz przewidzieć smile.gif
by_ikar
Cytat
Jesli juz ktos koniecznie chce brac bezposrednio z GET to musi regexpem wykasowac te znaki z parametru.


Nie musi, do tego celu wystarczy jedna funkcja, basename i powyżej danego katalogu już niestety poruszać się nie będzie mógł wink.gif
rumpelek
uFF... minęło 30 minut od kiedy zacząłem czytać temat... i w zasadzie się zgubiłem... Więc może ja zapytam, czy mój kod jest poprawny i ewentualnie jak go "zabezpieczyć"

  1. if(isset($_GET['zmienna'])){
  2. $przed = array("\"", "\'", "\\", ">", "<", " ", "%", "_", "&", "#", "0", "9", "2", ";", ":", "/", "$", "GET", "_", "[", "]");
  3. $po = array("", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "");
  4. $zmienna = str_replace($przed, $po, $_GET['zmienna']);
  5. }else{
  6. $zmienna='pusta';
  7. }


Bardzo proszę o konkretne wskazówki...
wookieb
Przed tym to ma zabezpieczać? Tutaj jedynie ucinasz sobie szereg funkcjonalności z GET-a zamiast rozważnie pisać kod (a to nie jest takie trudne)
rumpelek
no ma zabezpieczać przed atakiem... szeroko rozumianym... gdybym był pewnie na Twoim poziomie wiedzy, to bym tak banalnych pytań nie zadawał... Jeśli mam jakoś bardziej doprecyzować to powiedz jak, a na pewno udzielę odpowiedzi bo jestem żywnie zainteresowany tym, aby moja aplikacja była bezpieczna...

zmienne są różne niektóre numeryczne inne tekstowe...

na podstawie tej zmiennej ładuję np. pliki konfiguracyjne dla danej strony... np.

http://www.adres.pl/index.php?zmienna=nazwafirmy

na podstawie tego ładuję pliki

  1. include("$nazwafirmy/config.php");


dlaczego tak? ano dlatego, że obsługuję programem kilka firm i jak wprowadzam zmiany to w plikach skryptu ogólnego... i nie muszę tego robić oddzielnie w każdym katalogu...

  1. echo "\n<link rel=\"stylesheet\" type=\"text/css\" href=\"$nazwafirmy/style.css\" />";


np. dzięki temu rozwiązaniu ładuję plik css... i każda strona może wyglądać inaczej ale pracować na tym samym "silniku" smile.gif

vee
swoją drogą zamiast pisać tak:
  1. $po = array("", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "");
  2. $zmienna = str_replace($przed, $po, $_GET['zmienna']);

możesz zrobić
  1. $zmienna = str_replace($przed, null, $_GET['zmienna']);


to taki mały OT. CO do zabezpieczenia... tak jak mówił kolega powyżej - zdecydowanie łatwiej i skuteczniej jest pisać rozważnie kod, zamiast stosować takie "myki".
Inna sprawa, powinieneś określić jaki zestaw znaków dopuszczasz dla tej zmiennej i odfiltrować to wyrażeniami regularnymi moim zdaniem, tzn np dopuszczać same litery, cyfry i myślnik.

EDIT: Gwoli ścisłości, podane wskazówki raczej nie mają wpływu na bezpieczeństwo, ale na wygodę obsługi.

Pozdrawiam i powodzenia
marcio
Elo co stosujecie przed csrf i full path disclosure?

Co do pierwszego zastanawiam sie nad tokenami w url lub przez post (pole typu hidden).

Co do tego drugiego co stosujecie?error_reporting(0) to racej obejcie problemu niz jego likwidacja.
Stosujecie wlasne klasy obslugi bledow?
erix
Cytat
Elo co stosujecie przed csrf

Bez tokenów raczej nie przejdzie, aby było uniwersalne.

Cytat
Co do tego drugiego co stosujecie?error_reporting(0) to racej obejcie problemu niz jego likwidacja.

Niczego nie stosuję. Proces interpretera odpalam z chrootem.
marcio
Cytat
Niczego nie stosuję. Proces interpretera odpalam z chrootem

Dla mniej wtajemniczonych?
erix
Dla mniej wtajemniczonych jest Google i Wikipedia, której wystarczy użyć: http://pl.wikipedia.org/wiki/Chroot
marcinek37
Kilka ostatnich dni spędziłem na analizie tego, co wcześniej pisano na forum i tego, co pisano w artykułach na innych stronach.
Było kilka niejasnych pomysłów na zabezpieczenie strony stąd kilka moich pytań.

1. wielokrotnie mówiono, że dobrym zabezpieczeniem przed CSRF jest dodawanie do ważnych linków tokena - mam jednak pytanie, czy optymalnym rozwiązaniem jest, aby taki token był nadawany przy logowaniu i był on aktywny aż do czasu trwania sesji, czy za każdym razem koniecznie musi być nadawany nowy token? pytam, bo w przypadku drugiego rozwiązania będę mieć o wiele więcej pracy

2. czy koniecznie muszę filtrować nawet dane z tablicy SERVER?
przykład zapytania:
mysql_query("INSERT INTO tabela (`id`, `ip`) VALUES(NULL, '$_SERVER[REMOTE_ADDR]')");

3. znalazłem taki kod, który zabezpiecza system przed Session Fixation i Session Hijacking, jednak po jego użyciu mój system logowania nie działa poprawnie
wg mnie to największy problem, bo jeśli ktoś przejmie moją sesję, przejmę całkowitą kontrolę nad systemem i będzie mógł zrobić niemal wszystko
  1. <?
  2. if (!isset($_SESSION['inicjuj']))
  3. {
  4. $_SESSION['inicjuj'] = true;
  5. $_SESSION['ip'] = $_SERVER['REMOTE_ADDR'];
  6. }
  7.  
  8.  
  9. if($_SESSION['ip'] !== $_SERVER['REMOTE_ADDR'])
  10. {
  11. die('Proba przejecia sesji udaremniona!');
  12. }
  13. ?>


4. aby zabezpieczyć się przed dodawaniem identyfikatora sesji do adresu www, należy dodać kod:
session.use_only_cookies = 1

tyle że do którego pliku i w jaki sposób?

5. to samo tyczy się poniższego kodu, który należy dodać do .htacces:
php_value session.use_only_cookies 1
php_value session.use_trans_sid 0

ale gdy go dodaje, pojawia się błąd

6. znalazłem też informację, że warto regenerować identyfikator sesji przy każdym odświeżeniu (session_regenerate_id( )wink.gif, ale rodzi to problem - co, jeśli użytkownik otworzy stronę w dwóch oknach? wtedy w jednym zostanie wylogowany

7. czy dodatkowym zabezpieczeniem może być nadanie chmodu 600 na plik config?

8. aby hasło użytkowników było bezpieczne, przy rejestracji postanowiłem skorzystać ze schematu:
HASH = md5( sól systemowa [16 znaków] + md5(hasło użytkownika) + idywidualna sól nadana dla użytkownika zapisana w bazie [16 znaków] )

czy myślę dobrze, że jest to bezpieczne, bo, nawet jeśli ktoś ukradnie nam dane, nie zna soli systemowej (zapisanej w config), a jeśli wejdzie w posiadanie systemu, nie będzie znać soli przypisanej do użytkownika
polecano mi PHPass, ale wolę to zrobić tym sposobem, jeśli uznacie to za bezpieczne

9. czy naprawdę do sesji warto dodać identyfikator użytkownika (czyli ID, np. 123), jego IP oraz przeglądarkę? kod:
  1. <?
  2. if(isset($_SESSION['user_id']) && $_SESSION['user_agent'] == $_SERVER['HTTP_USER_AGENT'] && $_SESSION['user_ip'] == $_SERVER['REMOTE_ADDR']){
  3. echo'zalogowany';
  4. }
  5. else{
  6. echo'niezalogowany';
  7. }
  8. ?>


10. czy przy autologowaniu do ciastka powinienem dodać ID użytkownika oraz HASH, o którym mowa w punkcie 8? czy to aby na pewno bezpieczne?
hind
1. powinno być za każdym razem generowane z osobna
2. $_SERVER['HTTP_USER_AGENT'] zawiera dane potencjalnie niebezpieczne.
4. php.ini lub ini_set()
6. ni zostanie, chyba że otwarcie obu stron nastąpi w tym samym momencie.
7. i tak i nie, bo to proces httpd/cgi ma odczytać ten plik i uprawnienia muszą być dostosowane do uprawnień procesu wykonującego (choć zwykle jest to root/httpd)
9. sesja powinna być unikalna, więc ID jest nie potrzebne
10. jak przy 9.
marcinek37
1. rozumiem, szkoda
2. to dla pewności lepiej wszystkie zmienne z $_SERVER sprawdzę
3. [brak odpowiedzi]
4. działa
5. [brak odpowiedzi]
6. faktycznie, działa prawidłowo - czy zatem to jest najlepsze zabezpieczenie przed kradzieżą identyfikatora sesji, czy może jeszcze coś warto zrobić?
7. nie rozumiem, możesz troszkę jaśniej? który chmod będzie najbezpieczniejszy, skoro config jest jedynie includowany przez silniczek
8. [brak odpowiedzi]
9. tworzy się sesja i jedną z ich wartości jest 'user_id', system sprawdza, czy jest użytkownik o podanym ID i ładuje od niego informacje, jeśli bym do bazy zapisywał ID sesji, to bym zaraz go stracił, skoro używam session_regenerate_id() - chyba że po zalogowaniu się będziemy tworzyć w sesji unikalny 'hash', który będzie stały po odświeżeniach i jego wartość zapiszemy w bazie - ale w sumie co za różnica, ID usera to żadna tajemnica
10. [proszę o ponowną odpowiedź w związku z prowadzoną dyskusją w punkcie 9]
erix
  1. za każdym razem. Bo wystarczy, że komuś podeślesz (przypadkiem) raz linka i potem Ci odsyła kuku.
  2. wszystko, co pochodzi od użyszkodnika, jest złe. Sodoma i Gomora. Nawet, jeśli uważasz, że jest dobry. Jest zły, będziesz spał spokojniej z takim założeniem.
  3. tylko że to zawiedzie w przypadku NAT-a...
  4. i tak za pierwszym razem SID musi zostać wysłany przez parametr w żądaniu, bo ciastko zostanie wysłane do serwera dopiero za drugim razem.
  5. Cytat
    ale gdy go dodaje, pojawia się błąd

    Szklana kula rozwalona.
  6. dla mnie, to już poziom=paranoid... jak masz zabezpieczenie przed CSRF, to to nie ma sensu...
  7. zależy od uprawnień i serwera - jeśli proces PHP jest uruchamiany z Twoimi uprawnieniami - jak najbardziej, takie uprawnienie jest nawet wskazane. Wyjątek: sytuacja, gdy plik musi zostać zaczytany przez httpd, wtedy grupie nadajesz uprawnienia do odczytu.
  8. nie hashuj hasha! Sól doklejaj, ale nie rób z tego hasha. Dlaczego? Jest przyklejony wątek o podwójnym hashowaniu haseł. PHPass jest o tyle lepsze, że wolniejsze. A im wolniejszy hash, tym lepiej, bo wykonanie ataku brute-force jest trudniejsze.
  9. generalnie im więcej danych, które pozwalają użytkownika zidentyfikować, tym lepiej.
  10. ~hind, przejmę SID, wgram do siebie ciasteczko o odpowiedniej wartości i co, mogę sobie przejąć ot tak zawartość Twojej sesji?
hind
10. jak przejmiesz SID to co za problem (głównie ataki XSS i inne robactwo systemowe)?
Jedyne co w tym wypadku pozostaje to sprawdzanie danych dodatkowych jak adres IP (zmienny), przeglądarka internetowa, czy inne parametry, ale to wszystko i tak można przejąć.

Inna sprawa że autologowanie można ograniczyć do jednego komputera (tylko na jednym komputerze autologowanie) + regeneracja klucza autologowania.
A jeszcze lepsza opcja to prośba o podanie hasła przy ważniejszych zmianach.

ogólnie nie widzę żadnej możliwości zabezpieczenia się przed wykorzystaniem przejętego SID (wygoda VS bezpieczeństwo).
erix
Cytat
Jedyne co w tym wypadku pozostaje to sprawdzanie danych dodatkowych jak adres IP (zmienny), przeglądarka internetowa, czy inne parametry, ale to wszystko i tak można przejąć.

Połącz to sobie z JS, localStorage, w którym generujesz jakieś losowe tokeny, które są dolepiane do każdego żądania.
hind
Najlepiej jakby każda otwarta karta miała swój własny identyfikator, a do tego każde użycie sesji zliczane. Ale to tylko umożliwia zabezpieczenie przed przejęciem.

Ale jak skutecznie zabezpieczyć autologowanie?
(sprawdzanie IP, przeglądarki, danych JS jak localStorage, geolokacja, e-tagi, certyfikat, czy jeszcze jakieś inne możliwości)
marcinek37
1. wyjaśnione

2. wyjaśnione

3.
Cytat(erix @ 25.10.2012, 13:24:24 ) *
tylko że to zawiedzie w przypadku NAT-a...


zatem w jaki sposób mogę zabezpieczyć się przed przejęciem SID? bo w tym momencie, wystarczy, że ktoś pozna SID i robi ze stroną co mu się podoba...
moim jedynym pomysłem jest to, aby w sesji zapisać także jego IP, przeglądarkę - jeśli te dane nie będą się zgadzać, sesja zostanie zlikwidowana - drążę w dobrym kierunku?
czy wg Ciebie w tablicy $_SERVER są jeszcze jakieś dane, które warto zapisać i potem sprawdzić, czy aby na pewno ten, kto posiada SID, jest do tego upoważniony?

4.
Cytat(erix @ 25.10.2012, 13:24:24 ) *
i tak za pierwszym razem SID musi zostać wysłany przez parametr w żądaniu, bo ciastko zostanie wysłane do serwera dopiero za drugim razem.


czy mógłbyś rozwinąć myśl? czy sugerujesz, że mimo to problem istnieje? jeśli tak, masz pomysł, aby jemu zaradzić?

5. ten .htaccess chyba mogę zignorować, skoro działa ten kod:
  1. <?
  2. ini_set('session.use_only_cookies', 1);
  3. ?>


o którym mowa w punkcie 4.

6. zatem zrezygnuję z regeneracji SID

7. czyli ustawię chmod 600, a jeśli system przestanie działać, zmienię chmod na 666 - dobrze myślę?

8. właśnie cały przyklejony temat dotyczący hashowania przeczytałem uważnie i nie rozumiem, dlaczego mój pomysł jest zły - do hasła doklejam sól aż dwukrotnie (systemową i indywidualną) i dopiero wtedy przepuszczam przez md5, wklejam ponownie schemat z drobną zmianą:
HASH = md5( sól systemowa [16 znaków] + hasło użytkownika + idywidualna sól nadana dla użytkownika zapisana w bazie [16 znaków] )

nie jestem kryptologiem, ale jaka jest szansa, że ktoś znając chociaż jedną sól, może shakować hasło, skoro nie zna drugiej soli - czy ktoś łopatologicznie może mi to wyjaśnić

9.
Cytat(erix @ 25.10.2012, 13:24:24 ) *
generalnie im więcej danych, które pozwalają użytkownika zidentyfikować, tym lepiej


i też tak właśnie myślę, i tutaj ponawiam pytanie: jakie dane z tablicy $_SERVER mogę jeszcze wyciągnąć i zapisać w sesji - najlepiej, jeśli to możliwe - podaj proszę nazwy pól, np. "user_agent"

10. to może po wybraniu opcji "autologowanie" wyśle się ciastko z hashem, o którym mowa w punkcie 8, oraz ID usera
jeśli user wejdzie na stronę po tygodniu, system sprawdzi, czy jest takie ciastko, poszuka usera o podanym ID oraz hashem i wtedy porówna aktualne dane z tablicy $_SERVER z tymi, które przy logowaniu zostały zapisane w bazie danych, tj. "user_agent", "remote_addr" (+ te, które mam nadzieję ktoś poda w ramach pkt 9.) - tylko tworzy to pewien problem, bo jeśli ktoś ma zmienne IP, autologowanie nie nastąpi
Damonsson
Nie wiem czy dobrze zrozumiałem, ale chodzi o to, żeby zamiast $_SESSION['userId'] zapisywać $_SESSION['hashGenerowanyZUserId']? Po co?

I przy okazji mam jedno pytanie, na które każdy odpowiada inaczej, można w końcu manipulować danymi przechowywanymi w zmiennej sesyjnej czy też nie można? np. $_SESSION['czyAdmin']?
Pomijając kwiatki typu $_SESSION['czyAdmin'] = $_POST['jakiespole'] gdzieś w kodzie.
CuteOne
Legendy głoszą, że na serwerach współdzielonych, można było "podkradać" pliki sesji innych użytkowników danego serwera
d3ut3r
To zależy od konfiguracji serwera, ale generalnie local session hijacking to nie legenda smile.gif Wszystko opiera się na założeniu, że serwer składuje dane sesji w katalogu np. /tmp do którego dostęp jest globalny dla shared hostingu, przy takiej konfiguracji możesz sobie te pliki odczytać. Przynajmniej takie jest założenie.

Proste doświadczenie, uruchom skrypt:

  1. $files=(array)glob(session_save_path().'/*');
  2.  
  3. if (count($files)>0){
  4.  
  5. foreach ($files as $k=>$file){
  6.  
  7. $fileName=basename($file);
  8.  
  9. if (substr($fileName,0,5)=='sess_'){
  10.  
  11. $session_id=substr($fileName,5);
  12.  
  13. echo 'Dump for: '.$session_id.'<br />';
  14. var_dump(file_get_contents($files[$k]));
  15.  
  16. }
  17.  
  18. }
  19. }


naprzykład na xamppie i spokojnie sobie odczytasz wszystkie pliki sesji.
marcinek37
kwestią zabezpieczeń serwera chyba nie muszę się martwić, bo mam wykupiony serwer u porządnej firmy - z tego co wiem przynajmniej

czy ktoś może odpowiedzieć na moje pytania?
szczególnie na pytania: 3 (jak zabezpieczyć się przed kradzieżą sesji), 8, 9, 10
d3ut3r
Moim zdaniem jeżeli twoja strona będzie odporna na XSS dodatkowo masz regenerację id sesji i porządnie skonfigurowany serwer to jedyną opcją na przejęcie session_id jest bezmyślne podanie go komuś, jednak przed głupotą się nie uchronisz. Jeżeli masz taką możliwość użyj SSL.

Zabezpieczenie z IP jest jakimś rozwiązaniem, jednak ma swoje ograniczenia ktoś już wspominał o NAT.
Damonsson
Załóżmy, że session_regenerate_id się nie wywołało i ktoś przejął moje aktualne PHPSESSID z ciastka.
Kiedy będzie chciał się podać za mnie, to wtedy przy session_start, zrobi się session_regenerate_id(true) i jeśli np. ip będzie różne to session_destroy.
Wszystko ładnie, on się nie zaloguje. Ale jednocześnie session_destroy będzie też dotyczyć Bogu ducha winnego mnie, więc będę musiał się znowu zalogować. Jest na to jakiś sposób, aby nie wiem, niszczyło jemu sesję i zmieniało PHPSESSID, a mnie nadawało nowy PHPSESSID z wartościami sesji, takimi jakie miałem ?
hind
Nie ma takiej możliwości, chyba że umiesz w magiczny sposób rozpoznać kto jest prawidłowym właścicielem sesji. A tak to najbezpieczniej wywalić obu.
marcinek37
ok, więc skoro nie ma możliwości przed zabezpieczeniem się przed kradzieżą sesji, to czy ktoś może mi pomóc z punktami: 8, 9, 10?
CuteOne
Na twoim miejscu zamiast wymyślać koło na nowo(z możliwością popełnienia błędów) zobacz w gotowe skrypty np. tego forum IP.Board
jaslanin
2. adresów IP raczej nie powinno się przechowywać jako string tylko jako int
8. szybkie algorytmy hash'ujące nie są zalecane do przechowywania haseł, bo chcesz właśnie żeby atakujący musiał poświęcić dużo zasobów do odkrycia stringa odpowiadającego hash'owi. Tu masz to opisane:

http://php.net/manual/en/faq.passwords.php
https://www.owasp.org/index.php/Password_Storage_Cheat_Sheet
marcinek37
czy reasumując:
1. nie ma możliwości, aby napisać system w ten sposób, aby za jego pośrednictwem ktoś mógł wykraść sesję i ją wykorzystać
2. szybkie hashowanie jest niebezpieczne, bo jeśli ktoś ukradnie mi hash i pozna sól systemową i indywidualną dla użytkownika, będzie mógł poznać hasło (tyle że najpierw musi poznać obie sole)
3. przy logowaniu do sesji mam zapisać jak najwięcej danych, które się z nim będą identyfikowały, prócz adresu IP, bo ktoś może mieć zmienny adres
4. autologowanie jest niebezpieczne i lepiej go nie robić
jaslanin
Cytat
1. nie ma możliwości, aby napisać system w ten sposób, aby za jego pośrednictwem ktoś mógł wykraść sesję i ją wykorzystać


Można, wystarczy mieć luki XSS: https://www.owasp.org/index.php/Session_hijacking_attack
pyro
Cytat(marcinek37 @ 1.11.2012, 20:12:43 ) *
czy reasumując:
1. nie ma możliwości, aby napisać system w ten sposób, aby za jego pośrednictwem ktoś mógł wykraść sesję i ją wykorzystać
2. szybkie hashowanie jest niebezpieczne, bo jeśli ktoś ukradnie mi hash i pozna sól systemową i indywidualną dla użytkownika, będzie mógł poznać hasło (tyle że najpierw musi poznać obie sole)
3. przy logowaniu do sesji mam zapisać jak najwięcej danych, które się z nim będą identyfikowały, prócz adresu IP, bo ktoś może mieć zmienny adres
4. autologowanie jest niebezpieczne i lepiej go nie robić


Tak generalnie rzecz biorąc każdy z tych podpunktów to w mniejszym lub większym stopniu bzdura tongue.gif
Damonsson
Ale 3. do słowa "prócz" chyba jest prawdą? No bo jak inaczej identyfikować prawdziwego użytkownika?

edit: Również mając wzgląd na wyeliminowanie, multi-kontowości.
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.