2

All:

I have an issue with a project I am working on using C# MVC4

In the project, I am accepting a URL and other parameters from a user, then do some processing and send the result of the processing to the URL provided by the user.

The result is being sent using the following code:

var context = HttpContext.Current;

context.Response.Write("<html><head>");
context.Response.Write("</head><body>");

context.Response.Write(string.Format("<form name=\"myform\" method=\"post\" action=\"{0}\" >", postUrl));

context.Response.Write("</form>");
context.Response.Write("<script type=\"text/javascript\">document.myform.submit();</script></body></html>");

context.Response.Write("</body>");
context.Response.Flush();
context.Response.Clear();
context.ApplicationInstance.CompleteRequest();

Whenever a user attempts an XSS like passing a url value of javascript%3aalert('xss')%2f%2f, the JavaScript runs and the pop up shows up.

I've tried Antixss.HtmlEncode() to encode the URL before passing it into string.Format but still doesn't work. I've tried Antixss.UrlEncode() also, but this gives error as the form doesn't submit to the URL.

Please help me out, Is there something I am missing? What else can I do?

Thanks in advance.

LearningProcess
  • 607
  • 1
  • 8
  • 29
Sulaiman Adeeyo
  • 485
  • 6
  • 19
  • append element objects to the dom and set properties of those objects using the user-supplied values, which sidesteps all interpolation attacks... ship the user-given values as JSON. – dandavis Nov 04 '15 at 20:38
  • Sorry, I don't get you well. Please provide a sample code. – Sulaiman Adeeyo Nov 04 '15 at 20:43
  • I have no experience in c# but this seems a good solution: http://weblogs.asp.net/jongalloway/preventing-javascript-encoding-xss-attacks-in-asp-net-mvc – kazandzhiro Nov 04 '15 at 21:14

4 Answers4

1

You will need a three pronged approach to solve this issue.

Preventing XSS injection:

Note that if a user injected the url value

" /> <script>alert('xss')</script>

this would also leave you vulnerable:

<form name="myform" method="post" action="" /> <script>alert('xss')</script>" >

Therefore you should use the HttpUtility.HtmlAttributeEncode function to solve this one.

However, don't stop there. As noted, you should project against javascript: style URLs. For this I would ensure that the URL begins with http:// or https://. If not, throw a SecurityException which you should be logging and handling server-side, and showing the user a custom error page.

Finally, you want to protect against Open Redirect Vulnerabilities. This is to stop phishing attacks by redirecting users to other domains. Again, use a whitelist approach and ensure that the domain redirected to is one of your own. Be careful on the parsing here, as it is easy to get it wrong - a URL of http://example.org?http://example.com will pass the validation filter for example.com on many badly written validation routines. I recommend using the Uri object in .NET and retrieving the domain through that rather than rolling your own string functions.

You could also check if the URL is a relative URL, and allow it if acceptable. Use something like this function which uses a built in .NET library to ensure that it is relative or not.

Community
  • 1
  • 1
SilverlightFox
  • 32,436
  • 11
  • 76
  • 145
0

Just a thought - try putting this script in rather than just document.myform.submit (and remove the form's action property):

if("{0}".indexOf('http') !== 0) {
    //this is some sort of injection, or it's pointing at something on your server. Should cover http and https.
    //Specifically, it makes sure that the url starts with 'http' - so a 'javascript' url isn't going to work.
} else {
    document.myform.action="{0}"
    document.myform.submit();
}

There is more you could do, but this should help.

Stephen
  • 5,362
  • 1
  • 22
  • 33
0

Since you are adding the postUrl as an attribute "action" of the form tag, you can try using HtmlAttributeEncode method in the HttpUtility

[ValidateInput(false)]
public ActionResult Test(string url)
{
    var context = System.Web.HttpContext.Current;

    context.Response.Write("<html><head>");
    context.Response.Write("</head><body>");

    context.Response.Write(string.Format("<form name=\"myform\" method=\"post\" action=\"{0}\" >", HttpUtility.HtmlAttributeEncode(url)));

    context.Response.Write("</form>");
    context.Response.Write("<script type=\"text/javascript\">document.myform.submit();</script></body></html>");

    context.Response.Write("</body>");
    context.Response.Flush();
    context.Response.Clear();
    context.ApplicationInstance.CompleteRequest();
    return null;
}

http://localhost:39200/home/test?url=https%3A%2F%2Fwww.google.com - Worked http://localhost:39200/home/test?url=%3Cscript%3Ealert(%27test%27)%3C%2Fscript%3E - Worked(Did not show alert)

It is always good practice to Validate the user input against a white list of inputs, to prevent XSS exploits.

rmchndrng
  • 782
  • 1
  • 8
  • 18
0

try using HttpUtility.UrlEncode

something like Response.Write(HttpUtility.UrlEncode(urlString));

see How To: Prevent Cross-Site Scripting in ASP.NET for more steps =)

oCcSking
  • 888
  • 21
  • 43