WordPress <= 1.5.1.2 - xmlrpc Interface SQL Injection分析

  • 影响条件:

  • 程序:WordPress

  • 版本:<= 1.5.1.2

  • 严重程度:高危

基础知识

想要分析这个漏洞首先要了解xmlrpc的相关知识.

什么是xmlrpc?

xml rpc是使用http协议做为传输协议的rpc机制,使用xml文本的方式传输命令和数据调用远程的方法。

用wordpress xmlrpc.php的sayHello函数来演示一个例子

发送以下的xmlrpc数据包到wordpress的xmlrpc.php路径上,wordpress就会返回返回一个xmlrpc Response

POST /xmlrpc.php HTTP/1.1
Host: example.com
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.84 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate, sdch
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6
Content-Length: 114

<?xml version="1.0" encoding="iso-8859-1"?>
<methodCall>
<methodName>demo.sayHello</methodName>
</methodCall>

这是上面一个请求返回的数据包

E31985B9-FD8A-4813-B32E-5A80ABDA8DB9.png

我们可以看见在<string></string>标签中返回了一个Hello!

所以想要调用它的过程,只要遵循xmlrpc协议格式,例如以下

<?xml version="1.0"?>
<methodCall>
  <methodName></methodName>
  <params>
    <param>
        <value></value>
    </param>
  </params>
</methodCall>

漏洞分析正文

首先根据exp来定位漏洞点

<?xml version=\"1.0\"?>
<methodCall>
<methodName>pingback.ping</methodName>
<params>
<param><value><string>1'</string></value></param>
<param><value><string>http://wordpress1.5.1/?p=1#1</string></value></param>
<param><value><string>admin</string></value></param>
</params>
</methodCall>

上面这个xml文件是这个exp最核心的地方,我把原exp中填充payload的地方换成了1'

返回了如下数据,在这里可以看到返回数据库的错误提示信息

6A97CEB7-6745-48B9-BD52-E90070EC2449.png

来看一下整个执行流程

8D317E7F-120B-4BC2-94C7-98C5958030AD.png

#8中实例化了wp_xmlrpc_server()类,wp_xmlrpc_server()类是wordpress对IXR库的扩展,里面定义了wordpress xmlprc的API.

#3开始,流程就进入了wordpress所添加的api ->pingback_ping()中.

参数赋值语句

$pagelinkedfrom = $args[0];

args[0]哪来的?args是class IXR_Message中parse()函数处理之后返回的.

$data = $HTTP_RAW_POST_DATA;

$this->message = new IXR_Message($data);
        if (!$this->message->parse()) {
            $this->error(-32700, 'parse error. not well formed');
        }

我把上面的代码段给摘录出来,parse()解析了标签里面的内容.

解析出来的内容也就是args[0]直接赋值给了pagelinkedfrom没有经过任何处理直接拼接进了sql语句中.

        $result = $wpdb->get_results("SELECT * FROM $wpdb->comments WHERE comment_post_ID = '$post_ID' AND comment_author_url = '$pagelinkedfrom'");

导致的注入.

如果是导致数据库出错的sql语句可以看见它的内容不在xmlrpc response的标签里面

A89E1453-DE26-4594-91A5-843C2AA7BF30.png

因为调用到this->query()的函数中调用到了一个$this->print_error();函数.

这个函数是当发生数据库错误的时候显示上一条查询的sql语句

    function print_error($str = '') {
        global $EZSQL_ERROR;
        if (!$str) $str = mysql_error();
        $EZSQL_ERROR[] = 
        array ('query' => $this->last_query, 'error_str' => $str);

        // Is error output turned on or not..
        if ( $this->show_errors ) {
            // If there is an error then take note of it
            print "<div id='error'>
            <p class='wpdberror'><strong>WordPress database error:</strong> [$str]<br />
            <code>$this->last_query</code></p>
            </div>";
        } else {
            return false;    
        }
    }

所以说就是报错语句没有在xml里面的原因了