Details
Affected Software:WordPress
Fixed in Version:2.1
Issue Type:Defense in Depth
Original Code: Found Here
Description
I found this issue interesting for a couple reasons. Upon first glance,the patch appears to be a defense against SQL Injection and in essence,it is. It seems that the $q[‘cat’] value is controlled by the user and is eventually used to help build a SQL statement. Before the $q[‘cat’] value is used in a SQL statement,it is actually sanitized by the following lines:
$q['cat'] = ”.urldecode($q['cat']).”;
$q['cat'] = addslashes_gpc($q['cat']);
Once the value is sanitized,it is used to build various SQL statements. Now this particular patch was developed by the WordPress team because they discovered that when a user/attacker passes a “.” (period character) to $q[‘cat’],it would cause a SQL error which would be displayed to the user. While a single period character doesn’t give the attacker the ability to execute arbitrary SQL,it does give the attacker an information disclosure bug. In an academic sense however,the attacker has convinced the database that their provided value should be interpreted as code as opposed to data (ala SQL Injection). The reason the period character slips through is because it is not defined as a special character in the addslashes() php function… this could be useful in other situations.
The WordPress prevented the information leak by checking to see if $q[‘cat’] is an integer value. The patch here is a single line fix.
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 | // Category stuff if ((empty($q['cat'])) || ($q['cat'] == '0') || // Bypass cat checks if fetching specific posts ( $this->is_single || $this->is_page )) { $whichcat=''; } else { $q['cat'] = ''.urldecode($q['cat']).''; $q['cat'] = addslashes_gpc($q['cat']); $join = "LEFT JOIN $wpdb->post2cat ON ($wpdb->posts.ID = $wpdb->post2cat.post_id) "; $cat_array = preg_split('/[,\s]+/',$q['cat']); $in_cats = $out_cats = ''; foreach ( $cat_array as $cat ) { + $cat = intval($cat); $in = strstr($cat,'-') ? false:true; $cat = trim($cat,'-'); if ( $in ) $in_cats .= "$cat,". get_category_children($cat,'',','); else $out_cats .= "$cat,". get_category_children($cat,'',','); } $in_cats = substr($in_cats,0,-2); $out_cats = substr($out_cats,0,-2); if ( strlen($in_cats) >0 ) $in_cats = "AND category_id IN ($in_cats)"; if ( strlen($out_cats) >0 ) $out_cats = "AND category_id NOT IN ($out_cats)"; $whichcat = $in_cats . $out_cats; $distinct = 'DISTINCT'; } // Category stuff for nice URIs global $cache_categories; if ('' != $q['category_name']) { |


