Article powershell

Guide des commandes via PowerShell Remoting utiles en test d’intrusion

Sommaire

Avant d’être un outil puissant et très pratique pour la phase de latéralisation durant un test d’intrusion en environnement Active Directory, PowerShell Remoting est surtout une solution efficace pour administrer une machine en ligne de commande sous Windows. Abrégé en PowerShell Remoting, il désigne l’utilisation conjointe du langage PowerShell et du protocole de gestion à distance WinRM pour l’administration de machines Windows. Il est alors possible d’exécuter sur la machine distante des commandes ou des scripts, parmi les cas d’usage les plus courants. Cet article a été écrit par Remi Madec, Consultant Sécurité de NBS System. ll se présente davantage comme une cheatsheet des commandes PowerShell qu’un guide complet. Cependant, il n’aborde pas l’étape de l’activation et le paramétrage du PowerShell est bien décrite, notamment dans la Documentation Microsoft.

Exemple de lancement des commandes via PowerShell :

Invoke-Command

L’utilisation de cmdlet Invoke-Command permet fin de lancer une unique commande. La syntaxe est la suivante :

Invoke-Command -ScriptBlock{COMMAND} -ComputerName SERVERNAME -Credential DOMAINE\USERNAME

Par exemple, pour lancer la commande hostname sur le serveur Server avec le compte local remi, il suffit d’exécuter la ligne suivante :

Invoke-Command -ScriptBlock{hostname} -ComputerName Server -Credential remi

PS C:\Users\Public> hostname Client PS C:\Users\Public> Invoke-Command -ScriptBlock{hostname} -ComputerName Server -Credential remi Server

Invoke-Command

Authentification

Le paramètre Credential permet de soumettre au serveur des informations d’authentification. Plusieurs méthodes existent, la plus répandue en environnement Active Directory étant Kerberos, qui nécessite toutefois que le client et le serveur soient membres de la même forêt, ou qu’une relation de confiance soit établie en forêt.

1. Saisie d’informations d’authentification

  • Avec l’utilisateur courant

Dans le cas où l’utilisateur courant est membre du domaine et est autorisé sur le serveur, il n’est pas nécessaire de préciser dans la commande les informations d’authentification : celles de l’utilisateur courant seront relayées au serveur. La commande précédente devient donc :

Invoke-Command -ScriptBlock{COMMAND} -ComputerName SERVERNAME

Si l’on souhaite utiliser les informations d’authentification d’un autre utilisateur, il est nécessaire d’utiliser le paramètre Credential. Plusieurs solutions existent dans ce cas.

  • Avec le nom d’utilisateur et une popup

Si ces informations n’ont pas besoin d’être réutilisées pour des commandes ultérieures, il suffit de passer seulement le nom d’utilisateur (domaine et nom d’utilisateur dans le cas d’un compte du domaine). C’est ce qui est fait avec la commande suivante :

Invoke-Command -ScriptBlock{hostname} -ComputerName Server -Credential remi

Pour saisir le mot de passe, un popup s’affiche :

Saisie d’informations d’authentification
  • Stockées dans une variable (popup)

Il est également possible de stocker ces informations d’authentification dans une variable locale, évitant ainsi de devoir les saisir à nouveau lors de chaque commande. Pour les stocker dans la variable cred, la syntaxe suivante est utilisée :

$cred = Get-Credential

Comme dans le cas précédent, un popup apparaît pour saisir ses informations :

Stockées dans une variable (popup)

Cette variable doit ensuite être passée en argument du paramètre Credential :

Invoke-Command -ScriptBlock{COMMAND} -ComputerName SERVERNAME -Credential $cred

  • Stockées dans une variable (ligne de commande)

La méthode précédente est pratique, mais la saisie d’informations d’authentification dans une popup n’est pas toujours une solution envisageable pour diverses raisons. Par exemple, si le prompt PowerShell est obtenu depuis un reverse shell, la popup s’affichera sur l’ordinateur distant ! C’est d’autant plus regrettable qu’en plus de ne pas pouvoir s’authentifier, l’attaquant perd la main sur le shell.

Il est alors possible d’utiliser l’objet PSCredential avec la saisie du mot de passe en ligne de commande. La syntaxe à utiliser est alors la suivante :

$Username = « USERNAME »

$SecurePassword = « PLAINPASSWORD » | ConvertTo-SecureString -AsPlainText -Force

$PScred = New-Object System.Management.Automation.PSCredential -ArgumentList $UserName,$SecurePassword

L’utilisation de cette variable s’effectue de la même manière que précédemment :

    • Exit

    La commande Exit permet de revenir dans le contexte du client.

    2. Session persistante

    Il est également possible de créer des sessions persistantes.

    • New-PSSession

    Le cmdlet New-PSSession permet ceci :

    New-PSSession -ComputerName SERVERNAME -Credential $cred

Pour faciliter l’organisation et la gestion des sessions, il est possible de leur donner un nom et de les stocker dans une variable locale :

Pour faciliter l’organisation et la gestion des sessions, il est possible de leur donner un nom et de les stocker dans une variable locale :

$session1 = New-PSSession -Name Session1 -ComputerName Server -Credential $cred

  • Get-PSSession

La commande suivante effectue la visualisation des sessions existantes :

Get-PSSession
  • Les paramètres Name et Id (et bien d’autres, par exemple ComputerName) peuvent être utilisés pour filtrer les résultats. Ainsi, les deux commandes suivantes retournent le même résultat :

    Get-PSSession -Name Session1

    Get-PSSession -Id 19

Get-PSSession -Name Session1

De nombreuses possibilités d’interaction sont disponibles. Par exemple, il est possible d’assigner à une variable une session déjà existante, par exemple avec la commande suivante :

$session0 = Get-PSSession -Id 18

Possibilités d’interaction
  • Enter-PSSession

Pour interagir avec une session existante, il suffit d’utiliser le cmdlet Enter-PSSession accompagné d’un moyen d’identification de la session (son nom, son Id ou la variable dans laquelle elle est stockée). Les commandes suivantes aboutissent au même résultat :

Enter-PSSession -Id 19

Enter-PSSession -Name Session1

Enter-PSSession -Session $session1

  • Disconnect-PSSession & Connect-PSSession

La commande Exit est utilisée pour revenir dans le contexte du Client. Toutefois, la session est toujours active. Il est possible de la déconnecter à l’aide de la commande suivante :

Disconnect-PSSession -Id 18

Enter-PSSession
  • Celle-ci n’est cependant pas supprimée. Il est par exemple possible de lancer un script, de déconnecter la session, puis de reconnecter la session plus tard pour consulter les résultats. C’est d’autant plus pratique que cette session est conservée côté serveur, et il est donc possible de s’y reconnecter depuis une machine cliente différente de la première (ce qui nécessite tout de même d’utiliser le même compte utilisateur).

    Pour se reconnecter à une session existante, il convient d’utiliser le cmdlet Connect-PSSession :

    Connect-PSSession -Id 18

    La commande suivante est utilisée pour supprimer définitivement une session :

    Remove-PSSession -Id 18

utilisée pour supprimer définitivement une session
  • 3. Sessions multiples

    Pour lancer des commandes ou des scripts sur de multiples machines, par exemple lors de la phase de post-exploitation, plusieurs sessions (sur le même serveur ou sur plusieurs serveurs compromis) peuvent être stockées dans une unique variable :

    $sessions = New-PSSession -ComputerName Server,Server -Credential $cred

    Il suffit alors de l’utiliser de la même manière que précédemment pour obtenir le résultat de toutes les sessions :

    Invoke-Command -ScriptBlock{hostname} -Session $sessions

Sessions multiples

Dans certains cas, il peut également être intéressant de créer de multiples sessions, chacune stockée dans une variable. C’est possible en une unique ligne avec la syntaxe suivante :

$sess1, $sess2 = New-PSSession -ComputerName Server,Server -Credential $cred

Chaque variable correspond alors à une session :

Lancement des commandes à distance via le PowerShell Remoting

1. Le PowerShell Remoting explicite

Les commandes via PowerShell Remoting offrent de nombreuses possibilités pour lancer une ou plusieurs commandes, des scripts, importer des modules …

  • Commandes et scripts distants

Pour lancer plusieurs commandes, Il suffit de les séparer par un point-virgule dans le paramètre ScriptBlock :

Invoke-Command -ScriptBlock{hostname;whoami} -Session $session1

Il est possible de lancer un script déjà présent sur le serveur en précisant son chemin relatif dans le paramètre ScriptBlock :

Invoke-Command -ScriptBlock{C:\Users\Public\hostname.ps1} -Session $session1

Commandes et scripts distants

Ces fonctionnalités permettent par exemple de charger un module pour en exécuter des fonctions en une seule ligne :

Invoke-Command -ScriptBlock{Import-Module C:\PATHTOMODULE; MODULEFUNCTION} -Session $session1

  • Scripts stockés localement

Déposer des scripts sur une machines compromise n’est pas forcément la manière la plus furtive de procéder. Il est cependant possible d’exécuter sur la machine distante des scripts stockés sur le client. Pour ce faire, le paramètre FilePath est utilisé :

Invoke-Command -FilePath C:\Users\Public\local_hostname_script.ps1 -Session $session1

2. Le PowerShell Remoting implicite

L’ensemble des commandes utilisées précédemment est exécuté explicitement sur le serveur : il est clair que c’est à travers la session qu’elles sont envoyées.

Par exemple, pour importer le module Powerview.ps1 stocké sur la machine distante et en lancer une commande (ici Get-NetLoggedon), la syntaxe explicite est la suivante :

Invoke-Command -ScriptBlock{Import-Module C:\Users\Public\Powerview.ps1;Get-NetLoggedon}-Session $session1

Sur le serveur et la commande exécuté, il y a bien ce module qui est chargé :

  • Export-PSSession

Cette syntaxe est plutôt lourde, et c’est ici qu’intervient le Remoting implicite : il est possible d’exporter le contexte de la session pour lancer des commandes de ce module sur le serveur comme si le module était chargé localement. Pour ce faire, le cmdlet Export-PSSession est utilisé :

Export-PSSession -Session $Session1 -OutputModule Powerview

Cette commande stocke localement ce contexte dans le module passé en argument du paramètre OutputModule. Il suffit de l’importer et d’en utiliser les fonctions. De manière transparente, celles-ci sont toujours exécutées sur le serveur, au travers de la session dont provient l’export :

Interaction avec une session persistante

Enfin, autre fonctionnalité pratique : il est possible de se servir d’une session PowerShell pour transférer des fichiers.

  • Depuis le client vers le serveur

La commande à utiliser est :

Copy-Item -Path C:\LOCALPATHTOFILE -ToSession $session1 -Destination C:\REMOTEDESTINATIONFILEPATH

  • Depuis le serveur vers le client

Le paramètre FromSession remplace ToSession :

Copy-Item -Path C:\REMOTEPATHTOFILE -FromSession $session1 -Destination C:\LOCALDESTINATIONFILEPATH

Cheatsheet de commandes PowerShell Remoting

1. Syntaxe générique

Exécution de commande :

Invoke-Command -ScriptBlock{COMMAND} -ComputerName SERVERNAME

2. Authentification

Popup :

Invoke-Command -ScriptBlock{COMMAND} -ComputerName SERVERNAME -Credential DOMAINE\USERNAME

Stockage dans une variable (popup) :

$cred = Get-Credential
Invoke-Command -ScriptBlock{COMMAND} -ComputerName SERVERNAME -Credential $cred

Stockage dans une variable (CLI) :

$Username = « USERNAME »
$SecurePassword = « PLAINPASSWORD » | ConvertTo-SecureString -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential -ArgumentList $UserName,$SecurePassword
Invoke-Command -ScriptBlock{COMMAND} -ComputerName SERVERNAME -Credential $cred

3. Double saut Kerberos (CredSSP)

Activation du la délégation (client) :

Enable-WSManCredSSP -Role Client –

DelegateComputer CLIENTNAME :

Activation du la délégation (serveur) Enable-WSManCredSSP -Role Server -Force

Exécution de commande :

Invoke-Command -ScriptBlock{COMMAND} -ComputerName SERVERNAME -Credential $cred -Authentication Credssp

4. Gestion des sessions

Session interactive :

Enter-PSSession -ComputerName SERVERNAME -Credential $cred

Session persistante :

New-PSSession -ComputerName SERVERNAME -Credential $cred

Session persistante nommée et stockée :

$SESSIONVAR = New-PSSession -Name SESSIONNAME -ComputerName SERVERNAME -Credential $cred

Visualisation des sessions :

Get-PSSession

Filtre par nom/Id :

Get-PSSession -Name SESSIONNAME
Get-PSSession -Id SESSIONID

Interaction par Id/nom/variable :

Enter-PSSession -Id SESSIONID
Enter-PSSession -Name SESSIONNAME
Enter-PSSession -Session
 $SESSIONVAR

Déconnexion :

Disconnect-PSSession -Id SESSIONID

Reconnexion :

Connect-PSSession -Id SESSIONID

Suppression définitive :

Remove-PSSession -Id SESSIONID

Stockage X sessions dans 1 variable :

$SESSIONVAR = New-PSSession -ComputerName SERVERNAME1,SERVERNAME2 -Credential $cred

Stockage X sessions dans X variable :

$SESSIONVAR1, $SESSIONVAR2 = New-PSSession -ComputerName SERVERNAME1,SERVERNAME2 -Credential $cred

5. Commandes et scripts

Multiples commandes :

Invoke-Command -ScriptBlock{COMMAND1;COMMAND2} -Session $SESSIONVAR

Script distant :

Invoke-Command -ScriptBlock{REMOTEPATHTOSCRIPT\SCRIPT.ps1} -Session $SESSIONVAR

Module distant :

Invoke-Command -ScriptBlock{Import-Module C:\REMOTEPATHTOMODULE; MODULEFUNCTION} -Session $SESSIONVAR

Script local :

Invoke-Command -FilePath REMOTEPATHTOSCRIPT\SCRIPT.ps1 -Session $SESSIONVAR

Remoting implicite :

Export-PSSession -Session $SESSIONVAR -OutputModule OUTPUTMODULENAME

6. Transfert de fichiers

Client -> Serveur :

Copy-Item -Path C:\LOCALPATHTOFILE\FILE -ToSession $SESSIONVAR -Destination C:\REMOTEDESTINATIONFILEPATH

Serveur -> Client :

Copy-Item -Path C:\REMOTEPATHTOFILE\FILE -FromSession $SESSIONVAR -Destination C:\LOCALDESTINATIONFILEPATH

Article de Remi Madec, consultant sécurité de NBS System

Vous souhaitez en savoir plus ?

Nos équipes sont là pour vous accompagner concernant les commandes via le PowerShell

Article powershell
Autres articles
Synergie entre Formation et Recrutement

Synergie entre Formation…

Formation et recrutement, complémentaires Dans cet article, vous découvrirez comment formation et recrutement se complètent…

CRAM : Cas client Pentest Externe et Interne

CRAM : Cas…

Un Cas Client sur comment renforcer son SI grâce au pentest (Test d’intrusion) Découvrez dans…

Chef de projet : un rôle clé pour la réussite des missions NBS System

Chef de projet…

Quel est le rôle d’un chef de projet  Cybersécurité ? Être chef de projet au…

Retour en haut
Aller au contenu principal