Om te voldoen aan de wettelijke administratieve verplichtingen, maken vrijwel alle WooCommerce-webshops gebruik van plug-ins die automatisch PDF-facturen en pakbonnen genereren zodra een bestelling is afgerond. Deze PDF-generatoren moeten dynamisch sjablonen (templates) inladen om de lay-out van de factuur te bepalen. Als de plug-in de naam of de locatie van dit sjabloon baseert op een parameter die door de gebruiker kan worden gemanipuleerd, ontstaat er een ernstig risico op een Local File Inclusion (LFI) kwetsbaarheid.

Het mechanisme van een PDF-LFI lek

PDF-factuur plug-ins bieden vaak de mogelijkheid om de lay-out van de factuur aan te passen via de URL, bijvoorbeeld om een speciaal sjabloon te tonen voor zakelijke klanten of voor internationale bestellingen: https://uwshop.nl/wp-admin/admin-ajax.php?action=generate_pdf&template=business

De onderliggende PHP-code van de plug-in verwerkt dit verzoek en laadt het bijbehorende PHP-sjabloon in via een include statement:

PHP
 
$template_name = $_GET['template'];
include( WP_PLUGIN_DIR . "/woocommerce-pdf-invoices/templates/" . $template_name . ".php" );

Een aanvaller (bijvoorbeeld een geregistreerde klant die zijn eigen factuur bekijkt) kan de parameter template manipuleren met pad-traversatietekens (../): ?action=generate_pdf&template=../../../../wp-config

Wanneer de PDF-generator dit verzoek verwerkt, zal PHP het wp-config.php bestand inladen binnen de context van de PDF-generator. De PHP-code van de configuratie wordt uitgevoerd, en eventuele variabelen of foutmeldingen kunnen embedded raken in de gegenereerde PDF. Als de aanvaller de PDF vervolgens downloadt, kan hij de database-inloggegevens en geheime salts rechtstreeks uit de tekst van de factuur kopiëren.

Hoe ontwikkelaars PDF-sjablonen veilig inladen

Ontwikkelaars moeten ervoor zorgen dat gebruikers NOOIT directe invloed kunnen uitoefenen op de bestandsnaam of het pad van een in te laden sjabloon.

  1. Gebruik een strikte whitelist: Definieer vooraf welke sjablonen bestaan en sta alleen exacte overeenkomsten toe.

  2. Saniseer met basename(): Verwijder alle mappenstructuren en traversatiepogingen uit de invoer.

PHP
 
$allowed_templates = array('default', 'business', 'minimal');
$chosen_template = basename( $_GET['template'] );

if ( in_array( $chosen_template, $allowed_templates ) ) {
    include( WP_PLUGIN_DIR . "/woocommerce-pdf-invoices/templates/" . $chosen_template . ".php" );
} else {
    include( WP_PLUGIN_DIR . "/woocommerce-pdf-invoices/templates/default.php" );
}

Advies voor site-beheerders

  • Beveilig de uploads-map van facturen: PDF-plug-ins slaan gegenereerde facturen vaak tijdelijk op in een submap van wp-content/uploads/. Zorg ervoor dat deze specifieke map is beveiligd met een .htaccess bestand dat directe indexering (Options -Indexes) inschakelt en de toegang voor onbevoegden blokkeert.