Artikelformat

Webformulare für Bild-Upload absichern und Angriffe verhindern

Hinterlasse eine Antwort

Webformulare mit Uploadmöglichkeit für Bilder oder andere Dateien stellen eine große Sicherheitslücke dar. Wenn man nicht vernünftig prüft, was hochgeladen wird, sind es u.U. Scripte, die den kompletten Server lahmlegen können. Deshalb hab ich mich für ein aktuelles Projekt nochmal schlau gemacht, wie man sich am besten absichert.

  1. Prüfen ob es auch wirklich ein Bild ist und kein als jpg getarnter Code
  2. Session-Token nutzen und Referer checken um sicherzustellen, dass das verarbeitende Script nicht von fremden Adressen aufgerufen wird
  3. Dateinamen ändern (random)
  4. Datei nicht ausführbar machen 
  5. Passwortschutz auf das Uploadverzeichnis, damit die Dateien/Bilder nicht von jedem aufgerufen werden können
  6. maximale Dateigröße limitieren, wobei ich nicht weiß wozu das gut ist, weil schädlicher Code nicht lang sein muss.

Ja, teilweise redundant, aber nicht alle Punkte sind für alle Anwendungsfälle nutzbar.

In PHP sieht das dann so aus:

1. Nur PNGs, JPGs und GIFs werden erlaubt

$allowedTypes = array(IMAGETYPE_PNG, IMAGETYPE_JPEG, IMAGETYPE_GIF);
$detectedType = exif_imagetype($_FILES['image_file']['tmp_name']);
 
if(in_array($detectedType, $allowedTypes)) { ... }

2. Token generieren und prüfen

function generateFormToken($form) {
 // generate a token from an unique value
 $token = md5(uniqid(microtime(), true)); 
 // Write the generated token to the session variable to check it against the hidden field when the form is sent
 $_SESSION[$form.'_token'] = $token; 
 return $token;
}

function verifyFormToken($form) {
 // check if a session is started and a token is transmitted, if not return an error
 if(!isset($_SESSION[$form.'_token'])) { 
 return false;
 }
 
 // check if the form is sent with token in it
 if(!isset($_POST['token'])) {
 return false;
 }
 
 // compare the tokens against each other if they are still the same
 if ($_SESSION[$form.'_token'] !== $_POST['token']) {
 return false;
 }
 return true;
}

Im Formular
<input type="hidden" name="token" value="<?php echo generateFormToken('anfrage'); ?>">

Zum Prüfen
if (verifyFormToken('anfrage')) { ... }

3. Zufalls-Dateiname

$t = $_FILES['image_file']['tmp_name'];
$r = bin2hex(mcrypt_create_iv(16, MCRYPT_DEV_URANDOM)); //true random id 
$x = pathinfo($_FILES['image_file']['name'], PATHINFO_EXTENSION);
$newname = $r.'.'.$x;
move_uploaded_file($t, $uploadPath.$newname);

4. Dateirechte ändern

 chmod($uploadPath.$newname, 0644);

5. .htaccess

AuthType Basic
AuthName "restricted"
AuthUserFile /pfad/zur/htpass.datei
Require valid-user

//Generieren z.B. im Shell oder hier

6. Maximale Dateigröße

ini_set('post_max_size', '12M'); 
ini_set('upload_max_filesize', '12M');

Wenn ihr da noch schönere Ideen habt, her damit 🙂 Honeypot wäre vielleicht nochwas und Mindestdauer zum Ausfüllen des Formulars einführen.

Quellen:
Stackoverflow, Acunetix, CSS-Tricks

Magst Du diesen Artikel?
2

Schreibe eine Antwort

Pflichtfelder sind mit * markiert.