Brugernavn:




Kodeord: Husk
Forside Forum Artikler Downloads Søg
 

Sikkerhed - Upload

Forord

Sikkerheden er aldrig noget du bør sløse med når du udvikler i PHP. Og det er isært farligt at sløse på sikkerheden ved de smarte og kendte fil uploads løsninger. Læs denne artikel og ungå at blive et offer for hacking.

Indholdsfortegnelse

1.0   Indledning
2.0   Hvad er problemet?
   2.1   Hvorfor er de usikre?
3.0   Et simpelt upload system
   3.1   Hvad er problemet her?
   3.2   Hvad gør vi ved problemet?
      3.2.1   getimagesize() hvad er det?
4.0   Implantering af getimagesize()
   4.1   Er der nogle problemer ved denne metode?
5.0   Den færdige løsning.
6.0   Ekstra sikkerhed
   6.1   Slå PHP helt fra i mappen
7.0   Hvad har vi så lært?

1.0  Indledning

Vi kender alle de små smarte upload systemer. De lader os ligge filer op på vores webserver nemt og hurtigt, uden om FTP og andet bøvl. De er også smarte til CMS systemer hvor evt ansatte ville kunne uploade billeder til webserveren direkte fra et webinterface.
Selvom det hele lyder så praktisk og perfekt, så er der en bagside af det hele som de færreste er opmærksom på... et usikkert upload system VIL kunne lade ALLE OG ENHVER tage kontrollen over din webserver, hvorefter de ville kunne gøre alt hvad der passer dem med den.

2.0  Hvad er problemet?

Problemet er at folk typisk laver søgningen på google efter "php fil upload", det er der i selv ikke noget galt i men de fleste aner ikke hvilken sikkerheds risiko mere end halvdelen af alle de scripts man finder er.

2.1  Hvorfor er de usikre?

De fleste af disse systemer har INGEN indbyggede metoder imod at alle og enhver ville kunne uploade på din webserver. Derudover er det værste af det hele at de IKKE udføre tjek på hvad brugeren rent faktisk er i gang med at uploade til serveren. Faktisk ville en hacker kunne ved hjælp af at uploade et PHP shell (Kendte shells er C99 og R57) kunne downloade, slette eller modificere hele dit website efter eget ønske. På særligt usikre webservere ville hackeren direkte kunne overtage den! Det er derfor ekstremt vigtigt som med alle andre PHP scripts ikke at sløse med sikkerheden.

3.0  Et simpelt upload system

  1. <?
  2. if ($_GET['add'] == 'yes') {
  3.     $max = "1000"; // Maks størrelse i KB
  4.     if($_FILES["upfil"]["size"] > 0) {
  5.         $rand = rand(100000,999999);
  6.         $fra = $_FILES["upfil"]["tmp_name"];
  7.         $til = "../upload/" . $_FILES["upfil"]["name"];
  8.         $fil_stoerrelse = filesize($fra)/1024;
  9.         if($fil_stoerrelse > $max) {
  10.             die("Desværre - dit billede er for stort!<br>Billedet må maks fylde " . $konfiguration["max_stoerrelse"] . " kb, og din fil fylder " . ceil($fil_stoerrelse) . " kb");
  11.         }
  12.         copy($fra, $til);
  13.         echo "Billedet er nu tilføjet! Linket til billedet er: $dir";
  14.     } else {
  15.         echo "Du har ikke valgt et billede";
  16.     }
  17. } else {
  18.     ?>
  19.     <form action="?add=yes" method="post" enctype="multipart/form-data">
  20.     <table border="0" cellpadding="2" cellspacing="0" style="width: 100%;">
  21.     <tr>
  22.     <td width="35%"><b>Billede:</b><br/><em>Vælg et billede fra din computer (Max 1MB)</em></td>
  23.     <td width="65%"><input type="file" name="upfil" style="width: 99%;" /></td>
  24.     </tr>
  25.     </table>
  26.     <input type="submit" name="submit" value="Upload!" style="width: 99%;" />
  27.     </form>
  28.     <?
  29. }
  30. ?>
Dette er et eksempel på et meget nemt og simpelt upload system. Systemet har en HTML formular som lader os vælge det billede vi vil uploade. Systemet kan også tjekke fil størrelsen så vi slipper for kæmpe filer (.bmp anyone?).

3.1  Hvad er problemet her?

Det ser jo alt sammen meget fint ud. Systemet kan bruges til at udvælge en billede på ens computer, uploade det til webserveren og derefter gemme det så faldt at filen overholder fil størrelses grænsen.
Problemet her ligger i at vi ikke tjekker hvad brugeren rent faktisk uploader til webserveren. Det kunne være alt fra et billede til et ondsindet PHP script!

3.2  Hvad gør vi ved problemet?

For at neutralisere dette problem bliver vi nød til at tjekke efter hvad det er som brugeren har uploadet. Dette kan gøres via PHP funktionen getimagesize().

3.2.1  getimagesize() hvad er det?

Denne simple funktion kan udtrække en fils mime type. I dette tilfælde bruger vi funktionen til at udtrække mime type'n på den uploadede fil.
Læs evt mere omkring denne funktion i manualen på php.net: her
Du kan derudover også finde en samling over kendte mime typer på W3schools: her

4.0  Implantering af getimagesize()

Da vi kun ønsker at der kan uploades .png .jpg og .gif billeder så vil vi tjekke efter deres mime typer.
Her er et eksempel på hvor simpelt det vil være at implantere dette:
  1. $imageinfo = getimagesize($_FILES['upfil']['tmp_name']);
  2.     if ($imageinfo['mime'] == 'image/gif' or $imageinfo['mime'] == 'image/jpeg' or $imageinfo['mime'] == 'image/png') {
  3. //Upload gemme del her.
  4. } else {
  5.     echo "Dit billede skal være jpg png eller gif!";
  6. }

4.1  Er der nogle problemer ved denne metode?

Der er et enkelt problem her. Og der er at det er muligt at snyde denne metode! Dette kan gøres via et meget listigt trick. Tricket går ud på at filer kan have mere to dots!
Dette kan for eksempel være ondsindetfil.php.gif. Det er måske ikke noget problem på nogle webservere, men for andre usikre webservere (Ja jeg kigger på jer one, surftown, gigahost, servage og andre!) ser .php delen FØRST og ignorere derefter .gif delen. Denne fil ville kunne uploades uden problemer igennem overståene løsning! Derefter vil vi lave et meget simpelt lille tjek imod dette og modificere vores fil tjek.
  1. $imageinfo = getimagesize($_FILES['upfil']['tmp_name']);
  2.     if (($imageinfo['mime'] == 'image/gif' or $imageinfo['mime'] == 'image/jpeg' or $imageinfo['mime'] == 'image/png') and !eregi('.php', $_FILES['upfil']['tmp_name'])) {
  3. //Upload gemme del her.
  4. } else {
  5.     echo "Dit billede skal være jpg png eller gif!";
  6. }
Som du kan se så har vi nu en if sætning som siger:
Hvis at filens mime type enten er: image/gif, image/jpeg eller image/png OG at der ikke findes .php i filens navn så kan der forsættes.

5.0  Den færdige løsning.

  1. <?
  2. if ($_GET['add'] == 'yes') {
  3.     $max = "1000"; // Maks størrelse i KB
  4.     if($_FILES["upfil"]["size"] > 0) {
  5.         $rand = rand(100000,999999);
  6.         $fra = $_FILES["upfil"]["tmp_name"];
  7.         $til = "../upload/" . $_FILES["upfil"]["name"];
  8.         $fil_stoerrelse = filesize($fra)/1024;
  9.         if($fil_stoerrelse > $max) {
  10.             die("Desværre - dit billede er for stort!<br>Billedet må maks fylde " . $konfiguration["max_stoerrelse"] . " kb, og din fil fylder " . ceil($fil_stoerrelse) . " kb");
  11.         }
  12.         $imageinfo = getimagesize($_FILES['upfil']['tmp_name']);
  13.         if (($imageinfo['mime'] == 'image/gif' or $imageinfo['mime'] == 'image/jpeg' or $imageinfo['mime'] == 'image/png') and !eregi('.php', $_FILES['upfil']['tmp_name'])) {
  14.             copy($fra, $til);
  15.             echo "Billedet er nu tilføjet! Linket til billedet er: $dir";
  16.         } else {
  17.             echo "Dit billede skal være jpg png eller gif!";
  18.         }
  19.     } else {
  20.         echo "Du har ikke valgt et billede";
  21.     }
  22. } else {
  23.     ?>
  24.     <form action="?add=yes" method="post" enctype="multipart/form-data">
  25.     <table border="0" cellpadding="2" cellspacing="0" style="width: 100%;">
  26.     <tr>
  27.     <td width="35%"><b>Billede:</b><br/><em>Vælg et billede fra din computer (Max 1MB)</em></td>
  28.     <td width="65%"><input type="file" name="upfil" style="width: 99%;" /></td>
  29.     </tr>
  30.     </table>
  31.     <input type="submit" name="submit" value="Upload!" style="width: 99%;" />
  32.     </form>
  33.     <?
  34. }
  35. ?>
Dette er så vores meget simple sikre upload system.

6.0  Ekstra sikkerhed

Man kan aldrig få for meget sikkerhed!
Først og fremmest ville det være klogt at gemme upload siden bag et login system som sikre at det kun er dig og andre med tilladelse ville kunne uploade.

6.1  Slå PHP helt fra i mappen

Selvom vi sikre os at vi ikke får uploadet nogle PHP scripts så kan vi ikke afvise at der ville være andre metoder til at få sneget den onde fil ind på vores server. Derfor laver vi i vores mappe som indeholder vores filer en .htaccess fil og indsætter følgene i toppen af den:
  • php_flag engine off
Dette fortæller apache at den ikke skal benytte PHP i pågældene mappe.

7.0  Hvad har vi så lært?

Vi har lært at det at efterlade et usikret upload system kan føre til overtagelse af din webserver.
Vi er lært at beskytte os imod disse angreb og effektivt ungå dem.
Vi har også lært hvor vigtigt det er altid at have styr på vores sikkerhed og aldrig at sløse med den.
Sidst redigeret 12:50 14/01/2010
Oprettet af:

PHP

Point modtaget: 499

Rating: 4.2
09:24 14/01/2010

Kommentarer

Giv din mening tilkende om denne artikel, eller læs andres.
Har du spørgsmål eller brug for hjælp til denne artikel henvises du til forummet.
Selfølgelidt er intet 100% sikkert. Dog er det så dumt bare at lade sådanne døre her stå åbne. Der vil altid være FTP bruteforcere og dårlige adgangskoder. Dog er det at sige "alt kan hackes" forkert. Hva ALT bliver lavet med yderst opmærksomhed og omhyggelighed så er der intet end FTP bruteforcing osv tilbage.
Oprettet af:
  Mail
07:48 03/02/2010
Superrob, alt kan hackes :o)

Og dem der vil bruge denne artikel bliver nok ikke udsat for de store angreb vil jeg skyde på.
Tror du derudover superrob, at dine ting er lavet så super smarte, så tror jeg desværre du vil blive overrasket, hvis du fandt ud af hvor hurtigt man kan komme ind i det.

vh
Nikolaj
Oprettet af:
  Mail
17:51 10/02/2010
Well hader den typpiske "alt kan hackes" som folk kommer med. Jeg vil rettere rette den til "alt kan bruteforces".
Oprettet af:
  Mail
04:44 21/03/2010
CMS systemer .. Made me laugh :P
Dog er der små fejl med dine ord, stavefejl..
Ellers er det faktisk meget bedre end hvad jeg forventede af dig ;-)
Men så længe du kun sikrer imod .php filer, så er jeg ret så sikker på at det vil være brudt hurtigere end du tror.. ;-)
Oprettet af:
  Mail
19:50 14/07/2010
Så kan man jo så tænke over, at siden måske også kan læse ASP filer, og har man glemt det, så kan man jo igen allerede der være screwed.
Oprettet af:
  Mail
03:39 23/07/2010
Nicklas. Self! Men nu går jeg jo ikke udfra at alle er idoiter og tilladeler alle sprog at køre på ens box. Min server f.eks. har ikke andet end PHP slået til.
Oprettet af:
  Mail
23:13 12/10/2010
Du skal være oprettet og logget ind for at kommentere en artikel
Copyright © Rowl.dk v/ Michael Raagaard | 2005-12 | Alle rettigheder forbeholdes