Kirjautuminen

Haku

Tehtävät

Keskustelu: Koodit: PHP: Turvallinen ja monipuolinen Upload

Sivun loppuun

Frozenball [04.08.2006 19:41:05]

#

Netissä liikkuu vaikka minkälaisia upload scriptoja. Useat niistä sallivat PHP-scriptojen uppimisen. Monet scriptit ovat ns. "kusessa", kun samanniminen tiedosto onkin olemassa.

Siistissä ZIP:issä saat tämän: http://omena.org/~dd/blog/?page_id=59

<?php
// Olen kyllästynyt huonoihin uppiscriptoihin, jotka sallivat
// php-scriptojen uppaamisen jne.

/*
* Copyright (c) 2006 Frozenball <orkkiolento@gmail.com>
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
*     * Redistributions of source code must retain the above copyright
*       notice, this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright
*       notice, this list of conditions and the following disclaimer in the
*       documentation and/or other materials provided with the distribution.
*     * Names of its contributors may not be used to endorse or promote products
*       derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

// Asetukset
$conf['filetypes'] = array("bmp","jpg","jpeg","png","swf","svg","txt");
$conf['max_filesize'] = 1024; // Max. tiedoston koko Kt. Eli 1024 = 1MB, 2048 = 2MB.
$conf['kansio'] = "uploads/"; // Kansio minne kaikki laitetaan.
$conf['fix_pahat_kirjaimet'] = true; // Muuttaa ääkköset aakkosiksi, poistaa ()[] jne.
$conf['polku'] = ""; // Laitetaan alkuun joku osoite. Älä muuta jos et tiedä mitä olet tekemässä
$conf['banned_ips'] = array("123.123.123.123","123.123.123.123"); // IP:t, jotka eivät voi lisätä tiedostoja.
$conf['imagecheck'] = true; // Tarkistaa onko kyseessä oikeasti kuva, jos tiedostopääte on GIF, JPG, PNG, SWF, SWC, PSD, TIFF, BMP, IFF, JP2, JPX, JB2, JPC, XBM tai WBMP.
$conf['nayta_tiedostot'] = true; // Näyttää listauksen upatuista tiedostoista
$conf['session'] = "upload"; // SESSION:in nimi. Ei tarvitse muuttaa, jos et tajua sitä.
$conf['charset'] = "ISO-8859-15"; // Merkistö. Yleensä ISO-8859-15

// Itse scripta. Älä koske enää ;)

// Onko CSS?
if (isset($_GET['css'])) {
    header('Content-type:  text/css; charset='.$conf['charset']);
    print '    body {
        font-size:12px;
        font-family:Verdana,Arial,sans-serif;
    }
    .fileupload, #fileupload_error {
        border:1px #8099B3 solid;
        margin:4px;
        padding:4px;
        width:60%; min-width: 350px;
        background-color:#F0F7FF;
        text-align:left;
        min-height:100px;

    }
    #fileupload_error { background-color:#F7DDDD; border:1px #841C1C solid; }

    .fileupload label {
        float:left;
        width:100px;
        text-align:right;
        padding-right:10px;
    }
    .fileupload input {
        float:left;
        width:200px;
        text-align:left;
        font-size:12px;
        font-family:Verdana,Arial,sans-serif;


    }
    #submit {
        margin-top:3px; border:1px #3D5A7C solid; background-color:#CBD5E0;
        margin-left:110px; width:auto!important;
    }
    #submit:hover { background-color:#B1C1D3; }
    h1 { margin:0px; padding:0px; color:#893939; border-bottom:1px #E13232 dotted; }
    #ilo { color:#426854;  border-bottom:1px #2FB970 dotted; }
    .tieto { font-size:10px; color:#616161; margin-left:110px; }
    br { clear:left; }
    .tiedosto { width:50%; float:left; }
    ';
    exit;
}

session_start();
// Merkistö
header('Content-type: text/html; charset='.$conf['charset']);

// Tarvittavat functiot
function humanread($bytes) {
    $pp = array("B","KB","MB","GB","TB");
    $menossa = 0;
    while ($bytes >= 1024) {
        $menossa++;
        $bytes = $bytes / 1024;
    }
    return round($bytes,2).$pp[$menossa];
}

function msgdie($msg,$error=false) {
    print('<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
  <head>
    <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset='.$conf['charset'].'">
    <LINK rel="stylesheet" type="text/css" href="'.$_SERVER['PHP_SELF'].'?css">
    <title>File Upload - Ilmoitus</title>
    <style type="text/css">

    </style>
  </head>
  <body>
    <center>');


if ($error == true) print '<div id="fileupload_error"><h1>Virhe</h1>';
else  print '<div class="fileupload"><h1 id="ilo">Ilmoitus</h1>';

print ('
            '.$msg.'
        </div>
    </center>
  </body>
</html>');
exit();

}

// Käydään bannatut IP:t läpi
foreach ($conf['banned_ips'] as $ip) {
    if ($_SERVER['REMOTE_ADDR'] == $ip) msgdie("Olet bannattu eli sinulla on porttikielto.",true);
}
// Jos uppaus?
if (is_numeric($_POST['upload'])) {

    // Aikatarkistukset
    if (strlen($_POST['upload']) > (strlen(time()) * 100)) msgdie("Jotain ihmeellistä on tapahtunut...",true);
    if ($_POST['upload'] > time()) msgdie("Olet etuajassa.",true);
    if ($_SESSION[$conf['session']] == $_POST['upload']) msgdie("Olet nähtävästi yrittänyt painaa Refresh nappulaa. Paina mielummin <a href='".$_SERVER['PHP_SELF']."'>tästä</a>.",true);

    // Tiedostolle tarkistukset
    if ($_FILES['file']['size'] > ($conf['max_filesize'] * 1024)) msgdie("Tiedosto on liian suuri. Kokorajoitus on ".humanread($conf['max_filesize'] * 1024),true);
    if ($_FILES['file']['size'] == 0) msgdie("Yritätkö edes lähettää tiedostoa...?",true);

    // Tiedostonpääte
    list($tiedoston_paate) = array_reverse(explode(".",$_FILES['file']['name']));
    $tiedoston_paate = strtolower($tiedoston_paate);
    if ($tiedoston_paate == "") msgdie("Tällä tiedostolla ei ole tiedostonpäätettä tai jotakin ihmeellistä tapahtui.<br><br>Palaa <a href='".$_SERVER['PHP_SELF']."'>tästä</a> takaisin.",true);
    $sallitaanko = false;
    foreach ($conf['filetypes'] as $sallittu) {
        if ($tiedoston_paate == strtolower($sallittu)) $sallitaanko = true;
    }
    if ($sallitaanko == false) msgdie("Tiedostonpääte ".$tiedoston_paate." ei ole sallittu.<br><br>Palaa <a href='".$_SERVER['PHP_SELF']."'>tästä</a> takaisin.",true);

    // Tarkistus
    if ($conf['imagecheck'] == true) {
        #GIF, JPG, PNG, SWF, SWC, PSD, TIFF, BMP, IFF, JP2, JPX, JB2, JPC, XBM tai WBMP
        $tuetut = array("gif","jpg","jpeg","png","swf","swc","psd","tiff","bmp","iff","jp2","jpx","jb2","jpc","xbm","xbmp");
        if (in_array($tiedoston_paate,$tuetut)) {
            if (!@getimagesize($_FILES['file']['tmp_name'])) msgdie("Tiedostonpääte ".$tiedoston_paate." ei ole oikea. Olet saattanut nimetä esimerkiksi zip tiedoston tiedostopäätteen.<br><br>Palaa <a href='".$_SERVER['PHP_SELF']."'>tästä</a> takaisin.",true);
        }
    }


    // Nyt on siirron aika
    if (!is_dir($conf['kansio'])) { @mkdir($conf['kansio']) or msgdie("Kansiota ".$conf['kansio']." ei ole olemassa.",true); }
    $tiedoston_nimi_orginal = basename($_FILES['file']['name']);



    // ÄÄKKÖSKORJAUS
    if ($conf['fix_pahat_kirjaimet'] == true) {
        $tiedoston_nimi_orginal = str_replace(array("ä","ö","å","Ä","Ö","Å"," "),array("a","o","a","A","O","A","_"),$tiedoston_nimi_orginal);
        $tiedoston_nimi_orginal = preg_replace("[^a-zA-Z0-9]","",$tiedoston_nimi_orginal);
    }
    // Harvinaista - mutta mahdollista
    if ($tiedoston_nimi_orginal == "") { $tiedoston_nimi_orginal = base64_encode(basename($_FILES['file']['name']));  }

    $tiedoston_nimi = $tiedoston_nimi_orginal;

    $i = 1;
    while (is_file($conf['kansio'].$tiedoston_nimi)) {
        // Tiedosto on jo olemassa, eli keksitään uusi nimi
        $halkaistu = explode(".",$tiedoston_nimi_orginal);
        $halkaistu[0] = $halkaistu[0]."_".$i;
        $tiedoston_nimi = implode(".",$halkaistu);
        $i++;
    }

    if (@move_uploaded_file($_FILES['file']['tmp_name'], $conf['kansio'].$tiedoston_nimi)) {
        $polku = $conf['polku'].$conf['kansio'].$tiedoston_nimi;
        if ($conf['polku'] != "") $polku = $conf['polku'].$tiedoston_nimi;

        $_SESSION[$conf['session']] = $_POST['upload'];

        msgdie("Tiedosto ".$tiedoston_nimi." on siirretty onnistuneesti. Pääset käsiksi tiedostoosi tästä:<br><br>
        <a href='".$polku."'>".$tiedoston_nimi."</a><br><br>Palaa <a href='".$_SERVER['PHP_SELF']."'>tästä</a> takaisin.");
    } else {
        msgdie("Tiedoston siirto ei onnistunut. Tämä johtuu mm. seuraavista syistä:<br>* Tällä scriptillä ei ole oikeuksia upload kansioon.<br><br>Palaa <a href='".$_SERVER['PHP_SELF']."'>tästä</a> takaisin.",true);
    }


}

?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
  <head>
    <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=<?php print $conf['charset']; ?>">
    <LINK rel="stylesheet" type="text/css" href="<?php print $_SERVER['PHP_SELF']; ?>?css">
    <title>File Upload</title>
    <style type="text/css">

    </style>
  </head>
  <body>
    <center>

        <div class="fileupload">
            <form action="<?php print $_SERVER['PHP_SELF']; ?>" method="POST" enctype="multipart/form-data">
            <input type="hidden" name="upload" value="<?php print time(); ?>">
            <label for="file">Tiedosto:</label>
            <input type="file" name="file" id="file">
            <br>
            <div class="tieto">Sallitut tiedostopäätteet <?php print implode(", ",$conf['filetypes']); ?> ja suurin sallittu tiedostonkoko on <?php print humanread($conf['max_filesize'] * 1024); ?></div>
            <input type="submit" name="submit" id="submit" value="Upload">
            <br>
            </form>
        </div>
        <?php
        if ($conf['nayta_tiedostot'] == true) {
            print '
            <div class="fileupload" style="min-height:30px;">
            <b>Tiedostot:</b><br>
            ';
            $kayty_lapi = false;
            foreach (glob($conf['kansio']."*") as $filename) {
                $kayty_lapi = true;
                print "<div class='tiedosto'><a href='".$filename."'>".basename($filename)."</a></div>\n";
            }

            if ($kayty_lapi == false) print "Ei tiedostoja";

            print '
            <br>
            </div>
            ';
        }
        ?>
        <div id="footer">Powered by <a href="http://frozenblog.urli.net">FruitUpload</a>. | Valid <a href="http://validator.w3.org/check?uri=referer">HTML</a> and <a href="http://jigsaw.w3.org/css-validator/check/referer">CSS</a></div>

    </center>
  </body>
</html>

Frozenball [04.08.2006 19:48:10]

#

Demo löytyy tästä: http://dd.simppeli.org/upload_demo/

E.K.Virtanen [06.08.2006 21:41:18]

#

Hienosti toimii. Tällaiselle olisi käyttöä, ilmoitan toki sinulle sitten ensin =)

tgunner [07.08.2006 15:26:34]

#

Hieno koodi, mutta kyllä tästäkin on bugeja löydyttävä!
Hyvin kommentoitu! :)

NiLon [08.08.2006 06:02:57]

#

Hyvin kommentoitu? Tarkoitat varmaan ettei kommentointia ole.

Aika sörsseliä mikäli minulta kysytään, mutta hoitaa homman.

NanoSoft [14.08.2006 00:11:30]

#

Bugi: muutin tossa demossa yhden zipin txt päätteiseksi, uppasin sen ja kun painoin sen linkkiä niin tarjottiinkin taas zip tiedostoa..

riiali [21.08.2006 18:22:55]

#

Miten tohon sais lisättyä jotenkin, että noita tiedostoja voisi myös poistaa tuolta??

ZcMander [29.08.2006 19:37:49]

#

Teet PHP-skriptin joka osaa poistaa tiedosotoja "tuolta". Yksinkertaista.

hmmp [19.09.2006 00:19:13]

#

Toimiva, mutta kyllä tuohon kannattaisi lisätä $_FILES['file']['error'] -muuttujan käsittely. Kun siirrossa menee jotain pieleen, niin syykin olisi mukava tietää.

siansaksamies [08.10.2006 13:11:26]

#

Tarviiks tonne sulloo tunnuksii, salasanoi yms.?

tsuriga [10.10.2006 12:13:30]

#

Aika ahtaan näköistä koodia. Tästä saisi vaikka luokan, jota voisi käyttää suoraan luomalla siitä olion. Nyt käyttö on turhan rajoittunutta.

-"original" ei "orginal". Muutenkin kielien yhdistäminen ei ole selkeän dokumentoinnin kannalta suotavaa.

-Yhden rivin if-lauseet eivät tarvitse hakasulkuja. Kun nyt niitä tahdot kuitenkin käyttää niin jaottele ehto ja toiminto eri riveille, esim:

<?php
if (ehto) {
    toiminto; // käytin neljää väliä sisentämiseen kun ei tabi toimi
}
?>

En nyt muista suositteleeko myös PEARin syntaksiopas laittamaan tuon aloittavankin hakasulun omalle rivilleen, ainakin Javassa näin muistaakseni on, mutta itse en vain ole tavoille oppinut.

-Eikös kilon lyhenne ole pieni k?

-PHP_SELF ei ole turvallinen, käytä SCRIPT_NAMEa.
Esimerkki PHP_SELFin turvattomuudesta

-Ja paljon muuta pientä :).

tj-tommi [24.10.2006 17:11:37]

#

... mulla kun koitta avata uploadun kuvan se ilmottaa et se on frobbien 403... miten saan sen että kaikki näkee ne kuvat?

Codeprofile [21.11.2006 22:33:38]

#

Aluksi toi ei toiminu. Otin rivit 126-128 pois, ja nyt toimii.

Tuohan on mainiota. Himan höystettynä tuota voi käyttää vaikka missä.

Magicbullet [05.07.2008 23:24:51]

#

Nam, mikä koodi..

http://magicbullet.jouluserver.com/upload/upload.php

nerootto [14.07.2009 15:38:44]

#

Tässä koodissa pitäisi olla logi, johon kirjataan tiedoston lähettäjän ip näin:
tiedosto|ip

Lisäsin toiminnon itselleni.

Clacier [12.05.2010 17:03:09]

#

nerootto kirjoitti:

Tässä koodissa pitäisi olla logi, johon kirjataan tiedoston lähettäjän ip näin:
tiedosto|ip

Lisäsin toiminnon itselleni.

No ei ole vaikea tehdä.


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta