| DetailsAffected Software:Subscribe to Comments Plugin Fixed in Version:2.1 Issue Type:Cross Site Scripting (XSS) Original Code:Found Here DescriptionA familiar symptom here with the same ole result. In the vulnerable code we see a call to $_SERVER['REQUEST_URI']. For some reason,many developers assume REQUEST_URI cannot be tainted and used for XSS. REQUEST_URI will not only include the path to current php file,it will also include any querystring parameters in the URI as well. Here’s a few examples of what REQUEST_URI will return: http://spotthevuln.com/blah/ results in –>/ http://spotthevuln.com/blah//index.php results in –>/blah/index.php http://spotthevuln.com/blah/index.php?qs=value results in –>/blah/index.php?qs=value http://spotthevuln.com/blah/index.php/qs1/qs2 results in –>/blah/index.php/qs1/qs2
As you can see an attacker can easily taint the REQUEST_URI value,using it in XSS attacks. The developers addressed this vulnerability by encoding calls to REQUEST_URI. Developers Solution<?phpfunction show_subscription_checkbox ($id='0'){global $sg_subscribe;sg_subscribe_start();if ( $sg_subscribe->checkbox_shown ) return $id;if ( !$email = $sg_subscribe->current_viewer_subscription_status() ):?><?php ?><?php ?><?php ?><p <?php if ($sg_subscribe->clear_both) echo 'style="clear:both;"';?>class="subscribe-to-comments"> <input type="checkbox"name="subscribe"id="subscribe"value="subscribe"style="width:auto;"<?php if ($sg_subscribe->default_subscribed) echo 'checked="checked"';?>/> <label for="subscribe"><?php echo $sg_subscribe->not_subscribed_text;?></label></p><?php ?><?php elseif ( $email == 'admin' &¤t_user_can('manage_options') ):?><?php ?><?php ?><?php ?><p <?php if ($sg_subscribe->clear_both) echo 'style="clear:both;"';?>class="subscribe-to-comments"><?php echo str_replace('[manager_link]',$sg_subscribe->manage_link($email,true,false),$sg_subscribe->author_text);?></p><?php else:?><?php ?><?php ?><?php ?><p <?php if ($sg_subscribe->clear_both) echo 'style="clear:both;"';?>class="subscribe-to-comments"><?php echo str_replace('[manager_link]',$sg_subscribe->manage_link($email,true,false),$sg_subscribe->subscribed_text);?></p><?php ?><?php endif;$sg_subscribe->checkbox_shown = true;return $id}function show_manual_subscription_form (){global $id,$sg_subscribe,$user_email;sg_subscribe_start();$sg_subscribe->show_errors('solo_subscribe','<div class="solo-subscribe-errors">','</div>',__('<strong>Error:</strong>','subscribe-to-comments'),'<br />');if ( !$sg_subscribe->current_viewer_subscription_status() ):get_currentuserinfo();?><?php ?><?php ?><?php ?>-<form action="http://<?php echo $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] ?>"method="post">+<form action="http://<?php echo $_SERVER['HTTP_HOST'] . wp_specialchars($_SERVER['REQUEST_URI']);?>"method="post"><input type="hidden"name="solo-comment-subscribe"value="solo-comment-subscribe"/><input type="hidden"name="postid"value="<?php echo $id;?>"/>-<input type="hidden"name="ref"value="<?php echo 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];?>"/>+<input type="hidden"name="ref"value="<?php echo urlencode('http://' . $_SERVER['HTTP_HOST'] . wp_specialchars($_SERVER['REQUEST_URI']));?>"/><p class="solo-subscribe-to-comments"><?php _e('Subscribe without commenting','subscribe-to-comments');?><br /><label for="solo-subscribe-email"><?php _e('E-Mail:','subscribe-to-comments');?><input type="text"name="email"id="solo-subscribe-email"size="22"value="<?php echo $user_email;?>"/></label><input type="submit"name="submit"value="<?php _e('Subscribe','subscribe-to-comments');?>"/></p></form><?php ?>DetailsAffected Software:WebChat Module for Jive Fixed in Version:August of 2008 Issue Type:Cross Site Scripting Original Code: Found Here DescriptionThis week’s vulnerability affected a webchat module created by Jive Software. The bug is straightforward, the JSP code takes an attacker controlled value and uses it to build dynamic HTML. Although the bug is straightforward,this week’s example was a great/simple exercise in identifying a vulnerable pattern and tracing to find other vulnerable patterns in the code. This week’s sample has three separate vulnerabilities that were all addressed via single patch. All these have similar symptoms/patterns (although the specifics are a bit different). Identifying vulnerable patterns and searching for these patterns in other places in code is an essential skill for security code auditors. Did you find all three bugs that were patched? Developers Solution1 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
| public class FormUtils {
private FormUtils() { }
public static String createAnswers(FormField formField,HttpServletRequest request) { final StringBuffer builder = new StringBuffer(); if (formField.getType().equals(FormField.TYPE_TEXT_SINGLE)) { String cookieValue = getCookieValueForField(formField.getVariable(),request); String insertValue = ""; if(ModelUtil.hasLength(cookieValue)){ insertValue = "value=\""+cookieValue+"\""; } - builder.append("<input type=\"text\"name=\""+ formField.getVariable() + "\""+insertValue+"style=\"width:75%\">"); +builder.append("<input type=\"text\"name=\""+ formField.getVariable() + "\""+StringUtils.escapeHTMLTags(insertValue)+"style=\"width:75%\">"); } else if (formField.getType().equals(FormField.TYPE_TEXT_MULTI)) { builder.append("<textarea name=\""+ formField.getVariable() + "\"cols=\"30\"rows=\"3\">"); builder.append("</textarea>"); } else if (formField.getType().equals(FormField.TYPE_LIST_SINGLE)) { builder.append("<select name=\""+ formField.getVariable() + "\">"); Iterator iter = formField.getOptions(); String cookieValue = ModelUtil.emptyStringIfNull(getCookieValueForField(formField.getVariable(),request)); while (iter.hasNext()) { FormField.Option option = (FormField.Option)iter.next(); String selected = option.getValue().equals(cookieValue) ? "selected":""; - builder.append("<option value=\""+ option.getValue() + "\""+selected+">"+ option.getLabel() + "</option>"); +builder.append("<option value=\""+ StringUtils.escapeHTMLTags(option.getValue()) + "\""+selected+">"+ option.getLabel() + "</option>"); } builder.append("</select>"); } else if (formField.getType().equals(FormField.TYPE_BOOLEAN)) { Iterator iter = formField.getOptions(); int counter = 0; while (iter.hasNext()) { FormField.Option option = (FormField.Option)iter.next(); String value = option.getLabel(); builder.append("<input type=\"checkbox\"value=\""+ value + "\"name=\""+ formField.getVariable() + counter + "\">"); builder.append(" "); -builder.append(value); +builder.append(StringUtils.escapeHTMLTags(value)); builder.append("<br/>"); counter++; } } |
DetailsAffected Software:WordPress-to-lead for Salesforce CRM Fixed in Version:1.0.5 Issue Type:Cross Site Scripting Original Code: Found Here DescriptionThis week’s vulnerability is an XSS bug in a Salesforce plugin for WordPress. This bug is a bit interesting as it seems the developer attempted to sanitize an attacker controlled variable,but used the incorrect API. Looking at the vulnerable code,we see the following line: return ‘<label for=”‘.$id.’”>’.$label.’:</label><br/><input size=”45″name=”‘.$id.’”value=”‘.stripslashes($options[$id]).’”/><br/><br/>’;
In the line above,we see that $options[$id] is placed into the rendered HTML. $options[$id] appears to be attacker controlled and the developers used the stripslashes() API to sanitize $options[$id] before displaying the value in HTML. Unfortunately,stripslashes() doesn’t help prevent XSS vulnerabilities and created an opportunity for XSS. The developer fixed this vulnerability by using the correct API to sanitize against XSS vulnerability (htmlentities). Developers Solution1 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
| <?php if (!class_exists('OV_Plugin_Admin')) { class OV_Plugin_Admin {
var $hook = ''; var $filename = ''; var $longname = ''; var $shortname = ''; var $ozhicon = ''; var $optionname = ''; var $homepage = ''; var $accesslvl = 'manage_options';
function Yoast_Plugin_Admin() { add_action( 'admin_menu',array(&$this,'register_settings_page') ); add_filter( 'plugin_action_links',array(&$this,'add_action_link'),10,2 ); add_filter( 'ozh_adminmenu_icon',array(&$this,'add_ozh_adminmenu_icon' ) );
add_action('admin_print_scripts',array(&$this,'config_page_scripts')); add_action('admin_print_styles',array(&$this,'config_page_styles')); }
function add_ozh_adminmenu_icon( $hook ) { if ($hook == $this->hook) return WP_CONTENT_URL . '/plugins/' . plugin_basename(dirname($filename)). '/'.$this->ozhicon; return $hook; }
function config_page_styles() { if (isset($_GET['page']) &&$_GET['page'] == $this->hook) { wp_enqueue_style('dashboard'); wp_enqueue_style('thickbox'); wp_enqueue_style('global'); wp_enqueue_style('wp-admin'); wp_enqueue_style('ov-admin-css',WP_CONTENT_URL . '/plugins/' . plugin_basename(dirname(__FILE__)). '/yst_plugin_tools.css'); } }
function register_settings_page() { add_options_page($this->longname,$this->shortname,$this->accesslvl,$this->hook,array(&$this,'config_page')); }
function plugin_options_url() { return admin_url( 'options-general.php?page='.$this->hook ); }
function add_action_link( $links,$file ) { static $this_plugin; if( empty($this_plugin) ) $this_plugin = $this->filename; if ( $file == $this_plugin ) { $settings_link = '<a href="' . $this->plugin_options_url() . '">' . __('Settings') . '</a>'; array_unshift( $links,$settings_link ); } return $links; }
function config_page() {
}
function config_page_scripts() { if (isset($_GET['page']) &&$_GET['page'] == $this->hook) { wp_enqueue_script('postbox'); wp_enqueue_script('dashboard'); wp_enqueue_script('thickbox'); wp_enqueue_script('media-upload'); } }
function checkbox($id,$label) { $options = get_option($this->optionname); return '<input type="checkbox"id="'.$id.'"name="'.$id.'"'. checked($options[$id],true,false).'/><label for="'.$id.'">'.$label.'</label><br/>'; }
function textinput($id,$label) { $options = get_option($this->optionname); - return '<label for="'.$id.'">'.$label.':</label><br/><input size="45"type="text"id="'.$id.'"name="'.$id.'"value="'.stripslashes($options[$id]).'"/><br/><br/>'; + return '<label for="'.$id.'">'.$label.':</label><br/><input size="45"type="text"id="'.$id.'"name="'.$id.'"value="'.htmlentities(stripslashes($options[$id])).'"/><br/><br/>'; } |
DetailsAffected Software:DojoToolkit Fixed in Version:1.4.2 Issue Type:XSS Original Code: Found Here DescriptionThis week’s vulnerability is a DOM based XSS that could be found in a JavaScript file provided by the DojoToolkit. This JavaScript file was included (via script src) in many pages throughout the DojoToolkit,making those pages vulnerable to XSS. Unlike traditional XSS bugs,server side processing is not required for certain types of DOM based XSS. This is an important concept to understand as some code auditors will skip static pages assuming the attacker will not have the ability to control any values used by the page. The bug starts here: if(window.location.href.indexOf(“?”) >-1){
The JavaScript pulls the address of the loaded page and checks to see if the address contains the “?” character. If the “?” character is found,the JavaScript begins parsing and splitting the URI into various arrays. This parsing and splitting is done in the lines provided below: var str = window.location.href.substr(window.location.href.indexOf(“?”)+1).split(/#/); var ary = str[0].split(/&/); for(var i=0;i<ary.length;i++){ var split = ary[i].split(/=/),
The vulnerable assignment occurs here: value = split[1];
The JavaScript above essentially grabs a querystring value (attacker supplied) and assigns it to the “value” variable. Later,the “value” variable is used in several places,for example: dojo.config.locale = locale = value; document.getElementsByTagName(“html”)[0].dir = value; theme = value;
Considering the assignments listed above,we have a couple different variables that are tainted. I’ve highlighted the tainted variables in red. Tracing the “theme” assignment shown above,we see the tainted value being passed to a document.write statement,resulting in XSS. var themeCss = d.moduleUrl(“dijit.themes”,theme+”/”+theme+”.css”); var themeCssRtl = d.moduleUrl(“dijit.themes”,theme+”/”+theme+”_rtl.css”); document.write(‘<link rel=”stylesheet”type=”text/css”href=”‘+themeCss+’”>’); document.write(‘<link rel=”stylesheet”type=”text/css”href=”‘+themeCssRtl+’”>’);
The patch checked in by the DojoToolkit team sanitizes the “value” JavaScript variable by allowing only word characters (^\w). Developers Solution1 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
| if(window.location.href.indexOf("?") >-1){ var str = window.location.href.substr(window.location.href.indexOf("?")+1).split(/#/); var ary = str[0].split(/&/); for(var i=0;i<ary.length;i++){ var split = ary[i].split(/=/), key = split[0], -value = split[1]; +value = split[1].replace(/[^\w]/g,"");// replace() to prevent XSS attack switch(key){ case "locale": // locale string | null dojo.config.locale = locale = value; break; case "dir": // rtl | null document.getElementsByTagName("html")[0].dir = value; break; case "theme": // tundra | soria | noir | squid | nihilo | null theme = value; break; case "a11y": if(value){ testMode = "dijit_a11y";} } } }
// always include the default theme files: if(theme || testMode){
if(theme){ var themeCss = d.moduleUrl("dijit.themes",theme+"/"+theme+".css"); var themeCssRtl = d.moduleUrl("dijit.themes",theme+"/"+theme+"_rtl.css"); document.write('<link rel="stylesheet"type="text/css" href="'+themeCss+'">'); document.write('<link rel="stylesheet"type="text/css" href="'+themeCssRtl+'">'); }
if(dojo.config.parseOnLoad){ dojo.config.parseOnLoad = false; dojo.config._deferParsing = true; }
d.addOnLoad(function(){
// set the classes var b = dojo.body(); if(theme){ dojo.removeClass(b,defTheme); if(!d.hasClass(b,theme)){ d.addClass(b,theme);} var n = d.byId("themeStyles"); if(n){ d.destroy(n);} } if(testMode){ d.addClass(b,testMode);} if(dojo.config._deferParsing){ // attempt to elimiate race condition introduced by this // test helper file. 120ms to allow CSS to finish/process? setTimeout(dojo.hitch(d.parser,"parse",b),120); }
}); }
})(); |
DetailsAffected Software:Openfire by Ignite Realtime Fixed in Version:3.6.1 Issue Type:XSS Original Code: Found Here DescriptionThis is a straightforward XSS bug that affecting the Admin Console of OpenFire by Ignite Realtime/Jive software. The code fix is simple,encode a tainted URL variable before using it in markup. The URL variable is assigned an attacker controlled value here: String url = ParamUtils.getParameter(request,“url”);
And is later used in the HTML markup here: <input value=”<%= url %>”>
The one line fix is to encode the URL parameter,which was done here: url = org.jivesoftware.util.StringUtils.escapeHTMLTags(url);
Looking through the code,we see that OpenFire had previously fixed an XSS vulnerability just a few lines above in the USERNAME variable. There is even comment indicating so! It surprising that the Ignite Realtime/Jive developers missed this one as it is literally two lines below the previous fix. String username = ParamUtils.getParameter(request,“username”); if (username != null){ username = JID.escapeNode(username); } // Escape HTML tags in username to prevent cross-site scripting attacks. This // is necessary because we display the username in the page below. username = org.jivesoftware.util.StringUtils.escapeHTMLTags(username); String password = ParamUtils.getParameter(request,“password”); String url = ParamUtils.getParameter(request,“url”);
The assignment of the PASSWORD variable is interesting Developers Solution1 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 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283
| <%!
static String go(String url) {
if (url == null) {
return "index.jsp";
}
else {
return url;
}
}
%>
<%-- Check if in setup mode --%>
<%
if (admin.isSetupMode()) {
response.sendRedirect("setup/index.jsp");
return;
}
%>
<% // get parameters
String username = ParamUtils.getParameter(request,"username");
if (username != null) {
username = JID.escapeNode(username);
}
// Escape HTML tags in username to prevent cross-site scripting attacks. This
// is necessary because we display the username in the page below.
username = org.jivesoftware.util.StringUtils.escapeHTMLTags(username);
String password = ParamUtils.getParameter(request,"password");
String url = ParamUtils.getParameter(request,"url");
+ url = org.jivesoftware.util.StringUtils.escapeHTMLTags(url);
// SSO between cluster nodes
String secret = ParamUtils.getParameter(request,"secret");
String nodeID = ParamUtils.getParameter(request,"nodeID");
String nonce = ParamUtils.getParameter(request,"nonce");
// The user auth token:
AuthToken authToken;
... SNIP ...
<html>
<head>
<title><%= AdminConsole.getAppName() %><fmt:message key="login.title"/></title>
<script language="JavaScript">
<!--
// break out of frames
if (self.parent.frames.length != 0) {
self.parent.location=document.location;
}
function updateFields(el) {
if (el.checked) {
document.loginForm.username.disabled = true;
document.loginForm.password.disabled = true;
}
else {
document.loginForm.username.disabled = false;
document.loginForm.password.disabled = false;
document.loginForm.username.focus();
}
}
//-->
</script>
<link rel="stylesheet"href="style/global.css"type="text/css">
<link rel="stylesheet"href="style/login.css"type="text/css">
</head>
<body>
<form action="login.jsp"name="loginForm"method="post">
<% if (url != null) { try { %>
<input type="hidden"value="<%= url %>">
<% } catch (Exception e) { Log.error(e);} } %>
<input value="true">
<div align="center">
<!-- BEGIN login box -->
<div id="jive-loginBox">
<div align="center">
<span id="jive-login-header"style="background:transparent url(images/login_logo.gif) no-repeat left;padding:29px 0 10px 205px;">
<fmt:message key="admin.console"/>
</span>
<div style="text-align:center;width:380px;">
<table cellpadding="0"cellspacing="0"border="0"align="center">
<tr>
<td align="right">
<table cellpadding="2"cellspacing="0"border="0">
<noscript>
<tr>
<td colspan="3">
<table cellpadding="0"cellspacing="0"border="0">
<tr valign="top">
<td><img src="images/error-16x16.gif"width="16"height="16"border="0"alt=""vspace="2"></td>
<td><div style="padding-left:5px;color:#cc0000;"><fmt:message key="login.error"/></div></td>
</tr>
</table>
</td>
</tr>
</noscript>
<% if (errors.size() >0) { %>
<tr>
<td colspan="3">
<table cellpadding="0"cellspacing="0"border="0">
<% for (String error:errors.values()) { %>
<tr valign="top">
<td><img src="images/error-16x16.gif"width="16"height="16"border="0"alt=""vspace="2"></td>
<td><div style="padding-left:5px;color:#cc0000;"><%= error%></div></td>
</tr>
<% } %>
</table>
</td>
</tr>
<% } %>
<tr>
<td><input size="15"maxlength="50"value="<%= (username != null ? username:"") %>"></td>
<td><input size="15"maxlength="50"></td>
<td align="center"><input value=" <fmt:message key="login.login"/> "></td>
</tr>
<tr valign="top">
<td><label for="u01"><fmt:message key="login.username"/></label></td>
<td><label for="p01"><fmt:message key="login.password"/></label></td>
<td> </td>
</tr>
</table>
</td>
</tr>
<tr>
<td align="right">
<div align="right">
<%= AdminConsole.getAppName() %>,<fmt:message key="login.version"/>:<%= AdminConsole.getVersionString() %>
</div>
</td>
</tr>
</table>
</div>
</div>
</div>
<!-- END login box -->
</div>
</form>
<script type="text/javascript">
<!--
if (document.loginForm.username.value == '') {
document.loginForm.username.focus();
} else {
document.loginForm.password.focus();
}
//-->
</script>
</body>
</html> |
DetailsAffected Software:WP Category Manager plugin Fixed in Version:1.3.1.0 Issue Type:Sql Injection Original Code: Found Here DescriptionThis week’s vulnerability affected the WP Category Manager plugin. There were two interesting characteristics I noticed with this code fix. First,while there were a number of SQL injection vulnerabilities fixed with this change list,there were also a large number of non security fixes included in this change list as well. It’s generally a good idea to keep security change lists separate from other change lists. The number of non security fixes included in this particular list was so distracting,I removed them from the post. The SQL injection fixes are pretty straight forward,changing dynamically built SQL statements into WordPress’ built-in $wpdb->prepare() function. The second characteristic that caught my attention was usage of numeric IDs at the end of SQL statements. For example: where object_id = $postId and term_taxonomy_id= $categoryId”;
This syntax creates a condition in which the typical addslashes() used to protect against SQL injection can be bypassed. For example,an attacker could craft a SQL injection string like: Sqli.php?categoryId=-1 union select 1,2,3,4,5–
As you can see,the injection string above contains no special characters that would be escaped by addslashes(). Fortunately,the Category Manager plugin developers chose to utilze $wpdb->prepare() instead of addslashes(). Developers Solution1 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 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
| <?php
include_once('wpcm-options.php');
if( ! class_exists('wpcm_functions')):
class wpcm_functions { public static function remove_category($postId,$categoryId) { - global $wpdb; - $wpdb->show_errors(); - $queryStr = "DELETE FROM $wpdb->term_relationships - where object_id = $postId and term_taxonomy_id= $categoryId"; + echo $postId;
- $wpdb->query($queryStr); + if(is_int(intval($postId))) + { + global $wpdb; + + $wpdb->show_errors(); + + $queryStr = $wpdb->prepare("DELETE FROM $wpdb->term_relationships where object_id = %d and term_taxonomy_id= %s",$postId,$categoryId); + $wpdb->query($queryStr); + } }
public static function get_posts($category,$page) { global $wpdb; $wpdb->show_errors();
// First figure out how many posts to show per page. This will be your limit $pageSize = wpcm_options::get_option('postsperpage');
$finalQueryLine = '';
if($pageSize != -1) { // Next figure out how many posts to skip. This will be your offset $offset = $pageSize * $page;
$finalQueryLine = "limit ". $pageSize . "offset ". $offset;
+ } + + $querystr = $wpdb->prepare("select wposts.*,wp_term_taxonomy.term_taxonomy_id + from $wpdb->posts wposts + LEFT JOIN $wpdb->term_relationships wp_term_relationships ON wposts.ID = wp_term_relationships.object_id + LEFT JOIN $wpdb->term_taxonomy wp_term_taxonomy ON wp_term_relationships.term_taxonomy_id = wp_term_taxonomy.term_taxonomy_id + LEFT JOIN $wpdb->terms wp_terms ON wp_terms.term_id = wp_term_taxonomy.term_id + WHERE wp_term_taxonomy.taxonomy = 'category' + and wp_terms.name = '%s' + and wposts.post_status='publish' + ORDER BY wposts.ID ". $finalQueryLine ,$category); + + $postlist = $wpdb->get_results($querystr); + return $postlist; } - $querystr = "select wposts.*,wp_term_taxonomy.term_taxonomy_id - from $wpdb->posts wposts - LEFT JOIN $wpdb->term_relationships wp_term_relationships ON wposts.ID = wp_term_relationships.object_id - LEFT JOIN $wpdb->term_taxonomy wp_term_taxonomy ON wp_term_relationships.term_taxonomy_id = wp_term_taxonomy.term_taxonomy_id - LEFT JOIN $wpdb->terms wp_terms ON wp_terms.term_id = wp_term_taxonomy.term_id - WHERE wp_term_taxonomy.taxonomy = 'category' - and wp_terms.name = '". $category . "' - and wposts.post_status='publish' - ORDER BY wposts.ID ". $finalQueryLine; - - $postlist = $wpdb->get_results($querystr); - return $postlist; }
public static function get_postCount($category) { global $wpdb; $wpdb->show_errors();
- $querystr = "select count(*) - from $wpdb->posts wposts - LEFT JOIN $wpdb->term_relationships wp_term_relationships ON wposts.ID = wp_term_relationships.object_id - LEFT JOIN $wpdb->term_taxonomy wp_term_taxonomy ON wp_term_relationships.term_taxonomy_id = wp_term_taxonomy.term_taxonomy_id - LEFT JOIN $wpdb->terms wp_terms ON wp_terms.term_id = wp_term_taxonomy.term_id - WHERE wp_term_taxonomy.taxonomy = 'category' - and wp_terms.name = '". $category . "' - and wposts.post_status='publish'"; + $querystr = $wpdb->prepare("select count(*) + from $wpdb->posts wposts + LEFT JOIN $wpdb->term_relationships wp_term_relationships ON wposts.ID = wp_term_relationships.object_id + LEFT JOIN $wpdb->term_taxonomy wp_term_taxonomy ON wp_term_relationships.term_taxonomy_id = wp_term_taxonomy.term_taxonomy_id + LEFT JOIN $wpdb->terms wp_terms ON wp_terms.term_id = wp_term_taxonomy.term_id + WHERE wp_term_taxonomy.taxonomy = 'category' + and wp_terms.name = '%s' + and wposts.post_status='publish'",$category);
$result = $wpdb->get_var($querystr,0,0); return $result;
}
public static function render_posts($postlist) { if($postlist) { foreach($postlist as $post) { echo '<div id="catmanagerpost'. $post->ID .'">'; echo '<span ><a href="'. get_permalink($post->ID) .'"title="'.$post->post_title . '">' . $post->post_title . '</a></span><span >' . date_format(date_create($post->post_date),"F j,Y") . '</span>'; echo '<p ><a href="javascript:void(0);"postID="'.$post->ID.'"catID="'. $post->term_taxonomy_id .'"id="catmanremovepost'. $post->ID .'"title="Remove post from this category">Remove</a>| '; echo edit_post_link('Edit Post','','',$post->ID); echo '</p></div>'; } } else { echo '<strong>No posts found</strong>'; } }
public static function render_postcount($category) { $count = wpcm_functions::get_postCount($category);
echo '<span id="wpcmpostcount">'.$count.'</span>'; }
public static function get_categories() { global $wpdb;
$wpdb->show_errors();
$querystr = "select wt.name,wt.term_id from $wpdb->terms wt join $wpdb->term_taxonomy wtt on wtt.term_id = wt.term_id where wtt.taxonomy = 'category' order by wt.name";
$catlist = $wpdb->get_results($querystr); return $catlist; } } endif;
?> |
DetailsAffected Software:Dojo Toolkit SDK Fixed in Version: 1.4.2 Issue Type:Cross Site Scripting (XSS) Original Code: Found Here DescriptionThis was a bug reported by the Gotham Digital Science against the Dojo toolkit SDK. The Dojo toolkit is a popular toolkit used by numerous websites… so in essence this bug provided attackers an opportunity to XSS a large number of websites across the Internet. The bug begins by the capturing of untrusted parameter values from the querystring. This is done by the following JavaScript: 1
| var qstr = window.location.search.substr(1); |
qstr is then split based on the “&” character,proving values for various JavaScript variables including DoJoURL and TestURL. The attacker is free to provide arbitrary values for DoJoURL and TestURL by simply providing the proper querystring values. For example: runner.html?dojoUrl=attacker-controlled&testUrl=attackercontrolled
the attacker supplied values are then used in a document.write() statement,giving the attacker the opprotuntiy to inject arbitrary client side script into any website that happens to include the Dojo library. The vulnerable document.write() statements are provided below: document.write(“<scr”+”ipt type=’text/javascript’djConfig=’isDebug:true’src=’”+dojoUrl+”‘></scr”+”ipt>”); document.write(“<scr”+”ipt type=’text/javascript’src=’”+testUrl+”.js’></scr”+”ipt>”);
The Dojo developers addressed this vulnerability by replacing characters from the attacker controlled input. The specific regular expression used is provided below: value=tp[1].replace(/[<>"']/g,“”);
I see a major issue with this code fix… can you spot it as well? Developers Solution1 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
| <script type="text/javascript"> // workaround for bug in Safari 3. See #7189 if (/3[\.0-9]+ Safari/.test(navigator.appVersion)) { window.console = { origConsole:window.console, log:function(s){ this.origConsole.log(s); }, info:function(s){ this.origConsole.info(s); }, error:function(s){ this.origConsole.error(s); }, warn:function(s){ this.origConsole.warn(s); } }; } </script> <script type="text/javascript"> window.dojoUrl = "../../dojo/dojo.js"; window.testUrl = ""; window.testModule = ""; // parse out our test URL and our Dojo URL from the query string var qstr = window.location.search.substr(1); if(qstr.length){ var qparts = qstr.split("&"); for(var x=0;x<qparts.length;x++){ - var tp = qparts[x].split("="); - if(tp[0] == "dojoUrl"){ - window.dojoUrl = tp[1]; - } - if(tp[0] == "testUrl"){ - window.testUrl = tp[1]; - } - if(tp[0] == "testModule"){ - window.testModule = tp[1]; - } - if(tp[0] == "registerModulePath"){ - var modules = tp[1].split(";"); - window.registerModulePath=[]; - for (var i=0;i<modules.length;i++){ - window.registerModulePath.push(modules[i].split(",")); - } - } + var tp = qparts[x].split("="),name=tp[0],value=tp[1].replace(/[<>"']/g,""); // replace() to avoid XSS attack + switch(name){ + case "dojoUrl": + case "testUrl": + case "testModule": + window[name] = value; + break; + case "registerModulePath": + var modules = value.split(";"); + window.registerModulePath=[]; + for (var i=0;i<modules.length;i++){ + window.registerModulePath.push(modules[i].split(",")); + } + break; } } document.write("<scr"+"ipt type='text/javascript' djConfig='isDebug:true' src='"+dojoUrl+"'></scr"+"ipt>"); </script> <script type="text/javascript"> try{ dojo.require("doh.runner"); }catch(e){ document.write("<scr"+"ipt type='text/javascript' src='runner.js'></scr"+"ipt>"); } if(testUrl.length){ document.write("<scr"+"ipt type='text/javascript' src='"+testUrl+".js'></scr"+"ipt>"); } </script> <style type="text/css"> @import "../../dojo/resources/dojo.css"; var SHRSB_Globals ={src:"http://spotthevuln.com/wordpress/wp-content/plugins/sexybookmarks/spritegen_default",perfoption:""}; |
|