XSS攻击常识及实战

时间:2024-05-23 21:42:59

什么是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=小明
XSS攻击常识及实战
接着我们试着加载一个js脚本看看,访问:http://localhost:8080/jsp/user/xss_test.jsp?name=

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

实验二

大部分网站都会和数据库打交道,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输入信息
XSS攻击常识及实战
提交后跳转到user_insert_action.jsp,页面显示1,说明用户信息成功插入数据库
XSS攻击常识及实战
最后,访问user.jsp,XSS注入成功
XSS攻击常识及实战

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