面向 JAVA 开发人员的 XSS(跨站点脚本)入门

跨站点脚本 (XSS) 攻击是针对受害者浏览器的恶意攻击。它注入攻击者创建的恶意脚本以窃取凭据、劫持用户会话或尝试在受害者的计算机上下载和安装其他恶意软件。它是网络上最常见的攻击之一。 来自浏览器的任何输入机制(包括表单和 URL 参数)都可用于插入有效负载,然后可以将其传输回浏览器。来自浏览器的任何输入都必须被视为潜在恶意。您可以使用 Reshift 免费扫描您的项目,以查找任何可能的跨站点脚本漏洞。 

XSS 影响

成功的跨站点脚本 (XSS) 攻击对基于 Web 的应用程序造成的若干影响。

这些包括:

  • 帐户劫持
  • 凭证收集
  • 远程命令执行
  • 敏感数据的暴露
  • 安装恶意软件

帐户劫持

这是 XSS 攻击的最坏结果。在这种情况下,XSS 攻击可以捕获用户会话 cookie,从而允许攻击者接管用户会话。一旦攻击者拥有会话,他们就可以更改有效用户可以做的任何事情,包括更改用户的帐户凭据以阻止所有者获得访问权限。或者,攻击者可以在用户不知情的情况下窃取甚至更改用户的数据。6

远程命令执行 (RCE)

远程命令执行 (RCE) 或命令注入是一种攻击,远程攻击者可以调用系统级命令。在这种情况下,代表用户执行的脚本的 XSS 交付然后可以根据支持框架(例如,将 PHP Backdoor 注入 WordPress)注入后门代码。13

凭证收集

另一种常用的 XSS 攻击机制会安装一个脚本,将毫无戒心的用户重定向到另一个站点,该站点似乎是他们所在站点的登录页面。只有经过仔细检查,用户才能确定他们正在查看的页面托管在攻击托管的站点上,并且看起来像他们所在的站点。进入恶意副本后,系统会提示用户输入其凭据。一旦受害者的凭据被获取,攻击者就可以登录用户的帐户、更改密码以及更改或公开敏感数据。12

敏感数据的暴露

一旦帐户被入侵,攻击者就拥有普通用户拥有的所有权限,包括访问他们的所有数据。根据敏感度,数据可能会出售给竞争对手、用于影响市场价格或在所有者不知情的情况下进行修改。

安装恶意软件

一旦攻击者控制了受害者的浏览器,安装恶意软件可能会出现多种情况。这些包括将受害者的计算机变成僵尸网络的奴隶,扫描受害者的网络,安装一个键盘记录器来记录每个键入的键,或者使计算机被用作进一步攻击的启动点

在 Java 中测试 XSS

开发人员对 XSS 的测试可以在开发期间执行,并且可以从黑盒(使用该功能)和白盒(审查代码)的角度进行。开发人员更加关注白盒。

开发人员测试可以包括:

  • 代码审查
  • 使用自动和手动辅助静态代码分析工具(查看reshift)
  • 识别不受信任的输入源
  • 识别从不受信任的来源到消费端点(接收器)的数据流
  • 确保从源到汇进行验证
  • 确保在传输到浏览器之前对来自不受信任来源的任何数据进行编码/转义

识别不受信任的输入

来自浏览器/客户端的任何内容都必须被视为不受信任,包括参数值、参数名称和 HTTP 标头。

输入参数值

经典的 XSS 攻击案例是输入的 HTTP 参数值由服务器处理、存储,然后在没有输入验证或输出编码/转义的情况下反射回浏览器客户端。

Java 特定的 XSS 示例

  • 服务器接收参数并返回 HTTP 请求的参数,并在响应的 HTML 中呈现。输入未验证,输出未编码或转义。

  • 预期的有效请求:

http://mysite.com?username=johnsmith
  • 恶意攻击: 
http://mysite.com?username=
  • 如果服务器直接在页面中渲染请求:


欢迎使用我们的 Web 应用程序


欢迎 <%= request.getParameter("username")%>


  • 如果服务器直接在页面中渲染请求:


欢迎使用我们的 Web 应用程序


欢迎 <%= request.getParameter("username")%>


  • 结果显示会话 cookie,表明该站点易受攻击。

  • 真正的攻击可以提供备用有效负载,通过将请求作为参数包含到另一台服务器来泄露会话 cookie,例如:

document.write('')

或者

  • 为了在 HTML 上下文中纠正这种反射型 XSS 攻击,我们的代码必须执行两件事。
    • 第一次输入验证(对于有效的用户名)和
    • 其次,在呈现它的上下文中显示之前,对这个不受信任的源进行编码。
  • 要执行输入验证,
    • 确定所有用户名必须遵守的预期字符。字符集,大写,小写,数字。确定强制格式并添加代码以确保提供的用户名与该格式匹配
      • 例如 /^[A-Za-z0-9]+(?:[ _-][A-Za-z0-9]+)*$/,假设用户名只能包含 ASCII 字母和数字,连字符、下划线和空格作为内部分隔符
    • 如果输入的格式有效,请确认系统中存在使用该用户名的用户?
  • 最后,在文档中呈现之前对输入进行编码,下面显示了 HTML 上下文的编码:


  Welcome to Our Web Application


Welcome <%= ESAPI.encoder().encodeForHTML(request.getParameter("username")) %>

存储型 XSS

  • 攻击载荷作为不受信任的输入提供,与反射 XSS 相同,但是服务器将攻击载荷存储在其后端数据库中
  • 例如,如果网站在 Web 表单中有评论部分怎么办。当用户单击提交时,HTML 可能如下所示:
POST /article/comment HTTP/1.1
Host: yourserver.com
Conent-length: 50

comment=I+like+your+website
  • 然后,每当访问者查看评论页面并构建呈现信息的页面时,服务器都会检索此评论。


  Welcome to Our Web Application


  
I like your website
  • 但是,如果攻击者提供此评论怎么办:
POST /article/comment HTTP/1.1
Host: yourserver.com
Conent-length: 50

comment=%3C%2Fdiv%3E%3Cscript%3Ealert(document.cookie)%3C%2Fscript%3E
  • 这将呈现为:


  Welcome to Our Web Application


  
  • 浏览此评论的任何用户都会在他们的浏览器中运行该脚本
  • 为了在 HTML 上下文中纠正这种存储型 XSS 攻击,我们的代码必须执行两件事。
    • 第一次输入验证(对于有效的用户名)和
    • 其次,在呈现它的上下文中显示之前,对这个不受信任的源进行编码。
  • 要执行输入验证,
    • 确定您的输入必须遵守的预期字符。字符集,大写,小写,数字。确定强制格式并添加代码以确保提供的用户名与该格式匹配
      • 例如 /^[A-Za-z0-9]+(?:[ _-][A-Za-z0-9]+)*$/ ,假设评论只能包含 ASCII 字母和数字,连字符、下划线和空格作为内部分隔符
  • 最后,在文档中呈现之前对输入进行编码,下面显示了 HTML 上下文的编码
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {

  String comment = req.getParameter("comment");
  String encoded = ESAPI.encoder().encodeForHTML(comment);
   ..
}

DOM XSS

  • 在 DOM XSS 中,恶意内容通过修改浏览器的文档对象模型 (DOM) 环境中的内容来攻击受害者浏览器中的有效脚本。

  • 例如,也许有一个页面:

Choose your Region:
  • 普通用户可以输入预期值,例如:

http://www.thissite.com/page.html?default=APAC

  • 但是攻击者可以创建以下 URL 并将其发送给受害者并附上令人信服的消息:

http://www.thissite.com//page.html?default=

  • 与页面关联的脚本直接渲染攻击

  • 为了纠正 HTML 上下文中的 DOM XSS 攻击,我们的代码必须执行两件事。

    • 第一次输入验证(对于有效的用户名)和
    • 其次,在将其显示在渲染的上下文中之前,对这个不受信任的源进行编码。
  • 要执行输入验证,

    • 确定您的输入必须遵守的预期字符。字符集、大写、小写、数字等。确定强制格式并添加代码以确保提供的输入与该格式匹配
      • 例如,在这种情况下,期望是世界的特定区域,“EU”、“NA”、“SA”、“APAC”。在这种情况下,确保输入与有限列表匹配是微不足道的。
  • 最后,必须针对目标环境对不受信任的输入进行适当编码。由于这是一个影响 DOM 的目标,因此在插入 HTML 上下文之前,您必须 HTML Escape 和 JavaScript 转义不受信任的数据。29

在 Java 中预防和修复 XSS

修复和防止跨站脚本 (XSS) 攻击的通用最佳实践可以分为几类。类别不是非此即彼的解决方案,并且可以重叠以实现全面的深度防御。类别是:

  • 输入验证
  • 输出编码/转义
  • 内容安全政策
  • 安全标头
  • 使用现代 JS 前端
  • HTTPOnly Cookie 属性

输入验证

输入验证可用于防止多种不同的 Web 应用程序恶意攻击,包括 XSS。16 将所有外部输入视为不受信任,并验证接收到的数据是否已针对 已知良好语法和语义的白名单18进行测试。白名单优于黑名单。黑名单试图删除“已知的坏”字符(<、> 等),并且通常可以被顽固的有经验的攻击者破坏。正则表达式通常用于执行输入验证。

输出编码/转义

编码按照规则系统将数据从一种形式转换为另一种形式。 22 . 我们希望将 "dangerous characters" 可用于 XSS 攻击载荷的内容转换为安全的等价物。为了提供帮助,现有的安全编码项目专注于正确使用并避免与特定浏览器实现和晦涩的 javascript 规则相关的隐藏陷阱。

  • OWASP Java 编码器项目24
  • Microsoft 反跨站点脚本库23  ,它是 MS Web 保护库的一部分,
  • .NET 库 HTMLSanitizer 25 ](../References/Business-en.md)

应该避免创建自己的库,因为有许多与浏览器使用编码相关的复杂和深奥的规则,非专家可能会错过这些规则,这可能会导致漏洞。

请注意,根据数据插入响应页面的位置,正确的编码和转义是不同的。不同的上下文是:

  • HTML 上下文
    • 在普通 HTML 标记(例如 div)之间插入来自不受信任来源的数据
    • HTML 转义 &、<、>、“、' 和 /
  • HTML 简单属性上下文
    • 这种情况是指将来自不受信任的来源的数据插入到 HTML 标记的“简单”或“通用”属性中。这些不适用于下面列出的属性(如事件处理程序、src、href)
    • 确保所有属性都被引用(例如 name=”content”),因为没有引号的属性使攻击者更容易在页面中插入他们自己的 HTML(突破 HTML 上下文)
    • 对不受信任的数据进行编码,例如,使用 ESAPI encodeForHTMLAttribute 对给定的字符串进行编码,以便在 HTML 属性中使用安全输出28
  • HTML 事件处理程序上下文
    • 切勿将不受信任的数据放在事件处理程序中(例如,onmouseover)。尽管 HTML 编码可以防止 HTML 上下文中断,但 javascript 引擎仍将执行内容。

你可能感兴趣的:(java,xss,php)