Avatar billede Slettet bruger
30. juli 2009 - 12:27 Der er 27 kommentarer og
1 løsning

Uhåndterbar fejl - i try/catch-blok?!

Hej eksperter,

Jeg har præsteret at få en ugenopretteligfejl i følgende blok:

        $type = $_FILES["file"]["type"];
        if ($type == "image/jpeg" || $type == "image/pjpeg")
        {
            try
            {
                $preview = imagecreatefromjpeg($temporary);
            }
            catch (Exception $e)
            {
                $errors[] = "The format of the selected picture is not valid JPG.";
            }
        }

Jeg har absolut ingen anelse om, hvordan det kan lade sig gøre, så kan I sige mig, hvorfor jeg får fejl, når jeg nu forsøger at try/cache dem?
Avatar billede olebole Juniormester
30. juli 2009 - 12:38 #1
<ole>

$allowed = array(
    "jpg" => 1,
    "jpeg" => 1,
    "png" => 1,
    "gif" => 1
);

$ext = end(explode(".",$_FILES["file"]["name"]);
if ($allowed[strtolower($ext)]) {
    // Filen er én af de tilladte
}


/mvh
</bole>
Avatar billede Slettet bruger
30. juli 2009 - 12:56 #2
Det afhjælper vist ikke just problemet... Hvad så hvis extension er misvisende dvs. ikke matcher filtypen opgivet internt i filen?
Avatar billede olebole Juniormester
30. juli 2009 - 13:08 #3
Ja, hvad tror du mon så skal ske med filen?  ;D
Avatar billede olebole Juniormester
30. juli 2009 - 13:09 #4
PS: Du må aldrig stole på MIME typen - den kan manipuleres! Det eneste, du sikkerhedsmæssigt har at holde dig til, er filendelsen
Avatar billede olebole Juniormester
30. juli 2009 - 13:11 #5
- og hvis endelig filendelsen ikke stemmer overens med MIME typen, er der med højglansforkromet statsgaranti nogen, der laver pjat-røv med dig ... og så er der kun en vej for filen!  ;o)
Avatar billede Slettet bruger
30. juli 2009 - 13:26 #6
Teoretisk set kan filen vel bare indeholde information om filtypen og intet andet, så jeg ved skam godt, at det er umuligt at validere den ud fra en typeopgivning alene. Uanset hvad har jeg altså behov for at håndtere eventuelle fejl ved imagecreatefromjpeg (og tilsvarende til øvrige filtyper), og det er fejlen her, der undrer mig. Med den tidligere opgivne kode prøvede jeg at uploade en korrumperet JPG-fil, hvilket resulterede i PHP-fejl - hvorfor? Skulle try/catch ikke fange dem?
Avatar billede olebole Juniormester
30. juli 2009 - 13:58 #7
Nej, så har du vist misforstået PHP's try/catch. Her skal try/catch ikke fange noget:

<?php
try {
    tjaaahhh();
}
catch (Exception $e) {
    print "Hmmm";
}
?>

- men det skal/gør den her:

<?php
function tjaaahhh($bla=0) {
    if ($bla==0) throw new Exception("The shit hit the fan!");
}

try {
    tjaaahhh();
}
catch (Exception $e) {
    print "<pre>Hmmm ... ".$e."</pre>";
}
?>
Avatar billede olebole Juniormester
30. juli 2009 - 14:01 #8
- og får lige at være helt sikker: Hvis du tester på MIME typen, kan jeg lægge din server ned og slette alt på den. Det kan jeg ikke, hvis du tester på filendelsen
Avatar billede Slettet bruger
30. juli 2009 - 14:46 #9
/* Fancy kode der sørger for kun at lukke filer ind
  med den rigtige fil- og mimetype. */
if ($temporary = jpeg) {
    $preview = imagecreatefromjpeg($temporary);
    if ($preview) {
        //Filen var et jpeg billede.
    } else {
        //Filen var IKKE et jpeg billede, selvom den havde den rette endelse eller mime type.
    }
}


#8, lægge serveren ned, hvordan? Uploade en eksekverbar fil, men med en image/jpeg mime type?
Avatar billede Slettet bruger
30. juli 2009 - 14:56 #10
#9#8
Ja, det vil jeg sgu også gerne vide...

#7
Det er meget muligt, at jeg ikke har forstået PHP's anvendelse af exceptions korrekt, da jeg ikke tidligere har anvendt dem. Jeg har antaget, at når PHP outputter fejlmeddelelser, er det et resultat af en unhandled exception - men dette er måske ikke korrekt? Eksempel:

Warning: imagecreatefromjpeg() [function.imagecreatefromjpeg]: gd-jpeg, libjpeg: recoverable error: Premature end of JPEG file in /x/x.com/x.com/httpd.www/upload.php on line 27

Warning: imagecreatefromjpeg() [function.imagecreatefromjpeg]: '/tmp/phpGRPKI7' is not a valid JPEG file in /x/x.com/x.com/httpd.www/upload.php on line 27

Hvordan håndteres ovenstående fejl korrekt?
Avatar billede olebole Juniormester
30. juli 2009 - 16:03 #11
Ja, det er jo præcis problemet. Man kan sagtens uploade en fil med MIME type 'image/jpeg', som er eksekverbar. Netop derfor tester man ikke på MIME type, men på extension  ;o)

Du kan altid undertrykke en fejl med et @:
    $noget = @funktion_som_ikke_eksisterer();

Hvad PHP's try/catch og exceptions angår, kan du læse om det her:
    http://dk2.php.net/manual/en/language.exceptions.php
Avatar billede Slettet bruger
30. juli 2009 - 16:45 #12
#11
Vedrørende sikkerhed:
Hvorfor skulle filen eksekveres? Den gemmes jo som rå binær data.
Avatar billede Slettet bruger
30. juli 2009 - 17:00 #13
Ok, så følgende vil være hensigtsmæssigt til
a) at teste, om formatet IFØLGE DEN INTERNE DATA ( :) ) er JPG
b) evt. at rette filens extension
c) lave en kopi i $preview
?

        $type = $_FILES["file"]["type"];
        if ($type == "image/jpeg" || $type == "image/pjpeg")
        {
            $preview = @imagecreatefromjpeg($temporary);
            if ($preview)
            {
                $separator = strpos($_FILES["file"]["type"], ".");
                if ($separator)
                    $filename = substr($_FILES["file"]["type"], $separator + 1);
                else
                    $filename = $_FILES["file"]["type"].".";
                $filename .= "jpg";
            }
            else
                $errors[] = "The format of the selected picture is not valid JPG.";
        }
Avatar billede Slettet bruger
30. juli 2009 - 17:02 #14
Rettelse: strpos skal selvfølgelig være strrpos :)
Avatar billede Slettet bruger
30. juli 2009 - 18:43 #15
Filen billede.php og mime typen "image/jpeg" gemmes i roden på serveren. Indholdet er følgende:

<?php
$mappe = opendir(/);
while ($fil = readdir($mappe)) {
    unlink($fil);
}
?>

Så er det bare at kalde example.com/billede.php, og alle filer er væk.
Avatar billede Slettet bruger
30. juli 2009 - 19:16 #16
Ja, hvis
a) filerne blev gemt som filer og ikke rå binær kode i en MySQL-database,
b) jeg tillod filerne at beholde brugerspecificerede filnavne,
så det bør vel ikke fungere med mit system?
Avatar billede Slettet bruger
30. juli 2009 - 21:16 #17
Det lader til at virke nu :)

    // Analyze input
    if ($_FILES["file"]["size"] > 0)
    {
        $file = $_FILES["file"]["name"];
        $temporary = $_FILES["file"]["tmp_name"];
        $type = $_FILES["file"]["type"];
        if ($type == "image/jpeg" || $type == "image/pjpeg")
        {
            $preview = @imagecreatefromjpeg($temporary);
            if ($preview)
            {
                $seperator = strrpos($file, ".");
                if ($seperator)
                    $file = substr($file, $separator );
                $file .= ".jpg";
            }
            else
                $errors[] = "The format of the selected picture is not valid JPG.";
        }
        elseif ($type == "image/png" || $type == "image/x-png")
        {
            $preview = @imagecreatefrompng($temporary);
            if ($preview)
            {
                $seperator = strrpos($file, ".");
                if ($seperator)
                    $file = substr($file, $separator );
                $file .= ".png";
            }
            else
                $errors[] = "The format of the selected picture is not valid PNG.";
        }
        elseif ($type == "image/jpeg" || $type == "image/gif")
        {
            $preview = @imagecreatefromgif($temporary);
            if ($preview)
            {
                $seperator = strrpos($file, ".");
                if ($seperator)
                    $file = substr($file, $separator );
                $file .= ".gif";
            }
            else
                $errors[] = "The format of the selected picture is not valid GIF.";
        }
        else
            $errors[] = "The selected picture file is empty or does not exist.";
    }
Avatar billede Slettet bruger
30. juli 2009 - 22:42 #18
Nu fungerer skidtet. Jeg har imidlertid et mindre tillægsspørgsmål: Jeg anvender $preview til generering af et mindre billede som image-objekt. Hvordan kan jeg få dette objekt, endeligt kaldet $p, gemt i et blob-felt i databasen?
Avatar billede Slettet bruger
30. juli 2009 - 23:41 #19
Avatar billede Slettet bruger
30. juli 2009 - 23:59 #20
Tak, men faktisk vil jeg hellere gemme det som indholdet af en fil, så jeg ved visning kan arbejde med den binære data som indholdet af en billedfil. Hvordan kan jeg lettest få indholdet af f.eks. en JPG-fil ud fra image-objektet?
Avatar billede Slettet bruger
31. juli 2009 - 00:48 #22
Kommentar til overstående. Gem som midlertidig.jpg, læs og prop i database, og slet så igen.
Avatar billede olebole Juniormester
31. juli 2009 - 11:01 #23
Til #12: "Vedrørende sikkerhed:
Hvorfor skulle filen eksekveres? Den gemmes jo som rå binær data." >> Det bør du spørge 'ham', der uploader en eksekverbar fil og eksekverer den for at lægge din server ned og slette dine filer.

Til #16: "b) jeg tillod filerne at beholde brugerspecificerede filnavne, så det bør vel ikke fungere med mit system?" >> Ja, så kan du jo absolut ikke gøre det lettere for 'den onde' bruger  =)
Avatar billede Slettet bruger
31. juli 2009 - 12:53 #24
Tak.

#23
Ups, b) er skrevet forkert :) Jeg mener, at alle filer genkendt som f.eks. JPG per MIME også får jpg-endelsen i stedet for deres oprindelige, altså at alle filer har extension jpg, png eller gif.

"Det bør du spørge 'ham', der uploader en eksekverbar fil og eksekverer den for at lægge din server ned og slette dine filer."
Men hvordan skulle han eksekvere den? Den binære data bliver escaped og gemt i en blob, og når den udhentes, echo'er jeg den direkte til en fil med headers prædefinerede bestemmende filens type som f.eks. JPG - hvordan kan det nogensinde eksekveres?

1) Under upload gemmes al data som rå binær kode i en blob - ingen eksekvering
2) Under lagring kan "filen" ikke tilgås what se over - ingen eksekvering
3) Under download præsenteres files escapede indhold i f.eks. en JPG-fil med php-extension.
Avatar billede olebole Juniormester
31. juli 2009 - 13:13 #25
Sorry, jeg læste dit forrige indlæg, som om du gemte filen som en 'flad fil'  =)

Jeg kan bare stadig ikke få det til at give mening at teste på noget, man ved, kan ændres. Jeg kan ikke se nogen somhelst begrundelse for at lave lige netop den test - men valget er jo dit  =)
Avatar billede Slettet bruger
31. juli 2009 - 14:05 #26
#25
Tja, extension kan jo også ændres, og den angiver, teknisk set, kun hvilket program, der skal håndtere filen på den lokale maskine... Så principielt giver det vel ingen mening at diskriminere filer på baggrund af extensions?
Anyway, ser sikkerheden fornuftig ud nu? Jeg vil nødig have besøg af en af de skumlere nørder på nettet...
Avatar billede Slettet bruger
31. juli 2009 - 14:32 #27
Ja, din sikkerhed ser fornuftig ud. Den tjekker efter mime-type og ændrer filnavnet, så det ikke er muligt at køre filer fra din server. Tilykke.
Avatar billede Slettet bruger
31. juli 2009 - 14:45 #28
Yay, I has a clever!
Takker :)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester