Zabezpieczenie uploadu plików

0

Witam,

jak zabezpieczyć(ogólnie) upload plików na serwer bez ograniczeń typów oraz wielkości, da się w ogóle?.

0

Da się zabezpieczyć :)

podałeś że chcesz bez ograniczeń typów oraz wielkości - ale co rozumiesz przez zabezpieczenie w takim razie? Oczywiście możesz zaimplementować kontrole dostępu (nie każdy może uploadować). Wiadomo - tylko zarejestrowani userzy.

Dalej - to już inwencja twórcza. Jeśli chcesz dać bezpośredni dostęp do plików uploadowanych (jako download) to musisz w htaccess na pewno wyłączyć przetwarzanie/interpretacje plików przez serwer, czyli jak ktoś Ci wgra php to serwer ma tego nie wykonywać. To samo w sumie jeśli dostęp do pliku ma być przez bramkę w postaci skryptu - jasne że możesz czytać plik, ale nigdy go nie includować/uruchamiać.

Oprócz powyższego jest jeszcze parę zasad - po pierwsze NIGDY nie ufaj użytkownikowi. Nie idź na ślepo za $_FILES tylko sprawdź czy faktycznie jest w danych i w pliku. Możesz być wybredny i zakładać z góry że jeśli jakieś dane w $_FILES odnośnie pliku są błędne to cały plik jest zły (np size != filesize(uploaded)). Nigdy nie wierz w to co mówi rozszerzenie pliku, sprawdzaj MIME ale po stronie serwera ($_FILES ma mime, ale to ignoru/porównuj ze stanem faktycznym i patrz poprzednie porady). Sprawdzaj rozmiar pliku, nie pozwalaj ludziom na przekroczenie jakichś rozmiarów itp

Jeszcze jeśli masz możliwość - daj po stronie klienta walidację np w JS, ukryte pola, cuda bajery (;)) co by jakimś botem nie można było łatwo słać a po stronie serwera nie ufaj w ogóle plikom i skanuj je jakimś antyvierm/antymalware itp.

Ostatnia rzecz: jeśli dasz możliwość wgrywania archiwów - nigdy, ale to przenigdy nie dawaj możliwości ich rozpakowywania przez php. To jak prosić o zabicie serwera ;)

0

Johnny_Bit, dzięki! za solidną i konstruktywną odpowiedź.

Jeżeli chodzi o dostęp do plików to userzy nie mogą wyświetlać katalogu, w którym są pliki. Używam popularnego frameworka MVC Yii2.

Każdy user po upload-zie do pobrania pliku dostaję link w postaci:
http://serwer/kontroler/akcja/nr_identyfikacyjny/nr_identyfikacyjny, numery są generowane losowo i zapisane w bazie danych za pomocą ich mój skrypt identyfikuję jaki plik ma wyczytać, tak wygląda akcja odpowiedzialna za udostępnienie pliku:

 
     /**
      * @param int $time
      * @param string $access_key
      * @return null
      */
 public function actionDownload($time, $access_key)
     {

          $model = new GlobalFile;

          $file = $model->download($time, $access_key); //zapytanie SQL o istnienie pliku. Zwraca położenie pliku.

          if (is_null($file) || !file_exists($file->getAbsolutePath()))
          {
               throw new NotFoundHttpException('Sorry your file is not exists.');
          }
          $absolutePath = $file->getAbsolutePath();

          header('Content-Type: application/zip');
          header('Content-disposition: attachment; filename=' . basename($absolutePath ));
          header('Content-Length: ' . filesize($absolutePath ));
          readfile($absolutePath );
     }

Zawartość zwracam z typem "application/zip", ponieważ każdy plik po upload-zie jest pakowany do zipa.

W którym miejscu mogą mi się wykonać upload-owane pliki?.

0

przy takim podejściu - nie mogą się wykonać, więc jest ok :) download nie jest straszny. za to ten zip... @Gynvael Coldwind miał kiedyś prezentacje co może wyjść nie tak z zipami, ale nic z tego nie pamiętam oprócz tego że przy złym wietrze może byc niezłe kuku...

Ja przy upload/download wychodze z założenia że nie modyfikuje nawet 1 bit w pliku od uzytkownia i nie pozwalam go w jakikolwiek sposób czemukolwiek interpretować... No chyba że obrazy, ale w nich to robię strip na wszystko łącznie z exif/komentarzami/czymkolwiek co by gdzieś mogło przemycić cokolwiek ;)

0

No ja nie mam wyboru zip musi być. Tyle że do zip-u używam linuxa, po udanym upload-zie odpalam w konsoli program zip i gotowe.

Jak teraz sprawdzić, czy wrzucany plik nie posiada robaków - musiałbym to robić przed wrzuceniem przez PHP do tmp plików, jak rozumiem rozwiązanie leży po stronie serwera - jakiś program anty-wirusowy z automatycznym sprawdzaniem nowo pojawiających się plików + obsługa wyjątków PHP przy próbie przeniesienia nieistniejącego piku(wcześniej usuniętego przez anty-wirusa). Ciekawe jak rozwiązują te problemy tacy giganci jak GitHube, Google Dysk, Bitbucket - wiem, wiem na pewno nie korzystają z PHP :)

0

PHP pliku uploadowane wrzuca domyślnie w /tmp. po skończonym uploadze możesz uruchomić na pliku na żądanie skan, jak plik zostanie wywalony to przecież będziesz mieć że !file_exists($uploaded_file) i możesz dać do usera że "nasz system wykrył potencjalne niebezpieczeństwo w pliku przesłanym przez Ciebe. Sprawdź swój komp czy nie masz syfu, a jak bardzo się upierasz że nie masz syfu i koniecznie chcesz przesłać plik - skontaktuj sie z działem supportu".

Google - kiedyś na gmailu nie dało się przesłać żadnych wykonywalnych i jeszcze jakieś ograniczenia mieli. Po uploadze było "skanowanie plików" i jak nie przeszło to plik znikał ;) nie wiem jak reszta :)

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