Popular Vulnerable Code

Reboot – SQL Injection

Details

Affected Software: The Hacker’s Diet (WordPress Plugin)

Fixed in Version: 0.9.7b

Issue Type: SQL Injection

Original Code: Found Here

Description

This week’s vulnerability was a SQL injection vulnerability affecting the Hacker’s Diet WordPress plugin.  In the vulnerable version, the plugin assigns several variables using values obtained directly from the querystring.  The variable assignments are shown below:

$weeks = $_GET["weeks"];
$start_date = $_GET["start_date"];
$end_date = $_GET["end_date"];
$goal = $_GET["goal"];
$user_id = $_GET["user"];
$maint_mode = $_GET["maint_mode"];

No sanitization or validation is done before assigning the values.  Once the assignments are made, the attacker controlled values are then passed to a dynamic SQL string here resulting in SQL Injection:

$query = “select date, weight, trend from “.$table_prefix.”hackdiet_weightlog where wp_id = $user_id and date > \”".date(“Y-m-d”, strtotime(“$weeks weeks ago”)).”\” order by date asc”;

$query = “select date, weight, trend from “.$table_prefix.”hackdiet_weightlog where wp_id = $user_id and date >= \”$start_date\” and date <= \”$end_date\” order by date asc”;

The plugin authors patched this vulnerability by validating that the $_GET[“user”] and $_GET[“weeks”] parameters contains only numeric characters.  An interesting exercise would be to trace through the code and find where the following variables are being used:

$start_date = $_GET["start_date"];
$end_date = $_GET["end_date"];
$goal = $_GET["goal"];
$maint_mode = $_GET["maint_mode"];

Developers Solution

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
<?php
include (dirname(__FILE__)."/jpgraph/jpgraph.php");
include (dirname(__FILE__)."/jpgraph/jpgraph_line.php");
include (dirname(__FILE__)."/jpgraph/jpgraph_scatter.php");

// get our db settings without loading all of wordpress every save
$html = implode('', file("../../../wp-config.php"));
$html = str_replace ("require_once", "// ", $html);
$html = str_replace ("<?php", "", $html);
$html = str_replace ("?>", "", $html);
eval($html);

mysql_connect(DB_HOST, DB_USER, DB_PASSWORD);
mysql_select_db(DB_NAME);

+if (!is_numeric($_GET["user"]) || !is_numeric($_GET["weeks"])) {
+   exit;
+}

$weeks = $_GET["weeks"];
$start_date = $_GET["start_date"];
$end_date = $_GET["end_date"];
$goal = $_GET["goal"];
$user_id = $_GET["user"];
$maint_mode = $_GET["maint_mode"];

if ($weeks) {
-       $query = "select date, weight, trend from ".$table_prefix."hackdiet_weightlog where wp_id = $user_id and date > \"".date("Y-m-d", strtotime("$weeks weeks ago"))."\" order by date asc";
+       $query = "select date, weight, trend from ".$table_prefix."hackdiet_weightlog where wp_id = \"" . $user_id . "\" and date > \"".date("Y-m-d", strtotime("$weeks weeks ago"))."\" order by date asc";
} else if ($start_date and $end_date) {
-       $query = "select date, weight, trend from ".$table_prefix."hackdiet_weightlog where wp_id = $user_id and date >= \"$start_date\" and date <= \"$end_date\" order by date asc";
+       $query = "select date, weight, trend from ".$table_prefix."hackdiet_weightlog where wp_id = \"" . $user_id . "\" and date >= \"$start_date\" and date <= \"$end_date\" order by date asc";
}

result = mysql_query($query);
if (mysql_num_rows($result)) {
if (mysql_num_rows($result) == 1) {
// only one day, gotta finagle the display

$row = mysql_fetch_assoc($result);

// fake day before
$weight_data[] = 0;
if ($goal > 0) {
$goal_data[] = $goal;
}
$x_data[] = date("n/j", strtotime("yesterday", strtotime($row["date"])));

// data
$weight_data[] = $row["weight"];
if ($goal > 0) {
$goal_data[] = $goal;
}
$x_data[] = date("n/j", strtotime($row["date"]));

// fake day after
$weight_data[] = 0;
if ($goal > 0) {
$goal_data[] = $goal;
}
$x_data[] = date("n/j", strtotime("tomorrow", strtotime($row["date"])));
} else {
$num_rows = mysql_num_rows($result);
if ($num_rows <= 7 * 2) { // 0-2 weeks
$ticks = "daily";
} else if ($num_rows <= 31 * 4) { // 2 weeks - 4 months
$ticks = "weekly";
} else { // 4 months +
$ticks = "monthly";
}

$count = 1;
while ($row = mysql_fetch_assoc($result)) {
$weight_data[] = $row["weight"];
$trend_data[] = $row["trend"];
if ($goal > 0) {
$goal_data[] = $goal;
}
switch ($ticks) {
case "weekly":
if ($count == 1) {
$x_data[] = date("n/j", strtotime($row["date"]));
} else {
$x_data[] = "";
if ($count == 7) {
$count = 0;
}
}
break;
case "monthly":
if (date("j", strtotime($row["date"])) == "1") {
$x_data[] = date("n/j", strtotime($row["date"]));
} else {
$x_data[] = "";
}
break;
case "daily":
default:
$x_data[] = date("n/j", strtotime($row["date"]));
break;
}

$count++;
}
}

If you enjoyed this post, make sure you subscribe to the RSS feed!

Leave a Reply

 

 

 

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>