CVE-2015-10111: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection') (CWE-89)
value: A vulnerability was found in Watu Quiz Plugin up to 2.6.7 on WordPress. It has been rated as critical. This issue affects the function watu_exams of the file controllers/exam.php of the component Exam Handler. The manipulation of the argument quiz leads to sql injection. The attack may be initiated remotely. Upgrading to version 2.6.8 is able to address this issue. The patch is named bf42e7cfd819a3e76cf3e1465697e89f4830590c. It is recommended to upgrade the affected component. The associated identifier of this vulnerability is VDB-230651.
CWE description: The product constructs all or part of an SQL command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended SQL command when it is sent to a downstream component. Without sufficient removal or quoting of SQL syntax in user-controllable inputs, the generated SQL query can cause those inputs to be interpreted as SQL instead of ordinary user data.
CVSS v3 base score: 9.8
Published: 2023-06-04T12:15Z
Repository: https://github.com/wp-plugins/watu
Language: PHP
Files changed: controllers/exam.php, controllers/show_exam.php, readme.txt, script.js, views/show_exam.html.php, watu.php
Commit date: 2015-11-20 17:33:01 +0000
Commit message: Fixed security exploit

git-svn-id: https://plugins.svn.wordpress.org/watu/trunk@1290960 b8457f37-d9ea-0310-8a92-e5e31aec5664

Diff: diff --git a/controllers/exam.php b/controllers/exam.php
index 541890d..c15fcd1 100644
--- a/controllers/exam.php
+++ b/controllers/exam.php
@@ -5,13 +5,13 @@ function watu_exams() {
 	if( isset($_REQUEST['message']) && $_REQUEST['message'] == 'updated') print '<div id="message" class="updated fade"><p>' . __('Test updated', 'watu') . '</p></div>';
 	if(isset($_REQUEST['message']) && $_REQUEST['message'] == 'fail') print '<div id="message" class="updated error"><p>' . __('Error occured', 'watu') . '</p></div>';
 	if( isset($_REQUEST['grade']) )  print '<div id="message" class="updated fade"><p>' . $_REQUEST['grade']. '</p></div>';
 	
 	if(!empty($_GET['action']) and $_GET['action'] == 'delete') {
-		$wpdb->get_results("DELETE FROM ".WATU_EXAMS." WHERE ID='$_REQUEST[quiz]'");
-		$wpdb->get_results("DELETE FROM ".WATU_ANSWERS." WHERE question_id IN (SELECT ID FROM ".WATU_QUESTIONS." WHERE exam_id='$_REQUEST[quiz]')");
-		$wpdb->get_results("DELETE FROM ".WATU_QUESTIONS." WHERE exam_id='$_REQUEST[quiz]'");
+		$wpdb->get_results($wpdb->prepare("DELETE FROM ".WATU_EXAMS." WHERE ID=%d", $_REQUEST['quiz']));
+		$wpdb->get_results($wpdb->prepare("DELETE FROM ".WATU_ANSWERS." WHERE question_id IN (SELECT ID FROM ".WATU_QUESTIONS." WHERE exam_id=%d", $_REQUEST['quiz']));
+		$wpdb->get_results($wpdb->prepare("DELETE FROM ".WATU_QUESTIONS." WHERE exam_id=%d", $_REQUEST['quiz']));
 		print '<div id="message" class="updated fade"><p>' . __('Test deleted', 'watu') . '</p></div>';
 	}
 	
 	// Retrieve the quizzes
 		$exams = $wpdb->get_results("SELECT Q.ID,Q.name,Q.added_on,
diff --git a/controllers/show_exam.php b/controllers/show_exam.php
index 969446d..7cd4d79 100644
--- a/controllers/show_exam.php
+++ b/controllers/show_exam.php
@@ -194,11 +194,11 @@ if(isset($_REQUEST['do']) and $_REQUEST['do']) { // Quiz Reuslts.
 				$_SERVER['REMOTE_ADDR'], $user_ID, $exam->ID, $achieved, $g_id, $_POST['start_time']));				
 		}		
 		if(empty($taking_id)) {
 			$wpdb->query($wpdb->prepare("INSERT INTO ".WATU_TAKINGS." SET exam_id=%d, user_id=%d, ip=%s, date=CURDATE(), 
 				points=%d, grade_id=%d, result=%s, snapshot='', start_time=%s", 
-				$exam_id, $uid, $_SERVER['REMOTE_ADDR'], $achieved, $g_id, $grade, $_POST['start_time']));
+				$exam_id, $uid, $_SERVER['REMOTE_ADDR'], $achieved, $g_id, $grade, @$_POST['start_time']));
 			$taking_id = $wpdb->insert_id;
 		}
 	}
 	else $taking_id = 0;	
 	$GLOBALS['watu_taking_id'] = $taking_id;
diff --git a/readme.txt b/readme.txt
index 4c6b414..8f39e9a 100644
--- a/readme.txt
+++ b/readme.txt
@@ -124,18 +124,19 @@ Yes. You can create a folder called "watu" under your active WP theme folder. Th
 2. The form for creating and editing an exam/test
 3. You can add unlimited number of questions in each exam, and each question can of single-answer, multiple-answer, or open-end type. 
 
 == Changelog ==
 
-= Changes in 2.6.7 =
+= Changes in 2.6.8 =
 - Added option to limit the number of logged in user attempts for quizzes that require login.
 - You can specify one or more email addresses that will receive user's results (instead of just using the admin email from your WP Settings page)
 - You can now specify different content for the email sent to you when someone takes a quiz
 - New option lets you to send email to user with their results. If user is not logged in this will generate a required field to enter email on the quiz page.
 - You can specify different email contents of the email sent to user than the contents of the email sent to admin
 - All views /  templates can now be overriden by placing their copy under a folder called "watu" in your theme folder.
 - Added option to switch off Ajax submitting for certain quizzes. This is useful if you are embedding javascript via shortcodes from other plugins in the final screen of the quiz as some javascripts won't work when loaded by Ajax.
+- Fixed security exploit
 
 = Changes in 2.6 =
 - Added optional text-based "captcha" to prevent spam bot submissions on quizzes which do not require user login
 - Option to reoder the questions. Of course this takes effect only when you have not chosen "Randomize questions" in the quiz settings.
 - Removed the hardcoded text "your answers are shown below" and the setting "display answers at the end of the quiz". Instead of this use the variable %%ANSWERS%% which gives far more flexibility.
diff --git a/script.js b/script.js
index 2e9df38..44aea36 100644
--- a/script.js
+++ b/script.js
@@ -177,10 +177,11 @@ Watu.submitResult = function(e) {
 		
 		data[fieldName+'[]'] = ansvalues;
 	}
 	
 	data['post_id'] = Watu.post_id;
+	data['start_time'] = jQuery('#watuStartTime').val();
 	
 	// no ajax? In this case only return true to allow submitting the form	
 	if(e && e.no_ajax && e.no_ajax.value == 1) return true;	
 	
 	// if question captcha is available, add to data
diff --git a/views/show_exam.html.php b/views/show_exam.html.php
index 34aba7a..7cb2cc1 100644
--- a/views/show_exam.html.php
+++ b/views/show_exam.html.php
@@ -69,11 +69,11 @@ if($single_page != 1 and $answer_display!=2): ?>
 <input type="hidden" name="no_ajax" value="<?php echo $exam->no_ajax?>"><?php if(!empty($exam->no_ajax)):?>
 <input type="hidden" name="do" value="show_exam_result">
 <input type="hidden" name="post_id" value="<?php echo $post->ID?>">
 <?php endif; // end if(!empty($exam->no_ajax))?>
 <input type="hidden" name="quiz_id" value="<?php echo $exam_id ?>" />
-<input type="hidden" name="start_time" value="<?php echo current_time('mysql'); ?>" />
+<input type="hidden" id="watuStartTime" name="start_time" value="<?php echo current_time('mysql'); ?>" />
 </form>
 </div>
 <script type="text/javascript">
 var exam_id=0;
 var question_ids='';
diff --git a/watu.php b/watu.php
index 308f6e3..55bb46e 100644
--- a/watu.php
+++ b/watu.php
@@ -2,11 +2,11 @@
 /*
 Plugin Name: Watu
 Plugin URI: http://calendarscripts.info/watu-wordpress.html
 Description: Create exams and quizzes and display the result immediately after the user takes the exam. Watu for Wordpress is a light version of <a href="http://calendarscripts.info/watupro/" target="_blank">WatuPRO</a>. Check it if you want to run fully featured exams with data exports, student logins, timers, random questions and more. Free support and upgrades are available. Go to <a href="options-general.php?page=watu.php">Watu Settings</a> or <a href="tools.php?page=watu_exams">Manage Your Exams</a> 
 
-Version: 2.6.7
+Version: 2.6.8
 Author: Kiboko Labs
 License: GPLv2 or later
 
 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
@@ -324,11 +324,11 @@ function watu_vc_scripts() {
 		
 		wp_enqueue_script(
 			'watu-script',
 			WATU_URL.'script.js',
 			array(),
-			'2.3.2'
+			'2.3.3'
 		);
 		
 		$translation_array = array(
 			'missed_required_question' => __('You have missed to answer a required question', 'watu'),
 			'nothing_selected' => __('You did not select any answer. Are you sure you want to continue?', 'watu'),

Vulnerable code: 		$wpdb->get_results("DELETE FROM ".WATU_EXAMS." WHERE ID='$_REQUEST[quiz]'");
		$wpdb->get_results("DELETE FROM ".WATU_ANSWERS." WHERE question_id IN (SELECT ID FROM ".WATU_QUESTIONS." WHERE exam_id='$_REQUEST[quiz]')");
		$wpdb->get_results("DELETE FROM ".WATU_QUESTIONS." WHERE exam_id='$_REQUEST[quiz]'");
				$exam_id, $uid, $_SERVER['REMOTE_ADDR'], $achieved, $g_id, $grade, $_POST['start_time']));
= Changes in 2.6.7 =
<input type="hidden" name="start_time" value="<?php echo current_time('mysql'); ?>" />
Version: 2.6.7
			'2.3.2'
Fixed code: 		$wpdb->get_results($wpdb->prepare("DELETE FROM ".WATU_EXAMS." WHERE ID=%d", $_REQUEST['quiz']));
		$wpdb->get_results($wpdb->prepare("DELETE FROM ".WATU_ANSWERS." WHERE question_id IN (SELECT ID FROM ".WATU_QUESTIONS." WHERE exam_id=%d", $_REQUEST['quiz']));
		$wpdb->get_results($wpdb->prepare("DELETE FROM ".WATU_QUESTIONS." WHERE exam_id=%d", $_REQUEST['quiz']));
				$exam_id, $uid, $_SERVER['REMOTE_ADDR'], $achieved, $g_id, $grade, @$_POST['start_time']));
= Changes in 2.6.8 =
- Fixed security exploit
	data['start_time'] = jQuery('#watuStartTime').val();
<input type="hidden" id="watuStartTime" name="start_time" value="<?php echo current_time('mysql'); ?>" />
Version: 2.6.8
			'2.3.3'