| 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:Dojo Toolkit Fixed in Version:1.4.1 Issue Type:Defense in Depth Original Code: Found Here DescriptionThis was a vulnerability affecting the Dojo toolkit. Apparently,the dojo toolkit shipped with a SWF file that had a few vulnerabilities. This particular vulnerability affected one of those SWF files. First,SWF files are compiled files,however they can be decompiled. Unlike traditional server side web application languages (PHP,ASP,JSP…etc),SWF files are downloaded and rendered on the clientside. Decompiling the SWF file gives the attacker full access to the ActionScript source code for the SWF application. In this particular SWF file,we see that the developers explicitly set the Security.allowDomain to “*”. This makes it so SWF flies from other,external domains can include the Dojo toolkit SWF file and script/access its internal functionality. The Dojo toolkit devs fixed this particular issue by removing the allowDomain call and adding an Externalinterface call checking to see if a particular wrapper was available in HTML. If you’re interested in Flash security,an excellent presentation on Flash security given by Stefano Di Paola can be found here: http://www.slideshare.net/guestb0af15/owasp-wasc-app-sec2007-san-jose-finding-vulnsin-flash-apps 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
| public class FLVideo extends Sprite { private var videoUrl:String; private var video:Video; private var connection:NetConnection; private var autoPlay:Boolean; private var videoStream:NetStream; private var videoWidth:Number; private var videoHeight:Number; private var _currentVideo:VideoContainer; private var preview:VideoContainer; private var currentVolume:Number = 1; private var isFullscreen:Boolean = false; private var playlist:VideoPlaylist; private var hasPlaylist:Boolean = false; private var mode:String = "preview";
public function FLVideo() { - Security.allowDomain("*"); + var secure:* = ExternalInterface.call("swfIsInHTML"); + if(secure !== true){ + return; + } + //Security.allowDomain("*");
stage.scaleMode = StageScaleMode.NO_SCALE; stage.align = StageAlign.TOP_LEFT; stage.addEventListener(Event.RESIZE,onStageResize); stage.addEventListener(FullScreenEvent.FULL_SCREEN ,onFullscreenChange); stage.addEventListener(MouseEvent.CLICK,onClick);
var obj:Object = LoaderInfo(this.root.loaderInfo).parameters; trace(obj)
if(!obj.videoUrl){ obj = { autoPlay:true, isDebug:true, videoUrl:"demo_video.flv" }; }
// ugh - booleans not coming through if(obj.autoPlay===true || obj.autoPlay=="true"){ autoPlay = true; }
if(obj.volume) { currentVolume = obj.volume; }
if(obj.isDebug===true || obj.isDebug=="true"){ console.isDebug(true); Tracer.init({both:true}) Tracer.log("FLVideo initialized...") }
+ Tracer.log("secure?::",secure) MovieIdentity.identity = obj.id || "default"; this.playlist = new VideoPlaylist(autoPlay,currentVolume);
if(obj.videoUrl) { videoUrl = obj.videoUrl; }
preview = new VideoContainer(videoUrl,autoPlay,currentVolume); addChild(preview); provideCallbacks(); }
public function get currentVideo():VideoContainer{
if(mode=="playlist"&&hasPlaylist){ return this.playlist.current; }else{ return preview; } } |
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: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":null};;var SHRSB_Globals ={"src":"http:\/\/spotthevuln.com\/wordpress\/wp-content\/plugins\/sexybookmarks\/spritegen_default","perfoption":null}; |
|