CVE-2015-10124: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection') (CWE-89)
value: A vulnerability was found in Most Popular Posts Widget Plugin up to 0.8 on WordPress. It has been classified as critical. Affected is the function add_views/show_views of the file functions.php. The manipulation leads to sql injection. It is possible to launch the attack remotely. Upgrading to version 0.9 is able to address this issue. The patch is identified as a99667d11ac8d320006909387b100e9a8b5c12e1. It is recommended to upgrade the affected component. VDB-241026 is the identifier assigned to this vulnerability.
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-10-02T14:15Z
Repository: https://github.com/wp-plugins/most-popular-posts-widget-lite
Language: PHP
Files changed: functions.php, pp-popular-posts.php, readme.txt
Commit date: 2015-02-02 17:32:22 +0000
Commit message: sql injection fix, code cleanup

git-svn-id: https://plugins.svn.wordpress.org/most-popular-posts-widget-lite/trunk@1081078 b8457f37-d9ea-0310-8a92-e5e31aec5664

Diff: diff --git a/functions.php b/functions.php
index 8180f1a..08d78a6 100644
--- a/functions.php
+++ b/functions.php
@@ -2,36 +2,36 @@
 
 //zbieranie danych
 function add_views($postID) {
 	global $wpdb;
 	$popular_posts_statistics_table = $wpdb->prefix . 'popular_posts_statistics';
-	if (!$wpdb->query("SELECT hit_count FROM $popular_posts_statistics_table WHERE post_id = $postID") && $postID != 1 && !preg_match('/bot|spider|crawler|slurp|curl|^$/i', $_SERVER['HTTP_USER_AGENT'])) { //jeśli nie istnieje rekord hit_count z podanym ID oraz ID nie jest równe 1 oraz odwiedzający nie jest botem
-		$result = $wpdb->query("INSERT INTO $popular_posts_statistics_table (post_id, hit_count, date) VALUES ($postID, 1, NOW())"); //dodaje do tablicy id postu, date oraz hit
-	}elseif ($postID != 1 && !preg_match('/bot|spider|crawler|slurp|curl|^$/i', $_SERVER['HTTP_USER_AGENT'])) { //w innym przypadku...
-		$hitsnumber = $wpdb->get_results("SELECT hit_count FROM $popular_posts_statistics_table WHERE post_id = $postID", ARRAY_A);
+	if (!$wpdb->query($wpdb->prepare("SELECT hit_count FROM $popular_posts_statistics_table WHERE post_id = %d", $postID)) && !preg_match('/bot|spider|crawler|slurp|curl|^$/i', $_SERVER['HTTP_USER_AGENT'])) { //jeśli nie istnieje rekord hit_count z podanym ID oraz ID nie jest równe 1 oraz odwiedzający nie jest botem
+		$wpdb->query($wpdb->prepare("INSERT INTO $popular_posts_statistics_table (post_id, hit_count, date) VALUES (%d, 1, NOW())", $postID)); //dodaje do tablicy id postu, date oraz hit
+	}elseif (!preg_match('/bot|spider|crawler|slurp|curl|^$/i', $_SERVER['HTTP_USER_AGENT'])) { //w innym przypadku...
+		$hitsnumber = $wpdb->get_results($wpdb->prepare("SELECT hit_count FROM $popular_posts_statistics_table WHERE post_id = %d", $postID), ARRAY_A);
 		$hitsnumber = $hitsnumber[0]['hit_count'];
-		$result = $wpdb->query("UPDATE $popular_posts_statistics_table SET hit_count = $hitsnumber + 1, date =  NOW() WHERE post_id = $postID");
+		$wpdb->query($wpdb->prepare("UPDATE $popular_posts_statistics_table SET hit_count = %d + 1, date =  NOW() WHERE post_id = %d", $hitsnumber, $postID));
 	}
 }
 
 //wyświetlanie wyników
 function show_views($postID, $posnumber, $numberofdays, $ignoredpages) {
 	global $wpdb;
 	$popular_posts_statistics_table = $wpdb->prefix . 'popular_posts_statistics';
 	$posts_table = $wpdb->prefix . 'posts';
 	if ($wpdb->query("SELECT hit_count FROM $popular_posts_statistics_table")) {
-		$result = $wpdb->get_results("SELECT hit_count FROM $popular_posts_statistics_table WHERE date >= NOW() - INTERVAL $numberofdays DAY ORDER BY hit_count DESC", ARRAY_A);
-		$post_id_number = $wpdb->get_results("SELECT post_id FROM $popular_posts_statistics_table WHERE date >= NOW() - INTERVAL $numberofdays DAY ORDER BY hit_count DESC LIMIT $posnumber", ARRAY_A);
+		$result = $wpdb->get_results($wpdb->prepare("SELECT hit_count FROM $popular_posts_statistics_table WHERE date >= NOW() - INTERVAL %d DAY ORDER BY hit_count DESC", $numberofdays), ARRAY_A);
+		$post_id_number = $wpdb->get_results($wpdb->prepare("SELECT post_id FROM $popular_posts_statistics_table WHERE date >= NOW() - INTERVAL %d DAY ORDER BY hit_count DESC LIMIT %d", $numberofdays, $posnumber), ARRAY_A);
 		echo "<ol>";
 		for ($i = 0; $i < count($post_id_number); ++$i) {
 			$post_number = $post_id_number[$i]['post_id'];
 			$post_link = get_permalink($post_number); //zdobywanie permalinka
 			$countbeginning = "<br /><span id=\"pp-count\">";
 			$countending = "</span></span><br />";
-			$post_name_by_id = $wpdb->get_results("SELECT post_title FROM $posts_table WHERE ID = $post_number", ARRAY_A);
+			$post_name_by_id = $wpdb->get_results($wpdb->prepare("SELECT post_title FROM $posts_table WHERE ID = %d", $post_number), ARRAY_A);
 			if (!$post_name_by_id){ //sprawdza, czy post o danym ID istnieje, jeśli nie - kasuje rekord i przerywa skrypt (który by wyświetlał błąd w pierwszej linii)
-				$wpdb->query("DELETE FROM $popular_posts_statistics_table WHERE post_id = $post_number");
+				$wpdb->query($wpdb->prepare("DELETE FROM $popular_posts_statistics_table WHERE post_id = %d", $post_number));
 				break;
 			}
 			if (in_array($post_number, $ignoredpages)) { //sprawdza, czy postu nie ma na liście banów
 				$cat_or_post_check = TRUE;
 			}else {
diff --git a/pp-popular-posts.php b/pp-popular-posts.php
index c8af1e4..9f4f347 100644
--- a/pp-popular-posts.php
+++ b/pp-popular-posts.php
@@ -2,11 +2,11 @@
 /*
 Plugin Name: Most Popular Posts Widget Lite
 Plugin URI: http://smartfan.pl/
 Description: Widget which displays statistics of most popular posts based on mumber of visits. Lite version.
 Author: Piotr Pesta
-Version: 0.8
+Version: 0.9
 Author URI: http://smartfan.pl/
 License: GPL12
 */
 
 include 'functions.php';
diff --git a/readme.txt b/readme.txt
index 76a446e..4a476af 100644
--- a/readme.txt
+++ b/readme.txt
@@ -3,11 +3,11 @@ Plugin Name: Most Popular Posts Widget Lite
 Plugin URI: http://smartfan.pl/
 Tags: widget, bars, pupular, pupularity, visits, counter
 Author: Piotr Pesta
 Requires at least: 2.8.0
 Tested up to: 4.1
-Stable tag: 0.8
+Stable tag: 0.9
 License: GPLv2 or later
 License URI: http://www.gnu.org/licenses/gpl-2.0.html
 
 Widget which displays statistics of most popular posts based on mumber of visits. Lite version.
 
@@ -32,6 +32,9 @@ Or just add .zip file as a new plugin in your Wordpress administration panel.
 1. Most Popular Posts Widget Lite visible on right block.
 2. Options menu.
 
 == Changelog ==
 * 0.8
-Initial Release
\ No newline at end of file
+Initial Release
+* 0.9
+Code cleanup
+SQL Injection security fix
\ No newline at end of file

Vulnerable code: 	if (!$wpdb->query("SELECT hit_count FROM $popular_posts_statistics_table WHERE post_id = $postID") && $postID != 1 && !preg_match('/bot|spider|crawler|slurp|curl|^$/i', $_SERVER['HTTP_USER_AGENT'])) { //jeśli nie istnieje rekord hit_count z podanym ID oraz ID nie jest równe 1 oraz odwiedzający nie jest botem
		$result = $wpdb->query("INSERT INTO $popular_posts_statistics_table (post_id, hit_count, date) VALUES ($postID, 1, NOW())"); //dodaje do tablicy id postu, date oraz hit
	}elseif ($postID != 1 && !preg_match('/bot|spider|crawler|slurp|curl|^$/i', $_SERVER['HTTP_USER_AGENT'])) { //w innym przypadku...
		$hitsnumber = $wpdb->get_results("SELECT hit_count FROM $popular_posts_statistics_table WHERE post_id = $postID", ARRAY_A);
		$result = $wpdb->query("UPDATE $popular_posts_statistics_table SET hit_count = $hitsnumber + 1, date =  NOW() WHERE post_id = $postID");
		$result = $wpdb->get_results("SELECT hit_count FROM $popular_posts_statistics_table WHERE date >= NOW() - INTERVAL $numberofdays DAY ORDER BY hit_count DESC", ARRAY_A);
		$post_id_number = $wpdb->get_results("SELECT post_id FROM $popular_posts_statistics_table WHERE date >= NOW() - INTERVAL $numberofdays DAY ORDER BY hit_count DESC LIMIT $posnumber", ARRAY_A);
			$post_name_by_id = $wpdb->get_results("SELECT post_title FROM $posts_table WHERE ID = $post_number", ARRAY_A);
				$wpdb->query("DELETE FROM $popular_posts_statistics_table WHERE post_id = $post_number");
Version: 0.8
Stable tag: 0.8
Initial Release
Fixed code: 	if (!$wpdb->query($wpdb->prepare("SELECT hit_count FROM $popular_posts_statistics_table WHERE post_id = %d", $postID)) && !preg_match('/bot|spider|crawler|slurp|curl|^$/i', $_SERVER['HTTP_USER_AGENT'])) { //jeśli nie istnieje rekord hit_count z podanym ID oraz ID nie jest równe 1 oraz odwiedzający nie jest botem
		$wpdb->query($wpdb->prepare("INSERT INTO $popular_posts_statistics_table (post_id, hit_count, date) VALUES (%d, 1, NOW())", $postID)); //dodaje do tablicy id postu, date oraz hit
	}elseif (!preg_match('/bot|spider|crawler|slurp|curl|^$/i', $_SERVER['HTTP_USER_AGENT'])) { //w innym przypadku...
		$hitsnumber = $wpdb->get_results($wpdb->prepare("SELECT hit_count FROM $popular_posts_statistics_table WHERE post_id = %d", $postID), ARRAY_A);
		$wpdb->query($wpdb->prepare("UPDATE $popular_posts_statistics_table SET hit_count = %d + 1, date =  NOW() WHERE post_id = %d", $hitsnumber, $postID));
		$result = $wpdb->get_results($wpdb->prepare("SELECT hit_count FROM $popular_posts_statistics_table WHERE date >= NOW() - INTERVAL %d DAY ORDER BY hit_count DESC", $numberofdays), ARRAY_A);
		$post_id_number = $wpdb->get_results($wpdb->prepare("SELECT post_id FROM $popular_posts_statistics_table WHERE date >= NOW() - INTERVAL %d DAY ORDER BY hit_count DESC LIMIT %d", $numberofdays, $posnumber), ARRAY_A);
			$post_name_by_id = $wpdb->get_results($wpdb->prepare("SELECT post_title FROM $posts_table WHERE ID = %d", $post_number), ARRAY_A);
				$wpdb->query($wpdb->prepare("DELETE FROM $popular_posts_statistics_table WHERE post_id = %d", $post_number));
Version: 0.9
Stable tag: 0.9
Initial Release
* 0.9
Code cleanup
SQL Injection security fix