Failles et vulnérabilités de WordPress

Vulnérabilités XSS et CSRF dans le plugin WordPress LiveOptim free

Blog Failles et vulnérabilités de WordPress Vulnérabilités XSS et CSRF dans le plugin WordPress LiveOptim free
0 commentaire

Le plugin LiveOptim contient des vulnérabilités dans ses versions 1.1.3-free et inférieures, 1.1.6-free, 1.1.7-free, 1.1.8-free. Les failles sont du type XSS et CSRF.

Inutile de nous attarder sur chaque version, faisons plutôt un rapide tour des failles découvertes suite à la veille effectuée sur le plugin durant le mois d’avril/mai 2014

XSS

Le plugin WordPress LiveOptim est basé sur un script PHP standalone, ce qui se ressent bien à la vue du code :

	public function export_sql($table_name){
global $wpdb;
$table_name2 = str_replace("{prefix}",$wpdb->prefix,$table_name);
$connexion = mysql_connect(DB_HOST, DB_USER, DB_PASSWORD);
mysql_select_db(DB_NAME, $connexion);
$query = "show create table ".$table_name2."";
$creations="";
$insertions="";

$listeCreationsTables = mysql_query($query, $connexion);
while($creationTable = mysql_fetch_array($listeCreationsTables)) {
...

L’utilisation de mysql_connect, mysql_select_db, mysql_query, et mysql_fetch_array est signe de la provenance d’un script maison PHP, mal reconverti.

Avant que la 1.1.9-free ne corrige ces failles, on pouvait aussi y trouver des chaînes non désinfectées (sanitize) :

<td class="requete"><input name="requete" value="<?php echo $lMotCle['requete']; ?>" type="text" /></td>
<td class="destination"><input name="destination" value="<?php echo $lMotCle['destination']; ?>" type="text" /></td>
<td class="position"><input name="position" value="<?php echo $lMotCle['position']; ?>" type="text" /></td>

Il manque ici des esc_attr() après les echo. Ceci représente une faille XSS, le fait de pouvoir mettre dans le champs ">foobar et le voir s’écrire HORS du champ, indique alors qu’un code plus complexe en HTML et/ou JavaScript fonctionnerait aussi bien.

Le codex de WordPress contient pourtant bien une page complète sur le sujet : http://codex.wordpress.org/Data_Validation, encore faut-il savoir qu’il faut le faire.

CSRF

Nous pouvions aussi y trouver des formulaires sans aucun jeton de sécurité (nonce) :

public function execute() {
$requete = $_POST['requete'];
$destination = $_POST['destination'];
$position = $_POST['position'];

if ( !isset($position) || is_null($position) || strlen($position) <= 0 || !intval($position) ) $position = null;

$id = ConteneurMotCle::getInstance()->add( $requete, $destination, $position );
ConteneurConfig::getInstance()->suptouscache();

$this->redirection('action=mot-cle-lister');
}

Ici aucun jeton de sécurité n’est envoyé ni vérifié. Un pirate peut alors forcer une personne ayant les droits – ce qui indique que vérifier les droits avec un current_user_can( 'manage_options' ) est inutile – de valider le formulaire. Le pirate peut alors créer ou modifier les mots-clé de la page de réglages du plugin dans mon exemple.

XSRF²

Même chose avec les liens de type actions, c’est à dire un lien qui va faire des actions en base de données comme un lien “Supprimer le mot-clé” :

public function execute() {
$id = $_GET['id'];

ConteneurMotCle::getInstance()->remove($id);
ConteneurConfig::getInstance()->suptouscache();

$this->redirection('action=mot-cle-lister');
}

Pourtant, là aussi le codex a une page complète sur le sujet : https://codex.wordpress.org/WordPress_Nonces particulièrement wp_nonce_url(), wp_nonce_field et check_admin_referer() pour ce citer qu’elles.

Ce combo avec la faille XSS précédente est dévastatrice, le pirate va alors pouvoir ajouter du contenu JavaScript distant afin de récupérer des informations sensibles sur votre site. Aïe.

Concernant les requêtes en base de données, une non compréhension de la façon de les préparer se fait sentir :

public function modifCapping($valcap) {
global $wpdb;
$query = 'UPDATE '.$wpdb->prefix.'liveoptim_capping SET capping = '.$valcap.'';
$sql = $wpdb->prepare($query, null);
$rep = $wpdb->get_results($sql);
return null;
}

Le second paramètre de $wpdb->prepare() est null. La façon correcte est de passer le paramètre $valcap et de remplacer le $valcap dans $query par %s.

Celà dit, le get_results() est là aussi inutile puisqu’aucun résultat n’est renvoyé pour un update, le return null; aussi ne sert pas.

La fonction $wpdb->update() est faite pour ça ! C’est la façon WordPress de coder. Le plugin est comme le second paramètre de son propre $wpdb->prepare().

Premium ?

LiveOptim existe aussi en version payante, si vous utilisez cette, le changelog de la 1.6.0 n’indique rien sur ces correctifs :

/*
Plugin Name: Liveoptim
Plugin URI: http://www.liveoptim.com/
Description: <strong>Liveoptim</strong> est une extension qui vous simplifiera la vie.
Author: Erwan Milbeo - Copyright 2012
Version: 1.6.0
Author URI: http://www.liveoptim.com/
*/
...
== Changelog ==
= Version 1.2 (25/03/2013) =
- Seconde version

Est-ce corrigé ? Est-ce encore vulnérable ? Posez leur la question vous qui l’avez achetée.

Et le code étant obfusqué, il n’est pas possible de facilement le lire – il est possible de faire du reversing, mais c’est théoriquement illégal.

Ceci n’est pas en concordance avec la licence GPL pour information :

Sell the derivative work and publish the source code in obfuscated form

Un code de plugin obfusqué cherche habituellement à être masqué dans le but premier de ne pas être facilement modifiable et donc plagiable. Mais l’effet pervers est qu’il permet aussi cacher des choses qu’il ne souhaite pas que son utilisateur sache.

Récupérer des informations, envoyer des requêtes, inclure des redirections ou des publicités, la liste est aussi longue que votre imagination.

Je ne dis pas ce que LiveOptim le fait, je dis qu’un code obfusqué peut le faire et que LiveOptim Premium est obfusqué.

Prenez soin de vous et si vous utilisez encore ce plugin, tenez vous à jour plus que jamais !

 

0 commentaire