Kévin Subileau

Espace personnel

wordpress-hack

Local file disclosure vulnerability in Crayon Syntax Highlighter

I discovered a local file disclosure vulnerability affecting all versions before 2.7.0 of Crayon Syntax Highlighter, a popular syntax highlighter built in PHP and jQuery. According to wordpress.org, the vulnerable versions of this WordPress plugin are installed on more than 40,000 websites.

This critical vulnerability allows remote attackers to read arbitrary files on server's file system, even outside the web root. This includes PHP source code, configuration files and system files as /etc/passwd or wp-config.php for example. Furthermore, as you will see below, authentication is generally not required to exploit this vulnerability. Of course, the web server must have read access on the target files.

I tested a few versions between the old 1.10 to the latest 2.6.10, with a freshly installed WordPress 4.1 and the default configuration, and all tested versions were vulnerable. This means that the vulnerability exists since at least 3 years.

Technical analysis

Crayon Syntax Highlighter can highlight from a URL, inline code, or a local file. Here are some examples of normal markup that could be put inside post content in order to highlight code from these three source types:

<!-- Inline code -->
<pre class="lang:php">
    <?php //code to highlight here ?>
</pre>

<!-- URL -->
<pre class="lang:java" data-url="http://example.com/class.java"></pre>

<!-- Local file - the interesting case -->
<pre class="lang:java" data-url="/java_sample/class.java"></pre>

In the local file case, by default, the path given in the data-url attribute is relative to the WordPress root directory. In the plugin settings page, the user can also specify a sub-folder from which this relative path should start. But, as you can see below in this piece of code extracted from crayon, the problem is that there is absolutely no control over the file type or the path given (stored in the variable $url).

// Try to replace the site URL with a path to force local loading
if (strpos($url, $site_http) !== FALSE || strpos($url, $site_path) !== FALSE ) {
    $url = str_replace($site_http, $site_path, $url);
    // Attempt to load locally
    $local = TRUE;
    $local_url = $url;
} else if (empty($scheme)) {
    // No url scheme is given - path may be given as relative
    $local_url = preg_replace('#^((\/|\\\\)*)?#', $site_path . $this->setting_val(CrayonSettings::LOCAL_PATH), $url);
    $local = TRUE;
}
// Try to find the file locally
if ($local == TRUE) {
    if ( ($contents = CrayonUtil::file($local_url)) !== FALSE ) {
        $this->code($contents);
    } else {
        // [...]
    }
}

The given path is simply prepended with the base path at line 79, and then the file's content is loaded at line 84 (the method CrayonUtil::file just calls the function file_get_contents). So, for example, assuming that the administrator hasn't modified the standard WordPress file structure and with the default settings, it's possible to get the database credentials and WordPress secret keys simply by putting the code below inside a post or page content:

<pre data-url="/wp-config.php"></pre>

You can also use a directory traversal attack to reach the root directory and get the content of /etc/passwd for example:

<pre data-url="/../../../../../../../../../../../../../../../../../etc/passwd"></pre>

Of course it's also possible to get the content of theme's source files, .htaccess and .htpasswd files, log files, and other files that could contain highly sensitive information.

But so far, I told you that these exploits must be put inside a post or page, so normally this requires authentication. But the real issue is that unauthenticated visitors can also exploit the vulnerability simply by posting a comment containing the same malicious markup (except when an alternative comment system is used, as Disqus). It's because Crayon can also highlight inside comments, and this feature is enabled by default. This is why I say that authentication is generally not required to exploit this vulnerability.

Even if comments are moderated before publication, the issue remains the same because WordPress display the comment to its author before moderation with a message like "Your comment is awaiting moderation.". So the file content is revealed before the administrator can delete the malicious comment.

You can see bellow a screen capture showing the exploit in action, both inside the post content and a comment before moderation:

Disclosure of /etc/passwd and wp-config.php (click to enlarge)

Disclosure of /etc/passwd and wp-config.php (click to enlarge)

Vendor response

I sent the initial report of the vulnerability to the plugin author on January 4. He replied quickly and confirmed the issue.

On April 5, he informed me that he had patched the issue. Finally, on April 13, he released the version 2.7.0, which includes this patch.

I thank him for his cooperation and his excellent work.

Remediation

The preferred solution is to update quickly to the latest version (>= 2.7.0), which fix the vulnerability by removing support of local file highlighting.

In the event where you really cannot install the update, an alternative way to limit risks is to disable Crayon in comments, in order to prevent attacks from unauthenticated visitor. But it will still be possible to exploit the vulnerability through a post or page content...

Disable Crayons in comments to prevent unauthenticated attacks

Disable Crayons in comments to prevent unauthenticated attacks

CVSS Score

I evaluate the CVSS Score at 7.8 (AV:N/AC:L/Au:N/C:C/I:N/A:N).

References

Secunia : #63998.
WPVDB : #7904.
OSVDB : #121278.

About me

For non-French speakers that can't read others pages about me on this blog (sorry, it's currently primarly intended to French speakers), I will introduce me briefly in English here so that you can know who am I. I'm Kevin Subileau, 23 years old. I'm not a professional security researcher (yet), but I'm a passionate in computing science, junior system & network engineer by day, and web developer by night, also interested by computing security. You can contact me by leaving a comment below (in English or French), on Twitter or by filling this form (fields are, top to bottom, name / email / subject / comment).

wordpress-hack

Vulnérabilité mfunc dans W3 Total Cache et WP Super Cache

Le week-end dernier, j'ai reçu simultanément trois commentaires plutôt originaux à modérer sur ce site. En effet, ces derniers tentaient d'exploiter une vulnérabilité connue sur les deux plugins de cache les plus populaires, W3 Total Cache et WP Super Cache. Cette faille de sécurité a été reportée il y a un an environ par kisscsaby sur le forum WordPress, et a fort heureusement été totalement corrigée depuis. J'ai tout de même souhaité vous en parler car je l'ai trouvée intéressante à étudier et aussi parce qu'elle reste active sur les nombreux sites non mis à jour...

wp_mfunc_vulnerability

Voilà un commentaire plus que suspect...

Cette attaque s'appuie sur plusieurs fonctions (mfunc, mclude, et dynamic-cached-content) présentes sur les versions vulnérables (W3TC ≤ 0.9.2.8 ou WPSC ≤ 1.2), et permet d'exécuter un code PHP arbitraire sur le serveur. Autant dire que l'on peut tout faire ! Pour comprendre, il faut savoir qu'un site WordPress avec une version vulnérable d'un de ces plugins va exécuter le code PHP situé à l'intérieur de la balise ouvrante mfunc. Par exemple, le code <!--mfunc echo PHP_VERSION; -–><!–-/mfunc-–> va afficher la version de PHP utilisé.

Cette fonctionnalité permet initialement au développeur du site d'indiquer les éléments qui ne doivent pas être mis en cache par le plugin, comme par exemple la date ou le temps de génération de la page. Le code compris dans cette balise est alors exécuté à chaque fois, tandis que le reste de la page est mis en cache.

Lire la suite →

Casser le mot de passe VBA d’un fichier Excel

Ce n'est pas nouveau, quoi que l'on fasse, il arrive régulièrement que l'on perde un mot de passe... Heureusement, voici une méthode relativement simple pour contourner la protection par mot de passe qui empêche l'accès au code des macros VBA d'une feuille Excel. Plus précisément, elle permet de redéfinir un nouveau mot de passe sans connaitre l'ancien.

Attention : les informations et le programme mis à disposition dans cet article ne doivent pas être utilisés pour accéder au code d'un fichier protégé dont vous n'êtes pas le propriétaire, auquel cas vous seriez hors la loi (contrefaçon, accès frauduleux...).

Etape 1 : Modifier manuellement le fichier

Avant tout, sachez que je vous propose en fin d'article un petit utilitaire pour simplifier cette étape ;) . Si vous êtes suffisamment doué en informatique et que vous préférez le faire à la main, voici la procédure :

Pour commencer, il faut vous munir d'un éditeur hexadécimal pour pouvoir modifier le contenu du fichier Excel manuellement. Il en existe beaucoup, dont des gratuits qui feront très bien l'affaire, comme Frhed. Pensez également à sauvegarder votre fichier en cas de souci !

Ensuite, si votre fichier est au format Excel 2010 (extension .xlsm), vous devez changer cette extension en .zip (et oui, le format 2010 est avant tout une archive zip !), puis ouvrir l'archive et extraire le fichier xl/vbaProject.bin.

Ouvrez avec votre éditeur hexadécimal le fichier vbaProject.bin pour un classeur Excel 2010, ou directement le fichier Excel si vous utilisez l'ancien format (extension .xls). Recherchez la chaîne DPB= (généralement en fin de fichier) et remplacez la par DPX=. Enregistrez le fichier, puis fermez votre éditeur.

Modification du fichier Excel avec Frhed

Si votre fichier était au format 2010, ouvrez l'archive puis remplacez le fichier xl/vbaProject.bin par celui que vous venez de modifier. Enfin, rétablissez l'extension d'origine.

Etape 2 : Définir un nouveau mot de passe

Vous êtes ensuite obligé de définir un nouveau mot de passe, que vous pourrez retirer par la suite si vous le souhaitez. Ouvrez le fichier Excel modifié, puis accédez à l'éditeur VBA (Alt+F11). Un message d'avertissement s'affiche pour vous avertir qu'une "touche est incorrecte". Ignorez cet avertissement en cliquant sur Oui. Vous pouvez également obtenir une "erreur inattendue 40230", ignorez simplement en cliquant sur OK.

avertissement-casser-vba

Excel vous avertit que le fichier contient une "touche incorrecte", une mauvaise traduction pour "invalid key"...

Avant toute autre action, cliquez sur le menu Outils > Propriétés de ...,  et changez le mot de passe dans l'onglet Protection. Pour terminer, enregistrez le fichier, fermez puis ré-ouvrez, et retournez dans l'éditeur VBA. Vous pouvez désormais accéder au code source en tapant le nouveau mot de passe.

Bonus : Un petit programme  pour vous simplifier la tâche !

Pour simplifier la réalisation de la première étape, je vous ai préparé un petit programme pour le faire à votre place. Téléchargez-le et décompressez l'archive, puis :

  • Sous Windows, glisser-déplacer votre fichier Excel sur l'icône de l'application (VBAPwdRemover.exe). Une fenêtre noire apparait. Lorsque le message Appuyez sur une touche pour continuer... s'affiche, vous pouvez fermer cette fenêtre.

    Glisser votre fichier Excel sur l'icône de l'application.

  • Sous Linux, tapez la commande VBAPwdRemover.bin <chemin_du_fichier_Excel>

Le programme créé automatiquement une sauvegarde (nomfichier_bak.xls par exemple), mais si votre fichier est important je vous conseille d'en faire une manuellement avant de lancer la procédure : un bug peut toujours arriver...

Une fois le programme terminé, il ne vous reste plus qu'à redéfinir un mot de passe (reportez-vous à l'étape 2).

Liens de téléchargement :

Pour les plus curieux, je fournis également le code source C++ (licence GPL). A la compilation, vous avez la possibilité de désactiver le support du format Excel 2010 en définissant la constante NO_XLSM_SUPPORT (option de compilation -DNO_XLSM_SUPPORT). Si vous conservez le support de ce format, vous aurez besoin de la zlib et de la libzip (apt-get install libzip-dev sous Linux). Pour compiler sous Windows, j'ai utilisé MinGW et MSys.