0

I am using the below mentioned boolean statement to know if the string i got from the input box contains any special character. I want to know is it a good way to prevent XSS attack and can this filter be bypassed ?

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

Here's the complete code

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();
    }
}

Below is the jsp page, the string is entered here and on submit redirects to a different page where tag is called.

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

Here the tag is invoked

<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>
Mickäel A.
  • 9,012
  • 5
  • 54
  • 71
user3337264
  • 13
  • 1
  • 2
  • 8
  • Which programming language ? JavaScript ? – Mickäel A. Mar 03 '14 at 08:54
  • You also need to use a prepared statement for your query instead of a concatenated statement. Since you are concerned about security, that is the number one security flaw right there. – tom Mar 04 '14 at 12:32
  • @tom- yes i will certainly make more changes to the code against SQL injection, however can you tell me how and where to use StringEscapeUtils.escapeHtml in my code. – user3337264 Mar 04 '14 at 13:14
  • you have it at the right place but you are missing a '+'. `out.println(""+StringEscapeUtils.escapeHtml(rs.getString(1))+"");` – tom Mar 04 '14 at 13:39

2 Answers2

1

In fact what you want is to prevent XSS attacks using specials character. So you don't really have to care about the characters present in the String. You just have to espace them before doing any operation on your database, using a function with the same purposes as htmlspecialchars() in PHP.

Obviously such conversion can also be done in Java.

To replace all HTML entities (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;)"

To replace only a select subset of characters (source) :

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

EDIT :

To take your example, you would have to espace special characters in the variable reqnum because you'll use it in your SQL request :

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

Alternative (and better) solution

You should not handle this by yourself, but use something called PreparedStatement which can do it for you, plus other useful stuff.

Community
  • 1
  • 1
Mickäel A.
  • 9,012
  • 5
  • 54
  • 71
  • I am using MVC (custom Tag) and trying to incorporate in my code(StringEscapeUtils.escapeHtml) but seems i am unable to correctly implement it, in the doEndTag() i am trying to print the output in a table, please let me know is that the right way to do it ? because the code doesnt compile I have updated the full code in my original post. – user3337264 Mar 04 '14 at 11:44
  • If you check it when selecting from your DB, you assume that the data stored in your DB is not safe, which should not be the case ! You must use this method *before* actually inserting data from the user, not after. XSS breach is based on the fact that you won't verify input data. See my edited post for more details. – Mickäel A. Mar 04 '14 at 13:33
  • Sorry for being so naive,actually i am confused and have following doubts: 1.How different is StringEscapeUtils.escapeHtml(reqnum)instead of using !reqnum.matches(".*[%#^<>&;'\0-].*") to filter special characters ? 2.Where exactly do we use escapeHtml, validating string before inserting into DB or when the output is displayed in browser ? 3.You said better option is to use prepareStatement, aren't PreparedStatement only prevent against SQL injection how will that prevent XSS ? I have updated my code along with view page, please tell me where is the code vulnerable for XSS attack – user3337264 Mar 05 '14 at 07:12
  • 1. `escapeHtml()` actually replaces special characters by their equivalent HTML entities, whereas `matches()` only checks if your string contains such characters. 2. I would say that you have to do it *before* inserting into DB, as quotes could break your SQL statements. 3. Imagine you have `` as input string, it isn't an SQL injection right ? But if you don't *escape* the dbl quotes then when displaying it, it will not display text but execute the script ! PreparedStatement will warn you about that. Same for ; ' and so on. – Mickäel A. Mar 05 '14 at 07:34
0

Server side code:

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

Attack:

" onfocus=alert(1) autofocus b=

Result:

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

Input validation is not likely to block all XSS attacks. Focus on output escaping: https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet

Erlend
  • 4,336
  • 22
  • 25