使用CSP技术解决前端XSS攻击,防止广告注入H5页面
2018-06-27 13:50阅读:
问题由来:最近在升级公司APP中的积分功能,APP使用的是React
Native,积分部分则是嵌入的H5页面,回家测试连接上家里WIFI后测试,发现打开积分页面广告满天飞,都已经影响到我使用主要功能了,有时候还导致app强制退出。
和同事商量后,同事提高了服务器上项目文件的权限,提高到只读权限,效果稍微好一些,但还有广告,问了一下度娘,度娘说的其中一种原因是http劫持,解决办法就是加密成https,由于种种原因公司项目无法将服务换成https,则使用以下解决办法。
什么是XSS跨站脚本攻击?
XSS跨站脚本攻击是代码注入的一种,它指的是攻击者在网页中嵌入客户端脚本(例如js脚本),当用户浏览该网页时攻击脚本就会在用户的浏览器上运行,脚本就可以恶意盗取用户敏感信息、将用户重定向到其他网站、利用被攻击者身份执行一些管理操作或常规操作(如发微博、发私信)等等。
一般分为两类:
1.反射性XSS
反射性XSS,是指攻击者将脚本加入URL的参数中,
诱骗用户点击URL,服务器解析后响应,在返回的响应中隐藏和嵌入攻击者的XSS代码(如直接在页面输出脚本内容),被浏览器执行,从而攻击用户。这样的URL通常较长,容易识别,但如果攻击者使用短网址服务将网址缩短,用户就很难辨别了。
2.存储型XSS
存储型XSS是指攻击者将恶意数据提交到服务器,并且在其中嵌入攻击脚本,并且放在其他用户可以看到的地方,如评论、文章等。这样在其他用户浏览该页面时,就会从服务器请求这部分数据,从而被攻击。
r />
目前对付XSS攻击的方法之一就是对所有用户的输入及请求都进行过滤和检查,如对特殊字符进行过滤和编码、设置输入域的匹配规则等。这样可以避免大部分XSS攻击,但不保证对所有攻击有效,并且限制用户只能输入特定规则的特定字符也降低了业务系统的可用性。
常见XSS风险:
1.避免使用 href='javascript:;';
2.避免使用内联事件绑定如onclick=clickCallback
3.避免使用eval及会调用eval的写法:
setTimeout([string],...);
setInterval([string],...);
会话劫持
会话劫持就是在一次正常的会话过程当中,攻击者作为第三方参与到其中。他可以在正常数据包中插入恶意数据,或拦截正常的网络通信数据,并进行数据篡改;也可以在双方的会话当中进行监听,甚至可以是代替某一方主机接管会话。
针对会话劫持,https协议就可以通过校验保证数据的完整性(不能被篡改)、隐私性(加密传播)和身份有效性(防止被冒充)。
CSP应用场景
针对Web页面面临的安全问题:代码注入(例如XSS)。
CSP概念及原理
CSP是针对内容注入危害,其特点是:基于内容声明式,简单,强大。
目标及原理
目标定位
有效缓解内容注入危害
不能消除内容注入攻击
工作原理
通过指令声明的方式限制内容的加载和执行
有效范围
当前页面本身,插入到当前页面的任何内容
CPS应用
外联可行
支持http2.0
CSP2支持inline
浏览器支持率较高特别是移动端
CSP使用方法
告诉浏览器所允许的内容规则即可,即通过设置白名单的方式来限制脚本运行。
要素
CSP域: 告诉浏览器要使用CSP规则
CSP指令集: 所允许的内容规则
如何告知
- 通过页面响应头
Content-Security-Policy服务器设置,同一域名都生效
-
通过响应头
Content-Security-Policy-Report-Only
- 类似1,但是只上报违反规则的行为,不实际执行过滤(可作为正式启用CSP前的测试)
- 通过页面meta标签
只对当前页面有效
可用于前期调试
放置在head标签中
部分属性无效(例如report-uri)
- 通过js动态插入meta标签,基础库统一动态调整
-
服务器配置
支持Apache, Nginx, Node
语法规则
Content-Security-Policy:指令1(空格)指令值1 (空格)指令值2(空格) …;
指令2(空格)指令值2…
机制: 仅对指令声明内容有效类似白名单
1
CSP1
常用指令
| 指令 |
作用 |
| default-src |
定义针对所有类型(js/image/css/ajax/iframe/多媒体等)资源的默认加载策略,某类型资源如果没有单独定义策略,就使用默认 |
| script-src |
指定允许运行的脚本 |
| style-src |
允许的样式表 |
| img-src |
允许的图片 |
| report-uri |
上报地址 |
指令值及说明
| 指令值 |
说明 |
示例 |
| * |
不做限制(default) |
script-src * |
| ‘none’ |
不允许任何内容 |
script-src ‘none’ |
| ‘self’ |
允许同源内容 |
script-src ‘self’ |
| *.a.com |
允许a.com子域内容 |
script-src *.a.com |
| ‘unsafe-inline’ |
允许内联内容 |
script-src ‘unsafe-inline’ |
| ‘unsafe-eval’ |
允许将字符串转为js执行 |
script-src ‘unsafe-eval’ |
| protocol: |
允许指定伪协议内容 |
https: mqq: weixin: |
对内联的支持: 要么完全阻止,要么完全允许
实现难度大、
严格、有效
注意事项:
- 指令一旦声明,要确保白名单完整性
- 关键字须加单引号,如unsafe-inline, unsafe-eval
- 不声明unsafe-inline,则所有inline代码失效
- 不声明unsafe-eval,转为代码执行失效
1
CSP2
常用指令
| 指令 |
作用 |
| base-uri |
限制当前页面的url |
| child-src |
限制子窗口的源(iframe、弹窗等) |
| form-action |
限制表单能够提交到的源 |
| frame-ancestors |
限制了当前页面可以被哪些页面以iframe,frame,object等方式加载 |
对内联的支持: 限制非法内联
nonces (允许制定内联脚本或样式 )
- 特点
- 复杂、安全
- 不支持写在html标签属性script/style里的内联写法
-
不依赖与一个攻击者不知道的值,因此可以保持script和header不变,适用于静态页面
- 不让攻击者猜到
- 简单
- 每次都需要更改header,适用于动态产生的页面
- script-src ‘nonce-1’
- 使用128bits随机数+base64编码(对应在内联脚本上设置同样的值
- 例子
csp头:
content-security-policy: default-src 'self'; script-src
'nonce-2726c7f26c'
对应的script标签:
<</span>script
nonce='2726c7f26c'>
;
</</span>script>
一定要每次response都使用不同的、不易预测的nonce值。
特点:
hashes (允许制定内联脚本或样式, 会自动忽略unsafe-inline)
内容签名:base64(sha256/384/512(内容))
例子:
csp头:
content-security-policy:script-src
'sha256-cLuU6nVzrYJlo7rUa6TMmz3nylPFrPQrEUpOHllb5ic='
对应的script标签:
<</span>script>
;
</</span>script>
可见,我们需要对代码中的每一段script或style都进行hash的内容计算。可以将计算过程放在项目的build过程中。
我使用的是:
<</span>meta
http-equiv='Content-Security-Policy'
content='script-src 'self' 'unsafe-inline'
*.alicdn.com;style-src 'self' 'unsafe-inline'
*.alicdn.com'>
解释:
键:script-src (页面js文件的来源)
值:‘self’ (允许同源js文件加载到本页)
值:‘unsafe-inline’(不安全的,网上加载的js文件,比如引用了cdn上的js文件)
eg:

如果不设置unsafe-inline属性,页面引用了这些资源就全部屏蔽掉了,所以需要‘unsafe-inline’
*.alicdn.com这段代码对***.alicdn.com这个域名设置白名单,允许这个域名下的js加载到页面中。
键:style-src(页面css文件的来源)
值同上。
仅供参考,欢迎指出不足。
