Catalyst

前端安全(XSS & CSRF)

随便了。

XSS 攻击

定义

XSS(Cross Site Scripting,跨站脚本)攻击。在页面中插入恶意代码,在运行时攻击。

主要分为反射型(修改 URL),存储型(上传到数据库,从数据库中提取返回时运行)。重点在于处理用户输入。

防御

  • X-XSS-Protection

HTTP 响应头中的 X-XSS-Protection属性 (MDN非规范)。当检测到 XSS 攻击时,浏览器停止加载页面。

语法:

X-XSS-Protection: 0 //禁止xss过滤
X-XSS-Protection: 1  //开启(默认)
X-XSS-Protection: 1; mode=block //检测到攻击,阻止加载
  • Content-Security-Policy

HTTP 响应头中的 Content-Security-Policy属性(MDN)。控制页面能加载哪些资源。

语法:

//在 http header 上使用
Content-Security-Policy: <策略>; <策略>

//在 html 上使用
<meta http-equiv="content-security-policy" content="<策略>; <策略>">

举例:

所有资源均来自当前域名并使用 https 加载

Content-Security-Policy: default-src https:

如果 script-src 设置了unsafe-inline,则可以执行页面内的内联代码。

扩展阅读:Content Security Policy 入门教程

  • X-Content-Type-Options

此响应头提示客户端一定要遵循文件标识的 MIME 类型,禁用了客户端的 MIME 嗅探行为。

X-Content-Type-Options: nosniff
  • 对用户输入进行转义。

常见转义符号:

符号转义
<&lt;
>&gt;
&&amp;
"&quot;
'&apos;

使用正则

function escape(input) {
  const sheet = {
    "<": "&lt;",
    ">": "&gt;",
    "&": "&amp;",
    '"': "&quot",
    "'": `&apos;`,
  };
  return input.replace(/(['"<>&])/g, (c) => sheet[c]);
}

或者使用 div 的 innerText的方法:

function escape(input) {
  let div = document.createElement("div");
  div.innerText = input;
  return div.innerHTML;
}

CSRF 攻击

定义

CSRF(Cross-site request forgery,跨站请求伪造)。在钓鱼网站利用用户的登录凭证(cookie 等)冒充用户进行操作。

防御

  • 对请求网站的限制

判断请求头中的Referer

  • Token

Token是在服务器端生成的验证。可以设置每次请求都需携带特定的Token

session 和 token

  • session由服务端生成,保存在服务端。
  • token由服务端生成,存储在客户端。客户端请求时在请求头里携带token,服务端只需验证返回的token是否合法。

扩展:同源策略

同源策略是浏览器的一个安全功能,即默认(未授权情况下)只执行来自同一个源(协议域名端口都相同)的资源。

如果进行跨域操作,通常:

  • 写(链接,重定向,表单提交等):允许
  • 资源嵌入(CDN, img)等:允许
  • 读:不允许
  1. 请求非同源情况下,服务器返回结果,响应头中没有Access-Control-Allow-Origin相关(=CORS),则浏览器拦截。参考:跨源资源共享(CORS)
  • Access-Control-Allow-Origin:请求返回的响应头中含有Access-Control-Allow-Origin: *则表示资源可以被任意不同源域访问。或者可以Access-Control-Allow-Origin: http://web.com 只允许来自 http://web.com 的访问。
  • Access-Control-Allow-Methods: 用于预检请求的响应,其指明了实际请求所允许使用的 HTTP 方法。
  • Access-Control-Allow-Headers: 用于预检请求的响应,其指明了实际请求中允许携带的首部字段。

通常,简单操作(GET,POST,HEAD及常见的content-type)直接向服务器发送请求,其他复杂操作则浏览器会先向服务器发送请求(预请求 preflight,方法为OPTIONS)询问服务器对 CORS 的支持,返回的Access-Control-Allow-Headers中允许该方法时再发送真正的请求。所以,服务器也要相应的做对OPTIONS方法的处理。

  1. 可以使用<script>脚本 src 不检测跨源的特性绕过同源策略。 = jsonp,将数据填入回调函数。(只适用GET请求)。 示例:

    <script src="www.domain.com/api?callback=cb">
    
    function cb(data) {
      console.log(data);
    }
    

    服务器脚本内容是cb(data)。也就是本地定义函数,服务器调用

  2. WebSocket不遵循同源策略。XMLHttpRequestFetch API遵循。

参考:浏览器的同源策略