【问题标题】:Using (.matches) boolean statement prevents XSS attack?使用 (.matches) 布尔语句可以防止 XSS 攻击?
【发布时间】:2014-04-04 04:30:13
【问题描述】:

我正在使用下面提到的布尔语句来了解我从输入框中得到的字符串是否包含任何特殊字符。我想知道这是防止XSS攻击的好方法吗?这个过滤器可以绕过吗?

!id.matches(".*[%#^<>&;'\0-].*")

这是完整的代码

package pack.java;

import pack.java.findrequestmodel;
import java.io.*;
import java.lang.*;
import org.apache.commons.lang.StringEscapeUtils;
import java.sql.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;

public class findrequestcontrol extends TagSupport
{
    HttpServletRequest request;
    HttpServletResponse response;

    public int doStartTag() throws JspException
    {
        request = (HttpServletRequest) pageContext.getRequest();
        response = (HttpServletResponse) pageContext.getResponse();

        return EVAL_PAGE;
    }

    public ResultSet check()
    {
        JspWriter out = pageContext.getOut();
        Connection con;
        ResultSet rs = null;
        CallableStatement stmt;
        String checkreq = "";
        String reqnum = (String) findrequestmodel.requestno.trim();

        try
        {
            Class.forName("oracle.jdbc.driver.OracleDriver");
        }
        catch (ClassNotFoundException ex)
        {
        }
        try
        {
            if (!reqnum.matches(".*[%#^<>&;'\0-].*") )
            {
                con = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:XE","gaurav","oracle");
                stmt=con.prepareCall("begin requestdetail(?); end;");
                stmt.setString(1,reqnum);          
                rs=stmt.executeQuery();
            }
            else
                out.println("Invalid Number");
        }
        catch(SQLException ex)
        {
        }
        catch(Exception ex)
        {
        }

        return rs;
    }

    public int doEndTag() throws JspException
    {   
        JspWriter out=pageContext.getOut();
        ResultSet rs=check();

        try
        {      
            if (!rs.next()) 
            {  
                out.println("no data found");  
            }  
            else
            {   
                out.println("<table border=2>");
                out.println("<tr>");
                out.println("<th>EmployeId</th>");
                out.println("</tr>");

                do 
                {
                    out.println("<tr>");
                    out.println("<td>"+rs.getString(1)+"</td>");
                    out.println("</tr>");
                } while (rs.next());
            }

        }
        catch(Exception ex)
        {
        }

        return super.doEndTag();
    }
}

下面是jsp页面,这里输入字符串,提交时重定向到另一个调用tag的页面。

<html>
    <head>
    </head>
    <body>
        <form method=post>
            <input type=text style="color:grey" name=reqno </br>
            <input type = submit name = submit value = Submit>

            <%
                String r=request.getParameter("reqno");
                String btn=request.getParameter("submit");

                HttpSession session1=request.getSession();
                session1.setAttribute("requestno",r);

                if (btn != null)
                    response.sendRedirect("findrequest1.jsp");
            %>
        </form>
    </body>
</html>

这里调用了标签

<jsp:useBean id="MrBean" class="pack.java.findrequestmodel"/>
<jsp:setProperty name="MrBean" property="requestno" value=""/>
<%@ taglib uri="/WEB-INF/jsp2/taglib8.tld" prefix="easy" %>
<html>
    <head>
    <body>
        <form method=post>
            <input type = submit name = submit value = Back>
            <%
                HttpSession mysession = request.getSession();
                String req = (String) mysession.getAttribute("requestno");

                MrBean.setRequestno(req);

                String btn = request.getParameter("submit");

                if (btn != null)
                    response.sendRedirect("findrequest.jsp");
            %>
            <easy:myTag8/>
        </form>
    </body>
</html>

【问题讨论】:

  • 哪种编程语言? JavaScript ?
  • 您还需要为查询使用准备好的语句,而不是连接语句。既然您担心安全问题,那就是第一个安全漏洞。
  • @tom- 是的,我肯定会对代码进行更多更改以防止 SQL 注入,但是你能告诉我如何以及在哪里使用 StringEscapeUtils.escapeHtml 在我的代码中。
  • 您在正确的位置拥有它,但您缺少一个“+”。 out.println("&lt;td&gt;"+StringEscapeUtils.escapeHtml(rs.getString(1))+"&lt;/td&gt;");

标签: java xss boolean-expression


【解决方案1】:

服务器端代码:

<input type="text" name="something" value="<%= something %>">

攻击:

" onfocus=alert(1) autofocus b=

结果:

<input type="text" name="something" value="" onfocus=alert(1) autofocus b=">

输入验证不可能阻止所有 XSS 攻击。关注输出转义:https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet

【讨论】:

    【解决方案2】:

    实际上,您想要的是防止使用特殊字符的 XSS 攻击。因此,您不必真正关心字符串中存在的字符。在对数据库执行任何操作之前,您只需使用与 PHP 中的htmlspecialchars() 相同目的的函数来对它们进行分隔。

    显然这种转换也可以在 Java 中完成。

    替换所有 HTML 实体 (source):

    String source = "Escape the less than sign (<) and ampersand (&)";
    String escaped = StringEscapeUtils.escapeHtml(source);
    // Will output "Escape the less than sign (&lt;) and ampersand (&amp;)"
    

    仅替换选定的字符子集 (source):

    String escaped = StringUtils.replaceEach(source, new String[]{"&", "<"}, new String[]{"&amp;", "&lt;"});
    

    编辑:

    以您的示例为例,您必须在变量 reqnum 中对特殊字符进行转义,因为您将在 SQL 请求中使用它:

    String checkreq="";
    String reqnum=(String)findrequestmodel.requestno.trim();
    reqnum = StringEscapeUtils.escapeHtml(reqnum); // Espace special characters
    // ... skipped code ...
    rs=stmt.executeQuery(" select * from myadmin where reference_no='"+reqnum+"'"); // Safe
    

    替代(和更好的)解决方案

    你不应该自己处理这个,而是使用一个叫做PreparedStatement的东西,它可以为你做这件事,加上其他有用的东西。

    【讨论】:

    • 我正在使用 MVC(自定义标签)并尝试将其合并到我的代码中(StringEscapeUtils.escapeHtml),但似乎我无法正确实现它,在 doEndTag() 我试图打印输出在一张桌子上,请让我知道这是正确的做法吗?因为代码无法编译,所以我在原帖中更新了完整代码。
    • 如果您在从数据库中选择时检查它,则认为存储在数据库中的数据不安全,事实并非如此!您必须实际插入来自用户的数据之前使用此方法,而不是之后。 XSS 违规是基于您不会验证输入数据的事实。有关详细信息,请参阅我编辑的帖子。
    • 抱歉这么幼稚,其实我很困惑,有以下疑问: 1. StringEscapeUtils.escapeHtml(reqnum) 与使用 !reqnum.matches(".*[%#^&;'\0-].*") 过滤特殊字符? 2.我们究竟在哪里使用escapeHtml,在插入数据库之前或在浏览器中显示输出时验证字符串? 3.你说更好的选择是使用prepareStatement,PreparedStatement不只是防止SQL注入如何防止XSS?我已经更新了我的代码以及查看页面,请告诉我代码在哪里容易受到 XSS 攻击
    • 1. escapeHtml() 实际上将特殊字符替换为其等效的 HTML 实体,而 matches() 仅检查您的字符串是否包含此类字符。 2. 我会说你必须在插入数据库之前 这样做,因为引号可能会破坏你的SQL 语句。 3. 假设您有&lt;script&gt;alert("XSS breach !");&lt;/script&gt; 作为输入字符串,这不是SQL 注入对吗?但是,如果您不 escape dbl 引号,那么在显示它时,它不会显示文本而是执行脚本! PreparedStatement 会警告你。同样的; ' 等等。
    猜你喜欢
    • 2022-01-08
    • 1970-01-01
    • 1970-01-01
    • 2018-07-16
    • 2019-12-11
    • 1970-01-01
    • 2023-03-04
    相关资源
    最近更新 更多