Java Web 工程源代码安全审计实战,第 1 部分: 跨站 XSS
Java Web 运用安全问题日益严峻。源代码审计能够防备于未然。源代码审计人员要经过实战审计练习,才干熟练掌握 Java Web 源代码安全思路和技巧。
前语
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:输入<script>alert('Hacked.')</script>。
调查弹框呈现。弹框脚本的成功履行证明页面存在跨站缝隙。
图 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 文本框输入"<script>alert('Hacked.')</script>"点击提交按钮。污染数据存入后台数据库。进犯完结。
图 12. 存储跨站进犯场景
受害者发动一个新浏览器,在左边导航目录下点选" Stored XSS Attacks", 在页面上找到并点击" anyTitle"字样超链接,调查弹框呈现。证明页面存在履行歹意脚本的才能。
处理方案
快速修正
处理 WebGoat 工程的反射跨站问题,能够在 ReflectedXSS.java 第 75 行运用 WebGoat 自完结的 HtmlEncoder.encode() 对污染数据编码处理后再输出。代码片段如下:
图 13. 整改反射跨站的代码
相似的,处理 WebGoat 工程的存储跨站问题,能够在 StoredXSS.java 运用以下代码片段:
图 14. 整改存储跨站的代码
整改代码编译布置后,WebGoat 出产环境的进犯场景不再呈现。
以上代码的整改思路是”输出编码”。对输出到客户端的字符串进行编码能够使体系愈加安全。
将“<”编码为“<”,“"”编码为“"”,这样”<script>”保存后终究存储的会是:“<script>”;在展现时浏览器会对这些字符转换成文本内容<script>显现,而不是去履行一段可履行的代码。
除了“输出编码”,XSS 跨站的处理办法还有“输入验证和数据净化”。以下体系解说 XSS 各种处理方案。
触类旁通
XSS 跨站问题的底子原因是对输入参数处理不妥。处理思路有两条:“输入验证数据净化”和“输出编码”。
根据 HTTP 通信协议的 Web 运用中,服务器先接纳恳求,再应对恳求把字符串输出到客户端。对 XSS 跨站的防备应该布置在服务器输入和输出两个阶段。当服务器接纳输入恳求时,进行数据验证和净化。当服务器输出应对恳求时,对应对字符串进行编码。“输入验证”和“输出编码”能够独立施行,也可互为补充。
输入验证和数据净化
输入验证和数据净化一般运用过滤器,根据是非名单进行数据净化。运用过滤器有三点需求留意。
1. 首要着重过滤要在服务器端进行,客户端的验证简单被绕过。只需进犯者用抓包东西捕获从客户端发送到服务器的报文、修正并重放,就有或许进犯成功。在服务器端代码现已施行过滤的基础上,能够主张在客户端也能够进行过滤,屡次过滤的意图是削减服务器的负荷。
2. 其次要留意先标准化,然后再查验字符串。
由于不同版别 unicode 编码集的不同,所以同一个字符没有仅有的二进制表达,存在二义性。比方尖括号<>,在一种 unicode 版别中或许表达为“uFE64” “uFE65”, 在别的 unicode 版别或许表达为别的方式。
一般用 NFKC 格局对恣意编码的字符串进行标准化,消除二义性(当然还有 NFKD 标准化方式,总要选一种)。代码如下:
String s =“uFE64”+“script”+“uFE65”;
s = Normalizer.normalize(s, Form.NFKC);
pattern.matcher(s)
3. 还要留意过滤内容有必要充沛。依照安全权限最小化的思维,尽量运用白名单。由于黑名单罗列有限,挂一漏百。白名单能够结合事务逻辑进行编列,比方年纪字段只答应输入数字。假如事务逻辑不简单枚举白名单,只能经过黑名单过滤,那么要确保过滤内容的充沛,一级防备至少要过滤掉“<”、“>”、“'”、“"”和“”五个特别字符。代码如下:
Pattern patter = Pattern.compile(“<|>|’|”|”)
更深一步的防备能够考虑以下的内容:
过滤“<”、“>”将用户输入放入引号间,根本完结数据与代码阻隔;
过滤双引号,避免用户跨过答应的符号,增加自定义符号;
过滤 TAB 和空格,避免要害字被拆分;
过滤 script 要害字;
过滤 避免 HTML 特点绕过查看。
4 过滤规划要归纳考量功用要素,挑选屡次过滤或许单字符过滤。
首要认识到过滤的副作用,英语语义或许损坏,yours’ 会被过滤为 yours。其次有时需求屡次过滤,例如<scrip<script>t>过滤掉<script>后仍是<script>。需求留意多个过滤器的先后次第。当多个过滤器一同收效时,有或许后进行的过滤导致前面的过滤失效。例如过滤器 1 要过滤 ABC,过滤器 2 要过滤 DEF,那么 ABDEFC 在顺次经过 1,2 过滤器后变成了 ABC,这样相当于绕开过滤器 1。所以假如功用答应,要独自单字符过滤。
以上在服务器输入端进行整改。下面叙述在服务器输出端的整改办法。
输出编码 (Html encode)
以下三办法任选其一
1. 开发者自己完结编码输出,能够参阅 WebGoat 工程源码 HtmlEncoder.java,也能够扼要完结如下:
private String cleanXSS(String value) {
value = value.replaceAll("<", "& lt;");
value=value.replaceAll(">", "& gt;");
value = value.replaceAll("'", "& #39;");
// to be augmented..
return value;
}
2. 也能够运用 Apache 的 commons-lang.jar 供给体系库函数:
StringEscapeUtils.escapeHtml(str);
HTML 的输出编码是避免注入 XSS 的通用办法,除了 Java,其他言语都有供给对 HTML 的输出编码:
PHP 的 htmlentities() 或是 htmlspecialchars()。
Python 的 cgi.escape()。
ASP 的 Server.HTMLEncode()。
根据.net 开发的 Web 运用,体系库函数 AntiXss.HtmlEncode Java 的 xssprotect(Open Source Library)。
Node.js 的 node-validator。
3.WebGoat 是独立施行的 Web 运用。可是实际 Web 运用能够根据一些结构,比方 Spring Struts Hiberante。假如运用 Spring 结构进行 Java Web 开发,能够在 web.xml 文件中设置 HTML encode,在 JSP 文件页面元素 form 中确认施行。
web.xml 加上:
<context-param>
<param-name>defaultHtmlEscape</param-name>
<param-value>true</param-value>
</context-param>
forms 加上:
<spring:htmlEscape defaultHtmlEscape="true" />
纵深防护
除了通用的输入验证和输出编码防护思路。有些特定的页面元素,也有自己的防 XSS 特点设置。
1. 设置 cookie 的 HttpOnly 特点
XSS 一般被用于盗取 cookie 内容。在设置 cookie 时运用 HttpOnly 参数,约束 cookie 作为 DOM 方针存取。
2. 设置<frame>的 security 特点
IE6 今后的版别供给<frame>和<iframe>新的 security 特点,能够针对单个的 frame 或 iframe 设定 Restricted Sites,在 Restricted Sites 区块内将不支撑 scripts 语法的履行。代码片段如下:
<frame security="restricted"src="http://www.somesite.com/somepage.htm"></frame>
结束语
本文是 JavaWeb 工程源代码安全审计实战的第 1 部分,首要针对跨站进犯,解说审计逻辑,用 WebGoat 工程完结攻防演练。JavaWeb 工程源代码安全审计实战的第 2 部分,将审计 SQL 注入进犯,欢迎阅览。