站在Java的视角,深度分析防不胜防的小偷——“XSS”

简介: 站在Java的视角,深度分析防不胜防的小偷——“XSS”

1你的网站存在XSS漏洞!


yrzx404这两天比较闲,说我们给小伙伴们来写一个用来提建议的网站吧,能让小伙伴第一时间将想要说的话反馈给我们,并且所有小伙伴都可以看到其他小伙伴提出的建议。这还不简单,就一个单页网站,再结合CRUD就可以搞定,那这么简单的任务就分配给znlover那家伙去搞吧。那znlover是如何实现这个小网站的?说来有一套,znlover采用了spring-boot+jpa+thymeleaf技术栈不到半个小时就搞定了,虽然界面简陋,但功能基本完成了,界面如下:


image.png

东哥看到这个网站后,测试了5分钟,说“你这个网站不安全,有XSS漏洞!”。XSS漏洞?一个留言板,怎么会存在漏洞,znlover十分不解。通过查看东哥的留言,发现确实网站的运行状态不正常了,现在一打开留言网站,就会弹出一个提醒框:


image.png

这是什么鬼?html就没有使用过alert函数啊,怎么会有弹框?通过数据库查询,发现东哥输入的留言是这样的:


image.png


2FXSS漏洞攻击原理


首先我们来看一下造成XSS漏洞攻击的原因,获取留言与展示留言的前端代码如下:


image.png


image.png


可以看到,前端通过ajax向后台异步请求json数据,然后通过字符串拼接成一个table DOM的方式来实现留言显示,这是一种很常见也很常规的前后端数据交互的代码写法,在正常情况下是不会有问题的。但与SQL注入的原理本质相同,问题就出现在HTML代码与用户的输入产生了拼接,这就为恶意漏洞利用者提供了代码执行的机会。正如在上一节中,yrzx404输入的留言是一段合法的javasrcipt代码,在通过拼接后生成的的html页面,浏览器就会将其解析成可执行的javasrcipt代码进行执行,因此造成了XSS跨站脚本攻击(Cross Site Scripting),造成XSS执行拼接后的Html片段如下:


image.png

所以,XSS漏洞的执行本质上与很多漏洞的造成原因相同,都是由于“数据与代码未严格分离”,前端将用户的数据当做代码来执行了。


3FXSS漏洞的危害



XSS漏洞是在客户端执行,如果XSS攻击发生在访问量很大的页面,那将会是很严重的安全事件。试想,如果一个门户网站被小黑客利用XSS搞了个弹框恶作剧,那将会极大的损害公司的声誉与口碑,为公司带来无形的损失。如果仅仅是恶作剧,可能只是一次是不成熟的白帽行为,想借此提醒开发者网站存在漏洞,请尽快修补。但往以获取用户数据为目的黑客,会很隐蔽地收集用户的隐私数据,cookie,详细的用户主机信息,最严重的是进行种网马。这将会使我们的用户处于极其不安全的环境中,这也是为什么XSS漏洞攻击常年在OWASP榜首的位置。这里我们来看看黑客通过XSS获取用户cookie的恶意脚本:


image.png

上面js脚本构造一个<img> DOM,并通过document.cookie获取到了用户当前会话的cookie并藏在了img标签的url中,这样该页面被浏览器加载后便会带着用户的cookie去某一服务器访问图片了。黑客只需简单搭建一个Http服务器,看访问日志即可收货偷来的cookie:


image.png



我们知道,cookie是网站服务器用于与客户端保持会话与身份认证的关键属性,一旦黑客获取到了用户cookie,往往意味着黑客同时获取到了客户当前会话的访问权利,从而可以不用登陆验证便可进入用户的系统,这太危险了!

4FCookie的防御HttpOnly


为了解决XSS攻击漏洞会造成cookie被劫持攻击的问题,微软在IE 6开始支持Cookie HttpOnly标准,HttpOnly的作用是,如果在Http Response中,使用HttpOnly来标识的Cookie在浏览器中将无法被JavaScript访问,也就是说document.cookie就失效了。从Java EE 6.0开始,便支持通过Cookie.setHttpOnly(true)来设置HttpOnly类型的Cookie,代码如下:

image.png


此外还可以直接在WEB-INF/web.xml中将Session相关的Cookie添加HttpOnly标记,代码如下:

image.png


可以看到,我们的XSS Payload已经无法通过获取到用户的cookie了:

image.png


如今基本所有公开浏览器都对HttpOnly提供了支持,可以如此高效简单的防御一个web安全问题的手段可真不多见,真可谓四两拨千斤,但悲哀的是HttpOnly标准出现了15年了(2002年制定),但清楚知道其作用的网站开发人员却并不多。

5F前端XSS防护


既然XSS漏洞造成原因是由于执行了用户输入数据造成的,那么最直接的防御策略就是对用户的输入进行处理,将有可能造成XSS攻击的字符进行转义,这样就可以防止恶意XSS数据在浏览器中解析成合法的JavaScript脚本来执行。这里我们将留言进行敏感字符转意。作者这里使用了一个开源的用于XSS过滤转义的javascript库 -- js-xss,其支持以npm bower的方式依赖引入,在其github主页有详细安装与使用方法介绍。js-xss库提供了一个非常简单方便的XSS过滤转义函数filterXSS(),我们直接用它来对提交的留言进行过滤处理,代码如下:


image.png


此时,我们在将XSS Payload提交测试,可以发现浏览器没有触发XSS执行,因为js脚本确实被转义了:


image.png


这里filteXSS函数将敏感的括号尖括号等字符进行了转义,因此浏览器解析时XSS Payload就失效了。此外,通过测试,用来偷Cookie的XSS Payload也同样失效了。OK,防御策略小有成效,值得庆祝,产品可以上线了!但真的没有问题了吗,这样防御真的可以解决XSS攻击吗?


6F我们真的可以相信前端吗?


在上一节我们通过将用户的输入内容使用js-xss进行编码转义,便达到了防止用户输入恶意脚本的效果,但是我们能确保向服务器提交的数据一定是通过网站前端正常逻辑进行提交的吗?显然不能,如果黑客通过分析浏览器向服务器提交留言请求的Http数据包格式,手工构造向服务器留言的Http请求数据包,那就绕过了网站前端的XSS过滤逻辑,这里我们模仿黑客通过PostMan来向网站提交留言:

image.png


不出所料,留言提交成功了,打开网站前端,可以看到XSS Payload成功执行。

前端绕过问题,是一个具有普遍性的安全问题,这里安全不仅仅是指网络攻防安全,更多的情况是发生在业务安全中。作者曾接手过一个项目就是这样,系统中有一个类似消费转账的功能,既然是消费,那余额肯定应该是越消费越少,最起码消费金额不能是负数。网站前端对消费金额进行了数字,正负数和金额范围的校验,从而保证用户的消费金额一定是一个合法有效的数字。但是后端接收订单的接口却没有对消费金额的合法性进行判断,导致用户可以绕过前端向接口提交负数的消费金额的问题,用户的余额可以越花越多!虽然这个业务安全漏洞没有被非法利用,但是却为档次参与该项目的开发人员敲响了警钟,一切我们无法保证来源的输入,都应该校验

回归XSS防御的主题,既然我们不能依赖前端过滤,那还有必要在前端进行XSS的防御吗?作者认为,还是有必要的,一方面可以防御DOM Base类型的XSS;另一方面,从网站业务的角度来说,在前端对用户的输入进行合法性校验,可以避免合法用户误操作的问题,在一定程度减轻了服务器的请求压力。


7F依赖Thymeleaf模板


作者在开发该网站的过程中使用了thymeleaf模板作为前端view层,那么我们一起来看看thymeleaf对于XSS的防御效果如何。这里前端不再通过ajax异步请求的方式获取历史留言,而是采用务器端渲染,直接使用ModeAndView向页面传值:


image.png


现在进行XSS攻击测试,依然使用alert XSS Payload进行留言,可以发现XSS并没有触发执行,反而被按照正常的字符串显示出来了,打开控制台,可以发现XSS被转义了:


image.png


thymeleaf模板在对th:text标签进行渲染的时候,默认对于特殊字符进行了转义处理,这很符合“Security by Default”的安全原则。但是thymeleaf同时也提供了不转义的文本标签th:utext,使用th:utext将会按照数据原有的格式进行渲染,在页面拥有XSS漏洞情况下,依然会有HTML代码拼装的问题,所以这里需要大家在开发与审计过程中要多多留意,能不使用th:utext的地方尽量不要使用,如果必须使用,也要结合具体业务综合考虑此处XSS安全防御的问题。

即便如此,作者还是认为将安全问题交由公用框架还是相对靠谱的SDL(安全开发生命周期),结合当下很多公司采用前后端完全分离的技术框架,您可能会问,如果我们没有使用模板怎么办?前端可以考虑使用angular、vue等框架来构建。总之,一个原则就是尽量依赖专家代码(虽然并不能百分百保证安全)。


8FOWASP ESAPI企业级防护


OWASP中的ESAPI项目是专为解决web应用程序安全问题的开源项目,是由安全专家写的专家代码,很多著名公司都使用了ESAPI来为网站进行安全加固,ESAPI并不仅仅只提供了对java语言的支持,还提供了很多其他语言的版本库,但对java语言的支持是最完善的。java开发者可以很容易的将ESAPI应用入现有的项目。ESAPI Java项目大多以静态方法的方式提供接口,这里我们使用ESAPIencoder模块对留言的输入进行编码转义:


image.png


在实际项目中这样处理会存在一个问题,我们持久化的数据实际是被转义处理后的数据,并非用户的实际输入数据,会造成存储与实际输入不一致的问题,因此可以不在留言输入的接口中做编码,可以在输出接口中对留言做编码,也同样达到了防御XSS的效果,并且保证了数据的一致性。此外,ESAPI还有很多有用的解决web安全的功能,作者以后会陆续推出有关ESAPI使用的文章。


9F关于富文本编辑器的处理


在网站的一些业务需求中,往往需要允许用户上传具有自定义样式的文本,例如广告、文章、公告等,而这些具有样式的文本就是富文本,实际上富文本就是一段HTML代码,因此浏览器可以无缝对其提供支持,为用户提供了极大的方便。但富文本的特性也使其成为了XSS攻击的重灾区,因此必须对其防范。关于富文本的XSS防范,我们不能简单的采用前文的方法将输入进行转义,否则转以后的富文本将无法被浏览器渲染。那应该这么办?


处理富文本时,要严禁对任何JavaScript事件的支持的,因为在一般情况下,富文本的展示中不应该包含JavaScript事件这种动态效果。此外我们应考虑将一些敏感标签过滤掉,例如<script>、<iframe>、<base>、<form>等不应该出现在富文本中的HTML标签。此外在富文本中对于CSS的过滤也是件很麻烦的事情,需要检查其中是否包含恶意代码。对于威胁的监测,我们需要借助Html解析来进行识别过滤,好在对于富文本的防御过滤,OWASP开源了一个非常棒的项目Anti-Samy


image.png


OWASP ESAPI中的validator模块下 HTMLValidationRule 便是直接引用了AntiSamy,因此如果项目中已近引用了ESAPI,那么可以很方便的对富文本进行过滤:


image.png


10F 关于源码


应广小伙伴的要求,本文所涉及的示例代码都已上传至公众号专用代码仓库,看一遍不如写一遍,有兴趣的小伙伴可以去阅读原文去下载


此外关于XSS的攻击,还有很多绕过技巧,感兴趣的小伙伴可以阅读以下文章:


XSS学习笔记【一】

XSS学习笔记【二】


小结


作为抛砖引玉之文,本文并无法覆盖到了XSS防御的方方面面,意在让web开发者重视XSS漏洞的问题。具体的防护方案还需要考虑系统的方方面面,此外,本文只探讨了基于HTML页面的存储型XSS的攻击原理,XSS攻击并不仅仅只发生在html页面中,CSS、Flash等也有可能存在XSS漏洞,相对于HTML更加隐蔽,不易被发现,限于本文篇幅已经过长,剩余的内容将会在以后的文章中来展现,尽情支持和与关注。


相关文章
|
13天前
|
数据采集 存储 弹性计算
高并发Java爬虫的瓶颈分析与动态线程优化方案
高并发Java爬虫的瓶颈分析与动态线程优化方案
|
2月前
|
安全 Java 编译器
new出来的对象,不一定在堆上?聊聊Java虚拟机的优化技术:逃逸分析
逃逸分析是一种静态程序分析技术,用于判断对象的可见性与生命周期。它帮助即时编译器优化内存使用、降低同步开销。根据对象是否逃逸出方法或线程,分析结果分为未逃逸、方法逃逸和线程逃逸三种。基于分析结果,编译器可进行同步锁消除、标量替换和栈上分配等优化,从而提升程序性能。尽管逃逸分析计算复杂度较高,但其在热点代码中的应用为Java虚拟机带来了显著的优化效果。
59 4
|
2月前
|
机器学习/深度学习 安全 Java
Java 大视界 -- Java 大数据在智能金融反洗钱监测与交易异常分析中的应用(224)
本文探讨 Java 大数据在智能金融反洗钱监测与交易异常分析中的应用,介绍其在数据处理、机器学习建模、实战案例及安全隐私等方面的技术方案与挑战,展现 Java 在金融风控中的强大能力。
|
3月前
|
存储 Java 大数据
Java 大视界 -- Java 大数据在智能家居能源消耗模式分析与节能策略制定中的应用(198)
简介:本文探讨Java大数据技术在智能家居能源消耗分析与节能策略中的应用。通过数据采集、存储与智能分析,构建能耗模型,挖掘用电模式,制定设备调度策略,实现节能目标。结合实际案例,展示Java大数据在智能家居节能中的关键作用。
|
4月前
|
数据采集 搜索推荐 算法
Java 大视界 -- Java 大数据在智能教育学习社区用户互动分析与社区活跃度提升中的应用(274)
本文系统阐述 Java 大数据技术在智能教育学习社区中的深度应用,涵盖数据采集架构、核心分析算法、活跃度提升策略及前沿技术探索,为教育数字化转型提供完整技术解决方案。
|
4月前
|
Java 数据库连接 API
互联网大厂校招 JAVA 工程师笔试题解析及常见考点分析
本文深入解析互联网大厂校招Java工程师笔试题,涵盖基础知识(数据类型、流程控制)、面向对象编程(类与对象、继承与多态)、数据结构与算法(数组、链表、排序算法)、异常处理、集合框架、Java 8+新特性(Lambda表达式、Stream API)、多线程与并发、IO与NIO、数据库操作(JDBC、ORM框架MyBatis)及Spring框架基础(IoC、DI、AOP)。通过技术方案讲解与实例演示,助你掌握核心考点,提升解题能力。
172 2
|
传感器 分布式计算 安全
Java 大视界 -- Java 大数据在智能安防入侵检测系统中的多源数据融合与分析技术(171)
本文围绕 Java 大数据在智能安防入侵检测系统中的应用展开,剖析系统现状与挑战,阐释多源数据融合及分析技术,结合案例与代码给出实操方案,提升入侵检测效能。
|
5月前
|
缓存 安全 Java
【高薪程序员必看】万字长文拆解Java并发编程!(3-1):并发共享问题的解决与分析
活锁:多个线程相互影响对方退出同步代码块的条件而导致线程一直运行的情况。例如,线程1的退出条件是count=5,而线程2和线程3在其代码块中不断地是count进行自增自减的操作,导致线程1永远运行。内存一致性问题:由于JIT即时编译器对缓存的优化和指令重排等造成的内存可见性和有序性问题,可以通过synchronized,volatile,并发集合类等机制来解决。这里的线程安全是指,多个线程调用它们同一个实例的方法时,是线程安全的,但仅仅能保证当前调用的方法是线程安全的,不同方法之间是线程不安全的。
89 0
|
5月前
|
Java 程序员
【高薪程序员必看】万字长文拆解Java并发编程!(3-2):并发共享问题的解决与分析
wait方法和notify方法都是Object类的方法:让当前获取锁的线程进入waiting状态,并进入waitlist队列:让当前获取锁的线程进入waiting状态,并进入waitlist队列,等待n秒后自动唤醒:在waitlist队列中挑一个线程唤醒:唤醒所有在waitlist队列中的线程它们都是之间协作的手段,只有拥有对象锁的线程才能调用这些方法,否则会出现IllegalMonitorStateException异常park方法和unpark方法是LockSupport类中的方法。
92 0
|
5月前
|
人工智能 Java
Java参数传递分析
本文详细探讨了Java中参数传递的机制,明确指出Java采用的是值传递而非引用传递。通过基本数据类型(如int)和引用类型(如Map、自定义对象People)的实例测试,证明方法内部对参数的修改不会影响原始变量。即使在涉及赋值返回的操作中,表面上看似引用传递,实际仍是值传递的结果。文中结合代码示例与执行结果,深入解析了值传递的本质及容易引起混淆的情形,帮助读者准确理解Java参数传递的核心概念。