Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Pobranie wszystkich plików z folderu bez znania ich nazw
Forum PHP.pl > Forum > PHP
athabus
Witam,

pracuję nad skryptem, który ma udostępniać możliwość pobrania faktury z serwera. Skrypt będzie trochę bardziej złożony, ale dla uproszczenia załóżmy, że plik ma nazwę składającą się z 20 znaków (losowych). Klient dostaje link do swojego pliku, który znajduje się w folderze rok/miesiąc/dzień/nazwa_pliku.pdf

I tu rodzi się pytanie - czy istnieje możliwość, że ktoś pobierze wszystkie pliki z danego folderu (czyli potencjalne faktury innych klientów) nie znając ich nazw - oczywiście pomijając atak typu brute-force, bo przy takiej długości nazwy trafienie w nazwę pliku wymagałoby miliardów zapytań do serwera?

A może macie jakiś pomysł na bezpieczniejsze umożliwianie pobrania faktur?
pyro
Jak klienci żeby pobrać faktury muszą się zalogować to wystarczy zwykłe przypisanie faktur użytkownikom.

Tak jak napisałeś też można zrobić, ale wtedy trzeba przywiązać szczególną uwagę do ustawień webservera.
vieri_pl
Najlepiej by każdy klient w miejscu gdzie przetrzymujesz dane o nim miał jakiś hashkey, secure key - coś w tym stylu.

Klientowi dajesz link w stylu:

http://www.domena.pl/faktura/23/4624116c8f...2817761ad15c15/

Wtedy 23 to np. id_customer, po tym jest secure_key, porównujesz czy secure key jest zgodny z ID klienta i dopiero wtedy "wypluwasz" mu .pdf

W katalogu z .pdf dać .htaccess:

Kod
<Files ~ "\.pdf$">
  Order allow,deny
  Deny from all
</Files>
greycoffey
Dwudziestoznakowe nazwy plików - weźmy pod uwage [A-Za-z0-9]. Są to 62 znaki, czyli łącznie 62^20, czyli ~7.044*10^35 czyli trochę dużo. Nawet gdyby serwer przyjmował 100tys. zapytań na sekundę, rocznie zostałoby sprawdzone 3 153 600 000 000 potencjalnych plików faktur - czyli potrzebaby było ~2.23*10^23 lat, aby sprawdzić wszystkie wink.gif

Tak więc - NO WAI!

EDIT: Czyli serwuj plik z tym 20-znakowym kluczem, tylko przy ich ściąganiu nadaj im jakąś sensowną nazwę wink.gif
pyro
Cytat(vieri_pl @ 20.04.2012, 19:38:53 ) *
Najlepiej by każdy klient w miejscu gdzie przetrzymujesz dane o nim miał jakiś hashkey, secure key - coś w tym stylu.

Klientowi dajesz link w stylu:

http://www.domena.pl/faktura/23/4624116c8f...2817761ad15c15/

Wtedy 23 to np. id_customer, po tym jest secure_key, porównujesz czy secure key jest zgodny z ID klienta i dopiero wtedy "wypluwasz" mu .pdf


Taaaa... i niepotrzebnie zdradzać w linku ID klienta. A o tym "secure key" już sam autor napisał.

Cytat
W katalogu z .pdf dać .htaccess:

Kod
<Files ~ "\.pdf$">
  Order allow,deny
  Deny from all
</Files>


No pewnie. Jeśli nie chcemy, żeby ktoś niedobry pobrał fakturę to niech nikt jej nie pobiera. Nawet klient, do którego ta faktura przysługuje arrowheadsmiley.png
thek
Moim zdaniem najlepiej zablokować htaccessem katalog z fakturami, wewnątrz niego katalogi z id użytkowników i skrypt (dostępny tylko dla zalogowanych użytkowników), który jako jedyny może pobierać dane. No a jedynym parametrem skryptu jest nazwa pliku do pobrania. Skrypt bowiem z sesji pobierałby id klienta zalogowanego i na jego podstawie ustawiał ścieżkę pobierania. W ten sposób nawet dokładne znanie nazwy i id klienta czy całej ścieżki wywali Forbidden, gdyż skrypt wykryje nieprawidłowe id klienta i zwyczajnie nie pozwoli na pobranie pliku. Ogranicza go bowiem jedynie do jego własnych faktur z katalogu o jego ID. Ja tak zablokowałem dostęp na serwerze i działa wyśmienicie. Jedyna możliwość zdobycia dostępu do pliku to przejęcie sesji i w tym momencie idealne trafienie w nazwę, a jest to niezwykle trudne z racji regeneracji sesji co 3 requesty. Ma więc mocno ograniczone możliwości ataku nawet ktoś kto sesję przechwycił.
greycoffey
Wykazałem już, że nie ma sensu ukrywać inaczej tego, jeśli to ma być dostępne dla każdego, kto zna link. Jeśli potrzeba zaimplementować autoryzację, możemy stosować to samo, tylko przed tym dodać id użytkownika i jakiś unikalny dla danego użytkownika kod (aby 1/20452.pdf nie było tym samym co 2/20452.pdf) linkujący na prawidłowy dokument.
thek
Ale nie wziąłeś pod uwagę, iż nie każdy kto zna link powinien mieć do tego pliku dostęp. Właśnie po to jest autoryzacja. Inna sprawa, że waląc brute-force, drzesz każdy napotkany plik trafiony. Czyli nie masz 1 trafienie na każdą teoretyczną możliwość ale zapewne dziesiątki lub setki, zależnie ile faktur ma klient. Jeśli zaś masz jeden katalog dla wszystkich klientów to brucik zedrze masę plików od masy ludzi. A zauważ, że faktury zawierają dane osobowe i za coś takiego można jednak "beknąć".
pyro
Cytat(greycoffey @ 20.04.2012, 22:35:30 ) *
Wykazałem już, że nie ma sensu ukrywać inaczej tego, jeśli to ma być dostępne dla każdego, kto zna link. Jeśli potrzeba zaimplementować autoryzację, możemy stosować to samo, tylko przed tym dodać id użytkownika i jakiś unikalny dla danego użytkownika kod (aby 1/20452.pdf nie było tym samym co 2/20452.pdf) linkujący na prawidłowy dokument.


Jeśli była by autoryzacja to nie ma najmniejszego sensu robić tego poprzez podawanie bezpośredniego linka do pliku, tylko poprzez skrypt.

Cytat
Inna sprawa, że waląc brute-force, drzesz każdy napotkany plik trafiony. Czyli nie masz 1 trafienie na każdą teoretyczną możliwość ale zapewne dziesiątki lub setki, zależnie ile faktur ma klient. Jeśli zaś masz jeden katalog dla wszystkich klientów to brucik zedrze masę plików od masy ludzi. A zauważ, że faktury zawierają dane osobowe i za coś takiego można jednak "beknąć".


Załóżmy, że takich faktur znajduje się na serwerze i milion a hash w linku jest na podstawie MD5.

|A| = 1 000 000

|Ω| = 36^32 = 6.33402867 × 10^49

P(A) = |A| / |Ω| = 1.57877404 × 10^(-44)


Cytat
to brucik zedrze masę plików od masy ludzi


Jeżeli ktoś brutem trafiłby chociaż JEDEN plik to ja na jego miejscu zająłbym się grą w LOTTO, bo chyba by trafił szóstkę kilka razy pod rząd.
greycoffey
Cytat(thek @ 21.04.2012, 00:56:12 ) *
Ale nie wziąłeś pod uwagę, iż nie każdy kto zna link powinien mieć do tego pliku dostęp. Właśnie po to jest autoryzacja. Inna sprawa, że waląc brute-force, drzesz każdy napotkany plik trafiony. Czyli nie masz 1 trafienie na każdą teoretyczną możliwość ale zapewne dziesiątki lub setki, zależnie ile faktur ma klient. Jeśli zaś masz jeden katalog dla wszystkich klientów to brucik zedrze masę plików od masy ludzi. A zauważ, że faktury zawierają dane osobowe i za coś takiego można jednak "beknąć".


Mam miliard (10^9) faktur, 20 znakowy adres pliku z zakresu [A-Za-z0-9] (62^20), 1 milion żądań na sekundę sprawdzających czy plik istnieje (10^6), czyli rocznie sprawdzamy 10^6*60*60*24*365 = ~3.15*10^13 faktur. Szansa, że przez rok trafimy na chociaż jedną fakturę wynosi 10^9/(10^6*60*60*24*365) = ~3.17*10^-5 - przypominam, że założyliśmy MILION żądań na sekundę, czyli zapytanie, odpowiedź, przeparsowanie odpowiedzi... czyli pewnie dużo ponad możliwości serwera, na którym to będzie stało, a taki ruch przecież można blokować automatycznie wink.gif Każde żadanie to 10^9/62^20 = ~1.42*10^-27 szans na trafienie w fakturę.

Wartości tutaj i tak są zawyżone, system nie będzie przechowywał miliadra faktur, nie będzie taki wydajny by tak szybko odpowiadać, a ruch będzie się wydawał nienaturalny, nieprawdaż?
pyro
Cytat(greycoffey @ 21.04.2012, 13:16:42 ) *
Mam miliard (10^9) faktur, 20 znakowy adres pliku z zakresu [A-Za-z0-9] (62^20), 1 milion żądań na sekundę sprawdzających czy plik istnieje (10^6), czyli rocznie sprawdzamy 10^6*60*60*24*365 = ~3.15*10^13 faktur. Szansa, że przez rok trafimy na chociaż jedną fakturę wynosi 10^9/(10^6*60*60*24*365) = ~3.17*10^-5 - przypominam, że założyliśmy MILION żądań na sekundę, czyli zapytanie, odpowiedź, przeparsowanie odpowiedzi... czyli pewnie dużo ponad możliwości serwera, na którym to będzie stało, a taki ruch przecież można blokować automatycznie wink.gif Każde żadanie to 10^9/62^20 = ~1.42*10^-27 szans na trafienie w fakturę.

Wartości tutaj i tak są zawyżone, system nie będzie przechowywał miliadra faktur, nie będzie taki wydajny by tak szybko odpowiadać, a ruch będzie się wydawał nienaturalny, nieprawdaż?


athabus
Dzięki za odpowiedzi. Nawet ciekawie się temat rozwinął.

Co do brute-force, to raczej się tym nie przejmuje - co prawda nie wykonałem taki obliczeń, jak powyżej, ale ogólnie wiadomym jest, że żaden serwer nie jest nawet w stanie przyjąć takiej ilości żądań aby trafić w 20znakowy losowy ciąg (np. 20 znaków z sha).

U mnie sytuacja wygląda tak, że klient (nie koniecznie mający swoje id, bo także firma przyjmuje zamówienia np. przez telefon oraz konta anonimowe) dostaje zamówienie, a w nim umieszczone hasło ~5 znaków. Logowanie odbywa się poprzez wpisanie nr zamówienia + tego hasła. ALE chcę również mieć możliwość generowania bezpośredniego linku do faktury, tak aby klientowi móc wysłać link mailem bez konieczności logowania. To dlatego, że z doświadczenia wiem, że zalogowanie się do systemu często przerasta niestety ludzi - np. ktoś zamiast 0 wpisuje uparcie O itp. Może to i śmieszne, ale takie są fakty, a nie chcę potem dostać jakiegoś donosu do US, że do zamówienie nie ma faktury etc.

Mój plan jest w taki, że będę tworzył taką strukturę
/rok/miesiac/dzien(+jeszcze moze doloze tu 4 losowe znaki, aby nazwy folderow tez byly bardziej losowe)/20znakowa_nazwa_pliku_zupelnie_losowa.pdf

czyli np.

/2012/04/16a46d/ka83AU9o09mjKKipo5Q2.pdf

Docelowa zawartość każdego folderu to max ~1000 faktur (to już z nawiązką, bo obecnie pewnie jakieś 100-200).

Pytanie więc brzmi, czy konfigurując .htaccess zabraniając listowanie zawartości folderu mogę uznać ten system za bezpieczny (oczywiście pomijają ryzyko brute-force, którego samo wystąpienie jest bardzo mało prawdopodobne, a powodzenie chyba raczej niemożliwe).

greycoffey
Tak. wink.gif
Możesz nawet przechowaywać faktury poniżej DocumentRoot (or sth) i przez jeden skrypt PHP serwować plik, ale to chyba przerost formy nad treś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.