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 :
[pastacode provider=”manual” lang=”sql” manual=”%09public%20function%20export_sql(%24table_name)%7B%0A%09global%20%24wpdb%3B%0A%09%24table_name2%20%3D%20str_replace(%22%7Bprefix%7D%22%2C%24wpdb-%3Eprefix%2C%24table_name)%3B%0A%09%24connexion%20%3D%20mysql_connect(DB_HOST%2C%20DB_USER%2C%20DB_PASSWORD)%3B%0A%09mysql_select_db(DB_NAME%2C%20%24connexion)%3B%0A%09%24query%20%3D%20%22show%20create%20table%20%22.%24table_name2.%22%22%3B%09%0A%09%24creations%3D%22%22%3B%0A%09%24insertions%3D%22%22%3B%0A%09%0A%09%24listeCreationsTables%20%3D%20mysql_query(%24query%2C%20%24connexion)%3B%0A%09while(%24creationTable%20%3D%20mysql_fetch_array(%24listeCreationsTables))%20%7B%20%0A%09%09…”/]
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) :
[pastacode provider=”manual” lang=”markup” manual=”%3Ctd%20class%3D%22requete%22%3E%3Cinput%20name%3D%22requete%22%20value%3D%22%3C%3Fphp%20echo%20%24lMotCle%5B’requete’%5D%3B%20%3F%3E%22%20type%3D%22text%22%20%2F%3E%3C%2Ftd%3E%0A%3Ctd%20class%3D%22destination%22%3E%3Cinput%20name%3D%22destination%22%20value%3D%22%3C%3Fphp%20echo%20%24lMotCle%5B’destination’%5D%3B%20%3F%3E%22%20type%3D%22text%22%20%2F%3E%3C%2Ftd%3E%0A%3Ctd%20class%3D%22position%22%3E%3Cinput%20name%3D%22position%22%20value%3D%22%3C%3Fphp%20echo%20%24lMotCle%5B’position’%5D%3B%20%3F%3E%22%20type%3D%22text%22%20%2F%3E%3C%2Ftd%3E%0A”/]
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) :
[pastacode provider=”manual” lang=”php” manual=”public%20function%20execute()%20%7B%0A%09%24requete%20%3D%20%24_POST%5B’requete’%5D%3B%0A%09%24destination%20%3D%20%24_POST%5B’destination’%5D%3B%0A%09%24position%20%3D%20%24_POST%5B’position’%5D%3B%0A%0A%09if%20(%20!isset(%24position)%20%7C%7C%20is_null(%24position)%20%7C%7C%20strlen(%24position)%20%3C%3D%200%20%7C%7C%20!intval(%24position)%20)%20%24position%20%3D%20null%3B%0A%0A%09%24id%20%3D%20ConteneurMotCle%3A%3AgetInstance()-%3Eadd(%20%24requete%2C%20%24destination%2C%20%24position%20)%3B%0A%09ConteneurConfig%3A%3AgetInstance()-%3Esuptouscache()%3B%0A%09%09%0A%09%24this-%3Eredirection(‘action%3Dmot-cle-lister’)%3B%0A%7D”/]
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é” :
[pastacode provider=”manual” lang=”php” manual=”public%20function%20execute()%20%7B%0A%09%24id%20%3D%20%24_GET%5B’id’%5D%3B%0A%09%09%0A%09ConteneurMotCle%3A%3AgetInstance()-%3Eremove(%24id)%3B%0A%09ConteneurConfig%3A%3AgetInstance()-%3Esuptouscache()%3B%0A%09%09%0A%09%24this-%3Eredirection(‘action%3Dmot-cle-lister’)%3B%0A%7D”/]
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 :
[pastacode provider=”manual” lang=”php” manual=”public%20function%20modifCapping(%24valcap)%20%7B%0A%09global%20%24wpdb%3B%09%09%0A%09%24query%20%3D%20’UPDATE%20′.%24wpdb-%3Eprefix.’liveoptim_capping%20SET%20capping%20%3D%20′.%24valcap.”%3B%0A%09%24sql%20%3D%20%24wpdb-%3Eprepare(%24query%2C%20null)%3B%0A%09%24rep%20%3D%20%24wpdb-%3Eget_results(%24sql)%3B%0A%09return%20null%3B%0A%7D”/]
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 :
[pastacode provider=”manual” lang=”markup” manual=”%2F*%0APlugin%20Name%3A%20Liveoptim%0APlugin%20URI%3A%20http%3A%2F%2Fwww.liveoptim.com%2F%0ADescription%3A%20%3Cstrong%3ELiveoptim%3C%2Fstrong%3E%20est%20une%20extension%20qui%20vous%20simplifiera%20la%20vie.%0AAuthor%3A%20Erwan%20Milbeo%20-%20Copyright%202012%0AVersion%3A%201.6.0%0AAuthor%20URI%3A%20http%3A%2F%2Fwww.liveoptim.com%2F%0A*%2F%0A…%0A%3D%3D%20Changelog%20%3D%3D%0A%3D%20Version%201.2%20(25%2F03%2F2013)%20%3D%0A-%20Seconde%20version%20″/]
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 :
[pastacode provider=”manual” lang=”markup” manual=”Sell%20the%20derivative%20work%20and%20publish%20the%20source%20code%20in%20obfuscated%20form”/]
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 !