6

We have a legacy web application in ASP.Net and C#, for which we are getting around 400 plus cross site scripting flaw raised by Veracode scan. I have created a sample web application and simulated the issue, and found that whenever we are using any string input directly its raising the flaw. Doing HttpUtility.HtmlEncode(TextBox1.Text);"satisfies the veracode, however applying this change in all 400 places is not feasible as then there would be huge amount of work and testing efforts. I am looking for someway to implement some plug in in httphandler so that all the inputs get encoded at one place and we don't have to change it everywhere. Can someone please steer me if this is possible if yes even if you can guide me on just on approach would be good enough to have a direction at least. Many thanks in advance.

StringOps strop = new StringOps();
        string txt1, txt2;
        txt1 = HttpUtility.HtmlEncode(TextBox1.Text);
        txt2 = HttpUtility.HtmlEncode(TextBox2.Text);
        Response.Write(strop.Add(txt1, txt2));

If I remove the HttpUtility.HTMLEncode lines Veracode complains about it. Since there are so many places where in we are doing this string operations so implementing this everywhere is not feasible. Would this be possible to have this encoding implemented on a single place and all the response and request should go through that pipeline e.g. HTTPHandler and HTTPModule.

Alok
  • 266
  • 2
  • 14
  • Please [edit] your question to include a [mcve], including input and output. You _definitely_ don't want to percent-encode all inputs, you only need to encode the ones that are printed to HTML again. – CodeCaster Nov 20 '16 at 18:27
  • Thanks CodeCaster. I have updated the question as suggested. – Alok Nov 21 '16 at 09:15
  • 1
    @Alok you mean that the application writes raw input strings directly to the response, thus bypassing all of ASP.NET's security checks and protections? Then yes, you have to fix every single line of buggy code. *And* add validation to all textboxes so that they don't allow invalid input in the first place. – Panagiotis Kanavos Nov 21 '16 at 09:20
  • 2
    Yeah if you're going to `Response.Write(TextBox1.Text)` you're going to have a bad time. Does that pattern occur that much in your code? – CodeCaster Nov 21 '16 at 09:20
  • Either your page, or `StringOps` should *validate* the input and reject invalid data. The best place of course, would be the page itself. What does `StringOps` do? – Panagiotis Kanavos Nov 21 '16 at 09:23
  • Yes its mostly written in this way only. That's why looking for some interface which will do the encoding before sending it back to browser as response. – Alok Nov 21 '16 at 11:24
  • @PanagiotisKanavos: StringOps is just a mock class I have created for putting code snippet here. We have several classes which takes inputs from UI and perform some operations and send it back to UI. – Alok Nov 21 '16 at 12:30
  • 2
    @Alok you are *bypassing* any such interface by using `Response.Write`. This sends *raw* text to the client. *Why* are you doing this anyway? Is this a kind of REST service? In any case, the bug is that you don't validate your input. Encoding will only *hide* the bug from the verification tool. It won't prevent eg SQL injection if the client enters `x'; drop table users; --` – Panagiotis Kanavos Nov 21 '16 at 12:42
  • 2
    Alok, my feeling is that even if you find some way to prevent XSS in a single place, Veracode may not recognize that approach and still complain when it doesn't see the HtmlEncode used. That is just a feeling though. – GreatJobBob Nov 21 '16 at 22:18
  • If you `HTMLEncode` the argument to `Response.Write`, does veracode still flag this? – jdigital Nov 27 '16 at 06:14
  • as you indicated, you can probably handle this by defining and adding a custom `HttpModule` to your web.config.. what sort of application is this and pages are these? (webform - aspx?). also, is there an underline pattern that can be determined for these requests.. like in the url, fileExt, or in that respect... – Brett Caswell Nov 27 '16 at 16:00
  • you may be able to use [httpresponse.filter](https://msdn.microsoft.com/en-us/library/system.web.httpresponse.filter.aspx) for your purposes here.. in the end, what you're looking to do here is intercept the OutputStream of HttpResponse object.. SO related question: http://stackoverflow.com/questions/2282376/intercept-whats-being-written-to-httpresponse-outputstream – Brett Caswell Nov 27 '16 at 16:17

2 Answers2

1

You can accomplish this with a Custom HttpModule that conditionally assigns to HttpResponse.Filter to intercept and process HttpResponse.Write usage.


Module Example

this example uses the value of Content-Type of the request.Header to determine whether the html Encoding should be applied.

public class FilterResponseWriteModule : IHttpModule, IDisposable
{
    private System.IO.Stream filterStream;


    public FilterResponseWriteModule()
    {
    }

    public void Init(HttpApplication context)
    {
        context.BeginRequest += Context_BeginRequest;
    }

    private void Context_BeginRequest(object sender, EventArgs e)
    {
        var context = (sender as HttpApplication).Context;


        if (ShouldApplyFilter(context.Request))
            ApplyFilter(context.Response);
    }

    private bool ShouldApplyFilter(HttpRequest request)
    {
        return string.Equals(request.ContentType, @"text/plain", StringComparison.OrdinalIgnoreCase);
    }

    private void ApplyFilter(HttpResponse response)
    {
        filterStream = new EncodeStreamFilter(response.Filter);
        response.Filter = filterStream;
    }

    public void Dispose()
    {
        if (filterStream != null)
        {
            filterStream.Dispose();
        }
    }
}

Filter Stream Example (encapsulate and override)

Stream is an abstract class, so it will generate all relevant override method stubs.

public class EncodeStreamFilter : Stream, IDisposable
{
    private Stream _baseStream;

    public EncodeStreamFilter(Stream responseFilter)
    {
        _baseStream = responseFilter;            
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
        byte[] bufferBlock = new byte[count];
        Buffer.BlockCopy(buffer, offset, bufferBlock, 0, count);

        var encodedBytes = Encoding.UTF8.GetBytes(HttpUtility.HtmlEncode(Encoding.UTF8.GetString(bufferBlock)));

        _baseStream.Write(encodedBytes, 0, encodedBytes.Length);
    }

    public override bool CanRead
    {
        get
        {
            return _baseStream.CanRead;
        }
    }

    public override bool CanSeek
    {
        get
        {
            return _baseStream.CanSeek;
        }
    }

    public override bool CanWrite
    {
        get
        {
            return _baseStream.CanWrite;
        }
    }

    public override long Length
    {
        get
        {
            return _baseStream.Length;
        }
    }

    public override long Position
    {
        get
        {
            return _baseStream.Position;
        }

        set
        {
            _baseStream.Position = value;
        }
    }

    public override void Flush()
    {
        _baseStream.Flush();
    }

    public override int Read(byte[] buffer, int offset, int count)
    {
        return _baseStream.Read(buffer, offset, count);
    }

    public override long Seek(long offset, SeekOrigin origin)
    {
        return _baseStream.Seek(offset, origin);
    }

    public override void SetLength(long value)
    {
        _baseStream.SetLength(value);
    }



    protected override void Dispose(bool disposing)
    {
        if (!disposing)
        {
            _baseStream.Dispose();
        }
        base.Dispose(disposing);
    }
}

Add Module to Web.Config

Note: In this case, I've defined the module as a class in the App_Start folder of my application.

<system.webServer>
    <modules>
        <add name="FilterResponseWriteModule" type="HttpModulesTestApp.App_Start.FilterResponseWriteModule"/>
    </modules>
</system.webServer>
Brett Caswell
  • 1,486
  • 1
  • 13
  • 25
  • This appears to answer the question, but I'll bet that Veracode will still complain (?) – jdigital Nov 27 '16 at 18:49
  • @jdigital potentially, but it seems like this veracode framework/component/tool is crawling the application, making requests, and analyzing the response.. – Brett Caswell Nov 27 '16 at 18:55
  • which reminds me.. `byte[] buffer` being passed to write could be conditionally handled as well.. and it's likely the call to `Write` will be made several times. would need a better sample of the response OP gets to reflect that consideration. – Brett Caswell Nov 27 '16 at 19:08
0

Listen I also have a legacy site in asp.net 1.0 or 2.0. We did change its framework to 4.0.

So, mine suggestion is that do change its framework and run smoke test and might some issues would come then resolve as expected then comes to primary concern to handle things like Response.Write. As ASP.net is now open source get those code and make minimal changes in core functions and get your things done, try to utilize partial functionality as much as possible, or any thing like this in order to get upgrade without losing your changes.

Mohtisham Zubair
  • 723
  • 5
  • 15