[PHP allgemein] Zusatzbedingung in Script integrieren Remote

Fragen zu allen Themen rund ums Programmieren außerhalb von phpBB können hier gestellt werden - auch zu anderen Programmiersprachen oder Software wie Webservern und Editoren.
Antworten
Benutzeravatar
HabNurNeFrage
Ehemaliges Teammitglied
Beiträge: 1627
Registriert: 17.01.2010 20:22
Wohnort: An der Ostsee
Kontaktdaten:

[PHP allgemein] Zusatzbedingung in Script integrieren Remote

Beitrag von HabNurNeFrage »

Hi PHP-Pros,

in folgendes kleines Remote-Script soll eine Abfrage eingebaut werden, damit nur gif, jpg und png Dateien damit verlagert werden können.

Code: Alles auswählen

<?php
$upload_folder = "./upload/";
if (isset ($_POST["remote_url"]) )
 {
 $read = fopen ($_POST["remote_url"], "rb");
 $image_contents = null;
 if ($read)
 {
 while (!feof ($read) )
 {
 $image_contents = $image_contents . fread ($read, 8194);
 }
 fclose ($read);
 }
 else
 {
 echo "Kopieren nicht möglich. URL konnte nicht gelesen werden.";
 exit;
 }
 $url_part = explode ("/", $_POST["remote_url"]);
 $last_url_part = (count ($url_part) - 1);
 $filename = $url_part[$last_url_part];
 $write = fopen ($upload_folder . $filename, "w");
 fwrite ($write, $image_contents);
 fclose ($write);
 echo "Bild erfolgreich verschoben:" . $filename . " \r";
 }
else
 {
?>

[hier ist mein html-Formular, in dem die URL eingefügt und abgesendet wird]

<?php
 }
?>
Funktioniert soweit auch, enthält aber eine böse Sicherheitslücke. Das Script prüft leider nicht, ob es sich um eine Bild-Datei handelt.
Momentan wird damit ganz stupide jede Datei auf den Server remotet.

Gerne würde ich vor dem Speichern auf meinem Server sicherstellen, dass nur gif, jpg und png verschoben werden und bei sonstigen Datein eine Fehlermeldung erscheint.
Das Formular sendet die Daten per method="post" an sich selbst. Möglich wäre auch ein zweites PHP, dass die Daten empfängt und prüft.

Vielleicht könnte folgende Funktion eingebaut werden:

Code: Alles auswählen

function is_valid_type($file)
{
    $size = getimagesize($file);
    if(!$size) {
        return 0;
    }

    $valid_types = array(IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG);

    if(in_array($size[2],  $valid_types)) {
        return 1;
    } else {
        return 0;
    }
}
Wie kann ich nun vor dem Verschieben prüfen, ob es sich bei der Datei aus der Remote-URL um ein Bild handelt?

LG

PS: Später soll das Ganze dann auf einem Freehoster laufen und in einen bbCode eingebaut werden, um Remote-Uploads für Bilder zu ermöglichen.
| HomeStory.org - the friendly Community | Forum für alle Lebenslagen | <"}))}~ | Nicht nachmachen: Meine phpBB Spielereien |
var shoppen = geld.replace (/geld/g, 'bloedsinn'); if (geld < 1) { return home; };
Benutzeravatar
Unimatrix_0
Mitglied
Beiträge: 392
Registriert: 03.11.2007 10:50
Kontaktdaten:

Re: [PHP allgemein] Zusatzbedingung in Script integrieren Re

Beitrag von Unimatrix_0 »

Hi,

schau dir doch die Avatar-Functionen von phpBB an - geschickt "geklaut" ist halb gewonnen - und phpBB prüft ja auch ob die Datei ein Bild ist, ...

Als Einstiegspunkt würde ich zB https://github.com/phpbb/phpbb3/blob/ma ... .php#L1922 wählen
Benutzeravatar
gn#36
Ehrenadmin
Beiträge: 9313
Registriert: 01.10.2006 16:20
Wohnort: Ganz in der Nähe...
Kontaktdaten:

Re: [PHP allgemein] Zusatzbedingung in Script integrieren Re

Beitrag von gn#36 »

Zum einen das, zusätzlich würde ich das etwas zusammenstreichen, Dateien - egal ob remote oder lokal - einzulesen kannst du auch mit einem einzelnen befehl machen: [php:file] oder [php:file_get_contents].

Ich würde auch den Dateinamen nicht als Dateinamen auf der Festplatte nehmen - sonst führen zwei gleich benannte Dateien von unterschiedlichen Quellen dazu, dass die andere überschrieben wird.

Ansonsten kannst du die Datei z.B. auch erst speichern, dann überprüfen und anschließend wieder löschen.
Begegnungen mit dem Chaos sind fast unvermeidlich, Aber nicht katastrophal, solange man den Durchblick behält.
Übertreiben sollte man's im Forum aber nicht mit dem Chaos, denn da sollen ja andere durchblicken und nicht nur man selbst.
Benutzeravatar
HabNurNeFrage
Ehemaliges Teammitglied
Beiträge: 1627
Registriert: 17.01.2010 20:22
Wohnort: An der Ostsee
Kontaktdaten:

Re: [PHP allgemein] Zusatzbedingung in Script integrieren Re

Beitrag von HabNurNeFrage »

Hi,

vielen Dank für Eure Antworten.
Es wird augenscheinlich getimagesize () und includes/functions_upload.php zur Prüfung herangezogen.
Über file_get_contents () bin ich bei meiner Suche auch gestolpert und damit wird es wirklich sehr viel magerer.

Um die Dateien vor dem Upload zu prüfen, müsste man dabei die Post-Daten einem zweiten Script übergeben und dort weiter verarbeiten.

Im Netz habe ich nach einigem Suchen ein wirklich sicheres Script gefunden, welches die Bilder mittels php imagecreate neu erzeugt und dann speichert.
Das bietet dann wirkliche Sicherheit und hat den Vorteil, dass alles anhand eines einzigen Scriptes erledigt werden kann.

Falls jemand interesse hat, habe ich das komplette Script mal ins PasteBin geschmissen:
https://www.phpbb.de/support/pastebin.p ... iew&s=1245

Damit es nicht verloren geht, hier nochmal direkt:

Code: Alles auswählen

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>:: Bild von externer URL auf lokalem Server erzeugen :: Remote-Upload ::</title>
</head>
<body>

<?php

/*
 
 * thanx to the author: Swashata <swashata@intechgrity.com>
 * original script rights: do what ever you wish (lizenzfrei zur freien verfuegung / keine auflagen)
 * script and support: http://www.intechgrity.com/?p=808
 * kommentare uebersetzt, hilfe hinzugefuegt und formular ergaenzt: hirni
 *
 * hilfe: 
 * variable $store_dir in zeile function gibt den ordner an, in dem die bilder erzeugt werden
 * der ordner muss nicht vorhanden sein, wird bei bedarf automatisch erzeugt und erhaelt dabei saemtliche dateiberechtigungen (unix chmod 755)
 * das formular verweist auf sich selbst und uebergibt dabei die url an die funktion
 * wenn eine unerlaubte url abgesendet wird, die z.b. malware oder fiese scripte enthalten, wird das formular automatisch leer neu geladen
 * im erfolgsfall wird die url zum neu erzeugten bild auf dem lokalen server ausgegeben - verlinkt mit dem neuen bild
 * die dateinamen der neu erzeugten bilder werden dem original entnommen und bei bereits vorhandener bezeichnung aufsteigend nummeriert
 * der linktext zum bild kann im letzten echo angepasst werden (momentan erfolgt die ausgabe des relativen pfades)
 * der dateiname dieses dokumentes muss gleichlautend mit dem action="..." attribut des formulars sein, damit es an sich selbst gesendet wird

 */


function itg_fetch_image($img_url, $store_dir = 'remoted', $store_dir_type = 'absolute', $overwrite = false, $pref = false, $debug = false) 
	{
    //erzeugt bild-name ohne pfad
    $i_name = explode('.', basename($img_url));
    $i_name = $i_name[0];

    //finde bild-typ anhand der url
    //abfrage, ob die dateiendung erlaubt ist
    //ergibt hackerschutz
    if(preg_match('/https?:\/\/.*\.png$/i', $img_url)) {
        $img_type = 'png';
    }
    else if(preg_match('/https?:\/\/.*\.(jpg|jpeg)$/i', $img_url)) {
        $img_type = 'jpg';
    }
    else if(preg_match('/https?:\/\/.*\.gif$/i', $img_url)) {
        $img_type = 'gif';
    }
    else {
        if(true == $debug)
            echo 'URL falsch oder unlesbar.';
        return ''; 
    }

    $dir_name = (($store_dir_type == 'relative')? './' : '') . rtrim($store_dir, '/') . '/';

    //erzeugt ordner, wenn nicht vorhanden - name des ordners ./remoted/ mit allen datei-rechten
    if(!file_exists($dir_name))
        mkdir($dir_name, 0777, true);

    //erzeugt pfad zum bild
    $i_dest = $dir_name . $i_name . (($pref === false)? '' : '_' . $pref) . '.' . $img_type;

    //abfrage, ob pfad bereits vorhanden
    if(file_exists($i_dest)) {
        $pref = (int) $pref;

        //erzeugt bei bedarf neuen dateinamen, falls bereits vorhanden
        if(false == $overwrite)
            return itg_fetch_image($img_url, $store_dir, $store_dir_type, $overwrite, ++$pref, $debug);
        //wird das selbe bild erneut hochgeladen, wird das duplikat automatisch entfernt
        else
            unlink ($i_dest);
    }

    //abfrage, ob sich hinter der uebergenbenen url wirklich um ein bild handelt
    $img_info = @getimagesize($img_url);

    //abfrage, ob der bild-typ erlaubt ist mit eingrenzung auf jpg, gif und png
    if(false == $img_info || !isset($img_info[2]) || !($img_info[2] == IMAGETYPE_JPEG || $img_info[2] == IMAGETYPE_PNG || $img_info[2] == IMAGETYPE_JPEG2000 || $img_info[2] == IMAGETYPE_GIF)) 
	{
        if(true == $debug)
            echo 'Problem mit dem Datei-Inhalt entdeckt. Bild-URL erneut eingeben.<br />Es sind nur Bilder in den Formaten jpg, gif und png erlaubt.';
        return ''; //leere variable, wenn bild nicht erlaubt
    }

    //erzeugt neues bild aus dem alten, damit es keinesfalls zum upload von anderen dateien kommen kann
    if($img_type == 'jpg') {
        $m_img = @imagecreatefromjpeg($img_url);
    } else if($img_type == 'png') {
        $m_img = @imagecreatefrompng($img_url);
        @imagealphablending($m_img, false);
        @imagesavealpha($m_img, true);
    } else if($img_type == 'gif') {
        $m_img = @imagecreatefromgif($img_url);
    } else {
        $m_img = FALSE;
    }

    //abfrage, ob neues bild erfolgreich erzeugt werden konnte
    if(FALSE === $m_img) {
        if(true == $debug)
            echo 'Bild kopieren fehlgeschlagen.';
        return '';
    }

    //schreibt neues bild in den pfad auf dem lokalen server
    if($img_type == 'jpg') {
        if(imagejpeg($m_img, $i_dest, 100))
            return $i_dest;
        else
            return '';
    } else if($img_type == 'png') {
        if(imagepng($m_img, $i_dest, 0))
            return $i_dest;
        else
            return '';
    } else if($img_type == 'gif') {
        if(imagegif($m_img, $i_dest))
            return $i_dest;
        else
            return '';
    }

    return '';
}

$new_img = $_POST["remote_url"];
$new_img_path = itg_fetch_image ($new_img);


//erzeugt html-formular, wenn keine gueltige bild-url uebergeben wurde oder gibt das ergebnis aus, wenn das script erfolgreich war
if ($new_img_path !== '')
 {
 echo "Bild erfolgreich erstellt:<br /><a href=\"$new_img_path\">$new_img_path</a>";
 }

else
 {
?>



<form action="remote_image.php" method="post"><span>Nur <strong>JPG</strong>, <strong>GIF</strong> oder <strong>PNG</strong>. Bild-<strong>URL</strong> einf&uuml;gen:</span>
<br /><input type="text" name="remote_url" value="">&nbsp;&nbsp;<input type="submit" name="submit" value="Bild &uuml;bertragen">
</form>


<?php
 }
 ?>
</body>
</html>
Einziger Nachteil ist, dass animierte GIFs durch das Erzeugen eines neuen Bildes natürlich nicht mehr animiert sind.
Wenn jemand eine Änderung alla "if gif = animated gif {copy directly from remote-url}" weiß: Immer her damit...

Da meine php-Kenntnisse noch im Bereich Dummies angesiedelt sind, bitte ich um Nachsicht, wenn dumme Fragen kommen.

LG
| HomeStory.org - the friendly Community | Forum für alle Lebenslagen | <"}))}~ | Nicht nachmachen: Meine phpBB Spielereien |
var shoppen = geld.replace (/geld/g, 'bloedsinn'); if (geld < 1) { return home; };
Benutzeravatar
cYbercOsmOnauT
Ehemaliges Teammitglied
Beiträge: 3820
Registriert: 18.02.2004 23:02
Wohnort: Göttingen
Kontaktdaten:

Re: [PHP allgemein] Zusatzbedingung in Script integrieren Re

Beitrag von cYbercOsmOnauT »

Du kannst Deinen Check auch kaskadieren. Zuerst machst Du eine Vorprüfung mit

Code: Alles auswählen

$headers = get_headers($_POST["remote_url"], 1);
$isImage = strpos($headers['Content-Type'], 'image/') === 0; 
Wenn das true ist, lädst Du die Grafik herunter und prüfst noch einmal lokal mit getimagesize(); Dieser gibt bei inkorrekten Bildern im Rückgabearray bei den Indexes 0 und 1 (Höhe und Breite) jeweils eine 0 zurück. Damit kannst Du Dir den Weg über GD um die Sicherheit zu erhöhen sparen. Wenn es installiert ist, würde ich eher auf Imagemagick zurückgreifen. Damit geht es sehr viel einfacher und umfangreicher.

get_headers
getimagesize
Imagemagick convert
Imagemagick options

Viele Hoster die Imagemagick installiert haben, lassen den Aufruf von convert mittels exec() zu. Persönlich finde ich die Option -strip recht wichtig, denn damit löschst Du die EXIF-Daten eines Bildes.

Grüße,
Tekin

P.S.: Ich kann Dir nicht versprechen, dass ich auf folgende Fragen von Dir im Thread antworte. Ich bin mittlerweile viel zu selten hier auf phpbb.de. Hab Deinen Thread nur zufällig gesehen und wollte ein wenig mithelfen. :)
• prof. phpbb-Installation, Reparatur, Rettung nach Hackattacken, sowie PHP/JS Programmierung aller Art
Zend Certified Engineer, Linux Administrator und die Sicherheit von 34 Jahren Programmiererfahrung
• Interesse? Kontakt unter t.birduezen@web-coding.eu
Benutzeravatar
Crizzo
Administrator
Administrator
Beiträge: 12113
Registriert: 19.05.2005 21:45
Kontaktdaten:

Re: [PHP allgemein] Zusatzbedingung in Script integrieren Re

Beitrag von Crizzo »

cYbercOsmOnauT hat geschrieben: P.S.: Ich kann Dir nicht versprechen, dass ich auf folgende Fragen von Dir im Thread antworte. Ich bin mittlerweile viel zu selten hier auf phpbb.de. Hab Deinen Thread nur zufällig gesehen und wollte ein wenig mithelfen. :)
Was ersten sehr schade ist und zweitens gibt es doch die Funktion "Thema beobachten". :)
Antworten

Zurück zu „Coding & Technik“