网络安全

234 阅读3分钟

跨站请求伪造

英文全称Cross Site Request Forgery(CSRF),是一种冒充受信任用户,向服务器发送非预期的请求。例如可能在某个有权限访问的URL后加入恶意的参数实行攻击。

跨站脚本攻击主要的攻击手段是在网站注入恶意的客户端代码,获取到当前网站的用户私密信息从而进行攻击。而跨站请求伪造则是冒充已经受信任的用户来实现目的,方式略有不同。

一般通过以下方式来防御:

请求来源检查

检查请求来源是通过HTTP请求的头字段来实现:RefererOrigin。这两个字段不允许JavaScript对字段的值进行修改。

Origin只有在POST请求中才发送,和Referer不同的是,它也可以在HTTPS请求中存在。

如果在请求字段中都存在,那都需要校验,确定了请求的源头,那CSRF风险会大幅降低。

Origin: https://www.example.com:80
Referer: https://www.example.com:80

有时候会被问到GETPOST请求有什么区别?GET请求主要是获取资源,不会对资源进行修改;而POST请求会;当然你不按照标准,要用GET请求来修改资源,那也是可以实现的,只是存在一定的风险,像请求来源检查预防CSRF的字段只会在POST请求中。

使用CSRF令牌

在每一个会话中,服务器会发送一个令牌给客户端,当客户端请求服务端的时候,会通过表单或Ajax请求回传给服务器,服务器会检查令牌的真实性,是否过期,还有是否被篡改过,如果发生了类似情况,则令牌就会失效,请求则认为是不安全的。

只要CSRF令牌不能被伪造,并且在客户端发送给服务端的时候是安全的,那就可以大大降低CSRF的攻击。

跨站脚本攻击

英文全称Cross-site-scripting

根据开放式Web应用项目,XSS在2017年被认为是7种最常见的Web应用程序漏洞之一。

这种攻击的主要表现是攻击者在网站注入恶意的客户端代码,以此来突破网站限制,冒充被攻击者来实现自己的目的。

所以,为了防止跨站脚本攻击,我们大体可以从两个方面来预防:

  • 尽量不写那种会被攻击者利用的程序代码
  • 需要对执行的内容进行校验、净化

尽量避免的API

DOMParser API,它可以将parseFromString方法中的字符串内容加载到DOM节点上,相对于从服务器端加载结构化的DOM,这个方法是比较方便的,但有很严重的安全隐患。而通过document.createElement()document.appendChild()创建的DOM节点,则安全得多,虽然用起来可能更麻烦一点。

在SSR过程中,需要将标签属性值都拼装成字符串返回,例如:

value === '' ? ` ${key}` : ` ${key}="${escapeHtml(value)}"`

使用escapeHtml函数来转义也可以防止XSS攻击。

以下是一个在JavaScript中实现的escapeHtml函数实例:

function escapeHtml(str) {
  // 包含了字符到对应HTML实体的映射关系
  let escapeMap = {
    '&': '&',
    '<': '&lt;',
    '>': '&gt;',
    '"': '&quot;',
    "'": '&#39;',
    '/': '&#x2F;'
  }
  return str.replace(/[&<>"'/]/g, function(char) {
    return escapeMap[char];
  })
}

内容安全策略(CSP)

是一个安全配置工具。

允许我们以白名单的形式列出可以动态加载脚本的网站。并且默认情况下,CSP可以禁止任何内联脚本的执行,这样就很有效的防止了第三方攻击者注入的脚本执行。但需要注意的是,使用CSP的情况下,不要使用eval()函数,因为eval的传参是字符串,如果字符串内是可执行表达式的话,也会正常被执行。

<meta http-equiv="Content-Security-Policy" content="script-src https://www.example.com;">

字符串净化

字符串或类字符串虽然本身不是DOM结构,但有可能被解析成DOM节点。例如:

'<p>跨站脚本攻击XSS</p>'

这是个字符串,但如果赋值给innerHTML,则就是DOM节点了,而innerText就会做净化处理。

CSS净化

CSS净化主要指的是净化HTTP相关的CSS属性,或者只允许用户修改指定的CSS字段。