web安全策略
web安全对iOS开发者来说重要吗?重要!APP中通常会使用很多web页面,例如广告、登录流程、闪屏,或者需要使用跨平台功能的时候。你可能在页面中仅仅一部分使用web,也可以整个页面都是webView,甚至做一个web app。因此web安全对于app来说非常重要。
来自web的安全攻击有以下几种:
- 跨域攻击
- 预测执行攻击
- 窗口控制攻击
本文将针对这三种攻击类型,给出安全防御措施。
安全传输
网络传输相信大家都很熟悉了,安全的传输能够保证接收到的数据来自可信任的站点,并且在传输工程中不会被篡改。安全传输是其它安全措施的基础,采取的措施包括:
- HTTPS和WSS(webSocket Secure)
- Http Strict Transport Security(HSTS)遵循HTTPS安全协议的web只能访问同样遵循HTTPS安全协议的内容,不能访问遵循HTTP不安全协议的内容。
- Upgrade-Insecure-Requests 请求头中添加这一项表示web支持更加安全的升级机制,服务器可以重定向到这个站点的安全版本。
- 使用cookie确保安全,cookie只能被安全的传输,例如千万不要把cookie放到粘贴板上
-
在app的info.plist文件中
Allow Arbitrary Loads in Web Content 这个开关一定要置为 NO!
跨域封锁
web的内容可以来自任何站点,例如,webView上的一张图片可以来自任何服务器,也可以从任意服务器上加载一个脚本或iframe。需要注意的是要当心来自其它服务器的资源。跨域的保护已经有20多年的历史,并且形成了基本原则--同源策略:只有和页面来源相同的脚本才会被该页面执行。例如iframe来自不同的域名,同源策略不允许加载这个iframe。仅仅靠同源策略还是不够的,还需要采取其它的防御措施。
1. Subresource Integrity
服务器可能会发生异常导致下发错误的资源使得web发生crash,但是开发者通常是知道所要请求哪个资源的,在脚本里面增加一个检查签名。如果签名匹配则认为是下发了正确的资源,如果不匹配仍然可以正常工作,此时尝试从页面的资源里查找或者从自己的服务器重新加载。这样做虽然降低了性能,但是提升了安全性。
window.framwork || // reload from own domain
2. Content Security Policy
HTTP response:
:status:200
Content-Security-Policy:
default 'self'; // No inline
script-src cdn.example;
frame-src social.example;
frame-ancestors news.example;
HTTP response的Header里面,default设置成自己,默认只能加载同源的资源;script-src和frame-src 分别指定可信任的脚本和iframe的来源;frame-ancestor设置成news.example,指定只有news.example可以iframe我们的web。
另外不使用inline属性的脚本也是一种防御措施,不使用inline脚本,只从文件加载脚本,这么做分离了逻辑和文件,更加安全。
3. HttpOnly cookies
HTTPOnly cookies作为一种安全措施,已经有至少15年的使用历史。在这之前script通过document.cookie这个强大的api能拿到文档的cookie,留下安全隐患。HTTPOnly cookies能够阻止这种情况,只允许HTTP请求访问cookie,禁止使用script访问cookie。它的使用方式很简单,只需要在HTTP response的Header里面加上HttpOnly这一项,如下
HTTP response:
:status:200
Set-Cookie:
auth = abc...123; HttpOnly;
4. SameSite cookies
在HTTP response的Header里面将SameSite cookies这一项设置为Strict,那么将不允许把cookie从一个域名发送到另一个域名。例如其他人的web里面嵌入了我们的web,如果我们的服务器HTTP response的Header里面SameSite cookies = Strict,那么其他人将无法使用他的cookie来访问我们的服务器。
HTTP response:
:status:200
Set-Cookie:
auth = abc...123; HttpOnly;
SameSite=strict
5. Cross-Origin-Resource-Policy
Cross-Origin-Resource-Policy是推出的新功能。之前web可以加载任意web中的资源,例如图片或者script。在HTTP response的Header里面将Cross-Origin-Resource-Policy这一项设置为Same,将不允许别人的web向我们的服务器请求图片或者script,但是我们自己的web可以。
HTTP response:
:status:200
Cross-Origin-Resource-Policy:Same
6. Cross-Origin-Window-Policy
Cross-Origin-Window-Policy也是新推出的功能。之前通过window.open这个强大的api,其他人的web可以在新窗口中打开我们域名下的web,通过一些手段可以修改我们的web,导航到攻击者指定的页面。在HTTP response的Header里面将Cross-Origin-Resource-Policy这一项设置为Deny,将阻止其他人修改我们web中的内容,当然别人仍然还是可以打开我们的web。Cross-Origin-Resource-Policy适用于希望使用post message 进行窗口间通信,但是不想让别人控制我们自己web内容的情况。
HTTP response:
:status:200
Cross-Origin-Window-Policy:Deny
常见的web攻击及防御手段
1. Cross-Origin Attacks
- Cross-Site Scripting
- Compromised CDN
- Cross-Site Request Forgeries
1. Cross-Site Scripting
例如我们的web里面有一个文本框,用户可以输入文字,如下图。假如攻击者注入了这么一段脚本,如果没有采取防御措施,那么我们web的cookie就会被盗取。
在HTTP response的Header中添加HTTPOnly这一项,就能阻止脚本访问文档的cookie,从而防御跨域脚本攻击。
另外一种防御手段是Content-Security-Policy,如下
HTTP response:
:status:200
Content-Security-Policy:
default-src 'self'; // No inline
Content-Security-Policy能保证拒绝加载外部来源的脚本,并且不使用inline属性的脚本,只从文件中加载脚本。
2. Compromised CDN
例如我们的web需要从某个外部资源装载一个framework,攻击者可能拦截这个请求,并把它重定向到自己的攻击脚本上,如下图
使用Content-Security-Policy中script-src这个属性可以指定信任的脚本来源,并且在引用资源的时候指定来源和校验签名,如下
在HTTP response中:
HTTP response:
:status:200
Content-Security-Policy:
default-src 'self';
script-src cdn.example;
在HTML中:
window.framwork || // reload from own domain
3. Cross-Site Request Forgeries
攻击者可能在自己的web中嵌入我们的web,然后向我们的服务器发起一个伪造的网络请求(使用的是攻击者网站的cookie),如下图
如果采取了防御措施,将HTTP response的Header里面的SameSite设置为strict,那么就会禁止攻击者网站的cookie发动到我们的服务器上面,如下
HTTP response:
:status:200
Set-Cookie:
auth=abc...123; SameSite=strict
2. Speculative execution attacks (Spectre)
防御措施有:
- WKWebView
- Content Security Policy
- HttpOnly cookies
- SameSite cookies
- Cross-Origin-Resource-Policy
Speculative execution 的定义:预测执行类似于批量执行条件判断语句,例如计算机大量执行"x是否会造成数组array越界"这条指令,就能推测出这个数组的长度,进一步推测出这个数组在内存缓冲区中的地址边界。利用缓冲区溢出这种攻击手段,可以向web中注入攻击脚本。当x超过数组边界的时候,本来应该执行越界的error回调,但是确取出了攻击脚本并执行,造成数据泄露。显然只靠同源策略是无法防御这种攻击的,因为攻击脚本和文档处在同一个域名下,并且在同一个线程中。
防御预测执行攻击的方法是确保web内容和其他iframe(例如攻击脚本)处在不同的线程中。
1. WKWebView
以Safari app为例,WKWebView会单独分离出一个NetWork线程用于处理添加cookie等逻辑,而且每个网页处在不同的线程当中,所以evil网页是无法通过预测执行攻击手段攻击我们的页面。而且因为NetWork线程也是独立的,所以evil网页也无法通过预测执行攻击手段拿到重要数据,例如cookie。
如果使用UIWebView,所有的web包括NetWork线程都在app的同一个线程中,所以是无法防御预测执行攻击手段的。
2. Content security policy
Content security policy的封锁功能是处于Network线程中,和web线程是分离的,因此可以防御预测执行攻击手段。
例如web要加载一个广告iframe,但是这个广告iframe被重定向到了一个攻击脚本,如果使用了Content security policy,如下,因为攻击脚本不在信任的frame-src里面,所以会禁止加载。还有一种情况,攻击者的web引入了我们的web,因为设置了frame-ancestors为none,所以会禁止攻击者网站引入我们的web,从而防御攻击。
HTTP response:
:status:200
Content-Security-Policy:
default-src 'self';
frame-src ad.example
social.example
frame-ancestors 'none'
3. HttpOnly cookies 和 SameSite cookies
HttpOnly cookies 和 SameSite cookies的封锁功能也是处于Network线程中,和web线程是分离的,因此可以防御预测执行攻击手段。HttpOnly cookies能够禁止攻击者通过脚本拿到cookie。SameSite cookies设为strict能够禁止cookie从一个域发送到另一个域。
4. Cross-Origin-Resource-Policy
Cross-Origin-Resource-Policy的封锁功能也是处于Network线程中,和web线程是分离的,因此可以防御预测执行攻击手段。Cross-Origin-Resource-Policy设置成Same能禁止攻击者的web加载我们网站的资源。
3. Window Control Attacks
Cross-Origin-Window-Policy
攻击者的页面可以通过window.open这个api在新的窗口打开我们的web,攻击者趁我们不注意的时候,把我们的页面导航到钓鱼页面,然后诱导用户填写用户名和密码,这样就窃取到了用户信息。把HTTP response Header里面的Cross-Origin-Window-Policy设置为Deny,能够禁止攻击者修改我们的web,这样攻击者就无法导航到钓鱼页面。
总结
每种安全措施防御的攻击类型
建议
- 使用安全的网络传输(例如https,wss)
- 设置Cookies为HttpOnly和其它安全选项
- 把UIWebView升级到WKWebView
- 测试防御措施是否生效,web是否仍然能正常工作。安全措施都具有一定的限制功能,因此测试web是否能正常工作非常重要。例如Content-Securityp-Policy的script-src白名单里少些了一个允许的域名,那么这个域名下的web就无法正常使用了。