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

  • Google Analytics spamvrij maken en houden

    Last van referral spam? Door de stappen in dit artikel te volgen lees je weer betrouwbare gegevens af van Google Analytics. Toekomstige referral spam voorkomen Dit zouden standaardinstellingen voor ieder...
  • Coming soon pagina voor iedereen behalve een bepaald ip nummer

    Een handigheidje voor als je “live” werkt aan een site, maar niet wil dat iedereen kan meekijken, is om de iedereen naar een coming-soon.html pagina te leiden, behalve je eigen...
  • Extra velden toevoegen aan je custom post type

    Als je goed hebt nagedacht over je website structuur, dan heb je waarschijnlijk al een paar custom post types gedefinieerd, zoals testimonials, klanten, boeken, producten. Maar deze post types hebben...
  • 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...

Laat een reactie achter