Skip to content

XSS

概念

XSS (Cross Site Scripting),即跨站脚本攻击,是一种常见于 Web 应用中的计算机安全漏洞。恶意攻击者往 Web 页面里嵌入恶意的客户端脚本,当用户浏览此网页时,脚本就会在用户的浏览器上执行,进而达到攻击者的目的。比如获取用户的 Cookie、导航到恶意网站、携带木马等。

常见攻击方法

  1. 绕过 XSS-Filter,利用<>标签注入 Html/JavaScript 代码;
  2. 利用 HTML 标签的属性值进行 xss 攻击。例如:<img src="javascript:alert('xss')" />;(当然并不是所有的 Web 浏览器都支持 JavaScript 伪协议,所以此类 XSS 攻击具有一定的局限性)
  3. 空格、回车和 Tab。如果 XSS Filter 仅仅将敏感的输入字符列入黑名单,比如 JavaScript,用户可以利用空格、回车和 Tab 键来绕过过滤,例如:<img src="javas cript:alert(/xss/)" />
  4. 利用事件来执行跨站脚本。例如:<img src="#" onerror="alert(1)" />,当 src 错误的视乎就会执行 onerror 事件;
  5. 利用 CSS 跨站。例如:body {backgrund-image: url("javascript:alert('xss')" )};
  6. 利用字符编码,透过这种技巧,不仅能让 XSS 代码绕过服务端的过滤,还能更好地隐藏 Shellcode;(JS 支持 unicode、eacapes、十六进制、十进制等编码形式)
  7. 拆分跨站法,将 XSS 攻击的代码拆分开来,适用于应用程序没有过滤 XSS 关键字符(如<、>)却对输入字符长度有限制的情况下;
  8. DOM 型的 XSS 主要是由客户端的脚本通过 DOM 动态地输出数据到页面上,它不依赖于提交数据到服务器,而是从客户端获得 DOM 中的数据在本地执行。容易导致 DOM 型的 XSS 的输入源包括:Document.URLLocation(.pathname|.href|.search|.hash)Document.referrerWindow.nameDocument.cookielocalStorage/globalStorage

防御措施

原则不相信客户输入的数据 注意: 攻击代码不一定在 <script></script>

  1. 使用 XSS Filter

输入过滤,对用户提交的数据进行有效性验证,仅接受指定长度范围内并符合我们期望格式的的内容提交,阻止或者忽略除此外的其他任何数据。比如:电话号码必须是数字和中划线组成,而且要设定长度上限。过滤一些些常见的敏感字符,例如:< > ' " & # \ javascript expression "onclick=" "onfocus"过滤或移除特殊的 Html 标签。 例如: <script>,<iframe>,&lt;for <, &gt; for >, &quot for;过滤 JavaScript 事件的标签,例如 onclick=onfocus 等等。 输出编码,当需要将一个字符串输出到 Web 网页时,同时又不确定这个字符串中是否包括 XSS 特殊字符(如 < > &' " 等),为了确保输出内容的完整性和正确性,可以使用编码 HTMLEncode 进行处理。

  1. DOM 型的 XSS 攻击防御

把变量输出到页面时要做好相关的编码转义工作,如要输出到 <script>中,可以进行 JS 编码;要输出到 HTML 内容或属性,则进行 HTML 编码处理。根据不同的语境采用不同的编码处理方式。

  1. HttpOnly Cookie

将重要的 cookie 标记为 http only, 这样的话当浏览器向 Web 服务器发起请求的时就会带上 cookie 字段,但是在脚本中却不能访问这个 cookie,这样就避免了 XSS 攻击利用 JavaScriptdocument.cookie 获取 cookie

转义字符

javascript
function escapeHtml(str) {
  if (!str) return
  str = str.replace(/&/g, '&amp;')
  str = str.replace(/</g, '&lt;')
  str = str.replace(/>/g, '&gt;')
  str = str.replace(/"/g, '&quto;')
  str = str.replace(/'/g, '&#39;')
  str = str.replace(/`/g, '&#96;')
  str = str.replace(/\//g, '&#x2F;')
  return str
}

// use
escapeHtml('<script>alert(1)</script>')
// &lt;script&gt;alert(1)&lt;&#x2F;script&gt;

但是对于显示富文本来说,显然不能通过上面的办法来转义所有字符,因为这样会把需要的格式也过滤掉。对于这种情况,通常采用白名单过滤的办法,当然也可以通过黑名单过滤,但是考虑到需要过滤的标签和标签属性实在太多,更加推荐使用白名单的方式。 推荐使用 js-xss

CSRF

概念

CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack”或者 Session Riding,通常缩写为 CSRF 或者 XSRF,是一种对网站的恶意利用。

攻击原理

diagram1.jpg

CSRF 攻击的主要目的是让用户在不知情的情况下攻击自己已登录的一个系统,类似于钓鱼。如用户当前已经登录了邮箱,或 bbs,同时用户又在使用另外一个,已经被你控制的站点,我们姑且叫它钓鱼网站。这个网站上面可能因为某个图片吸引你,你去点击一下,此时可能就会触发一个 js 的点击事件,构造一个 bbs 发帖的请求,去往你的 bbs 发帖,由于当前你的浏览器状态已经是登陆状态,所以 session 登陆 cookie 信息都会跟正常的请求一样,纯天然的利用当前的登陆状态,让用户在不知情的情况下,帮你发帖或干其他事情。

防御措施

面试大白话

  1. 通过 referer、token 或者 验证码 来检测用户提交
  2. 尽量不要在页面的链接中暴露用户隐私信息
  3. 对于用户修改删除等操作最好都使用 post 操作
  4. 避免全站通用的 cookie,严格设置 cookie 的域

详细

验证码
原理:
CSRF攻击过程中,用户在不知情的情况下构造了网络请求,添加验证码后,强制用户必须与应用进行交互

*  优点:简洁而有效
*  缺点:网站不能给所有的操作都加上验证码
Referer Check
原理:
* 利用HTTP头中的Referer判断请求来源是否合法
* Referer首部包含了当前请求页面的来源页面的地址,一般情况下Referer的来源页就是发起请求的那个页面,如果是在iframe中发起的请求,那么对应的页面URL就是iframe的src

*  优点:简单易操作(只需要在最后给所有安全敏感的请求统一添加一个拦截器来检查Referer的值就行)
*  缺点:服务器并非什么时候都能取到Referer
        1.很多出于保护用户隐私的考虑,限制了Referer的发送。
        2.比如从HTTPS跳转到HTTP,出于安全的考虑,浏览器不会发送Referer
Anti CSRF Token
原理:把参数加密,或者使用一些随机数,从而让攻击者无法猜测到参数值,也就无法构造请求的 URL,也就无法发起 CSRF 攻击。

例子(增加token):
*  比如一个删除操作的URL是:`https://host/v1/user/crowd/delete?id=0530`
*  保持原参数不变,新增一个参数Token,Token值是随机的,不可预测
*  `https://host/v1/user/crowd/delete?id=0530&token=${getToken()}`

*  优点:比检查Referer方法更安全,并且不涉及用户隐私
*  缺点:
        加密
        1. 加密后的URL非常难读,对用户非常不友好
        2. 加密的参数每次都在改变,导致用户无法对页面进行搜索
        3. 普通参数也会被加密或哈希,将会给DBA工作带来很大的困扰,因为数据分析常常需要用到参数的明文

        token
        1. 对所有的请求都添加Token比较困难(解决方案:可以使用代理请求方法处理)

CSP

中间人攻击

点击劫持

概念

点击劫持是一种视觉上的欺骗手段。攻击者使用一个透明的、不可见的iframe,覆盖在一个网页上,然后诱使用户在网页上进行操作,此时用户将在不知情的情况下点击透明的iframe页面。通过调整iframe页面的位置,可以诱使用户恰好点击在iframe页面的一些功能性按钮上。

防御措施

javascript
1.X-Frame-Options HTTP响应头是用来给浏览器指示允许一个页面能否在`<frame>、<iframe>、<object>`中展现的标记

#### 有三个可选的值
1.  DENY:浏览器会拒绝当前页面加载任何frame页面(即使是相同域名的页面也不允许)
2.  SAMEORIGIN:允许加载frame页面,但是frame页面的地址只能为同源域名下的页面
3.  ALLOW-FROM:可以加载指定来源的frame页面(可以定义frame页面的地址)

2.禁止iframe的嵌套
if (window.top.location !== window.loaction) {
	window.top.location === window.self.location;
}

其他