Beveiliging Code snippets

Encrypted file upload en download in WordPress

Een bestand wordt in WordPress standaard geupload in de media library, en zijn vrij toegankelijk, zolang je het url maar hebt. Als je gebruikers bestanden willen uploaden met gevoelige informatie, moet het downloaden geblokkeerd worden. Om te voorkomen dat de inhoud op straat ligt bij een hack, is het verstandig ook de inhoud te versleutelen  met encryptie. Tot slot kan de bestandsnaam informatie bevatten. Deze vervangen we door een willekeurig gegenereerde titel.

In dit artikel ga ik ervan uit dat het je zelf lukt om bestanden te uploaden, met de standaard html, of wat gelikter met bijvoorbeeld dropzone.js.

De functie om te encrypten is vrij eenvoudig:

Eerst hebben we een functie nodig om de key en iv te genereren. De input hiervan kan je op vele manieren maken. Belangrijk is natuurlijk dat je altijd dezelfde wachtwoorden gebruikt voor encrypten en decrypten. Het beveiligen hiervan verdient wel de aandacht natuurlijk. Als deze te makkelijk te achterhalen zijn is de encryptie waardeloos. Je zou bijvoorbeeld bij elke gebruiker een aparte key kunnen opslaan voor zijn bestanden.

function dtc_get_passphrase(){
 $secret_iv = "Een geheim wachtwoord voor de iv";
 $secret_key = "Een geheim wachtwoord voor de key";
 $iv = substr(hash('sha256', $secret_iv),0,32);
 $key = substr(hash('sha256', $secret_pass),0,32);
 $opts = array('iv'=>$iv, 'key'=>$key);
 return $opts;

}

/* in: path to file */

public function encrypt($file){

$opts = dtc_get_passphrase();

$content = file_get_contents($file);
 $fp = fopen($file, 'wb');
 $content = rtrim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $opts["key"], $content, MCRYPT_MODE_CBC, $opts["iv"])), "\0\3");

fwrite($fp, $content);
 fclose($fp);
 }

Om te voorkomen dat de bestanden gedownload kunnen worden blokkeren we dit met de .htaccess. In de folder waar de bestanden komen, en die volledig geblokkeerd moet worden, maak je een htaccess bestand aan met de volgende inhoud:

<FilesMatch ".*">
 Order Allow,Deny
 Deny from All
 </FilesMatch>

Om het bestand te decrypten en dan te downloaden zonder het via een url aan te roepen moet je een link maken naar een bestand, bijvoorbeeld download.php. In dat bestand komt deze code, die ook WordPress inlaadt. Dit kan je bijvoorbeeld aanroepen met domein.nl/download.php?attachment_id=1

<?php
 # No need for the template engine
 define( 'WP_USE_THEMES', false );

#find the base path
 define( 'BASE_PATH', find_wordpress_base_path()."/" );

# Load WordPress Core
 require_once( BASE_PATH.'wp-load.php' );
 require_once( BASE_PATH.'wp-includes/class-phpass.php' );
 require_once( BASE_PATH . 'wp-admin/includes/image.php' );

if (is_user_logged_in() && isset($_GET["attachment_id"]) && is_numeric($_GET["attachment_id"])){

$attachment_id = intval($_GET["attachment_id"]);

$file =get_attached_file($attachment_id); //deze functie haalt het bestand uit de WordPress media library. Als je die niet gebruikt, moet je deze functie natuurlijk ook aanpassen.
 if (!$file) return "Niets gevonden.";
 $opts = dtc_get_passphrase();

$fp = fopen($file, 'rb');
 $content = file_get_contents($file);

if ($fp) {
 $fsize = filesize($file);
 $path_parts = pathinfo($file);
 $ext = strtolower($path_parts["extension"]);
 switch ($ext) {
 case "pdf":
 header("Content-type: application/pdf");
 break;
 case "zip":
 header("Content-type: application/zip");
 break;
 default:
 header("Content-type: application/octet-stream");
 break;
 }
 header("Content-Disposition: attachment; filename=\"".$path_parts["basename"]."\"");
 header("Content-length: $fsize");
 header("Cache-control: private"); //use this to open files directly
 $content = rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $opts["key"], base64_decode($content), MCRYPT_MODE_CBC, $opts["iv"]), "\0\3");

echo $content;
 }
 else {
 echo "Er is iets fout gegaan.";
 }
 fclose($fp);
 }
 if(!function_exists('_log')){
 function _log( $message ) {
 if( WP_DEBUG === true ){
 if( is_array( $message ) || is_object( $message ) ){
 error_log( print_r( $message, true ) );
 } else {
 error_log( $message );
 }
 }
 }
 }

function find_wordpress_base_path() {
 $dir = dirname(__FILE__);
 do {
 //it is possible to check for other files here
 if( file_exists($dir."/wp-config.php") ) {
 return $dir;
 }
 } while( $dir = realpath("$dir/..") );
 return null;
 }

 

 

 

Related Articles

  • Mailchimp opt-in checkbox toevoegen aan een eigen formulier

    Als je mailchimp gebruikt kan je met de WordPress plugin Mailchimp for wp eenvoudig een formulier op je site zetten om bezoekers zich te laten aanmelden voor je email nieuwsbrief....
  • Je WordPress website sneller maken

    Een WordPress website kan behoorlijk snel zijn: WordPress is niet zozeer de vertragende factor. Wat de snelheid vaak drukt is een zeer configureerbaar theme, of een combinatie van een theme...
  • Emails sturen in WordPress

    Voor een eenvoudig contactformulier kan ja het beste een plugin gebruiken. Contact form 7 bijvoorbeeld. Maar soms wil je wat meer maatwerk: een met een cronjob gegenereerde email (bijvoorbeeld elke...
  • Dynamisch de alt en title van een afbeelding aanpassen

    Alt en title vaak niet ingevuld Als je automatisch afbeeldingen importeert, je hebt website redacteuren die de alt tags niet invullen, of je neemt een site in beheer waar dat...

Laat een reactie achter