Bezpieczny upload plików - Skrypt

0

Witam.

Mam mały zgryz i waham się jak rozwiązać pewną sprawę. Chce kupić serwer na którym chcę postawić kilka stronek, więc nie mogę sobie pozwolić na żadne luki. Nie spodziewam się na niej dużego ruchu więc stwierdziłem że dla znajomych z klasy, mogę przy okazji zrobić mały serwer plików. No ale mam pewien problem. Chcę część plików umieścić w lokalizacji publicznej i nie wiem jak skutecznie zabezpieczyć serwer.
Np ktoś wyśle plik haker.php na serwer, mój skrypt zapisze go w katalogu publicznym dostępnym pod adresem www.mysite.pl/public/haker.php . I przy wpisaniu odpowiedniej ścieżki zamiast pobierania pliku uruchomimy potencjalnie złośliwy kod. Jak można zabezpieczyć coś takiego.

Czy da się odpowiednio ustawić uprawnienia, np chmod 0444, tak aby nie dało się wykonać tych plików??
(chmod testowałem i nie ma na to wpływu)

Jak według was można zabezpieczyć się przed takim dostępem??

0

filtrowanie nazw plikow wg. rozszerzen oraz typow MIME (przy wysylaniu - zakladam, ze wysylasz via HTTP POST?).

Jezeli poprzez FTP to kazdy user bedzie mial swoje uprawnienia i grupe do ktorej jest przypisany, prawda?

0

Przede wszystkim - jeśli masz formularz uploadu to normalnie filtrujesz po rozszerzeniu, tylko jest ważny błąd, który popełnia większość początkujących:

$extension = explode('.', $filename);
$extension = $extension[1];

Tak nie wolno pod żadnym pozorem robić, bo żadne sprawdzanie nie ma sensu, jako że patrzymy wyłącznie na tekst napotkany między pierwszą kropką, a końcem lub pierwszą kropką, a drugą kropką. Przy czym wrzucamy plik obrazek.jpg.php i mamy haxa na serwerze. Piszę o tym, bo bardzo często można napotkać strony podatne na właśnie taki atak.

$extension = explode('.', $filename);
$extension = $extension[count($extension)-1];

Tak już jest bezpiecznie. Zawsze sprawdzamy to, co jest po ostatniej kropce.

Dodatkowo jeśli masz ważny serwis, dobrą praktyką jest użycie skryptu serwującego, zamiast poleganie na samym serwerze. Skryptem serwującym może być na przykład eLouai's Force Download. Dzięki użyciu tego, mamy pewność że nawet jeśli skrypt PHP/ASP/wtf dostanie się na serwer, to zostanie on tylko przeczytany, nie ulegnie parsowaniu. Przy użyciu tego typu skryptu jednak należy zablokować dostęp do katalogu w którym są fizycznie pliki. Najlepiej plikiem .htaccess o treści:
deny from all
Tak, aby tylko skrypt serwujący miał do tego katalogu dostęp i użytkownik musiał każdorazowo używać skryptu żeby coś pobrać.

Jeśli chcesz dać FTP użytkownikom, to często trzeba mieć VPSa/dedyka, żeby do tak zaawansowanych opcji dobrnąć. Wtedy możesz sobie utworzyć blacklistę plików, rozszerzeń, poleceń, etc.

0
Demonical Monk napisał(a)
$extension = explode('.', $filename);
$extension = $extension[count($extension)-1];

Jeszcze dodam, ze wystarczy uzyc funkcji pathinfo() jezeli mowimy o PHP:

$suffix = pathinfo('foo.php', PATHINFO_EXTENSION);

albo:

$suffix = end(explode('.', 'foo.bar'));
0

albo:

if(!preg_match('/\.(?:jpeg|jpg|gif|png)$/i', $_FILES['photo']['name']))
  echo 'Nieprawidłowe rozszerzenie';
0

Właśnie brałem pod uwagę filtrowanie ale wydaje mi się że jest to dość upierdliwa opcja, dlatego że nie nie mam nic przeciwko plikom php (tylko nie mogą szkodzić stronce ;P ), a dla kogoś może to być problem (tym bardziej że mamy teraz okres projektów z php).

Co do skryptu wysyłającego plik to mam taki ale za idealne rozwiązanie uważam takie w którym wysyłanie publicznych plików odbywało się bez włączania parsera PHP (i ładowania do pamięci tych wszystkich zendowych bibliotek - w moim przypadku)

Ogólnie schemat działania mojej aplikacji jest taki:
(przeglądarka wysyła zapytanie)->serwer sprawdza katalog publiczny (zapisuje w nim cache wyników - standardowy cache zenda) -> jeśli nie ma pliku przeglądarka odpala mój skrypt)

I za pomocą skryptu chciałem wysyłać nie publiczne pliki ale jak tak dalej pójdzie to będę musiał wszystkie :(

Jeszcze dodam komentarz zabezpieczeń gdyby nie to że chce dodać dostęp przez ftp i bezpośrednio przez apache można by łatwo podoklejać np '._' i byłby spokój ;P

Tak więc czy jest jakiś sposób żeby z poziomu .htaccess wyłączyć interpretacje plików wykonywalnych dla danego katalogu (i podkatalogów)??

//Sorry że nie sprecyzowałem tak dokładnie w pierwszym poście

0

to również w .htaccess musisz się pobawić
coś w stylu

AddType application/x-httpd-php-source .php

nie jestem pewien bo nie testowałem ale z tego co pamiętam, powinno działać i wyświetlać pokolorowany kod php
musisz uważać na rozszerzenia typu .php5, .php4 i tym podobne, najlepiej trzymaj listę dozwolonych rozszerzeń i z nią porównuj mimo wszystko

poza tym musisz wywalić wszystkie kropki z nazwy pliku
łatwo można spreparować zapytanie i wysłać plik pod adres ../plik.php - wtedy plik zapisze się folder wyżej i już się wykona bo .htaccess go nie obejmie
dobrą praktyką jest w ogóle nie ufać użytkownikowi i plikowi nadać losową nazwę

aha, jeżeli nie chcesz pokolorowanego kodu, tylko prosty tekst to ustawiasz mime na text/plain, lub text/html żeby wyświetlić jako zwykłą stronę html

0

thenx. Mniej działa tak jak chciałem :)

Mam jeszcze jedno pytanie jak zablokować dostęp do plików .htaccess w podkatalogach??

0

Nadal można wrzucić .php4/.php3 etc.
Polecam wyłączyć parser zamiast kombinować

Wyłączanie nadpisywania .htaccess:

<Directory /cannot/use/htaccess/*>
AllowOverride None
</Directory>

W .htaccess oczywiście.

Blokada parsera:
php_value engine off

Przed użyciem sprawdź czy nie masz CGI/ASP włączonego, jak nie będzie się dało z tym nic zrobić to po prostu zablokuj rozszerzenia htaccessem/ftpem/wtf.

0

zasadniczo wystarczy zmienic nazwe pliku na jakis hash :P

0
cepa napisał(a)

zasadniczo wystarczy zmienic nazwe pliku na jakis hash :P

I powiedzieć userowi żeby po pobraniu sam sobie rozszerzenie dopisał?

0

Tylko takie coś nie przejdzie w pliku .htaccess a do głównego pliku konfiguracyjnego raczej nie będę miał dostępu :( Kiedy w zwykłym .htaccess daje AllowOverride None wyskakuje mi błąd serwera.

0

No to musisz użyć skryptu serwującego z PHP/CGI/ASP, albo zmienić handlery do wszystkich znanych ci rozszerzeń i okłamywać się że twój system jest idiotoodporny.

0
Demonical Monk napisał(a)
cepa napisał(a)

zasadniczo wystarczy zmienic nazwe pliku na jakis hash :P

I powiedzieć userowi żeby po pobraniu sam sobie rozszerzenie dopisał?

nie :P twoje rozszerzenie i nazwa pliku sa wylacznie wysylane w naglowku odpowiedzi http wiec moga byc trzymane w bazie, natomiast sam plik moze byc trzymany na dysku i kluczem do niego moze byc hash, jest to rozwiazanie w cholere lepsze bo skalowalne :P

co do obciazenia samego serwera, to apache ma rozrzeszerznie X-CosTam :S ktore powoduje ze serwer automatycznie dokleja zawarttosc pliku do wysylanej odpowiedzi wiec obciazenie php czy innej technologi jest znikome :P

0
cepa_nz napisał(a)

...

Ja [CIACH!], trójwarstwowe modele są po to żeby stosować je z umiarem, a nie do każdego Hello Worlda... Bo przy prostym skrypcie który ma spełniać określoną rolę ty przewidujesz jakby miał z tego rapidshare powstać nagle. Porobisz sobie hashe z plików, skojarzysz to w bazie i zanim nie będziesz trzymał użyteczniejszych informacji skalowalność twojego rozwiązania będzie polegała na tym, że chcesz podglądnąć danego użytkownika w FTPie, a widzisz:

92612efa-fc49-49bf-81d5-2368dd951100
79fa145f-0323-4a65-9a99-a2159111da30
e9d54c19-360c-44ad-b1da-5604492b8fd9
31590400-64eb-4434-9ff2-e50b614e4181
c86e6d64-acfc-4021-b554-cd160e9ee208

Przy czym musisz tracić czas na zapytania do bazy żeby sprawdzić co to za plik, albo pisać sobie panele admina do wszystkiego co jest czasami wkurwiającym rozwiązaniem.

Pomyśl jaki będzie burdel jak ktoś znajdzie lukę, a admin serwera będzie szukał po haszach tego odpowiedniego pliku...

0

jak juz cos robic to robic dobrze :P

1 użytkowników online, w tym zalogowanych: 0, gości: 1