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

Laat een reactie achter