JSP安全開發之XSS漏洞詳解_java

來源:互聯網
上載者:User

前言

     大家好,好男人就是我,我就是好男人,我就是-0nise。在各大漏洞舉報平台,我們時常會看到XSS漏洞。那麼問題來了,為何會出現這種漏洞?出現這種漏洞應該怎麼修複?

本文

1.XSS?XSS?XSS是什麼鬼?

     XSS又叫跨站指令碼攻擊(Cross Site Scripting),我不會告訴他原本是叫CSS的,但是為了不和我們所用的層疊樣式表(Cascading Style Sheets)CSS搞混。CSS(跨站指令碼攻擊),CSS(層疊樣式表)傻傻分不清。所以就叫XSS咯。

2.XSS的危害是什嗎?

實驗一:

0x00構造代碼

<%@ 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=

既然連本地檔案都可以開啟那麼遠程檔案木馬?來個電腦惡搞?這個自己慢慢象限。我可沒說啊。。。。。

檔案都可以開啟,那麼寫一些檔案呢?

訪問: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

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

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

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

<%@ 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標籤庫。

實驗一防禦代碼:

<%@ 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>

實驗二防禦代碼:

<%@ 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+"/";%>
<!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>

結束語

        技術無黑白,專研甚好。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.