Question

I am trying to block special characters like (&,%,--,>,<) from being submitted in the username field. Below is the code i have written , but its not getting complied i am getting error( unclosed character literal). Please tell me what wrong am i doing and is this the correct way to block those special characters ?

  package pack.java;
  import pack.java.MyModel;
  import java.io.*;
  import java.lang.*;
  import javax.servlet.*;
  import javax.servlet.http.*;
  import javax.servlet.jsp.*;
  import javax.servlet.jsp.tagext.*;
  import java.sql.*;
  public class MyController extends TagSupport
  {

HttpServletRequest request;
HttpServletResponse response;
String msg="";
 String empid="";
public int doStartTag()throws JspException
{

     request=(HttpServletRequest)pageContext.getRequest();              
     response=(HttpServletResponse)pageContext.getResponse();
    return EVAL_PAGE;
   }    

   public void check()
 {

   HttpSession mysession=request.getSession();
   Connection con;
   CallableStatement stmt;
   ResultSet rs;
   JspWriter out=pageContext.getOut();
   int f=0;
     try
    {
   Class.forName("oracle.jdbc.driver.OracleDriver");
    }
       catch(ClassNotFoundException ex)
    {
       msg=ex.getMessage();
     }
    try 
   {


    String aa=(String)MyModel.name.trim();
    String bb=(String)MyModel.pass.trim();
    String cc="";
    String dd="";
     int i;
     int user =aa.length();
     int pass = bb.length();
     for (i=0; i<user; i++)
    {
    char u = aa.charAt(i);

    if ( u.equals(%) || u.equals(<) || u.equals(>) || u.equals(&) || u.equals(;) || 

         u.equals(') || u.equals(--) || u.equals(0))
    {
    out.println("Invalid Username !");
    }
     else 
    {
              cc+= u.toString();
    }
  } 
 con= DriverManager.getConnection ("jdbc:oracle:thin:@localhost:1521:XE","gaurav","oracle");
    stmt=con.prepareCall("select usercheck1(?,?) from dual");
    stmt.setString(1,cc);
    stmt.setString(2,bb);       
    rs=stmt.executeQuery();

  try
 {
   while (rs.next())
 {
   empid=rs.getString (1);     
  mysession.setAttribute("user",empid);
   if(empid!=null)
 {
  response.sendRedirect("/Myjsp/selectaction.jsp");
  }
  else
  out.println("InValid User");
  }
 }
  catch(Exception ex)
 {
   msg=ex.getMessage();
 }

 }
catch(SQLException ex)
 {
  msg=ex.getMessage();
  }
 } 
   public int doEndTag() throws JspException
 {  
    check();
   return EVAL_PAGE;
  }
 }
Was it helpful?

Solution

You have some basic syntax errors with character literals, eg u.equals(%) should be u.equals('%') etc, but you can throw out most of your code if you use regex:

boolean ok = !username.matches(".*[%<>&;'\0-].*");

The characters in square brackets are a character class, which means "any one of" the listed characters. The entire expression will match if any of those characters are in the input, so the negation of such a match means the username doesn't contain an illegal character.

OTHER TIPS

I see some errors in your code. You use a primitive (char) as an object (equals method). Also you don't put quotes around the chars you wish to test. You should compare like this the chars

u == '%'

I see you also compare a string "--", but the same, it's wrong, you should have used

"--".equals(u)

I forgot to add, you should use '\'' when comparing the single quote char.

If you wish to use an object to make the tests, you can use the line to create a Character object:

 Character u = aa.charAt(i);

But since your code it's simple, I don't think it's really useful.

You should use a combination of ESAPI, JSoup and JSR-303's @SafeHtml annotation to prevent XSS and filter out harmful values before they are stored.

package com.domain.security.filter;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.ws.rs.core.MultivaluedMap;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Entities.EscapeMode;
import org.jsoup.safety.Whitelist;
import org.owasp.esapi.ESAPI;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.sun.jersey.spi.container.ContainerRequest;
import com.sun.jersey.spi.container.ContainerRequestFilter;

public class XSSFilter implements ContainerRequestFilter
{
    private static final Logger LOG = LoggerFactory.getLogger( XSSFilter.class );

    /**
     * @see ContainerRequestFilter#filter(ContainerRequest)
     */
    @Override
    public ContainerRequest filter( ContainerRequest request )
    {
        // Clean the query strings
        cleanParams( request.getQueryParameters() );

        // Clean the headers
        cleanParams( request.getRequestHeaders() );

        // Clean the cookies
        cleanParams( request.getCookieNameValueMap() );

        // Return the cleansed request
        return request;
    }

    /**
     * Apply the XSS filter to the parameters
     * @param parameters
     * @param type
     */
    private void cleanParams( MultivaluedMap<String, String> parameters )
    {
        LOG.debug( "Checking for XSS Vulnerabilities: {}", parameters );

        for( Map.Entry<String, List<String>> params : parameters.entrySet() )
        {
            String key = params.getKey();
            List<String> values = params.getValue();

            List<String> cleanValues = new ArrayList<String>();
            for( String value : values )
            {
                cleanValues.add( stripXSS( value ) );
            }

            parameters.put( key, cleanValues );
        }

        LOG.debug( "XSS Vulnerabilities removed: {}", parameters );
    }

    /**
     * Strips any potential XSS threats out of the value
     * @param value
     * @return
     */
    public String stripXSS( String value )
    {
        if( value == null )
            return null;

        // Use the ESAPI library to avoid encoded attacks.
        value = ESAPI.encoder().canonicalize( value );

        // Avoid null characters
        value = value.replaceAll("\0", "");

        // Clean out HTML
        Document.OutputSettings outputSettings = new Document.OutputSettings();
        outputSettings.escapeMode( EscapeMode.xhtml );
        outputSettings.prettyPrint( false );
        value = Jsoup.clean( value, "", Whitelist.none(), outputSettings );

        return value;
    }
}

And an example of using JSR-303

import org.hibernate.validator.constraints.SafeHtml;
import org.hibernate.validator.constraints.SafeHtml.WhiteListType;

public class MySecureModel {
    @SafeHtml( whitelistType = WhiteListType.NONE )
    private String userInput;
}

This is an example using Jersey 1.x and 2.x which can be easily adapted / changed into a regular HTTP filter: http://codehustler.org/blog/jersey-cross-site-scripting-xss-filter-for-java-web-apps/

Your application will still be vulnerable to XSS if you block those characters. You are missing some of the dangerous ones. Instead of trying to identify the bad characters (blacklisting), why not check that it only contains allowed ones(whitelisting). Normally the set of allowed characters is quite limited.

Also take a look at the OWASP XSS prevention cheat sheet.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top