AppSec Blog

Spot the Vuln - Expands - Cross Site Scripting

Details

Affected Software: WordPress Core

Fixed in Version: 2.8

Issue Type: Cross Site Scripting

Original Code: Found Here

Details

This week's bug was subtle. The patch submitted by the developer addresses an XSS bug. Looking at the diff, we see that $title and $selection come from the query string. These values are fixed up before being assigned to a variable. The developers changed the way $title is assigned in the diff. It's difficult to see why $title needs to be changed, so we'll ignore that change for now. $selection gives some hints towards XSS. $selection is assigned from the query string value $_GET[?s'] which is sent through the trim() and aposfix() functions. Immediately following the $selection variable assignment we see the $selection being manipulated with some HTML tags. This is a good indication that $selection will eventually be used to build HTML markup. I usually recommend developers encode/sanitize values as close to the point of consumption as possible, but this case is different. $selection contains HTML tags (the <p> and </p> tags), so encoding the whole value at the point of consumption will also encode those tags. The <p> tags are probably designed to be rendered by the browser. Due to the mixing of HTML tags and regular data, the developer will have to encode the user controlled values during variable assignment. This is exactly what the WordPress developers did in the patch.

Developers Solution

$image) // see if files exist in content - we don't want to upload non-used selected files. if( strpos($_REQUEST['content'], $image) !== false ) { $desc = isset($_REQUEST['photo_description'][$key]) ? $_REQUEST['photo_description'][$key] : "; $upload = media_sideload_image($image, $post_ID, $desc); // Replace the POSTED content with correct uploaded ones. Regex contains fix for Magic Quotes if( !is_wp_error($upload) ) $content = preg_replace('/]*)src=\\?(\"|\')'.preg_quote($image, '/').'\\?(\2)([^>\/]*)\/*>/is', $upload, $content); } // set the post_content and status $quick['post_status'] = isset($_REQUEST['publish']) ? 'publish' : 'draft'; $quick['post_content'] = $content; // error handling for $post if ( is_wp_error($post_ID)) { wp_die($id); wp_delete_post($post_ID); // error handling for media_sideload } elseif ( is_wp_error($upload)) { wp_die($upload); wp_delete_post($post_ID); } else { $quick['ID'] = $post_ID; wp_update_post($quick); } return $post_ID; } // For submitted posts. if ( isset($_REQUEST['action']) && 'post' == $_REQUEST['action'] ) { check_admin_referer('press-this'); $post_ID = press_it(); $posted = $post_ID; } else { $post_ID = 0; } // Set Variables -$title = isset($_GET['t']) ? esc_html(aposfix(stripslashes($_GET['t']))) : "; -$selection = isset($_GET['s']) ? trim( aposfix( stripslashes($_GET['s']) ) ) : "; +$title = isset( $_GET['t'] ) ? trim( strip_tags( aposfix( stripslashes( $_GET['t'] ) ) ) ) : "; +$selection = isset( $_GET['s'] ) ? trim( htmlspecialchars( html_entity_decode( aposfix( stripslashes( $_GET['s'] ) ) ) ) ) : "; if ( ! empty($selection) ) { $selection = preg_replace('/(\r?\n|\r)/', ' ', $selection); $selection = ' '.str_replace(' ', ", $selection).' '; } $url = isset($_GET['u']) ? esc_url($_GET['u']) : "; $image = isset($_GET['i']) ? $_GET['i'] : "; ...snip...

Post a Comment






Captcha


* Indicates a required field.