文章出处:https://www.ibm.com/developerworks/cn/java/j-lo-audit-xss/index.html
ava Web 工程源代码安全审计实战,第 1 部分
跨站 XSS
叶 林, 张 东升, 和 贺 新朋2015 年 11 月 02 日发布
WeiboGoogle+用电子邮件发送本页面
3
前言
Web 应用是互联网应用的重要形式,是金融、电信、政府部门等社会关键信息系统的门户应用首选。Web 应用的组件技术和支撑手段不断丰富变化。一般来讲分为使用 Java 的、使用 PHP 的和只使用 JavaScript 实现的三大类。其中的 Java Web 发展较早,所依托的 JEE 体系比较成熟,在企业级应用中比较常见。其中的 PHP Web, 因为 PHP 开发社区提供了很多优秀的论坛网站框架,所以在论坛网站开发中比较常用。而 JavaScript 通常用于浏览器的前端编程,近年其 Node.js 平台提倡在服务器端和客户端都使用 JavaScript,一时风行。传统的 Java Web 市场占有率较高,是本文讨论的对象。
Web 应用安全不容小觑。黑客对于 Web 应用的攻击热点,从早年的针对服务器系统平台,转到针对浏览器。因为寻找服务器上漏洞成本高,越来越难;而浏览器或者客户端的攻击技术,比如 SQL 注入、 跨站脚本 (XSS) 等技术门槛低,攻击成本低,相对容易实现,已显泛滥之势。WAP 防火墙虽然能根据内容过滤一些网络流量,但是如果所有进出的网络流量都需要在应用层上进行检测,系统性能和成本付出较大。对服务器配置 HTTPS,加密客户端和服务器之间的 HTTP 内容,虽然能保护信息隐私,但是还不足以单独对抗除了数据窃听之外的种类繁多的 Web 攻击。
提高 Web 信息系统的安全性一个有效手段是对系统源代码进行静态扫描。这样可以在系统代码上线、问题发生之前,检查系统可能存在的安全风险,防微杜渐,及时整改。
源代码审计是一个系统工作。针对 Java Web 的静态扫描工具很多,商用工具 Fortify 或者开源工具 Findbugs。各种工具并不健全,不同工具都具有不重复的功能,可以进行多种工具配合使用以获得更大的检验覆盖程度。同时,这些分析工具们产生的结果有可能包含误判或者漏判。这时还需要人工审计。开发人员要经过安全开发的训练,安全审计人员要经过审计训练,才能熟练掌握 Java Web 源代码安全审计方法。
“JavaWeb 工程源代码安全审计实战”系列基于著名的 Web 应用安全研究组织 OWASP 维护的 Java Web 开源项目 WebGoat,实战演练对整体工程的安全审计。按照漏洞严重从高到低程度,抽取几个审计结果展示。通过该系列可以了解以下几种高危漏洞的审计思路:跨站、SQL 注入、文件路径操纵和系统日志欺骗。
本文是 JavaWeb 工程源代码安全审计实战的第一部分,主要针对跨站攻击,讲解审计逻辑,用 WebGoat 工程实现攻防演练。
源代码审计概述
安全审计人员分析重点和思路都是围绕寻找 Source 和 Sink 展开。Source 是污染源,有害数据的入口点。Sink 是程序执行造成危害爆发部分。面对一个 Java Web 源码工程,审计人员:1)首先要在扫描工具的帮助下,初步了解所有的 Source(有文献也叫 Taint) 和 Sink;2)接下来追踪污染路径,确定 Source–Path–Sink ,逻辑再现攻击,避免工具的漏报误报;3)如果条件允许,可以进行漏洞利用开发,Web 渗透测试,真实攻击;4)对于定位出的源码漏洞,要提出整改意见;5)对修改后的源码进行二次审计,避免整改副作用。
工程目标
对 WebGoat 工程项目的源代码进行安全审核。WebGoat 是应用安全研究组织 OWASP 精心设计并不断更新的,专门设计用于展示各种 Web 漏洞的 Java Web 工程。涉及语言为 Java 和 JSP,也包含部分 JavaScript。涉及文件包括这些编程语言源码文件,也包括工程部署描述符和服务器运行环境配置文件。
审核源代码中的漏洞,包括能引发常见 Web 应用威胁的漏洞和基于语言缺陷的漏洞,并给出解决方案。审核环境配置文件,并给出安全加固建议。
漏洞类型
Web 应用威胁
Web 攻击和应用威胁种类繁多。早年间攻击者对服务器系统安置可执行文件,通过本地访问或远程访问这些文件,达到控制服务器目的。现在更倾向攻击客户端,因为技术门槛低,实施成本小。国际组织 OWASP 按危害程度排出前十名 Web 应用安全威胁,成为业内标杆参考。通过代码审计发现程序薄弱点后,整改这些薄弱点,可以对抗部分 Web 应用威胁。
表 1.OWASP Top 10 2013
Web 应用安全
威胁种类
威胁实施途径
导致结果
A1. 注入
(SQL 注入、OS 命令注入、XPATH 注入、LDAP 注入、JSON 注入、URL 注入)
页面输入,拼凑字符串,语句执行
代码逻辑依赖于外部输入,可导致不可预期的行为
A2. 失效的身份认证和会话管理
改变 cookie 内容
扮演成为其他用户身份
A3. 跨站脚本(XSS)
利用 URL 夹带/附加 JavaScript 执行脚本,嵌入木马代码
访问服务端敏感数据或者威胁客户本地安全
A4. 不安全的直接对象引用
URL 参数解码
猜测 URL 对象内容
A5. 安全配置错误
修改权限配置文件
越权访问修改执行,捣毁服务器或应用程序
A6. 敏感数据暴露
各种
不可预料的问题
A7. 功能级别访问控制缺失
文件路径操纵
捣毁服务器或应用程序
A8. 跨站请求伪造(CSRF)
诱骗点击恶意 URL
扮演成为合法用户身份
A9. 使用已知易受攻击组件
使用第三方组件,不注意维护
不可预料的问题
A10. 未验证的重定向和转发
登录页面跳转
用户密码泄露
Java 和 JSP 语言代码缺陷
能工作的代码并不代表好代码。编程语言天然的代码缺陷,易引导开发者犯错,造成程序不健壮,是代码审计的靶点。
部署描述符和生产环境配置问题
Java Web 应用工程部署并运行在服务器环境中,所以代码安全审计除了检查编程语言(Java, JSP,JavaScript)文件,还要检查应用和服务器的配置文件,对生产环境进行安全加固。
源代码审核结果综述
本次源代码审计工作共检查 WebGoat 工程代码行数 39,422 行,包括 Java(34,349 行), JavaScript(632 行)和 JSP(4441 行)。
共发现累计上百个代码缺陷。其中接近一半高危缺陷。具体情况如下表所示。
表 2. 源代码审计结果综述表
Web 应用威胁之跨站 (XSS)
技术原理
WebGoat 工程源代码有跨站的问题。跨站的本质在于执行脚本,让受害者浏览器执行攻击者设计的 JavaScript/Flash/Html 等。
跨站发生的条件有两个:1)来自不可信数据源的污染数据。在反射性跨站攻击中,污染数据来自页面请求。在存储型跨站中,污染数据来自服务器后台数据库。2)污染数据未经检验就被作为动态内容提交给用户浏览器执行。
问题分析之反射跨站 ReflectedXSS.java:187
源代码审计发现 ReflectedXSS.java 第 187 行 addElement () 方法向浏览器发送未经验证的数据,如果这个数据是来自攻击者的 JavaScript 代码,浏览器会执行攻击者命令。
本例中,完成一次完整的污染传播 Source-Path-Sink 三步骤如下:
ParameterParser.java 第 615 行使用 getParameterValues() 从网页 request 获取数据,代码片段如下:
图 1. 污染数据来自不可信任的数据源 (Source)
ReflectedXSS.java 第 597 行使用 getRawParameter() 传播污染数据,代码段如下:
图 2. 污染数据在程序体内部沿路径传播(Path)
ReflectedXSS.java 第 75 行使用来自污染源 field1 的数据对 param1 赋值,并用 param1 构造页面元素,代码段如下:
图 3. 污染源 field1 对 param1 赋值
点击查看大图
下图来自 Fortify 分析工具,红色箭头指示传播路径,右紫色框代表 Source,左红色框代表 Sink。
图 4. 污染数据传播路径图
SqlStringInjection.java 第 187 行 addElement () 使用了来自不可信数据源的污染数据构建页面元素,代码片段如下:
图 5. 污染数据被用来构造页面元素 (Sink)
至此污染源,路径,爆发点(Source-Path-Sink)确定。注意到污染数据在传播路径上,没有校验过滤过,满足技术原理中 XSS 攻击条件:1) 来自不可信数据源的污染数据;2) 污染数据未经检验就被作为动态内容提交给用户浏览器执行。代码审计逻辑上可以判断这是一个 XSS 漏洞。
攻击场景
在已部署的 WebGoat 工程,启动生产环境(WebGoat 工程使用见附录)。
在左侧导航目录下点选" Reflected XSS Attacks", 在右侧页面最下方的文本框 Enter your three digit access code:输入。
观察弹框出现。弹框脚本的成功执行证明页面存在跨站漏洞。
图 6. 反射跨站攻击场景
弹框脚本不具强大攻击力,但是其他恶意脚本可以作为系列高级可持续攻击 (APT) 的组成部分。比如先诱骗受害者访问攻击者构造的 html 页面元素 Image,而 Image.src 属性要求浏览器访问某个地址 (URL),该 URL 是恶意脚本读取受害者当前用户页面的 session、cookie 等敏感信息并动态拼接而成,形如 http://hacker.com&victomCookie=cookie。这些敏感信息被发送到攻击者可控制的 URL,被攻击者读取。在金融操作中,用户帐号、余额等敏感信息可以这样被泄露。
XSS 攻击永远不止步于弹框、收集页面 cookie 信息。XSS 的本质在于浏览器端执行脚本。有人甚至说 览 XSS is the New Buffer Overflow, JavaScript Malware is the new shell code”。这是类比传统对服务器的攻击手法:在服务器操作系统堆栈中用缓冲区溢出,改写程序返回地址的方法,把执行程序引向执行恶意代码。这种传统的针对服务器的攻击实施门槛高。XSS 攻击在受害者环境引导浏览器执行恶意代码。进而通过攻击用户本地电脑其他服务。跨站攻击实施门槛低,攻击力强大,需要认真审计源码,规避 XSS 漏洞。
以上审计分析的反射跨站,污染数据直接来自受害者浏览器页面请求 web request,攻击要临机操作,执行有难度。下面审计分析存储跨站。存储跨站的攻击者和受害者使用各自现场浏览器,执行攻击相对容易。
问题分析之存储跨站 StoredXSS.java:230
源代码静态扫描发现 StoredXSS.java 第 230 行 makeCurrent() 方法向浏览器发送未经验证的数据,如果这个数据是来自攻击者的 JavaScript 代码,浏览器会执行攻击者命令。本例中,完成一次完整的污染传播 Source-Path-Sink 三步骤如下:
StoredXss.java 第 218 行使用 executeQuery() 从数据库读取数据,代码片段如下:
图 7. 污染数据来自不可信任的数据源 (Source)
点击查看大图
本案例数据库是不可信任的数据源,因为进一步分析数据库发现数据来自未经校验的网页用户输入。
更进一步分析数据库的数据来源:
ParameterParser.java 第 615 行使用 getParameterValues() 从网页 request 获取数据,代码片段如下:
图 8. 从网页获取数据
StoredXss.java 第 97 行执行 getRawParameter() 从网页 request 获取数据,付给 message。第 110 行执行 execute(),向数据库写入 message 。代码片段如下:
图 9. 向数据库写数据
点击查看大图
观察数据传播过程,没有对写入数据的校验过滤。
从数据库中读取到的污染数据,在程序体内流转后到达爆发点,即红色框代表的 Sink。下图来自 Fortify 分析工具:
图 10. 污染数据在程序体内部沿路径传播(Path)
StoredXss.java 第 230 行 makeCurrent() 使用了来自不可信数据源的污染数据 results,构建页面元素,代码片段如下:
图 11. 污染数据被用来构造页面元素 (Sink)
至此污染源,路径,爆发点(Source-Path-Sink)确定。注意到污染数据在传播路径上,没有被校验过滤过,满足 XSS 攻击的两个条件:1) 来自不可信数据源的污染数据。2) 污染数据未经检验就被作为动态内容提交给用户浏览器执行。所以代码审计逻辑上可以判断这是一个 XSS 漏洞。被污染的数据存放在服务器数据库中。进一步推断这是存储型 XSS 漏洞。
攻击场景
在已部署的 WebGoat 工程,启动生产环境。(WebGoat 工程使用见附录)
模拟攻击者登录,在左侧导航目录下点选" Stored XSS Attacks", 在 Title 文本框输入" anyTitle", 在 Message 文本框输入""点击提交按钮。污染数据存入后台数据库。攻击完成。
图 12. 存储跨站攻击场景
点击查看大图
受害者启动一个新浏览器,在左侧导航目录下点选" Stored XSS Attacks", 在页面上找到并点击" anyTitle"字样超链接,观察弹框出现。证明页面存在执行恶意脚本的能力。
解决方案
快速修复
解决 WebGoat 工程的反射跨站问题,可以在 ReflectedXSS.java 第 75 行使用 WebGoat 自实现的 HtmlEncoder.encode() 对污染数据编码处理后再输出。代码片段如下:
图 13. 整改反射跨站的代码
类似的,解决 WebGoat 工程的存储跨站问题,可以在 StoredXSS.java 使用以下代码片段:
图 14. 整改存储跨站的代码
整改代码编译部署后,WebGoat 生产环境的攻击场景不再出现。
以上代码的整改思路是”输出编码”。对输出到客户端的字符串进行编码可以使系统更加安全。
将“<”编码为“<”,“"”编码为“"”,这样”