Pytanie Podejście bezpieczeństwa do przesyłania obrazu w języku PHP


Opracowuję skrypt php, który zastąpi bieżący, który będzie miał dużo ekspozycji na różne rynki / kraje. Ten skrypt między innymi oferuje funkcję przesyłania zdjęć.

Po wielu lekturach na ten temat postępowałem zgodnie z podejściem opisanym poniżej. Byłbym głęboko wdzięczny za twoje komentarze na temat bezpieczeństwa.

  1. Zdjęcie jest umieszczane w prywatnym folderze 777 poza katalogiem głównym.
  2. Sprawdzane są rozszerzenia z widocznymi białymi literami (dozwolone tylko pliki jpg, gify, png). Wszystkie inne elementy są usuwane.
  3. Wykorzystanie getimagesize do sprawdzenia wymiarów min-max i ważności zdjęć.
  4. Sprawdź dopasowanie typu MIME i rozszerzenia pliku.
  5. Zmiana rozmiaru przesłanego zdjęcia na wymiary standardowe (za pomocą imagecopyresampled).
  6. Zapisywanie utworzonych plików jako jpg.
  7. Usunięcie oryginalnego pliku.
  8. Zapisz zdjęcia za pomocą nowej (nie losowej nazwy), np. Img51244.jpg.
  9. Przenieś nowe zdjęcia do zmiennych podkatalogów folderu publicznego (777 uprawnień) zgodnie z nie przewidywalnym algorytmem. To znaczy., img10000.jpg będą przechowywane w photos/a/f/0/img10000.jpg podczas img10001.jpg będą przechowywane w photos/0/9/3/img10001.jpg. Odbywa się to z innych powodów (wykorzystanie subdomen do przesyłania statycznych treści lub korzystanie z CDN).

Skrypt będzie działał na dedykowanym serwerze linuksowym.


12
2017-09-06 08:36


pochodzenie


nic tu na mnie nie wyskakuje. oprócz uprawnienia 777 do folderu - jak rozumiem, jeśli ma 777 uprawnień, nie jest prywatny. ale o ile mogę powiedzieć, że to naprawdę miałoby znaczenie, gdyby twój serwer został przejęty (co nie wygląda na to, że prawdopodobnie przejdę przez ten skrypt) - totallyNotLizards
777 nie brzmi bezpiecznie. Możliwe związane z stackoverflow.com/questions/3644138/... - ajreal
Brzmi bardzo dobrze dla mnie, może z wyjątkiem bardzo liberalnych uprawnień. Może mogą być nieco ograniczone? W przeciwnym razie robi to wszystko, co jest mi potrzebne, w tym usunięcie danych EXIF - Pekka 웃
Nazywam folder wysyłania "prywatny" jako przeciwieństwo publicznego (w folderze głównym sieci) - Alex


Odpowiedzi:


  1. Katalog z chmod 0777 jest, z definicji, publiczny dla innych użytkowników zalogowanych na twoim serwerze, a nie prywatny. Prawidłowe uprawnienia będą wynosić 700 i będą własnością apache (lub jakikolwiek użytkownik, na którym działa twój serwer sieciowy). Nie jestem pewien, dlaczego nie używałbyś domyślnego katalogu tymczasowego php tutaj, ponieważ on również znajduje się poza katalogiem głównym.
  2. Biała lista to dobry pomysł. Uważaj, aby mieć poprawną implementację. Na przykład wyrażenie regularne /.png/ właściwie mecze apng.php.
  3. Ten krok to świetny pomysł. W zasadzie sprawdza magię pliku.
  4. Nie jest to bezwzględnie konieczne. W dwóch poprzednich krokach ustaliliśmy, że rozszerzenie i format pliku są poprawne. Jeśli potrzebujesz poprawnego typu MIME, który ma być określony przez klienta, powinieneś również sprawdzić, czy dany typ MIME i określony powyżej są równoważne.

Kroki od 5 do 8 nie są związane z bezpieczeństwem.

Krok 9: Zakładam, że Twoja strona pozwala każdemu zobaczyć każde zdjęcie. Jeśli tak nie jest, powinieneś mieć schemat URL o znacznie dłuższym adresie URL (np. Hashsum obrazu).


4
2017-09-06 08:46



(-1) 777 nie oznacza publicznego pod względem dostępu poprzez sieć - o tym właśnie mówi. A twój przykład regex sugeruje, że i tak ma on jakiekolwiek znaczenie ... a BTW exe jest rozszerzeniem Windows ...: - / - Raffael
@ Raffael1984 Myślę, że phihag to wie. Nadal jest publiczny pod względem dostępność dla innych użytkowników na tym samym serwerze internetowym, który jest problem. Ale zgadzam się, że krok 2) jest niepotrzebny, jeśli robisz 3) prawidłowo - Pekka 웃
@ Raffael1984 True. Nie jestem pewien, dlaczego ten krok jest konieczny. Zaktualizowano odpowiedź. - phihag
@ Raffael1984 Zaktualizowano zakończenie w przykładzie na .php, chociaż jest to tylko przykład czegoś, co nie powinno się prześlizgnąć. Ponownie zaktualizowałem odpowiedź, aby uzyskać dostęp do jawnej dostępności HTTP i ogólnosystemowych katalogów publicznych. - phihag
700? Dlaczego dajesz prawa do wykonywania zdjęć? - rook


Powinieneś również sprawdzić rozmiar przesłanego pliku, ponieważ getimagesize może czasami przekraczać dostępną pamięć RAM. Dobrze jest także założyć, że skrypt może się zawiesić w dowolnym momencie (na przykład, gdy elektryczność spadnie), więc powinieneś zaimplementować pewne procedury czyszczenia, aby usunąć lewe, niepotrzebne pliki.


3
2017-09-06 08:44



Maksymalny uploadowany rozmiar pliku jest już ograniczony w php.ini. - Maerlyn
Tak, ale to nie znaczy, że wystarczy, aby uniknąć przekroczenia limitu pamięci RAM. - Sebastian Nowak
Jeśli przekroczy on rozmiar w php.ini, nie otrzymasz nazwy pliku $_FILES - więc nie możesz sprawdzić jego wielkości. - Maerlyn
Istnieje również minimalny i maksymalny sprawdzian rozmiaru pliku. Istnieje również czek dla zestawu php post_max_size - Alex
@Merierlyn: Tak geniusz, nie będzie. Ale co, jeśli limit w php.ini jest ustawiony na 128 MB a 32 MB wystarczy, aby zawiesić skrypt? - Sebastian Nowak


To dość kompletne podejście, ale nie widzę żadnego mechanizmu zapobiegania wykonywaniu kodu.

Powinieneś się upewnić, że zawartość obrazu nigdy nie jest zawarta (z włączeniem lub wymaganiem wywołania) lub wykonana przez eval ().

W przeciwnym razie można by wykonać kod php znajdujący się na końcu pliku.

Możesz także spróbować wykryć kod php w treści obrazu (z file_get_contents, a następnie na przykład wyszukując wyrażenie "<? Php"), ale nie mogłem znaleźć w 100% bezpiecznego sposobu na wyeliminowanie podejrzanego kodu bez zniszczenia niektórych (poprawne) obrazy.


-1
2017-09-06 08:44



Nie widzę, jak kod PHP byłby wykonywany w pliku JPG, chyba że serwer jest źle skonfigurowany? - Pekka 웃
Nie ma sensu, bo jest oczywiste, że nikt nie zadzwoni do eval ani nie zawrze obrazu. Nie mogę wymyślić żadnego scenariusza, w którym ktoś mógłby pomyśleć o zrobieniu tego (chyba że po prostu zaczął używać PHP). - Sebastian Nowak
Oryginalny plik zostanie usunięty, gdy tylko zostaną usunięte poprawione zdjęcia. jest używany tylko z następującymi funkcjami php w następującej kolejności: move_uploaded_file, filesize, getimagesize, imagecreatefromjpeg, imagecopyresampled. - Alex
@Sebastian Nowak: Nie można zakładać, że programiści nie popełnią błędów. Znane są ataki na szeroko rozpowszechnione systemy, takie jak phpBB z wtryskiem kodu poprzez przesyłanie obrazów (awatary w ich przypadku). Mówienie, że nikt już nigdy nie popełni tego błędu, spowoduje tylko, że błąd zostanie zapomniany, dopóki ktoś go nie użyje. Znalazłem ten post z interesującymi sposobami na wykorzystanie takich luk (komentarze też są dobre, z przykładem null-char injection dla zachowania rozszerzenia .php na nazwie pliku): ha.ckers.org/blog/20070604/... - Benjamin Dubois