| DetailsAffected Software:Lazyest-Gallery Fixed in Version:0.9 Issue Type:Cross Site Scripting (XSS) Original Code:Found Here DetailsFor most security issues,I give the developer the benefit of the doubt. It’s tough to keep track of all the corner cases and security nuances. For this diff however,there is no excuse. First,let’s cover what the patch fixes. On line 18,the developer was taking a tainted value passed via query string parameter and using that value to build HTML markup. This is XSS in its most classic form. Also,on line 58 the same tainted input is used to build the SRC attribute for an image tag,also resulting in XSS. The developer chose to encode both of these tainted values before using them in the HTML output. Now,let’s talk about the problems with this patch. First,the tainted value used to build the SRC attribute for an image tag needs additional validation. SRC attributes are tricky as they usually cause the browser to issue a request. Escaping the tainted SRC value only prevents the attacker from breaking out of the attribute and injecting their own HTML. Escaping doesn’t prevent the attacker from passing a well formed URI like javascript:javascript-payload-here. I can let the developer slide on this one… chalk it up as a lesson on corner cases. Now,if you look at the patched line,you’ll see that the ALT attribute for the same image tag also contains a XSS vulnerability. Yes,the developer missed a XSS vulnerability that is less than 5 characters away from a fixed XSS vulnerability. This also shows that the developer never tested the patch. The tainted query string parameter is the same for all the vulnerable sections. If the developer tried to test this patch,they would have discovered they were still exposed… Developers Solution<?php// Don't remove this lines:require_once('../../../wp-blog-header.php');global $lg_gallery;?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN""http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type"content="<?php bloginfo('html_type');?>;charset=<?php bloginfo('charset');?>"/><meta name="generator"content="WordPress <?php bloginfo('version');?>"/>-<title><?php echo $_GET['image'] ?></title>+<title><?php echo esc_html($_GET['image']) ?></title><style type="text/css">body{text-align:center;margin:0;padding:0}img{border:none}</style><script type="text/javascript">function WinWidth(){if (window.innerWidth!=window.undefined) return window.innerWidth;if (document.compatMode=='CSS1Compat') return document.documentElement.clientWidth;if (document.body) return document.body.clientWidth;return window.undefined}function WinHeight(){if (window.innerHeight!=window.undefined) return window.innerHeight;if (document.compatMode=='CSS1Compat') return document.documentElement.clientHeight;if (document.body) return document.body.clientHeight;return window.undefined}function FitPic(){iWidth=WinWidth();iHeight=WinHeight();iWidth = document.images[0].width - iWidth;iHeight = document.images[0].height - iHeight;window.resizeBy((iWidth),(iHeight))self.focus()} </script></head><body onload="FitPic()"><a href="javascript:self.close()"title="<?php _e('Click to close',$lg_text_domain);?>">-<img src="<?php echo str_replace("","%20",$lg_gallery->address.$_GET['folder'].$_GET['image']);?>"alt="<?php echo $_GET['image'];?>"/>+<img src="<?php echo str_replace("","%20",$lg_gallery->address.esc_attr($_GET['folder']).esc_attr($_GET['image']));?>"alt="<?php echo $_GET['image'];?>"/></a></body></html><?php?>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:DojoX Fixed in Version:1.4.1 Issue Type:Cross Site Scripting (XSS) Original Code:Found Here DescriptionThis week’s bug was an easy one with a straightforward fix. The vulnerable code sample is basically a single switch statement. Most of the cases don’t do anything interesting (from a security standpoint) however,the default case at the end of the switch statement leads to a vulnerable condition. If all of the case statements fail,the application throws a useful error message echoing back a value directly from the query string. The DojoX developers addressed the vulnerability by html encoding the value before echoing it back to the user. Simple bug,simple fix. I hope all the readers have a good weekend and a Happy Halloween! Developers Solution<?php// this file is just a bouncer for ContentPane.html testerror_reporting(E_ALL ^ E_NOTICE);if(isset($_GET['mode'])){switch($_GET['mode']){case 'htmlPaths':echo "<img src='../images/testImage.gif' id='imgTest'/><div id='inlineStyleTest' style='width:188px;height:125px;background-image:url(../images/testImage.gif)'></div><style>@import 'getResponse.php?mode=importCss';</style><link type='text/css' rel='stylesheet' href='getResponse.php?mode=linkCss'><div id='importCssTest'></div><div id='linkCssTest'></div><div id='importMediaTest'></div><div id='linkMediaTest'></div><!-- these may download but not render --><style media='print'>@import 'getResponse.php?mode=importMediaPrint';</style><link media='print' type='text/css' rel='stylesheet' href='getResponse.php?mode=linkMediaPrint'>";break;case 'importCss':header('Content-type:text/css;charset=utf-8');echo "#importMediaTest{margin:4px;border:1px dashed red;width:200px;height:200px}#importCssTest{margin:4px;border:1px solid blue;width:100px;height:100px}";break;case 'linkCss':header('Content-type:text/css;charset=utf-8');echo "#linkMediaTest{margin:4px;border:2px dashed red;width:200px;height:200px}#linkCssTest{margin:4px;border:2px dashed red;width:100px;height:100px}";break;case 'importMediaPrint':// may download but not renderheader('Content-type:text/css;charset=utf-8');echo "#importMediaTest{margin:10px;border:5px dashed gray;width:100px;height:100px}";break;case 'linkMediaPrint':// may download but not renderheader('Content-type:text/css;charset=utf-8');echo "#linkMediaTest{margin:10px;border:5px dashed gray;width:100px;height:100px}";break;case 'remoteJsTrue':header('Content-type:text/javascript;charset=utf-8');echo "unTypedVarInDocScope = true;";break;case 'remoteJsFalse':header('Content-type:text/javascript;charset=utf-8');echo "unTypedVarInDocScope = false;";break;case 'entityChars':header('Content-type:text/css;charset=utf-8');if($_GET['entityEscaped'] == null){print("var div = document.createElement(\"div\");document.body.appendChild(div);div.innerHTML = \"<div id=\\\"should_not_be_here2\\\"></div>\";window.__remotePaneLoaded2 = true;")}else{print("window.__remotePaneLoaded2 = true;")}break;default:-echo "unkown mode{$_GET['mode']}";+echo "unkown mode{htmlentities($_GET['mode'])}"}}?>DetailsAffected Software:Dojox Fixed in Version:1.4.1 Issue Type:XSS Original Code: Found Here DescriptionThe code sample presented this week have a few XSS vulnerabilities. The first XSS bug is caused when $_GET[‘messId’] doesn’t match any of the switch cases. The default behavior is to throw a friendly error message indicating the messId is unknown along with the value passed via the querystring. Unfortunately,the error message can also contain attacker controlled HTML/SCRIPT resulting in XSS. The two other XSS bugs fixed by the developers in this patch are classic XSS. Both issues take user/attacker controlled variables and display the variables in markup without sanitization/encoding. Although the XSS bugs are fairly straight forward,what I find interesting in this example is why this page is here in the first place. The code don’t seem to provide any useful functionality (other than to provide a place for attackers to abuse XSS). If you were a security engineer assigned to audit this page,it might be a good idea to ask WHY this page exists in the first place. It turns out that this page is indeed a test/debugging page that is included with dojox,offering no functionality intended for production users. Think long and hard before exposing test and debug functionality in your production environment. Check production systems for example/testing/debugging functionality and disable/remove this functionality if possible. Code developed for testing and debugging rarely undergoes the scrutiny of production code and will like contain security issues. 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
| <?php // this just bounces a message as a response,and optionally emulates network latency.
// default delay is 0 sec,to change: // getResponse.php?delay=[Int milliseconds]
// to change the message returned // getResponse.php?mess=whatever%20string%20you%20want.
// to select a predefined message // getResponse.php?messId=0
error_reporting(E_ALL ^ E_NOTICE);
$delay = 1;// 1 micro second to avoid zero division in messId 2 if(isset($_GET['delay']) &&is_numeric($_GET['delay'])){ $delay = (intval($_GET['delay']) * 1000); }
if(isset($_GET['messId']) &&is_numeric($_GET['messId'])){ switch($_GET['messId']){ case 0: echo "<h3>WARNING This should NEVER be seen,delayed by 2 sec!</h3>"; $delay = 2; break; case 1: echo "<div dojotype='dijit.TestWidget'>Testing attr('href',...)</div>"; break; case 2: echo "<div dojotype='dijit.TestWidget'>Delayed attr('href',...) test</div> <div dojotype='dijit.TestWidget'>Delayed by ". ($delay/1000000) . "sec.</div>"; break; case 3: echo "IT WAS the best of times,it was the worst of times,it was the age of wisdom,it was the age of foolishness,it was the epoch of belief,it was the epoch of incredulity,it was the season of Light,it was the season of Darkness,it was the spring of hope,it was the winter of despair,we had everything before us,we had nothing before us,we were all going direct to Heaven,we were all going direct the other way -- in short,the period was so far like the present period,that some of its noisiest authorities insisted on its being received,for good or for evil,in the superlative degree of comparison only"; break; case 4: echo "There were a king with a large jaw and a queen with a plain face,on the throne of England;there were a king with a large jaw and a queen with a fair face,on the throne of France. In both countries it was clearer than crystal to the lords of the State preserves of loaves and fishes,that things in general were settled for ever."; break; case 5: echo "It was the year of Our Lord one thousand seven hundred and seventy- five. Spiritual revelations were conceded to England at that favoured period,as at this. Mrs. Southcott had recently attained her five-and- twentieth blessed birthday,of whom a prophetic private in the Life Guards had heralded the sublime appearance by announcing that arrangements were made for the swallowing up of London and Westminster. Even the Cock-lane ghost had been laid only a round dozen of years,after rapping out its messages,as the spirits of this very year last past (supernaturally deficient in originality) rapped out theirs. Mere messages in the earthly order of events had lately come to the English Crown and People,from a congress of British subjects in America:"; break; default: -echo "unknown messId:{$_GET['messId']}"; +echo "unknown messId:". htmlentities($_GET['messId']); } }
if(isset($_GET['bounceGetStr']) && $_GET['bounceGetStr']){ -echo "<div id='bouncedGetStr'>{$_SERVER["QUERY_STRING"]}</div>"; +echo "<div id='bouncedGetStr'>".htmlentities($_SERVER["QUERY_STRING"])."</div>"; }
if(isset($_GET['message']) &&$_GET['message']){ -echo $_GET['message']; +echo htmlentities($_GET['message']); }
usleep($delay);
?> |
DetailsAffected Software:Members-only WordPress plugin Fixed in Version:0.6.7 Issue Type:SQL Injection Original Code: Found Here DescriptionThis week’s vuln was an easy one The vulnerability affected the “members-only” plug-in for WordPress and was patched in version 0.6.7. There are a couple changes in the diff,but the most important change (from a security standpoint) is the transition from a string-built,dynamic SQL statement to a prepared statement. The following lines show the SQL injection bug: $feedkey = $_GET['feedkey']; … <snip>… $find_feedkey = $wpdb->get_results(“SELECT umeta_id FROM $wpdb->usermeta WHERE meta_value = ‘$feedkey’”);
The members-only developers assigned a value for the $feedkey variable directly from the querystring. They then used the attacker controlled value to build a SQL statement,using the $feedkey value to complete the SQL WHERE clause. The symptoms presented above are classic SQL injection. I’m happy to see that the members-only developers chose to use prepared statements to fix the SQL injection. There are a few other fixes here,but the SQL injection was the most important security fix. 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
| -if (empty($userdata->ID) &&$members_only_opt['feed_access'] != 'feednone') //Check if user is logged in or Feed Keys is required +if (empty($userdata->ID) || $members_only_opt['feed_access'] != 'feednone') //Check if user is logged in or Feed Keys is required { $feedkey = $_GET['feedkey']; if (!empty($feedkey)) { // Check if Feed Key is in the Database -$find_feedkey = $wpdb->get_results("SELECT umeta_id FROM $wpdb->usermeta WHERE meta_value = '$feedkey'"); +$find_feedkey = $wpdb->get_results( $wpdb->prepare( + "SELECT umeta_id FROM $wpdb->usermeta WHERE meta_value = %s", + $feedkey +) );
if (!empty($find_feedkey) &&$members_only_opt['feed_access'] == 'feedkeys') //If Feed Key is found and using Feed Keys { $feedkey_valid = TRUE; if (empty($feedkey) &&$members_only_opt['feed_access'] == 'feedkeys') { $feed = members_only_create_feed('No Feed Key Found',$errormsg['feedkey_missing']); -header("Content-Type:application/xml;charset=ISO-8859-1"); +header("Content-Type:application/xml;charset=". get_bloginfo( 'charset' ),true); echo $feed; exit; } elseif ($feedkey_valid == FALSE &&$members_only_opt['feed_access'] == 'feedkeys') { $feed = members_only_create_feed('Feed Key is Invalid',$errormsg['feedkey_invalid']); -header("Content-Type:application/xml;charset=ISO-8859-1"); +header("Content-Type:application/xml;charset=". get_bloginfo( 'charset' ),true); echo $feed; exit; }
if (empty($feedkey) &&$members_only_opt['feed_access'] == 'feedkeys') { $feed = members_only_create_feed('No Feed Key Found',$errormsg['feedkey_missing']); -header("Content-Type:application/xml;charset=ISO-8859-1"); +header("Content-Type:application/xml;charset=". get_bloginfo( 'charset' ),true); echo $feed; exit; } |
DetailsAffected Software:The Hacker’s Diet (WordPress Plugin) Fixed in Version:0.9.7b Issue Type:SQL Injection Original Code: Found Here DescriptionThis week’s vulnerability was a SQL injection vulnerability affecting the Hacker’s Diet WordPress plugin. In the vulnerable version,the plugin assigns several variables using values obtained directly from the querystring. The variable assignments are shown below: $weeks = $_GET["weeks"]; $start_date = $_GET["start_date"]; $end_date = $_GET["end_date"]; $goal = $_GET["goal"]; $user_id = $_GET["user"]; $maint_mode = $_GET["maint_mode"];
No sanitization or validation is done before assigning the values. Once the assignments are made,the attacker controlled values are then passed to a dynamic SQL string here resulting in SQL Injection: $query = “select date,weight,trend from “.$table_prefix.”hackdiet_weightlog where wp_id = $user_id and date >\”".date(“Y-m-d”,strtotime(“$weeks weeks ago”)).”\”order by date asc”; $query = “select date,weight,trend from “.$table_prefix.”hackdiet_weightlog where wp_id = $user_id and date >= \”$start_date\”and date <= \”$end_date\”order by date asc”;
The plugin authors patched this vulnerability by validating that the $_GET[“user”] and $_GET[“weeks”] parameters contains only numeric characters. An interesting exercise would be to trace through the code and find where the following variables are being used: $start_date = $_GET["start_date"]; $end_date = $_GET["end_date"]; $goal = $_GET["goal"]; $maint_mode = $_GET["maint_mode"];
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
| <?php include (dirname(__FILE__)."/jpgraph/jpgraph.php"); include (dirname(__FILE__)."/jpgraph/jpgraph_line.php"); include (dirname(__FILE__)."/jpgraph/jpgraph_scatter.php");
// get our db settings without loading all of wordpress every save $html = implode('',file("../../../wp-config.php")); $html = str_replace ("require_once","// ",$html); $html = str_replace ("<?php","",$html); $html = str_replace ("?>","",$html); eval($html);
mysql_connect(DB_HOST,DB_USER,DB_PASSWORD); mysql_select_db(DB_NAME);
+if (!is_numeric($_GET["user"]) || !is_numeric($_GET["weeks"])) { + exit; +}
$weeks = $_GET["weeks"]; $start_date = $_GET["start_date"]; $end_date = $_GET["end_date"]; $goal = $_GET["goal"]; $user_id = $_GET["user"]; $maint_mode = $_GET["maint_mode"];
if ($weeks) { - $query = "select date,weight,trend from ".$table_prefix."hackdiet_weightlog where wp_id = $user_id and date >\"".date("Y-m-d",strtotime("$weeks weeks ago"))."\"order by date asc"; + $query = "select date,weight,trend from ".$table_prefix."hackdiet_weightlog where wp_id = \"". $user_id . "\"and date >\"".date("Y-m-d",strtotime("$weeks weeks ago"))."\"order by date asc"; } else if ($start_date and $end_date) { - $query = "select date,weight,trend from ".$table_prefix."hackdiet_weightlog where wp_id = $user_id and date >= \"$start_date\"and date <= \"$end_date\"order by date asc"; + $query = "select date,weight,trend from ".$table_prefix."hackdiet_weightlog where wp_id = \"". $user_id . "\"and date >= \"$start_date\"and date <= \"$end_date\"order by date asc"; }
result = mysql_query($query); if (mysql_num_rows($result)) { if (mysql_num_rows($result) == 1) { // only one day,gotta finagle the display
$row = mysql_fetch_assoc($result);
// fake day before $weight_data[] = 0; if ($goal >0) { $goal_data[] = $goal; } $x_data[] = date("n/j",strtotime("yesterday",strtotime($row["date"])));
// data $weight_data[] = $row["weight"]; if ($goal >0) { $goal_data[] = $goal; } $x_data[] = date("n/j",strtotime($row["date"]));
// fake day after $weight_data[] = 0; if ($goal >0) { $goal_data[] = $goal; } $x_data[] = date("n/j",strtotime("tomorrow",strtotime($row["date"]))); } else { $num_rows = mysql_num_rows($result); if ($num_rows <= 7 * 2) { // 0-2 weeks $ticks = "daily"; } else if ($num_rows <= 31 * 4) { // 2 weeks - 4 months $ticks = "weekly"; } else { // 4 months + $ticks = "monthly"; }
$count = 1; while ($row = mysql_fetch_assoc($result)) { $weight_data[] = $row["weight"]; $trend_data[] = $row["trend"]; if ($goal >0) { $goal_data[] = $goal; } switch ($ticks) { case "weekly": if ($count == 1) { $x_data[] = date("n/j",strtotime($row["date"])); } else { $x_data[] = ""; if ($count == 7) { $count = 0; } } break; case "monthly": if (date("j",strtotime($row["date"])) == "1") { $x_data[] = date("n/j",strtotime($row["date"])); } else { $x_data[] = ""; } break; case "daily": default: $x_data[] = date("n/j",strtotime($row["date"])); break; }
$count++; } } |
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:""}; |
|