Support » Plugin: Contextual Related Posts » SQL injection vulnerability (possible patch)

  • Resolved flynsarmy


    I was checking my PHP error log and got the following:

    WordPress database error You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘) LIMIT 5’ at line 1 for query SELECT DISTINCT ID FROM wp_60_posts WHERE MATCH (post_title,post_content) AGAINST (‘

    — huge multiline post content stuff here —

    ‘) AND post_date <= ‘2013-11-18 11:49:33’ AND post_date >= ‘2010-11-20 11:49:33’ AND post_status = ‘publish’ AND ID != 20787 AND ( ) LIMIT 5 made by

    I checked your plugin and found this block of code:

    $sql = "SELECT DISTINCT ID "
    . " FROM ".$wpdb->posts." WHERE "
    . "MATCH (post_title,post_content) AGAINST ('".$stuff."') "
    . "AND post_date <= '".$now."' "
    . "AND post_date >= '".$current_date."' "
    . "AND post_status = 'publish' "
    . "AND ID != ".$post->ID." ";
    if ($crp_settings['exclude_post_ids']!='') $sql .= "AND ID NOT IN (".$crp_settings['exclude_post_ids'].") ";
    $sql .= "AND ( ";
    $multiple = false;
    foreach ($post_types as $post_type) {
    	if ( $multiple ) $sql .= ' OR ';
    	$sql .= " post_type = '".$post_type."' ";
    	$multiple = true;
    $sql .=" ) ";
    $sql .= "LIMIT ".$limit;
    $results = $wpdb->get_results($sql);

    This is bad! Never just drop your content into the SQL like that! Your addslashes() won’t always help you. This is an SQL injection vulnerability. Take a look at the wpdb documentation.

    Your query should look like the following (completely untested):

    $args = array(
    $sql = "
    	FROM ".$wpdb->posts."
    	WHERE MATCH (post_title,post_content) AGAINST (%s)
    	AND post_date < %s
    	AND post_date >= %s
    	AND post_status = %s
    	AND ID != %d
    // I really hope the below is already sanitized! If not do something like
    // implode(',', array_map('intval', array_map('trim', explode(",", $crp_settings['exclude_post_ids']))))
    // but over multiple lines to avoid PHP reference warnings
    if ($crp_settings['exclude_post_ids']!='')
    	$sql .= "AND ID NOT IN (".$crp_settings['exclude_post_ids'].") ";
    $sql .= " AND (";
    foreach ($post_types as $post_type) {
    	if ( $multiple ) $sql .= ' OR ';
    	$sql .= " post_type = '%s";
    	$multiple = true;
    	$args[] = $post_type;
    $args[] = $limit;
    $sq .= " ) LIMIT %d";
    $results = $wpdb->query($wpdb->prepare($sql, $args));

Viewing 5 replies - 1 through 5 (of 5 total)
  • I didn’t check the rest of your plugin but if you’re using RAW sql anywhere else, please fix that up also.

    Plugin Author Ajay


    Understood. I’ll fix the plugin along the lines above and also other instances across this one.

    Plugin Author Ajay



    I’ve got this fixed in the current version of the plugin

    You’re still calling addslashes() on the $stuff variable. It’s already being escaped correctly in your $wpdb->prepare() call so you’re escaping it twice. This will mean no results with ‘ or ” characters in the title will ever be found in the related posts list I believe.

    You need to remove the addslashes() calls.

    EDIT: Confirmed. Adding a ‘ to the title of a related post causes it to disappear from the related posts list.

    Plugin Author Ajay


    Understood. I’ll fix this in the next version along with the shorcode.

Viewing 5 replies - 1 through 5 (of 5 total)
  • The topic ‘SQL injection vulnerability (possible patch)’ is closed to new replies.