重温XSS

目录


title: XSS的一些基本概念 date: tags: 外围打点


同源策略与跨域

同源策略

同源的定义

若两个URL 协议,端口,host都相同,则这两个URL同源。 这个方案叫做“协议/主机/端口元组”,或者直接是 “元组”

同源策略又分为DOM同源策略(禁止对不同源的页面的DOM进行操作)和XMLHttpRequest(禁止XHR对象项不同源的服务器地址发起HTTP请求)同源策略

同源策略的作用

限制一个JS脚本对不同源的URL进行操作。

这么说可能会有点抽象,那不如看看下面的例子:

1.如果没有DOM同源策略,就意味着一个页面可以对任意页面的DOM进行操作。那么就会导致以下安全问题: 做一个假网站,并插入一个占满全页面的iframe指向一个登陆界面如银行登录界面。用户进来后会发现除了域名不同,其他都和正常的银行登陆界面一致。若用户输入了账号密码,那么我们就可以跨域读取到银行登陆界面的dom树,从而读取用户输入的账号密码。

2.如果没有XMLHttpRequest,就意味着可以一个页面可以向任意页面发起HTTP请求。那么就会导致以下安全问题: 当一个用户登陆了某个系统,如银行个人系统,此时银行网站会给用户返回cookie。如果用户此时访问了我们的恶意网站,就会执行我们恶意网站中的恶意AJAX代码,此AJAX代码会向银行网站发起HTTP请求,比如发起查询账户余额的请求(此时会默认附带用户的cookie)。银行页面发现cookie无误,就会返回请求的数据:账户余额,造成数据泄露。

跨域

上面我们说了同源策略中,一个页面不能对不同源的页面进行操作。但是在实际情况中,还是有一些js标签能摆脱这种束缚,如script标签就能通过src属性获取不同源页面上的js代码,iframe能嵌入不同源站点的资源等等。 这样的标签有如下

<script src="..."></script>
<link rel="stylesheet" href="...">
<img> / <video> / <audio>
<object> <embed> 和 <applet> 的插件
@font-face
<frame> 和 <iframe>

但仅仅是这样,有些时候还是无法达到业务的需求,我们有时需要突破这种限制来达到业务需求,也就是避开同源策略,以下是几种解决方案。

CORS

CORS,即跨域资源共享,它是一个W3C标准,定义了必须访问跨域资源时,浏览器和服务器该如何协商。 其实质就是以AJAX为载体,使用自定义HTTP头让浏览器与服务器进行协商,从而决定跨域请求是否应该成功。 所以实现CORS通信的关键是服务器是否实现了CORS接口。

另外,并不是所有浏览器都支持CORS,比如IE6,IE7,Opera min 不支持CORS。

实现原理

浏览器把CORS的请求分成两类:简单请求与非简单请求

简单请求: 满足以下条件,即为简单请求

请求方法是以下三种方法之一:
HEAD
GET
POST

且HTTP的头信息不超出以下几种字段:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限于三个值 application/x-www-form-urlencoded、multipart/form-data、text/plain

只要不满足以上条件,都为非简单请求。

对于简单请求,其实现原理如下:

1.在请求头中加一个额外头:Origin, 其包含发出请求的页面的协议,域名,端口,服务器以此来判断是否给予响应。 2.服务器收到请求后,判别该Origin指向的站点能否跨域。若能跨域,就在 Access-Control-Allow-Origin 头部中回发相同的源信息(如果是公共资源,可以回发 * );若不能跨域,则没有这个头部或者源信息不匹配(即Access-Control-Allow-Origin内容非*且与Origin不符) 3.同时如果服务器返回的头中有 Access-Control-Allow-Credentials: true ,则说明可以跨域向服务器发送带有cookie的HTTP请求。

对于非简单请求,它会实现进行预检,其原理如下: 1.进行预检,以OPTIONS方法向服务器发送Origin头部,Access-Control-Request-Method头部(接下来的请求方法,如POST),Access-Control-Request-Headers(自定义头部信息,可选) 2.服务器响应,有如下头:Access-Control-Allow-Origin,Access-Control-Allow-Methods(允许的请求方法),Access-Control-Allow-Headers(允许的自定义头部信息),Access-Control-Max-Age(应该将预检请求缓存多长时间,以秒为单位) 3.通过预检请求后,以后每次浏览器的CORS请求都会和简单请求一样。

JSONP

我们不妨通过一个例子来窥视JSONP的实现原理。

我们有如下文件test.html

<html>
    <head></head>
    <body>
        <h1>HI</h1>
        <script>
            var fun1=function(data){
                alert(data)
            }
        </script>
        <script type="text/javascript" src="http://192.168.111.1/a.js"></script>
    </body>
</html>

其包含的a.js如下

fun1("remote data");

访问test.html,成功触发弹窗,我们将test.html中的fun1函数称为回调函数

image-20210322211050387

于是就出现了利用这种原理来实现跨域传输数据的方法:JSONP

下面说说JSONP的具体实现流程:

客户端: 1.定义获取数据后的回调函数 2.动态生成服务端JS进行引用的代码

关于此处第2点,我们可以说道说道。
我们再用这个方法实现跨域时,怎么让远程JS知道我们本地的回调函数叫什么名字?
这就需要通过一些手段动态生成服务端的JS代码了。
比如我们可以通过get参数来控制其返回的本地回调函数名,如: http://a.com?callback=fun1

服务端: 返回由回调函数名包裹的JSON数据,如

fun1({
  "key1":"value1"
});

这里为什么要特别强调是JSON呢?因为JSON不仅可以简洁的表述复杂的数据,而且JS原生支持JSON,可以在客户端自由处理JSON数据,所以服务端多传回JSON数据,JSONP这个名字也是这么来的。

CSP

CSP,即内容安全策略。它通过白名单策略,告诉客户端哪些外部资源可以加载和执行。 同时需要注意的是,CSP目前有1.0 2.0 3.0 版本,每个版本的规则都有不同

CSP规则

CSP通过定义一系列规则来实现安全管理。

首先我们来看看一条CSP规则的范例

Content-Security-Policy: default-src https://host1.com https://host2.com; frame-src 'none'; object-src 'none'
多个CSP指令间用分号隔开,多个指令值之间用空格隔开

下面是各个指令及其指令值的效果

摘自https://blog.csdn.net/qq_37943295/article/details/79978761

image-20210322214229302

image-20210322214238476

启用CSP

那么如何启用CSP呢?有两种方式

1.在HTTP头添加 在HTTP头响应添加content-security-policy头并写入CSP规则以后,就能启用CSP了

图引用于http://www.ruanyifeng.com/blog/2016/09/csp.html

image-20210322214736472

2.在meta标签里添加 向内添加如下内容

<meta http-equiv="Content-Security-Policy" content="script-src 'self'; object-src 'none'; style-src cdn.example.org third-party.org; child-src https:">
即可

一些其他XSS保护机制

X-Frame

X-Frame-Options 是一个响应头,指定此页面能否在\或者\