tnsnames.ora配置未生效_CSP策略的配置与应用(下)

       在本文的上半部分(一至三章中),介绍了CSP策略的基本概念及相关的配置。本文的下半部分将会介绍如何将CSP策略使用到一个真实的网站,在落地的过程中可能会遇到哪些问题,以及一些对于CSP策略其他需要关注的地方。

04

CSP基本配置方法

      CSP策略作用于浏览器,有两种配置方法:配置在页面的meta标签中;配置在返回包的响应头中。具体使用哪种方法可以根据实际情况进行取舍。

      1、通过meta标签配置CSP策略

       可以通过直接在页面中加入meta标签的方式配置CSP策略,如

       其中content后面的值为具体的CSP策略。

       CSP策略是一个无状态的机制,因此只会在配置了CSP策略的页面中生效。因此这种配置方法可能比较适合独立的H5页面。

       值得注意的是,这种方式配置CSP策略无法使用report-uri,因此无法监控CSP的运行状态(比如是否阻止了不应该阻止的资源),有可能在测试环境中CSP策略运行的很完美,但到了线上环境却出现了各种问题,因此个人认为这种配置方式不太值得推荐,只适合在本地测试CSP策略时使用这种方式。

       目前,一些主流的包管理工具可以使用插件通过这种方式引入CSP策略(如npm的csp-html-webpack-plugin等等),但具体CSP策略的"指令-来源"仍需手动配置。

       2、将CSP策略配置在响应头中

      如果希望对整站进行CSP策略的配置,比较常用的方法是将CSP策略配置在前端页面的http响应头中(显然在后端api接口的响应头中配置CSP是无效的),其中的Contant-Secruity-Policy即为gitlab官方给自己网站配置的CSP响应头。配置响应头的方法一般来说有以下几种

    (1)对于前后端不分离的工程

       如果工程没有对前后端进行分离,可以直接在过滤器或拦截器(以java项目为例)中,将CSP响应头增加到前端请求的响应中,如使用setHeader(name, value)方法(或addHeader方法)。由于csp策略在制定时很难考虑到所有的请求源,且在后续的开发中,可能会不断新增”指令-来源“,因此会难免会有更改CSP策略的情况发生,如果将CSP策略的具体规则直接写死在代码中,可能会造成更新的不便,因此建议在这种情况下可以将CSP策略的具体规则写在一个统一配置平台中。

    (2)前后端分离工程

      对于前后端分离的工程,由于在后端接口的响应头中增加的CSP不会在前端页面中生效,因此无法采用“(1)”中的方法,我们建议采用以下几种方式添加CSP策略。当然,“(2)”中的几种配置方法,同样适用于前后端不分离的工程。

      a.前端nginx

      可以在前端nginx的配置中,以增加响应头的方式配置CSP策略,如在nginx的配置中增加:

add_header Content-Security-Policy-Report-Only "default-src ‘self' ";

69667549395ae91ec9f5a83004e1bdaa.png

      实际上通过include引入文件的方式可能会更方便一些,不需要每次都修改nginx.conf文件了,直接替换引入的文件即可:

3b90466abed6753ff6fc6936a07b4200.png

      csp.conf中的具体内容如下:

1044d41205c2f24d15b05465a1a804d2.png

       b.在其他中间件的配置中增加csp策略

       其他的中间件服务器(如apache,iis等),同样可以增加响应头,因此也可以配置CSP策略,如

  • Apache:

        在VirtualHost的httpd.conf文件或者.htaccess文件中加入以下代码

Header set Content-Security-Policy "default-src 'self';"

  • iis:

   web.config:中添加

        这几种方式修改后需要重启,CSP策略才能生效。

05

CSP策略规则编写原则

      在实际编写CSP策略的规则时,最好能够遵循加白范围最小的原则,可以理解为使白名单中的内容尽可能的少,只要满足需求即可,这样才能最大限度的减小风险。不过在对实际业务配置CSP策略时,这很难实现,因为业务总有一些不太推荐的写法(如内联脚本),或允许从任意的地址引入资源(如图片等)。下面会介绍一些能够提高安全性的原则:

      (1)可执行脚本(script-src)

        'unsafe-inline':script-src指令在配置了该来源时,浏览器会允许内联脚本的执行,因此在存在xss漏洞的情况下,能够使浏览器执行如"

      'unsafe-eval':eval函数能够执行js脚本,因此也有造成安全问题的可能,如插入标签改变页面样式等,在没有必要的情况下不要加上该”来源“

       在CSP策略中加入这两个配置,使得无法防御如"

      (2)设置某指令的来源为通配符"*"

       将CSP指令的来源设置为“*”,这将允许浏览器将该指令对应的大部分来源引入页面,只能在确认业务确实有必要这样做时再配置通配符“*”。在某些业务场景下(如需要允许外链图片等),可以将部分需要的指令,增加“*”配置。由于default-src为大部分指令的回退指令,因此非常不推荐将default-src的来源设置成通配符“*”。

     (3)“*.abc.com”配置

       在abc.com为本公司的域名时(如example.com),可以直接在某指令的来源中添加*.example.com以减轻工作量。在abc.com不为本公司的域名时,如(baidu.com),建议不要添加*.baidu.com,而是尽可能的添加其host,如hm.baidu.com等。

       (4)“http:”配置(必须不使用)

       将某些指令加入"http:"或"https:"来源,将会将所有来源的http或https请求加白,因此需要比较慎重。在需要允许通过http的方式请求资源时,可以在某"指令"的"来源"中添加http://hm.baidu.com或http://*.example.com

06

CSP策略的迭代

       由于网站的前端一般引入的资源较多,因此很难一次性的将CSP策略的规则编写到位,下面推荐两种进行CSP策略迭代的方法以供参考。在不保证CSP策略的规则能够完全编写正确时,可以使用Content-Security-Policy-Report-Only响应头进行测试。

       需要特别注意的是,对于比较大型的系统,需要在线上环境使用Content-Security-Policy-Report-Only响应头对CSP策略进行测试,因为测试环境无法模拟所有用户的操作环境,包括但不限于测试环境与正式环境存在少许不一致、大多数用户都会使用的插件、较少在测试环境被访问的页面等等。

       1、通过浏览器的报警

       浏览器在根据CSP策略进行资源阻塞时,会在控制台输出一条报警,如下图所示

fb0322d289501e3c4230ab0ae3410846.png

       当前页面代码为:

      在报警中,详细显示了CSP策略阻塞了script标签中的“http://www.example.com/abc.js”资源,由于未找到script-src-elem指令,因此回退到default-src,且该资源未在default-src中被添加为白名单。(需要说明的是,script-src-elem为script-src的更具体配置,浏览器查找指令的顺序为script-src-elem->script-src->default-src,由于不同浏览器支持的指令略有不同,建议使用script-src即可)

       因此,可以通过查看浏览器报警,来判断哪些资源未被添加到CSP策略中。

       2、通过查看report-uri

      前文中已经说过,CSP策略在与当前页面产生冲突时,会向report-uri所指定的地址发送一条请求,若在CSP中配置“report-uri https://logs.example.com/log/csplog",则浏览器在检测到冲突时,会发送如下请求

POST /log/csplog HTTP/1.1

Host: logs.example.com

Connection: keep-alive

Content-Length: 354

User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36

Content-Type: application/csp-report

Accept: */*

Origin: http://localhost:30080

Sec-Fetch-Site: cross-site

Sec-Fetch-Mode: no-cors

Referer: http://localhost:30080/csptest.html

Accept-Encoding: gzip, deflate, br

Accept-Language: zh-CN,zh;q=0.9

{"csp-report":{"document-uri":"http://localhost:30080/csptest.html","referrer":"","violated-directive":"script-src-elem","effective-directive":"script-src-elem","original-policy":"default-src 'self' ;report-uri https://logs.example.com/log/csplog","disposition":"enforce","blocked-uri":"https://www.baidu.com/","status-code":200,"script-sample":""}}

      其中,请求体中包含的内容,会告诉我们页面引入的资源未在CSP规定的白名单中,比较重要的字段说明如下:

字段

含义

blocked-uri

阻塞的资源,如地址、协议等

document-uri

冲突页面

original-policy

当前CSP策略

violated-directive

冲突策略

      业务方可以实现远程接口,用于接收CSP策略发送的冲突报告。由于当设置的CSP策略请求头为”Content-Security-Policy-Report-Only“时,不会对线上环境产生影响,因此可以先上线基础版本的CSP策略,之后利用冲突报告来不断调整CSP的策略。

      另外需要提醒的是,目前有更为强大的,用于替代report-uri指令的report-to指令,但目前浏览器对report-to的支持情况并不好,因此需要慎用。

07

CSP策略后期维护

      CSP策略是一个白名单策略,在网站业务更新时,可能会引入新的资源来源,CSP也有可能更新其规则,此外,可能业务方也需要对CSP策略的运行情况进行跟踪,因此我们有以下几点建议:

      1、后端实现CSP策略报告接口

      根据前文所述,report-uri指令可以在CSP拦截了页面中某些资源加载或脚本执行时,向指定的地址发送一条post请求,因此可以利用这个功能,对CSP的拦截情况进行跟踪。

      需要值得注意的是,由于在每次CSP策略拦截时,都会发起请求,而CSP的请求同样会占用服务器的资源,因此用户量较大需要注意限制该接口的QPS,以免造成拒绝服务问题。

      由于一般来讲报告的数量可能较多,可以使用脚本对CSP策略的关键字进行提取处理。下面是使用nginx日志对CSP的报告请求进行记录,并通过python进行处理,关键代码可供参考

烂烂的python代码

import re

import json

import csv

import re

from urllib.parse import urlparse

import sys

import requests

import json

import time

repeatlog=[]

f = open('./domain.log',encoding='UTF-8')       //nginx请求日志

cf = open('csp.csv', 'w', encoding='utf-8')     //将内容保存至csv

csv_writer = csv.writer(cf)

csv_writer.writerow(["document-uri","violated-directive","blocked-uri","original-policy"])     //csv中第一行为列标题

for line in f:                                //nginx将每个请求记录为1行

   j=json.loads(line)

   if j['post-data'] == '':                   //判断该请求是否是csp报告,当前该nginx只需CSP报告请求和探活请求(get型)进入,因此只需判断该请求是否为post即可,业务方需要根据自己的情况进行调整。

       continue

   postdata=json.loads(j['post-data'])

   cspreport=postdata['csp-report']

   reporturi = cspreport['original-policy']

   if 'http://csplog.example.com/csplog/business1' not in reporturi:  //由于可能一个接口会接入多个网站的CSP报告,判断是否为关注的CSP报告接口收到的数据。

       continue

   try:                     //repeat、repeatlog用于去重

       repeat='document-uri:'+urlparse(cspreport['document-uri']).netloc+'violated-directive:'+cspreport['violated-directive']+'blocked-uri:'+urlparse(cspreport['blocked-uri']).netloc

   except Exception as e:

       repeatlog.append(repeat)

       print(e)

       continue;

   if repeat not in repeatlog:

       csv_writer.writerow([cspreport['document-uri'], cspreport['violated-directive'], cspreport['blocked-uri'],        //不在repeatlog中的报告写入csv中

                            cspreport['original-policy']])

       repeatlog.append(repeat)

f.close()

cf.close()

       在生成了csv后,可以使用csv中的排序功能,对报告进行再次排序,方便人工进行查看。

       2、接入报警系统

       目前的公司一般使用grafana或其他系统进行监控或打点,CSP策略同样可以接入。但建议保留原始的CSP报告(即post请求中的请求体),便于后续的分析。

08

使用CSP的公司

   以下是几个目前使用CSP策略的公司,可供参考。

1、gitlab.com      

connect-src 'self' https://assets.gitlab-static.net https://gl-canary.freetls.fastly.net wss://gitlab.com https://sentry.gitlab.net https://customers.gitlab.com https://snowplow.trx.gitlab.net https://sourcegraph.com https://ec2.ap-east-1.amazonaws.com https://ec2.ap-northeast-1.amazonaws.com https://ec2.ap-northeast-2.amazonaws.com https://ec2.ap-northeast-3.amazonaws.com https://ec2.ap-south-1.amazonaws.com https://ec2.ap-southeast-1.amazonaws.com https://ec2.ap-southeast-2.amazonaws.com https://ec2.ca-central-1.amazonaws.com https://ec2.eu-central-1.amazonaws.com https://ec2.eu-north-1.amazonaws.com https://ec2.eu-west-1.amazonaws.com https://ec2.eu-west-2.amazonaws.com https://ec2.eu-west-3.amazonaws.com https://ec2.me-south-1.amazonaws.com https://ec2.sa-east-1.amazonaws.com https://ec2.us-east-1.amazonaws.com https://ec2.us-east-2.amazonaws.com https://ec2.us-west-1.amazonaws.com https://ec2.us-west-2.amazonaws.com https://iam.amazonaws.com; frame-ancestors 'self'; frame-src 'self' https://www.google.com/recaptcha/ https://www.recaptcha.net/ https://content.googleapis.com https://content-cloudresourcemanager.googleapis.com https://content-compute.googleapis.com https://content-cloudbilling.googleapis.com https://*.codesandbox.io; img-src * data: blob:; object-src 'none'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://assets.gitlab-static.net https://gl-canary.freetls.fastly.net https://www.google.com/recaptcha/ https://www.gstatic.com/recaptcha/ https://www.recaptcha.net/ https://apis.google.com 'nonce-D41Y+Bgf6DE4s6X9qQ+bwQ=='; style-src 'self' 'unsafe-inline' https://assets.gitlab-static.net https://gl-canary.freetls.fastly.net; worker-src https://assets.gitlab-static.net https://gl-canary.freetls.fastly.net https://gitlab.com blob:

2、知乎

default-src * blob:; img-src * data: blob:; connect-src * wss: blob:; frame-src 'self' *.zhihu.com mailto: tel: weixin: *.vzuu.com mo.m.taobao.com getpocket.com note.youdao.com safari-extension://com.evernote.safari.clipper-Q79WDW8YH9 zhihujs: captcha.guard.qcloud.com pos.baidu.com dup.baidustatic.com; script-src 'self' blob: *.zhihu.com g.alicdn.com qzonestyle.gtimg.cn res.wx.qq.com open.mobile.qq.com 'unsafe-eval' unpkg.zhimg.com unicom.zhimg.com captcha.gtimg.com captcha.guard.qcloud.com pagead2.googlesyndication.com cpro.baidustatic.com pos.baidu.com dup.baidustatic.com i.hao61.net 'nonce-e152d922-cde3-4ced-b7f9-3d8a2b70dfdf' hm.baidu.com zz.bdstatic.com; style-src 'self' 'unsafe-inline' *.zhihu.com unicom.zhimg.com captcha.gtimg.com

3、https://www.applysquare.com/

default-src *; script-src 'self' 'unsafe-eval' 'unsafe-inline' cdn.applysq.com cdn.applysquare.net ana.applysquare.com pingjs.qq.com hm.baidu.com *.map.baidu.com *.map.bdimg.com res.wx.qq.com s13.cnzz.com c.cnzz.com cdn.bootcss.com cdn.staticfile.org static.bcedocument.com img.baidu.com doc.baidubce.com static.exp.bcedocument.com *.google-analytics.com *.google.com maps.gstatic.com *.amap.com *.googleapis.com *.bootstrapcdn.com *.cloudflare.com cdn.applysquare.net/a2/lib assets-cli.s2.udesk.cn 1372979.s2.udesk.cn basevistor.s2.udesk.cn js.intercomcdn.com widget.intercom.io; style-src 'self' 'unsafe-inline' 1372979.s2.udesk.cn static.bcedocument.com img.baidu.com doc.baidubce.com static.exp.bcedocument.com cdn.applysq.com cdn.applysquare.net cdn.staticfile.org cdn.bootcss.com *.amap.com *.googleapis.com *.bootstrapcdn.com *.cloudflare.com cdn.applysquare.net/a2/lib; font-src * data:; img-src * data: blob:; connect-src * data:

4、phabricator

https://secure.phabricator.com/

default-src https://p.phcdn.net; img-src https://p.phcdn.net data:; style-src https://p.phcdn.net 'unsafe-inline'; script-src https://p.phcdn.net; connect-src 'self'; frame-src 'self' https://www.youtube.com; frame-ancestors 'none'; object-src 'none'; form-action 'self'; base-uri 'none'

       目前phabricator可以算作对CSP的比较优秀的实现,这是由于其对资源来源和脚本执行的限制较为严格。但存在瑕疵的地方是仍然允许在style标签中配置内联样式(即style-src 中的'unsafe-inline'),如:

测试代码:

      在插入p标签后,会向http://www.example.com发起一个请求(可能造成的问题和img类型的csrf相同),值得注意的是,csp策略并不会拦截向”http://www.example.com"尝试发起的请求。

09

CSP策略的缺陷

       CSP策略实际存在一些缺陷,导致某些情况下并不能够完美的解决XSS与劫持问题。下面将对这些情况进行说明

1、'unsafe-inline'和'unsafe-eval'

     上文中提到过,如果配置了'unsafe-inline'和'unsafe-eval',CSP策略会允许形如

2、浏览器兼容性问题

      CSP策略最终作用于用户的浏览器,且不同浏览器实现CSP的方式与标准并不完全统一,各浏览器对CSP的实现也在不断地更新。因此,假如用户使用了非主流的浏览器内核或其旧版本,可能会存在不支持CSP策略的情况。

      关与浏览器对CSP策略的支持,详情可参见 https://caniuse.com/#feat=contentsecuritypolicy ,目前大多数浏览器都能够支持CSP策略,无需特别担心。

3、CSP策略本身漏洞

      作为一种程序,CSP在实现上也会出现一定的漏洞,如:

      CSP对link标签的预加载功能考虑不完善。在Chrome下,可以使用如下标签发送cookie(比较老的Chrome上出现)

4、流量劫持

       CSP策略能够一定程度上防止流量劫持问题,但对于有针对性的劫持,可能无法完美防御。由于流量能够被中间人(浏览器、运营商等)完全控制,因此理论上完全可以删除响应包中的CSP策略。

      基于这些缺陷,CSP策略无法独立作为XSS与流量劫持问题的防御手段,需要与其他策略共同构建防御纵深。

      对于防御XSS问题,推荐业务方采用的防御策略有:

(1)从前端代码层面防止XSS。(2)正确配置CSP策略。(3)Cookie中的身份校验参数增加httponly属性。

      对于防御流量劫持问题,推荐业务方采用的防御策略有:

(1)使用https。(2)使用CSP策略。(3)对于重要页面,可以在客户端校验前端代码,如有不一致则向服务器发送一封报告,方便进行原因排查。

10

相关参考资料

       在对CSP策略的研究,及本文成文的过程中,我参考了大量的相关资料,下面列出了对我有较大帮助的相关资料,当然由于篇幅有限(主要是因为我记不得了),没有列出全部的参考内容。

      (1) 根据选项在线生成CSP(实际并不好用。。)

              https://www.cspisawesome.com/

      (2)csp配置详解

              https://cloud.tencent.com/developer/chapter/13541 (中文,可能部分有错误)

              https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Content-Security-Policy (英文,推荐直接看这个)

              包含比较详细的配置规则

      (3)CSP 部分绕过方式

              https://xz.aliyun.com/t/444  (主要是使用浏览器缓存绕过CSP加载规则)

              https://www.freebuf.com/column/184587.html (利用DNS解析绕过CSP)

              https://www.jianshu.com/p/f1de775bc43e  (其他一些绕过方法)

              https://xz.aliyun.com/t/2438   (其他一些绕过方法)

        (4)我的公众号:

               暮夕水寒的碎碎念

               虽然现在啥也木有,不过说不定哪一天就突然多了东西呢╮(╯▽╰)╭

       本文分为上下两部分,介绍了CSP策略的基本概念与配置方法。由于篇幅的问题,隐藏了大量的细枝末节,不过相信读者都能够通过自己的实践了解到这些内容。由于个人的关注点和精力有限,本文不可避免的会出现一定的错误,欢迎大家指出哈。最后,感谢快手SRC的约稿,希望快手SRC越办越好。

38b6fc653368400f55a68e388d3687fc.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值