首页 > 编程笔记 > Java笔记 阅读:1

XSS漏洞是什么,常见的XSS漏洞(非常详细)

跨站脚本(Cross-Site Scripting,XSS)是经常出现在 Web 应用程序中的一种计算机安全漏洞。

XSS 主要是由于 Web 应用程序对输入和输出过滤不足而产生的。攻击者可以利用这一漏洞把恶意的脚本代码(通常包括 HTML 代码和客户端 JavaScript 脚本)注入网页中。当其他用户浏览这些网页时,这些恶意代码就会被执行,进而进行 Cookie 信息窃取、会话劫持、钓鱼欺骗等各种攻击。

常见的XSS漏洞

XSS 漏洞大概可以分为 3 个类型:反射型 XSS 漏洞、存储型 XSS 漏洞和 DOM 型 XSS 漏洞。本节主要介绍这些漏洞产生的形式。

1) 反射型XSS漏洞

反射型 XSS 漏洞的利用一般是攻击者通过特定手段(如利用电子邮件),诱惑用户去访问一个包含恶意代码的URL。当用户点击这些专门设计的链接时,恶意 JavaScript 代码会直接在用户的主机上执行。这种类型的XSS 漏洞的特点是只在用户点击时触发,而且只执行一次,非持久化。

利用反射型 XSS 漏洞攻击的流程如下图所示:


图 1 利用反射型XSS漏洞攻击的流程

此类 XSS 漏洞通常出现在网站的搜索栏、用户登入口等地方,常用来窃取客户端 Cookie 或进行钓鱼欺骗。

下面是导致反射型 XSS 漏洞的示例代码:
<%
String id = request.getParameter("id");
out.println("id = "+id);
%>

正常访问 http://localhost:8080/reflective-xss.jsp?id=111,结果如下:

id = 111


从示例代码中可以看到,输出语句没有进行任何过滤就直接把用户的输入内容给输出了,因此可以构造如下恶意链接:http://localhost:8080/reflective-xss.jsp?id=<script>alert("xss")</script>。

当目标用户访问该链接时,服务器接受该目标用户的请求并进行处理,然后服务器把带有 XSS恶意代码的脚本发送给目标用户的浏览器,浏览器解析这段脚本后,就会触发反射型XSS漏洞。

访问恶意链接的结果如下图所示。


图 2 访问恶意链接的结果

2) 存储型XSS漏洞

存储型 XSS 漏洞和反射型 XSS 漏洞的原理是一样的,区别在于存储型 XSS 漏洞会把恶意脚本存储在服务器,每次访问内容都会有触发恶意脚本的可能,所以相比反射型 XSS 漏洞,存储型 XSS 漏洞的危害更大。

反射型 XSS 漏洞须构造恶意 URL 来诱导用户点击,而存储型 XSS 漏洞由于有效载荷已直接被写入服务器中,且不需要将有效载荷输入到 URL 中,往往可以伪装成正常页面,其迷惑性更强。因此,存储型 XSS 漏洞对于普通用户而言很难及时被发现。

利用存储型 XSS 漏洞攻击的流程如下图所示:


图 3 利用存储型XSS漏洞攻击的流程

下面是导致存储型 XSS 漏洞的示例代码:
<%@ page import="java.sql.*" %>
<%
String url = "jdbc:mysql://localhost:3306/test1";
String user = "root";
String password = "root";
Connection conn = null;
Statement statement = null;
ResultSet resultSet = null;
 
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection(url,user,password);
statement = conn.createStatement();
          String sqlQuery = "select * from message";
          resultSet = statement.executeQuery(sqlQuery);
          while(resultSet.next()){
             out.println("name: " + resultSet.getString("name"));
          }
%>

正常访问 http://localhost:8080/storage-xss.jsp,结果如下:

name: 111


下图所示为将恶意脚本存储到服务器的数据库中:


图 4 将恶意脚本存储到服务器数据库中

当其他用户浏览该页面时,站点即从数据库中读取恶意脚本,然后显示在页面中,如下图所示:


图 5 利用存储型XSS漏洞成功攻击

3) DOM型XSS漏洞

DOM 型 XSS 漏洞是基于 Document Object Model(文档对象模型)的一种 XSS 漏洞。

DOM 是一个与平台、编程语言无关的接口,它允许程序或脚本动态地访问或更新文档内容、结构和样式,处理后的结果能够直接显示在网页上。DOM 中有很多对象,其中一些是用户可以操控的,如 URL、location、referer 等。客户端的脚本程序无须依赖服务器,即可通过 DOM 动态地检查和修改页面内容。因此如果 DOM 中的数据没有经过严格确认,就会引发 DOM 型 XSS 漏洞。

下面是导致 DOM 型 XSS 漏洞的示例代码:
<script>
   var pos = document.URL.indexOf("#")+1;
   var name = document.URL.substring(pos, document.URL.length);
   document.write(name);
   eval("var a = " + name);
</script>

通过浏览器访问构造的恶意 Poc 链接(http://localhost:8080/DOM-xss.html#1;alert(/xss/))即可触发 DOM 型 XSS 漏洞,访问结果如下图所示:


图 6 访问http://localhost:8080/DOM-xss.html#1;alert(/xss/)的结果

DOM 型 XSS 漏洞常见的输入点和输出点如下。
输入点:

document.URL
document.location
document.referer
document.forms


输出点:

eval
document.write
document.innerHTML
document.outerHTML

XSS漏洞代码审计要点

根据前面的内容可知,XSS 漏洞是由于 Web 应用程序对输入和输出过滤不足而产生的。从 Web 应用程序来看,攻击者可以操控的参数包括 URL、POST 提交的表单数据,以及通过搜索框提交的搜索关键字。

因此,在对 Java 代码进行审计以挖掘 XSS 漏洞时,需要收集所有的输入点和输出点,并仔细检查输入点和输出点的上下文环境,判断 Web 应用程序是否对输入点和输出点做了过滤、扰乱或编码等工作。

XSS漏洞的防御方法

XSS 漏洞防御的总体思路是:对输入进行过滤,对输出进行编码。

1) 使用 XSS Filter

使用 XSS Filter 对用户提交的信息进行严格验证,仅接受指定长度范围内且格式合适的信息,阻止或忽略此外的其他任何信息。此外,还需要过滤和净化有害的输入信息。

2) 使用编码

HTML 编码在防御利用 XSS 漏洞进行攻击时可以起到很大的作用,它主要是用对应的 HTML 实体替代字面量字符,来确保浏览器能够安全地处理可能存在的恶意字符,并将其视为 HTML 文档的内容而非结构元素。

3) 对不可信数据进行JavaScript编码

此方法主要针对动态生成的 JavaScript 代码,包括脚本部分以及 HTML 标签的事件处理属性(如 onerror、onload等)。

在往 JavaScript 代码中插入数据时,只有一种情况是安全的,即对不可信数据进行 JavaScript 编码,并且只把这些数据放到使用引号括起来的值(data value)中。

4) 设置HttpOnly

利用 XSS 漏洞攻击的目的大多数是获取用户的 Cookie。如果我们将重要的 Cookie 标记为 HttpOnly,当浏览器向服务器发起请求时虽会带上 Cookie 字段,但在脚本中却不能访问 Cookie,从而防止利用 XSS 漏洞获取 Cookie。

相关文章