Thursday, 25 September 2014

Symmetric encryption without using a key in the C# code

Either symmetric or Asymmetric encryptions, managing keys are a bigger problem than doing the encryption decryption itself. There is a way that we encrypt the data using key in the scope of the machine or user.

Following is the code

// To Encrypt
var textToSecure = "This is the text that we need to secure with encryption";
var textBytes = Encoding.Unicode.GetBytes(textToSecure);
var encryptedText = ProtectedData.Protect(textBytes, null, DataProtectionScope.CurrentUser);
// To Decrypt
var decryptedBytes= ProtectedData.Unprotect(encryptedText, null, DataProtectionScope.CurrentUser);
var decryptedText = Encoding.Unicode.GetString(decryptedBytes);

Note that as the 2nd Param we can pass in an additional byte array as an additional entropy.
 
Eg : static byte[] s_aditionalEntropy = { 9, 8, 7, 6, 5 };

DataProtectionScope can be either user or Machine. If we select the machine level scope anyone who has the access to the machine can decrypt the encrypted data.
 
 

Hashing passwords … How much security we can guarantee ??


There are many ways where we can store application passwords securely. We can use existing frameworks like membership provider in .Net and there are other 3rd party providers as well. We can use either encryption or hashing in this regard but the most famous way of securing passwords is hashing.

First if all we need to understand that Hashing and Encryption are totally different methods in cryptography. Bit confused eh ? ;) let me explain..

In Encryption what we are doing is we are using one or several keys to do the encryption. So this is called symmetric encryption and normally it is a reversible process.

But Hashing is a one-way process, ie : there is nothing called un-hashing. Hashing using deterministic algorithms. We use our hashing algorithm to create the hash with a the value we need to hash ( password ) and store them. So when we need to do check the value again ( during login process as an example ) the hashing algorithm generates the hash again with given password and check against the saved value.

Normally hashing algorithms are not cracked. Instead, what attackers do is , they are using existing password list and generate hashes and compared vis brute force. We can use tools such as hash cat for this process. Attackers using consumer hardware such as high end GPUs to perform these kind of brute force cracks. If we take an example , the VS2010 membership provider ( default using the SHA1 ) can be cracked up to 60% within 15 mins.

Rainbow tables

Rainbow tables are pre compute hashes where we can use to compare rapidly with breached accounts. Rainbow crack provides pre-configured rainbow tables to download. But these files are huge. As an example , md5_ascii collection for password length 1 to 8 is around 576GB.

 How to secure hashing

Technically we cant secure hashing 100% . What we can do is, we can slow down the cracking process hence it is taking much longer time to do the brute force attack on it.


Using Salt 

Salt is a sequence of random bytes which got appended with the value ( password ) we need to store securely. So the salt is also saved along with the hashed password. This would eliminate the use of Rainbow tables up to some limit. But if we have a salt rainbow table, still we can use the brute force but would take much longer time to do the cracking.
 

Using hash algorithms which takes much longer time to compute

VS2012 using the PBKDF2( Password base key derivation function)  with HMAC-SHA. This hashing process iterates 1000 times in the crypto.cs class which comes with the VS2010. To compare this with VS2010 method, this takes 10 days( with 1 GPU ) to crack with brute force attack compared to 14 mins in VS2010. But still, it is a matter of time !

Use much stronger hashing algorithms

Instead of using standard hashing algos , we can switch to much stronger hashing algorithms such as BCrypt or Ztetic. Ztetic can be replaced .Net membership provider with some configuration changes. Ztetic using 5000 computations of PBKDF2.

 

 

 

 

 

 

Wednesday, 24 September 2014

Securing ASP.Net configurations from being hacked



ASP.Net configurations are pretty easy to use and highly manageable feature. But this can lead up to many misconfigurations which would lead into high security vulnerabilities.  

ELMAH is a handy 3rd party configuration tool that developers can use to log errors and other information. But bad configuration can be lead up to many loopholes in the security perspective of the application. In following sections I’m explaining how to avoid those misconfigurations.

Handling Errors and redirect properly


First and foremost, we need to enable the customErrors in the web.config file. This is mainly to prevent the yellow screen of death in the browser.

<customErrors mode ="On" defaultRedirect ="Error.aspx"/>

This would solve the YSD issue but it would reveal the error page path in the url section in the browser. To eliminate that, we need to use the redirect mode attribute as below.

<customErrors mode ="On" defaultRedirect ="Error.aspx" redirectMode="ResponseRedirect"/>

This would keep the existing url in the browser’s url section while it is getting redirected to the appropriate error page.

Disable Tracing

Tracing is a handy tool that developers are using to get a log of requests been made and to get information about trace log information.

When you go to the View Details section, you can view various details such as detailed request details, origin .Net framework info etc.. But most dangerously, there can be trace logs that developers have logged and forgot to remove in production code. To remove all these make sure that the following attribute is set to false.  
<trace enabled="false"/>
 

Encrypt config sections



We used to keep sensitive data such as connection string passwords in the web.config file. But leaving these sensitive data in plain text in anywhere is a high security vulnerability. There are many tools and methods where we can encrypt these sections and I’m going to discuss one of the easiest ways we can achieve it using regiis tool.

  1. Run the command prompt in Admin mode

  2. Browse to the .Net framework’s path > eg : C:\Windows\Microsoft.NET\Framework\v4.0.30319

  3. Run the following command
    Aspnet_regiis –site “MySecureSite ” –app “/” –pe “ConnectionStrings”
Note : -app is the application folder relative to root of the IIS. In my case I hosted mySecureSite in the root.  –pe is the section we need to encrypt
After this you can see the given section is hashed.
Use the –pd attribute in same manner to decrypt the given section.
This may not the most appropriate way to encrypt the config sections but it is fairly easy.

Use config transforms


We can use the Web.Release.Config’s config transform to make sure we are not leaking out any dev related config entries to the production code. Following are two examples of how we can use it.
Following sections would make sure that error mode is remoteonly, the 500 error would redirected to a production error page and the trace attribute is removed.
Keep in mind that in order to take this into the action, we need to publish the web project.
 <customErrors mode="RemoteOnly" xdt:Transform="Replace">

      <error statusCode="500" redirect="InternalServeError.html"/>

    </customErrors>

    <trace xdt:Transform="Remove"/>

In the production environment, it is advisable to enable the retail mode in machine.config file.
<deployment retail="true"/>



Saturday, 9 August 2014

Converting MVC 4 Web Application to MVC 5

Most of you guys might have many web applications build on MVC 4 and wanted to take some advantages introduced in the MVC 5. Good news is, you can migrate your MVC 4 application to MVC 5 pretty easily with few configuration changes.  The MVC 5 shipped with many cool features to enhance  web development using MVC.

Following are the main features that got added or enhanced in MVC 5 and above
  • ASP.NET Identity
  • Bootstrap
  • Authentication filters
  • Filter overrides
  • Attribute routing
I am not going to discuss these new features. You can find these new feature enhancements at official ASP.Net site.
  1. Make sure your Target Framework is at least in .Net Framework 4.5 ( or above )  : Go To Project Properties --> Application --> Target Framework :
  2. We need to update following NuGet Packages 
    1. Microsoft ASP.Net MVC 
    2. Entity Framework 
    3. .Net Web API 2 
  3. Make sure your packages.config update as follow 
<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="DotNetOpenAuth.AspNet" version="4.1.4.12333" targetFramework="net45" />
  <package id="DotNetOpenAuth.Core" version="4.1.4.12333" targetFramework="net45" />
  <package id="DotNetOpenAuth.OAuth.Consumer" version="4.1.4.12333" targetFramework="net45" />
  <package id="DotNetOpenAuth.OAuth.Core" version="4.1.4.12333" targetFramework="net45" />
  <package id="DotNetOpenAuth.OpenId.Core" version="4.1.4.12333" targetFramework="net45" />
  <package id="DotNetOpenAuth.OpenId.RelyingParty" version="4.1.4.12333" targetFramework="net45" />
  <package id="EntityFramework" version="6.1.1" targetFramework="net45" />
  <package id="jQuery" version="1.8.2" targetFramework="net45" />
  <package id="jQuery.UI.Combined" version="1.8.24" targetFramework="net45" />
  <package id="jQuery.Validation" version="1.10.0" targetFramework="net45" />
  <package id="knockoutjs" version="2.2.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.Mvc" version="5.2.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.Mvc.FixedDisplayModes" version="5.0.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.Razor" version="3.2.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.Web.Optimization" version="1.0.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi" version="5.2.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.Client" version="5.2.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.Core" version="5.2.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.OData" version="4.0.30506" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.WebHost" version="5.2.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebPages" version="3.2.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebPages.Data" version="2.0.20710.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebPages.OAuth" version="2.0.30506.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebPages.WebData" version="2.0.30506.0" targetFramework="net45" />
  <package id="Microsoft.Data.Edm" version="5.2.0" targetFramework="net45" />
  <package id="Microsoft.Data.OData" version="5.2.0" targetFramework="net45" />
  <package id="Microsoft.jQuery.Unobtrusive.Ajax" version="2.0.30506.0" targetFramework="net45" />
  <package id="Microsoft.jQuery.Unobtrusive.Validation" version="2.0.30506.0" targetFramework="net45" />
  <package id="Microsoft.Net.Http" version="2.0.20710.0" targetFramework="net45" />
  <package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net45" />
  <package id="Modernizr" version="2.6.2" targetFramework="net45" />
  <package id="Newtonsoft.Json" version="4.5.11" targetFramework="net45" />
  <package id="System.Spatial" version="5.2.0" targetFramework="net45" />
  <package id="WebGrease" version="1.3.0" targetFramework="net45" />
</packages>

         Main elements to consider are :
  • MVC should get update 4 to 5 
  • Razor should get update 2 to 3 
  • WebPages should get update 2 to 3 

 Next we need to update few references in the root level we.config file as follows 

<?xml version="1.0" encoding="utf-8"?>
<!--
  For more information on how to configure your ASP.NET application, please visit
  http://go.microsoft.com/fwlink/?LinkId=169433
  -->
<configuration>
  <configSections>
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
  </configSections>
  <connectionStrings>
    <add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=aspnet-MyTestMVC4WebApp-20140806052351;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnet-MyTestMVC4WebApp-20140806052351.mdf" providerName="System.Data.SqlClient" />
  </connectionStrings>
  <appSettings>
    <add key="webpages:Version" value="3.0.0.0" />
    <add key="webpages:Enabled" value="false" />
    <add key="PreserveLoginUrl" value="true" />
    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" />
    <authentication mode="Forms">
      <forms loginUrl="~/Account/Login" timeout="2880" />
    </authentication>
    <pages>
      <namespaces>
        <add namespace="System.Web.Helpers" />
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Optimization" />
        <add namespace="System.Web.Routing" />
        <add namespace="System.Web.WebPages" />
      </namespaces>
    </pages>
  </system.web>
  <system.webServer>
    <validation validateIntegratedModeConfiguration="false" />
    
  <handlers>
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <remove name="OPTIONSVerbHandler" />
      <remove name="TRACEVerbHandler" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers></system.webServer>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="DotNetOpenAuth.Core" publicKeyToken="2780ccd10d57b246" />
        <bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="DotNetOpenAuth.AspNet" publicKeyToken="2780ccd10d57b246" />
        <bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="0.0.0.0-1.3.0.0" newVersion="1.3.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-5.2.0.0" newVersion="5.2.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
      <parameters>
        <parameter value="v11.0" />
      </parameters>
    </defaultConnectionFactory>
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
  </entityFramework>
</configuration>

 Next We need to take a look at the web.config file in the views folder to update Razor configurations.

  <configuration>
  <configSections>
    <sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
      <section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
      <section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
    </sectionGroup>
  </configSections>

  <system.web.webPages.razor>
    <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
    <pages pageBaseType="System.Web.Mvc.WebViewPage">
      <namespaces>
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Optimization"/>
        <add namespace="System.Web.Routing" />
      </namespaces>
    </pages>
  </system.web.webPages.razor>

  <appSettings>
    <add key="webpages:Enabled" value="false" />
  </appSettings>

  <system.web>
    <httpHandlers>
      <add path="*" verb="*" type="System.Web.HttpNotFoundHandler"/>
    </httpHandlers>

    <!--
        Enabling request validation in view pages would cause validation to occur
        after the input has already been processed by the controller. By default
        MVC performs request validation before a controller processes the input.
        To change this behavior apply the ValidateInputAttribute to a
        controller or action.
    -->
    <pages
        validateRequest="false"
        pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
        pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
        userControlBaseType="System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
      <controls>
        <add assembly="System.Web.Mvc, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" namespace="System.Web.Mvc" tagPrefix="mvc" />
      </controls>
    </pages>
  </system.web>

  <system.webServer>
    <validation validateIntegratedModeConfiguration="false" />

    <handlers>
      <remove name="BlockViewHandler"/>
      <add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler" />
    </handlers>
  </system.webServer>
</configuration>

 Next We need to remove the ASP.Net GUID from the Web Project's .csproj file. The main purpose of this GUID is to identify that particular web project is a MVC web project. But from MVC 5 onwards , this is no longer use. Because there is no specific significance of identifying MVC project as it is. In different words this means, now you can have MVC, Web Forms , Web API ... all combine together in one project. 

Remove the highlighted GUID. You need to unload the Web project from the solution and edit the .csproj file. And then reloads the Web project. 

<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProductVersion>
    </ProductVersion>
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{116A3134-16A8-46D3-9482-44E4F5457C60}</ProjectGuid>
    <ProjectTypeGuids>{E3E379DF-F4C6-4180-9B81-6769533ABE47};{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
    <OutputType>Library</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>MyTestMVC4WebApp</RootNamespace>
    <AssemblyName>MyTestMVC4WebApp</AssemblyName>
    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
    <MvcBuildViews>false</MvcBuildViews>
    <UseIISExpress>true</UseIISExpress>
    <IISExpressSSLPort />
    <IISExpressAnonymousAuthentication />
    <IISExpressWindowsAuthentication />
    <IISExpressUseClassicPipelineMode />
  </PropertyGroup>