网站地图    收藏   

主页 > 后端 > 网站安全 >

Flash XSS 漏洞详解 根治的好办法 - 网站安全 - 自学

来源:自学PHP网    时间:2015-04-16 23:15 作者: 阅读:

[导读] 本文的目的是深层次的分析Flash的ExternalInterface的XSS漏洞,并提出比较有效的解决方案。首先,我们看看什么情况下,会出现XSS。第一种情况:把flashvars传入的参数(或者其他能被别人控...

 本文的目的是深层次的分析Flash的ExternalInterface的XSS漏洞,并提出比较有效的解决方案。

 首先,我们看看什么情况下,会出现XSS。 第一种情况:      把flashvars传入的参数(或者其他能被别人控制的方式)当ExternalInterface.call的第一个参数

package
{ import flash.display.Sprite; import flash.external.ExternalInterface; public class XSSTest extends Sprite
       { public function XSSTest()
              { var jsFunction:String = loaderInfo.parameters.jsFunction; var param:String = "abc";
                     ExternalInterface.call(jsFunction, param);
              }
       }
}

  注意,这里通过flashvars传递了一个参数,是js的函数。这种方式比较常见,swf可以做成通用,放到不同的业务中使用,每次只需要传入对应的js函数即可。但是,这里就存在漏洞了。     在浏览器中,构造url: XSSTest.swf?jsFunction=alert(/XSS/),访问swf,并以get参数的形式传入flashvars,结果,造成了 

\

 甚至更狠一点,jsFunction=function(){alert(1);alert(2);}。。。 当然,这么恶作剧alert一下,貌似对小白用户没什么损失,但如果在function内调用这个域名的CGI,就能带来很大的惊喜了~~~因为这里能获取到对应的cookie,时间有限,具体攻击的方式,这里不多说。

 

  

 第二种情况:      把flashvars传入的参数(或者其他能被别人控制的方式)当ExternalInterface.call的第二和第三个参数     这次,我们使用这段代码: 
   public function XSSTest()
   { var param:String = loaderInfo.parameters.param;
          ExternalInterface.call("console.log", param);
   }
     这个方式也许没有这么简单进行XSS,但对于黑客来说,还是有办法的。  在IE8下调试模式下,我们可以看到ExternalInterface的代码:\ 正常情况下,Flash player会生成这样的代码: 
try { __flash__toXML(console.log("good" )) ; } catch (e) { "<undefined/>"; }
 对比自己写的as代码和生成的这段js代码,可以猜测,Flash player是以一种简单的拼接字符串的方式实现的。 稍稍做个小把戏,结果就可以注入代码执行了。 \

 

 是不是很神奇?怎么做到的呢?为什么url稍稍变化可以达到这样呢。我们看看现在的js代码: 
try { __flash__toXML(console.log("\\" ));alert(/XSS/);}catch(e){} //")) ; } catch (e) { "<undefined/>"; }
 正好跟原来的双引号对上了,结果,最后的catch也被替换了。。。也就是说,黑客可以写自己的函数了,想怎么执行都可以了。。。至于为什么这里双引号对上了,可以简单猜测flash遇到字符串中有双引号的时候,只是简单的以  \"  方式打印成js代码,但如果用户再恶意拼一个\,就负负得正了。。。 (这里__flash__toXML的代码并不是关键点了,所以将在文章最后再列出)  第三种情况:      没有对swf Object的id没有过滤      页面加载Flash,我们需要设定Object或者embed的id,否则ExternalInterface会失效。而这个地方,也会被黑客利用。      我们看看实际执行的代码: 
try { document.getElementById("XSSTest" ).SetReturnValue(__flash__toXML(alert( null)) ); } catch (e) { document.getElementById("XSSTest" ).SetReturnValue("<undefined/>"); }     
      看到这里,应该发现跟上边说的第二种情况很类似,黑客可以通过修改了Object id,恶意闭合双引号,达到目的。

 

    接下来,简洁的总结一下怎么防XSS。 对于第一和第三种情况,我们应该对字符进行过滤,例如用以下的两个函数:    
  public static function checkJsFunctionValid(functionName:String):Boolean { var reg:RegExp = /^[a-zA-Z0-9_\.]+$/; return reg.test(functionName);
              } public static function checkObjectIdValid():Boolean { if (ExternalInterface.available)
                     { var objectId:String = ExternalInterface.objectID; if (!objectId || (objectId == objectId.replace(/[^0-9a-zA-Z_]/g , ""))) return true; else return false;
                     } return true;
              } 
对于第二种情况,我们应该尽量避免这样跟js传递数据,但如果实在无法避免。可以用这样的方式转义字符串: 
str.replace( /[\"\\]/g , function(d:String, b:*, c:*){ return '\\' + d.charCodeAt(0).toString(8); });
 简单解释一下,这里把双引号和反斜杠这样比较敏感的字符,替换为转义表示。再输出成js代码时,正好又还原回去了。 例如:\\\"\\\"})));}catch(e){alert(/xss/);}//    变成了     \134\42\134\42})));}catch(e){alert(/xss/);}//  

 

   附带额外的在IE8 开发工具中抓获到的代码:
function __flash__arrayToXML(obj) { var s = "<array>" ; for (var i=0; i<obj.length; i++) {
                s += "<property id=\"" + i + "\">" + __flash__toXML(obj[i]) + "</property>";
        } return s+"</array>" ;
} function __flash__argumentsToXML(obj,index) { var s = "<arguments>" ; for (var i=index; i<obj.length; i++) {
                s += __flash__toXML(obj[i]);
        } return s+"</arguments>" ;
} function __flash__objectToXML(obj) { var s = "<object>" ; for (var prop in obj) {
                s += "<property id=\"" + prop + "\">" + __flash__toXML(obj[prop]) + "</property>" ;
        } return s+"</object>" ;
} function __flash__escapeXML(s) { return s.replace(/&/g, "&" ).replace(/</g, "<").replace(/>/g, ">" ).replace(/"/g, "" ").replace(/'/g, "'");
} function __flash__toXML(value) { var type = typeof(value); if (type == "string" ) { return "<string>" + __flash__escapeXML(value) + "</string>";
        } else if (type == "undefined") { return "<undefined/>" ;
        } else if (type == "number") { return "<number>" + value + "</number>";
        } else if (value == null) { return "<null/>" ;
        } else if (type == "boolean") { return value ? "<true/>" : "<false/>";
        } else if (value instanceof Date) { return "<date>" + value.getTime() + "</date>";
   } else if (value instanceof Array) { return __flash__arrayToXML(value);
   } else if (type == "object") { return __flash__objectToXML(value);
   } else { return "<null/>" ; //???  }
} function __flash__addCallback(instance, name) {
  instance[name] = function () { return eval(instance.CallFunction("<invoke name=\"" +name+"\" returntype=\"javascript\">" + __flash__argumentsToXML(arguments,0) + "</invoke>" ));
  }
} function __flash__removeCallback(instance, name) {
  instance[name] = null;
} 

 


自学PHP网专注网站建设学习,PHP程序学习,平面设计学习,以及操作系统学习

京ICP备14009008号-1@版权所有www.zixuephp.com

网站声明:本站所有视频,教程都由网友上传,站长收集和分享给大家学习使用,如由牵扯版权问题请联系站长邮箱904561283@qq.com

添加评论