JSP安全开发之XSS漏洞详解

XSS又叫CSS (Cross Site Script) ,跨站脚本攻击。它指的是恶意攻击者往Web页面里插入恶意脚本代码,而程序对于用户输入内容未过滤,当用户浏览该页之时,嵌入其中Web里面的脚本代码会被执行,从而达到恶意攻击用户的特殊目的。

前言

     大家好,好男人就是我,我就是好男人,我就是-0nise。在各大漏洞举报平台,我们时常会看到XSS漏洞。那么问题来了,为何会出现这种漏洞?出现这种漏洞应该怎么修复?

正文

1.XSS?XSS?XSS是什么鬼?

     XSS又叫跨站脚本攻击(Cross Site Scripting),我不会告诉他原本是叫CSS的,但是为了不和我们所用的层叠样式表(Cascading Style Sheets)CSS搞混。CSS(跨站脚本攻击),CSS(层叠样式表)傻傻分不清。所以就叫XSS咯。

2.XSS的危害是什么?

实验一:

0x00构造代码

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

<%@ 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 'index.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>

 <div style="margin: 0 auto">

 <%

//设置编码

   request.setCharacterEncoding("UTF-8");

//接收用户传入值

   String tmp = request.getParameter("opr");

   //减速传入值是否为空

   if(tmp == null){

     out.print("111");

   }else{

     //转码

     String opr = new String(tmp.getBytes("ISO-8859-1"),"utf-8");

     out.print(opr);

   }

 %>

   我是内容

 </div>

 </body>

</html>

0x01环境布局

0x02漏洞演练

我们访问:http://localhost:8080/XSS/index.jsp?opr=i%E6%98%A5%E7%A7%8B

然后访问:http://localhost:8080/XSS/index.jsp?opr=0nise

最后我们发现了一个“伟大的规律”:

   opr参数等于什么页面就打印什么。(好像是废话)

我们接着来加载一个图片看看

访问:http://localhost:8080/XSS/index.jsp?opr=%3Cimg%20src=%221.png%22%3E%3C/img%3E

既然图片都可以加载,那么我们JS文件是不是也阔以加载呢?

访问:http://localhost:8080/XSS/index.jsp?opr=%3Cscript%3Ealert(/i%E6%98%A5%E7%A7%8B%E7%A4%BE%E5%8C%BA%E6%AC%A2%E8%BF%8E%E5%A4%A7%E5%AE%B6/)%3C/script%3E

Js?Js?那么是不是可以来改变跳转后地址?

访问:http://localhost:8080/XSS/index.jsp?opr=%3Cscript%3Elocation.href=%27http://bbs.ichunqiu.com%27%3C/script%3E

既然xss都可以加载js,那么,我们是不是通过js来打开本地的某些东西?

提前放了一个MD5.exe文件

访问:http://localhost:8080/XSS/index.jsp?opr=<script> var objShell = new ActiveXObject("wscript.shell");objShell.Run("G:/work/XSS/WebRoot/Md5.exe");</script>

既然连本地文件都可以打开那么远程文件木马?来个电脑恶搞?这个自己慢慢象限。我可没说啊。。。。。

文件都可以打开,那么写一些文件呢?

访问:http://localhost:8080/XSS/index.jsp?opr=%3Cscript%3Evar%20fso,tf;fso%20=%20new%20ActiveXObject(%22Scripting.FileSystemObject%22);tf%20=%20fso.CreateTextFile(%22d:\\test.txt%22,true);tf.WriteLine(%22i%E6%98%A5%E7%A7%8B%E7%A4%BE%E5%8C%BA%E6%AC%A2%E8%BF%8E%E6%82%A8%22);tf.Close();alert(%22%E6%96%87%E4%BB%B6%E5%86%99%E5%85%A5%E6%88%90%E5%8A%9F%EF%BC%81%22);%3C/script%3E

通过以上实验我们可以看出opr参数赋值操作。如果opr参数没有值的话,就无法执行执行,被攻击者必须访问攻击者提前设计好的才能攻击。这种XSS攻击方式叫做:存储型XSS

如果你想看到更给力的实验,请接着往下看。

实验二:

前言:

大部分网站都会和数据打交道那么,XSS漏洞出现这些网站是什么样子的?

0x00构造代码

数据库部分

BaseDao.java

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.sql.Statement;

public class BaseDAO {

  //打开连接

  public Connection getConn(){

    Connection conn = null;

    try {

      Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");

      conn = DriverManager.getConnection("jdbc:sqlserver://localhost:1433;databaseName=SQLTMP","sa","sa");

    } catch (ClassNotFoundException e) {

      e.printStackTrace();

    } catch (SQLException e) {

      e.printStackTrace();

    }

  

    return conn;

  }

    

  //关闭链接的方法

  public void closeAll(Connection conn,Statement stat,ResultSet rs){

    try {

      if(rs != null)

        rs.close();

      if(stat != null)

        stat.close();

      if(conn != null)

        conn.close();

        

    } catch (SQLException e) {

      e.printStackTrace();

    }

  }

  //重载关闭方法

  public void closeAll(Connection conn,PreparedStatement pstat,ResultSet rs){

    try {

      if(rs != null)

        rs.close();

      if(pstat != null)

        pstat.close();

      if(conn != null)

        conn.close();

        

    } catch (SQLException e) {

      e.printStackTrace();

    }

  }

  //继续重载

  public void closeAll(Connection conn,PreparedStatement pstat){

    try {

      if(pstat != null)

        pstat.close();

      if(conn != null)

        conn.close();

    } catch (SQLException e) {

      e.printStackTrace();

    }

  }

  //增删改的公用方法

  public int upDate(String sql,Object[] pram){

      

    PreparedStatement pstat = null;

    Connection conn = null;

    int a = 0;

      

    try {

      conn = getConn();

      pstat =conn.prepareStatement(sql);

      //遍历参数集合,将集合中的参数对应添加到sql语句中

      for (int i = 1; i <= pram.length; i++) {

        pstat.setObject(i, pram[i-1]);

      }

      //调用方法

      a = pstat.executeUpdate();

        

    } catch (SQLException e) {

      e.printStackTrace();

    }finally{

      closeAll(conn, pstat);

    }

    return a;

  }

}

  

CommentDao.java

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

import java.sql.*;

import java.util.*;

import entity.*;

public class CommentDao extends BaseDAO {

  /**

   * 获取所有留言

   * */

  public List<comm> GetComment(){

    //SQL语句

    String sql = "SELECT CID,CName,CContext FROM Comments";

    List<comm> list = new ArrayList<comm>();

    //数据库连接对象

    Connection conn = null;

    //SQL执行对象

    PreparedStatement pstmt = null;

    //数据库执行返回值

    ResultSet rs = null;

    try {

      //创建数据库链接

      conn = this.getConn();

      //创建SQL执行对象

      pstmt = conn.prepareStatement(sql);

      //执行SQL语句  返回值

      rs = pstmt.executeQuery();

      //读取

      while (rs.next()) {

        comm comment = new comm();

        comment.setCID(rs.getInt("CID"));

        comment.setCName(rs.getString("CName"));

        comment.setCContext(rs.getString("CContext"));

        list.add(comment);

      }

    } catch (Exception e) {

      e.printStackTrace();

    }finally{

      //关闭

      this.closeAll(conn, pstmt, rs);

    }

    return list;

  }

  public int AddComment(comm comment){

    String sql = "INSERT INTO Comments VALUES(?,?)";

    //受影响行数

    int result = 0

    //数据库连接对象

    Connection conn = null;

    //SQL执行对象

    PreparedStatement pstmt = null;

    try {

      //创建数据库链接

      conn = this.getConn();

      //创建SQL执行对象

      pstmt = conn.prepareStatement(sql);

      //设置参数

      pstmt.setString(1, comment.getCName());

      pstmt.setString(2, comment.getCContext());

      //执行SQL语句

      result = pstmt.executeUpdate();

    } catch (Exception e) {

      e.printStackTrace();

    }finally{

      this.closeAll(conn, pstmt);

    }

    return result;

  }

}

CommentServlvet

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

import java.io.*;

import javax.servlet.*;

import javax.servlet.http.*;

import entity.*;

public class CommentServlvet extends HttpServlet {

  /**

   * doGet()

   */

  public void doGet(HttpServletRequest request, HttpServletResponse response)

      throws ServletException, IOException {

    request.setCharacterEncoding("UTF-8");

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

    PrintWriter out = response.getWriter();

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

    CommentDao commentDao = new CommentDao();

    //检索参数是否为空

    if(opr == null || opr.equals("all")){

      request.setAttribute("all", commentDao.GetComment());

      //转发

      request.getRequestDispatcher("comment.jsp").forward(request, response);

    }else if (opr.equals("add")){

      comm comment = new comm();

      comment.setCName(request.getParameter("UName"));

      comment.setCContext(request.getParameter("context"));

      if(commentDao.AddComment(comment) > 0){

        out.print("<script>alert('留言成功');location.href='CommentServlvet?opr=all';</script>");

      }else{

        out.print("<script>alert('留言失败');location.href='CommentServlvet?opr=all';</script>");

      }

    }else{

      request.setAttribute("all", commentDao.GetComment());

      //转发

      request.getRequestDispatcher("comment.jsp").forward(request, response);

    }

    out.flush();

    out.close();

  }

  

  /**

   * doPost()

   */

  public void doPost(HttpServletRequest request, HttpServletResponse response)

      throws ServletException, IOException {

    doGet(request, response);

  }

}

Comment.jsp

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

<%@ page language="java" import="java.util.*,entity.*" 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 'comment.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>

 <%

   request.setCharacterEncoding("UTF-8");

   if(request.getAttribute("all") == null){

     request.getRequestDispatcher("CommentServlvet?opr=all").forward(request, response);

   }

 %>

 <table>

 <%

   List<entity.comm> list = (List<entity.comm>)request.getAttribute("all");

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

 %>

     <tr>

     <td><%=list.get(i).getCName() %></td>

     <td><%=list.get(i).getCContext() %></td>

     </tr>

     <%

   }

 %>

 </table>

 <form action="CommentServlvet?opr=add" method="post">

   <textarea rows="5" cols="30" name="context"></textarea>

   昵称:<input type="text" name="UName" />

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

 </form>

 </body>

</html>

0x01漏洞实验

root@1~#

我们在留言板留言:

<script> var objShell = new ActiveXObject("wscript.shell");objShell.Run("G:/work/XSS/WebRoot/Md5.exe");</script>

然后访问:http://localhost:8080/XSS/comment.jsp

这样只要访问这个页面,软件就自动打开了,来个远程文件?慢慢领悟。

root@2~#

我们在留言板留言:

 

复制代码 代码如下:

<script>var fso,tf;fso = new ActiveXObject("Scripting.FileSystemObject");tf = fso.CreateTextFile("d:\\test.txt",true);tf.WriteLine("i春秋社区欢迎您");tf.Close();alert("文件写入成功!");</script>

 

然后访问: http://localhost:8080/XSS/comment.jsp

文件写入成功。

root@3~#

留言内容:

[code]<script>location.href='http://bbs.ichunqiu.com'</script>[code]

访问页面:http://localhost:8080/XSS/comment.jsp

访问留言页面自动跳转到攻击者特定的网站。难道这就是传说中的劫持吗?

3.XSS防御方案

正所谓哪里有攻击,哪里就有防御。XSS一样,有攻击的方式,也有防御的方案。

EL表达式+JSTL标签库

EL(Expression Language):[size=12.0000pt]为了使JSP写起来更简单。表达式语言的灵感来自于ECMAScript和XPath表达式语语言,他提供了JSP中简化表达式的方法,让jsp代码更简单。

JSTL(JSP Standard Tag Library):开放源代码的JSP标签库。

实验一防御代码:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

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

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<%

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 'index.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>

 <div style="margin: 0 auto">

 <%

   request.setCharacterEncoding("UTF-8");

   String tmp = request.getParameter("opr");

   //减速传入值是否为空

   if(tmp == null){

     out.print("111");

   }else{

     //转码

     String opr = new String(tmp.getBytes("ISO-8859-1"),"utf-8");

     request.setAttribute("name", opr);

     %>

     <c:out value="${requestScope.name }"></c:out>

     <%

   }

 %>

   我是内容

 </div>

 </body>

</html>

实验二防御代码:

?

1

2

3

4

5

6

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

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<%

String path = request.getContextPath();

String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

%>

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

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

<html>

 <head>

 <base href="<%=basePath%>">

 <title>My JSP 'comment.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>

 <%

   request.setCharacterEncoding("UTF-8");

   if(request.getAttribute("all") == null){

     request.getRequestDispatcher("CommentServlvet?opr=all").forward(request, response);

   }

 %>

 <table>

<!-- 防御XSS方案 -->

 <c:forEach var="x" items="${requestScope.all }">

 <tr>

   <td>

   <c:out value="${x.getCName() }"></c:out>

   </td>

   <td>

   <c:out value="${x.getCContext() }"></c:out>

   </td>

 </tr>

 </c:forEach>

 </table>

 <form action="CommentServlvet?opr=add" method="post">

   <textarea rows="5" cols="30" name="context"></textarea>

   昵称:<input type="text" name="UName" />

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

 </form>

 </body>

</html>

结束语

        技术无黑白,专研甚好。

 

原文地址:https://www.jb51.net/article/92585.htm

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JSP(JavaServer Pages)是一种用于开发动态Web页面的Java技术。在JSP页面中,可以使用script标签来包含JavaScript代码。xss(跨站脚本攻击)是一种常见的网络安全漏洞,攻击者通过在网页中注入恶意的脚本代码,使得用户的浏览器执行这些脚本并达到攻击目的。 对于JSP页面中的script标签,存在一些潜在的XSS漏洞,这些漏洞主要来源于两个方面。 首先,通过动态生成的页面内容,如果不经过合适的处理就直接输出到script标签中,就可能导致XSS漏洞。攻击者可以在输入框中输入恶意脚本代码,并提交给服务器,服务器将此代码动态生成到JSP页面中的script标签中,当用户访问该页面时,恶意脚本就会被执行,从而对用户造成安全威胁。 其次,对于从其他地方获取的数据,如果没有进行适当的过滤和验证,也可能导致XSS漏洞。比如从URL参数、表单数据、cookie等位置获取的数据,如果直接被输出到JSP页面的script标签中,也可能被攻击者利用。 为了解决这些XSS漏洞,我们可以采取一些有效的措施。比如对用户输入的数据进行合适的过滤和转义,确保使用合适的编码方式输出到script标签中,可以使用如JSTL的c:out标签或者其他安全的输出方式。另外,对于从其他位置获取的数据,也要进行合适的验证和过滤,确保输出到script标签中的数据是安全可信的。 总之,对于JSP页面中的script标签,我们需要意识到可能存在的XSS漏洞,并采取适当的措施进行防范,以保护用户的信息安全

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值