Skip to content

Instantly share code, notes, and snippets.

@holizz
Created June 19, 2012 13:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save holizz/2954136 to your computer and use it in GitHub Desktop.
Save holizz/2954136 to your computer and use it in GitHub Desktop.
Fix many SQL injection vectors.
diff --git a/admin/your_subscriptions.php b/admin/your_subscriptions.php
index ddf74ae..97dbba5 100755
--- a/admin/your_subscriptions.php
+++ b/admin/your_subscriptions.php
@@ -7,7 +7,7 @@ global $user_ID, $s2nonce;
if ( isset($_GET['email']) ) {
global $wpdb;
- $user_ID = $wpdb->get_var("SELECT ID FROM $wpdb->users WHERE user_email = '" . urldecode($_GET['email']) . "'");
+ $user_ID = $wpdb->get_var($wpdb->prepare("SELECT ID FROM $wpdb->users WHERE user_email = %s", urldecode($_GET['email'])));
} else {
get_currentuserinfo();
}
diff --git a/classes/class-s2-admin.php b/classes/class-s2-admin.php
index 0d2b529..0220380 100755
--- a/classes/class-s2-admin.php
+++ b/classes/class-s2-admin.php
@@ -364,20 +364,20 @@ class s2_admin extends s2class {
$count['all_users'] = $wpdb->get_var("SELECT COUNT(ID) FROM $wpdb->users");
}
if ( $this->s2_mu ) {
- $count['registered'] = $wpdb->get_var("SELECT COUNT(meta_key) FROM $wpdb->usermeta WHERE meta_key='" . $wpdb->prefix . "capabilities' AND meta_key='" . $this->get_usermeta_keyname('s2_subscribed') . "'");
+ $count['registered'] = $wpdb->get_var($wpdb->prepare("SELECT COUNT(meta_key) FROM $wpdb->usermeta WHERE meta_key='" . $wpdb->prefix . "capabilities' AND meta_key=%s", $this->get_usermeta_keyname('s2_subscribed')));
} else {
- $count['registered'] = $wpdb->get_var("SELECT COUNT(meta_key) FROM $wpdb->usermeta WHERE meta_key='" . $this->get_usermeta_keyname('s2_subscribed') . "'");
+ $count['registered'] = $wpdb->get_var($wpdb->prepare("SELECT COUNT(meta_key) FROM $wpdb->usermeta WHERE meta_key=%s", $this->get_usermeta_keyname('s2_subscribed')));
}
$count['all'] = ($count['confirmed'] + $count['unconfirmed'] + $count['all_users']);
// get subscribers to individual categories but only if we are using per-post notifications
if ( $this->subscribe2_options['email_freq'] == 'never' ) {
if ( $this->s2_mu ) {
foreach ( $all_cats as $cat ) {
- $count[$cat->name] = $wpdb->get_var("SELECT COUNT(a.meta_key) FROM $wpdb->usermeta AS a INNER JOIN $wpdb->usermeta AS b ON a.user_id = b.user_id WHERE a.meta_key='" . $wpdb->prefix . "capabilities' AND b.meta_key='" . $this->get_usermeta_keyname('s2_cat') . $cat->term_id . "'");
+ $count[$cat->name] = $wpdb->get_var($wpdb->prepare("SELECT COUNT(a.meta_key) FROM $wpdb->usermeta AS a INNER JOIN $wpdb->usermeta AS b ON a.user_id = b.user_id WHERE a.meta_key='" . $wpdb->prefix . "capabilities' AND b.meta_key=%s", $this->get_usermeta_keyname('s2_cat') . $cat->term_id));
}
} else {
foreach ( $all_cats as $cat ) {
- $count[$cat->name] = $wpdb->get_var("SELECT COUNT(meta_value) FROM $wpdb->usermeta WHERE meta_key='" . $this->get_usermeta_keyname('s2_cat') . $cat->term_id . "'");
+ $count[$cat->name] = $wpdb->get_var($wpdb->prepare("SELECT COUNT(meta_value) FROM $wpdb->usermeta WHERE meta_key=%s", $this->get_usermeta_keyname('s2_cat') . $cat->term_id));
}
}
}
@@ -532,9 +532,9 @@ class s2_admin extends s2class {
global $wpdb;
$useremails = explode(",\r\n", $emails);
- $useremails = implode("', '", $useremails);
+ $useremails = implode(", ", array_map(function ($c) use ($wpdb) {return $wpdb->prepare('%s', $c);}, $useremails));
- $sql = "SELECT ID FROM $wpdb->users WHERE user_email IN ('$useremails')";
+ $sql = "SELECT ID FROM $wpdb->users WHERE user_email IN ($useremails)";
$user_IDs = $wpdb->get_col($sql);
foreach ( $user_IDs as $user_ID ) {
@@ -564,7 +564,7 @@ class s2_admin extends s2class {
global $wpdb;
$useremails = explode(",\r\n", $emails);
- $useremails = "'" . implode("', '", $useremails) . "'";
+ $useremails = implode(", ", array_map(function ($c) use ($wpdb) {return $wpdb->prepare('%s', $c);}, $useremails));
$sql = "SELECT ID FROM $wpdb->users WHERE user_email IN ($useremails)";
$user_IDs = $wpdb->get_col($sql);
@@ -597,10 +597,10 @@ class s2_admin extends s2class {
global $wpdb;
$subscribers = explode(",\r\n", $subscribers_string);
- $emails = "'" . implode("', '", $subscribers) . "'";
- $ids = $wpdb->get_col("SELECT ID FROM $wpdb->users WHERE user_email IN ($emails)");
- $ids = implode(',', $ids);
- $sql = "UPDATE $wpdb->usermeta SET meta_value='{$format}' WHERE meta_key='" . $this->get_usermeta_keyname('s2_format') . "' AND user_id IN ($ids)";
+ $emails = implode(", ", array_map(function ($c) use ($wpdb) {return $wpdb->prepare('%s', $c);}, $subscribers));
+ $ids = $wpdb->get_col($wpdb->prepare("SELECT ID FROM $wpdb->users WHERE user_email IN ($emails)"));
+ $ids = implode(',', array_map(function ($c) use ($wpdb) {return $wpdb->prepare('%d', $c);}, $ids));
+ $sql = $wpdb->prepare("UPDATE $wpdb->usermeta SET meta_value=%s WHERE meta_key=%s AND user_id IN ($ids)", $format, $this->get_usermeta_keyname('s2_format'));
$wpdb->get_results($sql);
} // end format_change()
@@ -612,7 +612,7 @@ class s2_admin extends s2class {
global $wpdb;
$useremails = explode(",\r\n", $emails);
- $useremails = "'" . implode("', '", $useremails) . "'";
+ $useremails = implode(", ", array_map(function ($c) use ($wpdb) {return $wpdb->prepare('%s', $c);}, $useremails));
$sql = "SELECT ID FROM $wpdb->users WHERE user_email IN ($useremails)";
$user_IDs = $wpdb->get_col($sql);
@@ -660,9 +660,9 @@ class s2_admin extends s2class {
if ( 'yes' == $this->subscribe2_options['show_autosub'] ) {
if ( $this->s2_mu ) {
- $sql = "SELECT DISTINCT a.user_id FROM $wpdb->usermeta AS a INNER JOIN $wpdb->usermeta AS b WHERE a.user_id = b.user_id AND a.meta_key='" . $this->get_usermeta_keyname('s2_autosub') . "' AND a.meta_value='yes' AND b.meta_key='" . $this->get_usermeta_keyname('s2_subscribed') . "'";
+ $sql = $wpdb->prepare("SELECT DISTINCT a.user_id FROM $wpdb->usermeta AS a INNER JOIN $wpdb->usermeta AS b WHERE a.user_id = b.user_id AND a.meta_key=%s AND a.meta_value='yes' AND b.meta_key=%s", $this->get_usermeta_keyname('s2_autosub'), $this->get_usermeta_keyname('s2_subscribed'));
} else {
- $sql = "SELECT DISTINCT user_id FROM $wpdb->usermeta WHERE $wpdb->usermeta.meta_key='" . $this->get_usermeta_keyname('s2_autosub') . "' AND $wpdb->usermeta.meta_value='yes'";
+ $sql = $wpdb->prepare("SELECT DISTINCT user_id FROM $wpdb->usermeta WHERE $wpdb->usermeta.meta_key=%s AND $wpdb->usermeta.meta_value='yes'", $this->get_usermeta_keyname('s2_autosub'));
}
$user_IDs = $wpdb->get_col($sql);
if ( '' == $user_IDs ) { return; }
@@ -694,9 +694,9 @@ class s2_admin extends s2class {
global $wpdb;
if ( $this->s2_mu ) {
- $sql = "SELECT DISTINCT a.user_id FROM $wpdb->usermeta AS a INNER JOIN $wpdb->usermeta AS b WHERE a.user_id = b.user_id AND a.meta_key='" . $this->get_usermeta_keyname('s2_cat') . "$deleted_category' AND b.meta_key='" . $this->get_usermeta_keyname('s2_subscribed') . "'";
+ $sql = $wpdb->prepare("SELECT DISTINCT a.user_id FROM $wpdb->usermeta AS a INNER JOIN $wpdb->usermeta AS b WHERE a.user_id = b.user_id AND a.meta_key=%s AND b.meta_key=%s", $this->get_usermeta_keyname('s2_cat') . $deleted_category, $this->get_usermeta_keyname('s2_subscribed'));
} else {
- $sql = "SELECT DISTINCT user_id FROM $wpdb->usermeta WHERE meta_key='" . $this->get_usermeta_keyname('s2_cat') . "$deleted_category'";
+ $sql = $wpdb->prepare("SELECT DISTINCT user_id FROM $wpdb->usermeta WHERE meta_key=%s", $this->get_usermeta_keyname('s2_cat') . $deleted_category);
}
$user_IDs = $wpdb->get_col($sql);
if ( '' == $user_IDs ) { return; }
diff --git a/classes/class-s2-core.php b/classes/class-s2-core.php
index 9120d6c..6456e5c 100755
--- a/classes/class-s2-core.php
+++ b/classes/class-s2-core.php
@@ -213,7 +213,7 @@ class s2class {
foreach ( $public_subscribers as $email ) {
$new_email = $this->sanitize_email($email);
if ( $email !== $new_email ) {
- $wpdb->get_results("UPDATE $this->public SET email='$new_email' WHERE CAST(email as binary)='$email'");
+ $wpdb->get_results($wpdb->prepare("UPDATE $this->public SET email=%s WHERE CAST(email as binary)=%s", $new_email, $email));
}
}
return;
@@ -742,7 +742,7 @@ class s2class {
if ( !$id ) {
return false;
}
- return $wpdb->get_var("SELECT email FROM $this->public WHERE id=$id");
+ return $wpdb->get_var($wpdb->prepare("SELECT email FROM $this->public WHERE id=%d", $id));
} // end get_email()
/**
@@ -754,7 +754,7 @@ class s2class {
if ( !$email ) {
return false;
}
- return $wpdb->get_var("SELECT id FROM $this->public WHERE email='$email'");
+ return $wpdb->get_var($wpdb->prepare("SELECT id FROM $this->public WHERE email=%s", $email));
} // end get_id()
/**
@@ -769,12 +769,12 @@ class s2class {
if ( false !== $this->is_public($email) ) {
// is this an email for a registered user
- $check = $wpdb->get_var("SELECT user_email FROM $wpdb->users WHERE user_email='$this->email'");
+ $check = $wpdb->get_var($wpdb->prepare("SELECT user_email FROM $wpdb->users WHERE user_email=%s", $this->email));
if ( $check ) { return; }
if ( $confirm ) {
- $wpdb->get_results("UPDATE $this->public SET active='1', ip='$this->ip' WHERE CAST(email as binary)='$email'");
+ $wpdb->get_results($wpdb->prepare("UPDATE $this->public SET active='1', ip=%s WHERE CAST(email as binary)=%s", $this->ip, $email));
} else {
- $wpdb->get_results("UPDATE $this->public SET date=CURDATE() WHERE CAST(email as binary)='$email'");
+ $wpdb->get_results($wpdb->prepare("UPDATE $this->public SET date=CURDATE() WHERE CAST(email as binary)=%s", $email));
}
} else {
if ( $confirm ) {
@@ -793,7 +793,7 @@ class s2class {
global $wpdb;
if ( !is_email($email) ) { return false; }
- $wpdb->get_results("DELETE FROM $this->public WHERE CAST(email as binary)='$email'");
+ $wpdb->get_results($wpdb->prepare("DELETE FROM $this->public WHERE CAST(email as binary)=%s", $email));
} // end delete()
/**
@@ -809,9 +809,9 @@ class s2class {
if ( false === $status ) { return false; }
if ( '0' == $status ) {
- $wpdb->get_results("UPDATE $this->public SET active='1' WHERE CAST(email as binary)='$email'");
+ $wpdb->get_results($wpdb->prepare("UPDATE $this->public SET active='1' WHERE CAST(email as binary)=%s", $email));
} else {
- $wpdb->get_results("UPDATE $this->public SET active='0' WHERE CAST(email as binary)='$email'");
+ $wpdb->get_results($wpdb->prepare("UPDATE $this->public SET active='0' WHERE CAST(email as binary)=%s", $email));
}
} // end toggle()
@@ -853,7 +853,7 @@ class s2class {
if ( '' == $email ) { return false; }
// run the query and force case sensitivity
- $check = $wpdb->get_var("SELECT active FROM $this->public WHERE CAST(email as binary)='$email'");
+ $check = $wpdb->get_var($wpdb->prepare("SELECT active FROM $this->public WHERE CAST(email as binary)=%s", $email));
if ( '0' == $check || '1' == $check ) {
return $check;
} else {
@@ -906,7 +906,7 @@ class s2class {
if ( '' == $email ) { return false; }
- $check = $wpdb->get_var("SELECT user_email FROM $wpdb->users WHERE user_email='$email'");
+ $check = $wpdb->get_var($wpdb->prepare("SELECT user_email FROM $wpdb->users WHERE user_email=%s", $email));
if ( $check ) {
return true;
} else {
@@ -922,7 +922,7 @@ class s2class {
if ( '' == $email ) { return false; }
- $id = $wpdb->get_var("SELECT id FROM $wpdb->users WHERE user_email='$email'");
+ $id = $wpdb->get_var($wpdb->prepare("SELECT id FROM $wpdb->users WHERE user_email=%s", $email));
return $id;
} // end get_user_id()
@@ -972,7 +972,7 @@ class s2class {
// text or HTML subscribers
if ( 'all' != $r['format'] ) {
$JOIN .= "INNER JOIN $wpdb->usermeta AS b ON a.user_id = b.user_id ";
- $AND .= " AND b.meta_key='" . $this->get_usermeta_keyname('s2_format') . "' AND b.meta_value=";
+ $AND .= $wpdb->prepare(" AND b.meta_key=%s AND b.meta_value=", $this->get_usermeta_keyname('s2_format'));
if ( 'html' == $r['format'] ) {
$AND .= "'html'";
} elseif ( 'html_excerpt' == $r['format'] ) {
@@ -989,7 +989,7 @@ class s2class {
$JOIN .= "INNER JOIN $wpdb->usermeta AS c ON a.user_id = c.user_id ";
$and = '';
foreach ( explode(',', $r['cats']) as $cat ) {
- ('' == $and) ? $and = "c.meta_key='" . $this->get_usermeta_keyname('s2_cat') . "$cat'" : $and .= " OR c.meta_key='" . $this->get_usermeta_keyname('s2_cat') . "$cat'";
+ ('' == $and) ? $and = $wpdb->prepare("c.meta_key=%s", $this->get_usermeta_keyname('s2_cat') . $cat) : $and .= $wpdb->prepare(" OR c.meta_key=%s", $this->get_usermeta_keyname('s2_cat') . $cat);
}
$AND .= " AND ($and)";
}
@@ -997,17 +997,17 @@ class s2class {
// specific authors
if ( '' != $r['author'] ) {
$JOIN .= "INNER JOIN $wpdb->usermeta AS d ON a.user_id = d.user_id ";
- $AND .= " AND (d.meta_key='" . $this->get_usermeta_keyname('s2_authors') . "' AND NOT FIND_IN_SET(" . $r['author'] . ", d.meta_value))";
+ $AND .= $wpdb->prepare(" AND (d.meta_key=%s AND NOT FIND_IN_SET(%s, d.meta_value))", $this->get_usermeta_keyname('s2_authors'), $r['author']);
}
if ( $this->s2_mu ) {
$sql = "SELECT a.user_id FROM $wpdb->usermeta AS a " . $JOIN . "WHERE a.meta_key='" . $wpdb->prefix . "capabilities'" . $AND;
} else {
- $sql = "SELECT a.user_id FROM $wpdb->usermeta AS a " . $JOIN . "WHERE a.meta_key='" . $this->get_usermeta_keyname('s2_subscribed') . "'" . $AND;
+ $sql = $wpdb->prepare("SELECT a.user_id FROM $wpdb->usermeta AS a " . $JOIN . "WHERE a.meta_key=%s" . $AND, $this->get_usermeta_keyname('s2_subscribed'));
}
$result = $wpdb->get_col($sql);
if ( $result ) {
- $ids = implode(',', $result);
+ $ids = implode(',', array_map(function ($c) use ($wpdb) {return $wpdb->prepare('%s', $c);}, $result));
$registered = $wpdb->get_col("SELECT user_email FROM $wpdb->users WHERE ID IN ($ids)");
}
@@ -1325,7 +1325,7 @@ class s2class {
if ( $subscribe != '1' ) { return $comment_ID; }
// Retrieve the information about the comment
- $sql = "SELECT comment_author_email, comment_approved FROM $wpdb->comments WHERE comment_ID='$comment_ID' LIMIT 1";
+ $sql = $wpdb->prepare("SELECT comment_author_email, comment_approved FROM $wpdb->comments WHERE comment_ID=%s LIMIT 1", $comment_ID);
$comment = $wpdb->get_row($sql, OBJECT);
if ( empty($comment) ) { return $comment_ID; }
@@ -1413,21 +1413,21 @@ class s2class {
}
$s2_post_types = apply_filters('s2_post_types', $s2_post_types);
foreach( $s2_post_types as $post_type ) {
- ('' == $type) ? $type = "'$post_type'" : $type .= ", '$post_type'";
+ ('' == $type) ? $type = $wpdb->prepare("%s", $post_type) : $type .= $wpdb->prepare(", %s", $post_type);
}
// collect posts
if ( $resend == 'resend' ) {
if ( $this->subscribe2_options['cron_order'] == 'desc' ) {
- $posts = $wpdb->get_results("SELECT ID, post_title, post_excerpt, post_content, post_type, post_password, post_date, post_author FROM $wpdb->posts WHERE post_date >= '$last' AND post_date < '$prev' AND post_status IN ($status) AND post_type IN ($type) ORDER BY post_date DESC");
+ $posts = $wpdb->get_results($wpdb->prepare("SELECT ID, post_title, post_excerpt, post_content, post_type, post_password, post_date, post_author FROM $wpdb->posts WHERE post_date >= %s AND post_date < %s AND post_status IN ($status) AND post_type IN ($type) ORDER BY post_date DESC"), $last, $prev);
} else {
- $posts = $wpdb->get_results("SELECT ID, post_title, post_excerpt, post_content, post_type, post_password, post_date, post_author FROM $wpdb->posts WHERE post_date >= '$last' AND post_date < '$prev' AND post_status IN ($status) AND post_type IN ($type) ORDER BY post_date ASC");
+ $posts = $wpdb->get_results($wpdb->prepare("SELECT ID, post_title, post_excerpt, post_content, post_type, post_password, post_date, post_author FROM $wpdb->posts WHERE post_date >= %s AND post_date < %s AND post_status IN ($status) AND post_type IN ($type) ORDER BY post_date ASC"), $last, $prev);
}
} else {
if ( $this->subscribe2_options['cron_order'] == 'desc' ) {
- $posts = $wpdb->get_results("SELECT ID, post_title, post_excerpt, post_content, post_type, post_password, post_date, post_author FROM $wpdb->posts WHERE post_date >= '$prev' AND post_date < '$now' AND post_status IN ($status) AND post_type IN ($type) ORDER BY post_date DESC");
+ $posts = $wpdb->get_results($wpdb->prepare("SELECT ID, post_title, post_excerpt, post_content, post_type, post_password, post_date, post_author FROM $wpdb->posts WHERE post_date >= %s AND post_date < %s AND post_status IN ($status) AND post_type IN ($type) ORDER BY post_date DESC"), $prev, $now);
} else {
- $posts = $wpdb->get_results("SELECT ID, post_title, post_excerpt, post_content, post_type, post_password, post_date, post_author FROM $wpdb->posts WHERE post_date >= '$prev' AND post_date < '$now' AND post_status IN ($status) AND post_type IN ($type) ORDER BY post_date ASC");
+ $posts = $wpdb->get_results($wpdb->prepare("SELECT ID, post_title, post_excerpt, post_content, post_type, post_password, post_date, post_author FROM $wpdb->posts WHERE post_date >= %s AND post_date < %s AND post_status IN ($status) AND post_type IN ($type) ORDER BY post_date ASC"), $prev, $now);
}
}
} else {
@@ -1641,7 +1641,7 @@ class s2class {
// do we need to install anything?
$this->public = $table_prefix . "subscribe2";
- if ( $wpdb->get_var("SHOW TABLES LIKE '{$this->public}'") != $this->public ) { $this->install(); }
+ if ( $wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $this->public)) != $this->public ) { $this->install(); }
//do we need to upgrade anything?
if ( is_array($this->subscribe2_options) && $this->subscribe2_options['version'] !== S2VERSION ) {
add_action('shutdown', array(&$this, 'upgrade'));
diff --git a/classes/class-s2-frontend.php b/classes/class-s2-frontend.php
index 809eda9..a3d69bb 100755
--- a/classes/class-s2-frontend.php
+++ b/classes/class-s2-frontend.php
@@ -64,7 +64,7 @@ class s2_frontend extends s2class {
$this->email = $this->sanitize_email($_POST['email']);
$this->ip = $_POST['ip'];
// does the supplied email belong to a registered user?
- $check = $wpdb->get_var("SELECT user_email FROM $wpdb->users WHERE user_email = '$this->email'");
+ $check = $wpdb->get_var($wpdb->prepare("SELECT user_email FROM $wpdb->users WHERE user_email = %s"), $this->email);
if ( '' != $check ) {
// this is a registered email
$this->s2form = $this->please_log_in;
@mattyrob
Copy link

Okay, there's a syntax error in the code change for class-s2-frontend.php, the updated line needs the brackets adjusting:

$check = $wpdb->get_var($wpdb->prepare("SELECT user_email FROM $wpdb->users WHERE user_email = %s", $this->email));

Also, the array_map() type code will only work in PHP 5.3 and up, it fails in PHP 5.2 so those sections needs another way for WordPress sites as minimum of current WordPress is 5.2.4

@mattyrob
Copy link

I think I've got a way around the array_map issue, I've created a new function:

/**
Function to sanitise array of data for SQL
*/
function prepare_in_data($data) {
    global $wpdb;
    return $wpdb->prepare('%s', $data);
} // end prepare_in_data()

And all the array_map lines now look something like this:
$ids = implode(',', array_map(array($this, 'prepare_in_data'), $result));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment