zoukankan      html  css  js  c++  java
  • Java应对Flash XSS攻击

    问题引出:

      今天公司派出安全任务,说是要解决一个Flash XSS攻击,一看顿时傻眼,都没听说过。而且flash已经淘汰了,根本没研究过flash,搜了资料才开始慢慢开始工作。

    要求:

    1、过滤URL参数。

    2、禁止外部嵌套。

     

    1.Flash XSS漏洞出现的原因

    1.1原因方式一:把flashvars传入的参数(或者其他能被别人控制的方式)当ExternalInterface.call的第一个参数

     1 package
     2 {
     3         import flash.display.Sprite;
     4         import flash.external.ExternalInterface;
     5        
     6         public class XSSTest extends Sprite
     7        {
     8                public function XSSTest()
     9               {
    10                       var jsFunction:String = loaderInfo.parameters.jsFunction;
    11                       var param:String = "abc";
    12                      ExternalInterface.call(jsFunction, param);
    13               }
    14        }
    15 }

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

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

    1.2原因方式二:把flashvars传入的参数(或者其他能被别人控制的方式)当ExternalInterface.call的第二和第三个参数

    1  public function XSSTest()
    2    {
    3           var param:String = loaderInfo.parameters.param;
    4           ExternalInterface.call("console.log", param);
    5    }

    这个方式也许没有这么简单进行XSS,但对于黑客来说,还是有办法的。在IE8下调试模式下,我们可以看到ExternalInterface的代码:

    正常情况下,Flash player会生成这样的代码:

    1 try { __flash__toXML(console.log("good" )) ; } catch (e) { "<undefined/>"; }

    对比自己写的as代码和生成的这段js代码,可以猜测,Flash player是以一种简单的拼接字符串的方式实现的。稍稍做个小把戏,结果就可以注入代码执行了。

    是不是很神奇?怎么做到的呢?为什么url稍稍变化可以达到这样呢。我们看看现在的js代码:

    1 try { __flash__toXML(console.log("\" ));alert(/XSS/);}catch(e){} //")) ; } catch (e) { "<undefined/>"; }

    正好跟原来的双引号对上了,结果,最后的catch也被替换了。也就是说,黑客可以写自己的函数了,想怎么执行都可以了。至于为什么这里双引号对上了,可以简单猜测flash遇到字符串中有双引号的时候,只是简单的以  "  方式打印成js代码,但如果用户再恶意拼一个,就负负得正了。(这里__flash__toXML的代码并不是关键点了,所以将在文章最后再列出)。

    1.3原因方式三:没有对swf Object的id没有过滤

     页面加载Flash,我们需要设定Object或者embed的id,否则ExternalInterface会失效。而这个地方,也会被黑客利用。

     我们看看实际执行的代码:
    1 try { document.getElementById("XSSTest" ).SetReturnValue(__flash__toXML(alert( null)) ); } catch (e) { document.getElementById("XSSTest" ).SetReturnValue("<undefined/>"); }  

    看到这里,应该发现跟上边说的第二种情况很类似,黑客可以通过修改了Object id,恶意闭合双引号,达到目的。

     

    2.防止XSS攻击。 

    对于第一和第三种情况,我们应该对字符进行过滤,例如用以下的两个函数:
     1 public static function checkJsFunctionValid(functionName:String):Boolean
     2 {
     3     var reg:RegExp = /^[a-zA-Z0-9_.]+$/;
     4     return reg.test(functionName);
     5 }          
     6     
     7 public static function checkObjectIdValid():Boolean
     8 {
     9      if (ExternalInterface.available)
    10     {
    11          var objectId:String = ExternalInterface.objectID;
    12          if (!objectId || (objectId == objectId.replace(/[^0-9a-zA-Z_]/g , "")))
    13              return true;
    14          else
    15              return false;
    16       }
    17       return true;
    18 }

    对于第二种情况,我们应该尽量避免这样跟js传递数据,但如果实在无法避免。可以用这样的方式转义字符串:

    1 str.replace( /["\]/g , function(d:String, b:*, c:*){ return '\' + d.charCodeAt(0).toString(8); });

    简单解释一下,这里把双引号和反斜杠这样比较敏感的字符,替换为转义表示。再输出成js代码时,正好又还原回去了。

    例如:
    \"\"})));}catch(e){alert(/xss/);}//    变成了     1344213442})));}catch(e){alert(/xss/);}//
    附带额外的在IE8 开发工具中抓获到的代码:
     1 function __flash__arrayToXML(obj) {
     2          var s = "<array>" ;
     3          for (var i=0; i<obj.length; i++) {
     4                 s += "<property id="" + i + "">" + __flash__toXML(obj[i]) + "</property>";
     5         }
     6          return s+"</array>" ;
     7 }
     8 function __flash__argumentsToXML(obj,index) {
     9          var s = "<arguments>" ;
    10          for (var i=index; i<obj.length; i++) {
    11                 s += __flash__toXML(obj[i]);
    12         }
    13          return s+"</arguments>" ;
    14 }
    15 function __flash__objectToXML(obj) {
    16          var s = "<object>" ;
    17          for (var prop in obj) {
    18                 s += "<property id="" + prop + "">" + __flash__toXML(obj[prop]) + "</property>" ;
    19         }
    20          return s+"</object>" ;
    21 }
    22 function __flash__escapeXML(s) {
    23          return s.replace(/&/g, "&amp;" ).replace(/</g, "&lt;").replace(/>/g, "&gt;" ).replace(/"/g, "&quot; ").replace(/'/g, "&apos;");
    24 }
    25 function __flash__toXML(value) {
    26    var type = typeof(value);
    27          if (type == "string" ) {
    28                  return "<string>" + __flash__escapeXML(value) + "</string>";
    29         } else if (type == "undefined") {
    30         return "<undefined/>" ;
    31         } else if (type == "number") {
    32         return "<number>" + value + "</number>";
    33         } else if (value == null) {
    34         return "<null/>" ;
    35         } else if (type == "boolean") {
    36         return value ? "<true/>" : "<false/>";
    37         } else if (value instanceof Date) {
    38         return "<date>" + value.getTime() + "</date>";
    39    } else if (value instanceof Array) {
    40        return __flash__arrayToXML(value);
    41    } else if (type == "object") {
    42        return __flash__objectToXML(value);
    43    } else {
    44             return "<null/>" ; //???
    45         }
    46 }
    47 function __flash__addCallback(instance, name) {
    48   instance[name] = function () {
    49     return eval(instance.CallFunction("<invoke name="" +name+"" returntype="javascript">" + __flash__argumentsToXML(arguments,0) + "</invoke>" ));
    50   }
    51 }
    52 function __flash__removeCallback(instance, name) {
    53   instance[name] = null;
    54 }

     

  • 相关阅读:
    CSS选择器之伪类选择器(元素)
    CSS选择器之基本选择器+属性选择器
    bugku 点击1000000次
    bugku web 5
    bugku 矛盾 30
    bugku 域名解析题 50
    bugku 好多压缩包
    六子冲 模拟棋盘
    poj3126 Prime Path(c语言)
    poj1426 Find The Multiple(c语言巧解)
  • 原文地址:https://www.cnblogs.com/guanghe/p/6485035.html
Copyright © 2011-2022 走看看