0

In our application, we have a XSS filter which handle every request and checks the values ..

But we discovered a case when the request is Ajax and our filter does not work ..

It does not work when AJAX request is done like :

$.ajax({
            url:         '${someUrl}' ,
            type:        'POST',
            cache:        false,
            data:        JSON.stringify(checkForm),
            dataType:    'json',
            contentType: 'application/json',

Here the values are in JSON format, looks like:

{"poNumber":"123144","voucher":"","quoteNumber":"","collectNumber":"","otherCarrier":"","deliveryMethodCode":"21","paymentMethodCode":"invoice","concerns":""}

It does work when:

ACC.pg = {
    addToCart: function() {
        var productCode = $(this).data("productcode");
        var params = {
            "productCodePost": productCode,
            "qty": 1
        };
        $.post("${url}", params, ACC.quickordercustom.handleSuccess);

qty=1&productCodePost=12123

The filter takes the params from the request like

  Map<String,String[]> params = req.getParameterMap();
  for (Map.Entry<String,String[]> entry : params.entrySet()) {
    String v[] = entry.getValue();
    ....
  }

But for case 1 , req.getParameterMap() is empty .. any suggestions?

Thanks Y

J. Su.
  • 451
  • 1
  • 6
  • 18
brakebg
  • 414
  • 3
  • 11
  • 24
  • I hope your filter stops everything listed [here](https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet) and in every context. – SilverlightFox Feb 19 '16 at 15:37

3 Answers3

1

The parameters of a servlet request are populated from URL parameters and - in case of a POST request with content-type application/x-www-form-urlencoded - from the parsed request body.

Since you are sending a JSON payload in case 1, the parameter map is empty.

wero
  • 32,544
  • 3
  • 59
  • 84
  • Ok, how can i get it from the Filter .. ? thanks for the answer. – brakebg Feb 18 '16 at 17:03
  • @brakebg you would need to parse it yourself using a JSON library. But the request body can only be read once. If you consume it in the filter you can't simply reread it in a servlet. A solution would be to put the parsed JSON in a request attribute in order for the serlvet to pick it up from there. – wero Feb 18 '16 at 17:16
0

Here is how i did it in case someone is interested.

As in the comment of "wero" was said, params are populated from the url or requesr body depend of the method (POST or GET)..

So, in my case i have JSON object which i need to read , perform stripXSS and wrapp it again and doFilter ..

This is how i identify Ajax requests

final HttpServletRequest httpServletRequest = ((HttpServletRequest) paramServletRequest);
    final boolean ajax = "XMLHttpRequest".equals(httpServletRequest.getHeader("X-Requested-With"));

All this is going on in a Filter, so next is to read JSON object and perform stripXSS

    private String jsonToString(final HttpServletRequest httpServletRequest) throws IOException
{
    final StringBuilder buffer = new StringBuilder();
    final BufferedReader reader = httpServletRequest.getReader();
    String line;
    while ((line = reader.readLine()) != null)
    {
        buffer.append(line);
    }
    final String data = buffer.toString();
    return data;
}

And the stripXSS, where paterns are defined in a config file

    private String stripXSS(String value)
{
    if ((value != null) && (value.length() > 0))
    {
        for (final Pattern scriptPattern : patterns)
        {
            value = scriptPattern.matcher(value).replaceAll("");
        }
    }
    return value;
}

After the request is already consumed, we need to wrap it in order other consumers being able to read it.

    public class AjaxXSSRequestWrapper extends HttpServletRequestWrapper
{

    private final ServletInputStream inputStream;

    /**
     * @param request
     */
    public AjaxXSSRequestWrapper(final HttpServletRequest request, final ServletInputStream inputStream)
    {
        super(request);
        this.inputStream = inputStream;
    }

    /*
     * (non-Javadoc)
     *
     * @see javax.servlet.ServletRequestWrapper#getInputStream()
     */
    @Override
    public ServletInputStream getInputStream() throws IOException
    {
        return this.inputStream;
    }
}

In this example, only getInputStream is overriden, but you can do it for other methods as well ..

And at the end ..

paramFilterChain.doFilter(requestWrapper, paramServletResponse);
brakebg
  • 414
  • 3
  • 11
  • 24
0

You can always clean out the form values once they are converted to an object using JSR-303 and @SafeHtml.

Take a look here for an example: How to Modify QueryParam and PathParam in Jersey 2

Alessandro Giannone
  • 885
  • 1
  • 10
  • 27