Friday, 8 July 2016

Some Notes about ASP.NET Request Validation and Cross Site Scripting

ASP.NET framework has a built-in feature enabled by default to protect application against Cross Site Scripting (XSS) attack. It uses Request Validation feature that checks query string, cookie and posted form values to make sure that those inputs do not contain malicious script. It will throw an error if it encounters malicious script.


Request Validation version
For the recent version of ASP.NET framework, we should use the latest validation mode. In our web.config file, it should have something like:
<httpRuntime requestValidationMode="4.5" targetFramework="4.5" />
ASP.NET version 4.0 should use   requestValidationMode="4.0"


Turning off Request Validation feature in the application
We could also turn off Request Validation feature and only have this feature on some pages. To do this, in web.config set
<pages validateRequest="false" /> 
then set the validation feature on the pages that we would like to have it
<@ Page ValidateRequest="true" %> 


Disable Request Validation in a Controller
We also can disable Request Validation feature for a particular controller by setting [ValidateInput(false)] attribute:
[ValidateInput(false)] 
public ActionResult Index(MyModel m) 
{ 
    . . . 
} 


Disable Request Validation on a class property
To disable the feature at a more granular level, we can use [AllowHtml] attribute on a class property:
public class MyModel 
{ 
    public string MyProperty1 { get;  set; } 

    [AllowHtml] 
    public string MyProperty2 { get; set; } 

    . . . 

} 


Encoding input data
If we would like to allow input data that contains HTML or JavaScript codes, we can encode the input with HtmlEncode() function that are provided by ASP.NET framework. In ASP.NET version 4.5 or above, they have included AntiXss Library in the System.Web.Security.AntiXss namespace. This library prevents XSS better as it uses whitelisting approach compared to the default one which uses blacklisting approach. To set AntiXss Library as the default library for encoding, specify the encoderType in httpRuntime node in web.config:
<httpRuntime  . . .  encoderType="System.Web.Security.AntiXss.AntiXssEncoder" />


Sanitising data
When we need to accept HTML format data, then we should sanitise the data first from any malicious codes. The AntiXss Library 4.3.0 contains sanitiser functionalities however this has reached an end of life. The newer version that is included with ASP.NET 4.5 does not contain sanitiser.

We have some options to add sanitation functionality, a couple of those are:
- Write our own custom method using HTML Agility Pack. See this article for an example
- Use a third party library such as the open source HtmlSanitizer

Using the open source HtmlSanitizer library is easy. We can download the package from NuGet. Below is an example of a simple usage of it:
var sanitiser = new HtmlSanitizer(); 
sanitiser.Sanitize(inputString); 

If we would like to disallow some HTML tags, just use .AllowedTags.Remove() method. For example:
sanitiser.AllowedTags.Remove(“img”); 

Below is an example of a method that uses reflection to sanitise string properties of an object passed to it:
public object CleanStringsFromXSS(object data) 
        {  
            var sanitiser = new HtmlSanitizer(); 

            PropertyInfo[] properties = data.GetType().GetProperties(); 
            foreach (PropertyInfo property in properties) 
            { 
                Type propertyType = property.PropertyType; 
                if ((propertyType == typeof(string)) && (propertyType != null)) 
                { 
                    object value = property.GetValue(data); 
                    if (value != null && property.CanRead && property.CanWrite) 
                    { 
                        string sanitisedValue = sanitiser.Sanitize(value.ToString()); 
                        property.SetValue(data, sanitisedValue); 
                    } 
                } 
            } 

            return data; 
        } 


Request Validation vulnerabilities
There is a known vulnerability in Request Validation. Some types of JSON (JavaScript Object Notation) postback can bypass this feature. Therefore it is important to scan JSON input manually. The sanitation library above can be used to check or sanitise malicious codes.


References:
OWASP: ASP.NET Request Validation
Preventing XSS in ASP.NET Made Easy

Tuesday, 26 April 2016

Migrating Existing TFS Database to Another TFS Server Instance

This post explains how to have a new TFS 2013 server with existing database copied from an existing TFS 2013 server.

These are the steps:
1. Backup each existing TFS database
2. Restore the databases in the new server environment. Make sure the databases names are similar like the old ones.
3. Install TFS in the new server by running TFS installer or executable file.
Choose 'Application Tier Only' or 'Upgrade' option on the wizard. Use 'Application Tier Only' if the new server has exactly the same version as the existing server. Use 'Upgrade' option if they have different versions, i.e; different version of service packs installed.
4. Once the installation is successful, go to the TFS Admin Console and change the configurations that still refer to the old server. Also change other configurations such as in Build Configuration and Backups.

Below are the screenshots of step by step running the installation wizard:
1. run the installer


2. choose 'Application Tier Only' option on left hand side menu if the TFS servers versions are similar

otherwise 'Upgrade' option if the versions are different


3. continue with the installation wizard


4. the wizard will detect local SQL instance and TFS databases


5. confirm the url and service account


6. keep progressing until the wizard finishes installation

Sunday, 10 January 2016

Config File Changes for AppFabric Upgrade

When upgrading from AppFabric 1.0 to 1.1, there are some configurations that need to be changed.

In configuration configSections node:
<!-- Old --> 
<section name="dataCacheClient" 
type="Microsoft.ApplicationServer.Caching.DataCacheClientSection, Microsoft.ApplicationServer.Caching.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" 
allowLocation="true" allowDefinition="Everywhere"/>

<!-- New -->
<section name="dataCacheClients"
type="Microsoft.ApplicationServer.Caching.DataCacheClientsSection, Microsoft.ApplicationServer.Caching.Core"
allowLocation="true" allowDefinition="Everywhere"/>

Also the dataCacheClient node can be more than one now:
<!-- Old --> 
<dataCacheClient>
    <hosts>
      <host name="oldcacheserver" cachePort="22233"/>
    </hosts>
</dataCacheClient>

<!-- New -->
<dataCacheClients> <!-- new parent node -->
    <dataCacheClient name="default">
    <hosts>
      <host name="newcacheserver" cachePort="22233"/>
    </hosts>
  </dataCacheClient>
</dataCacheClients>

If using AppFabric as session state provider, this needs to be changed as well:
<!-- Old --> 
<sessionState mode="Custom" customProvider="AppFabricCacheSessionStoreProvider">
  <providers>
 <add name="AppFabricCacheSessionStoreProvider" 
 type="Microsoft.ApplicationServer.Caching.DataCacheSessionStoreProvider, Microsoft.ApplicationServer.Caching.Client, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"                         
  cacheName="CacheName" sharedId="SomeID" />
  </providers>
</sessionState>

<!-- New -->
<sessionState mode="Custom" customProvider="AppFabricCacheSessionStoreProvider">
  <providers>
 <add name="AppFabricCacheSessionStoreProvider"
 type="Microsoft.Web.DistributedCache.DistributedCacheSessionStateStoreProvider, Microsoft.Web.DistributedCache"
 cacheName="CacheName" sharedId="SomeID"/>
  </providers>
</sessionState>


References:
How to: Configure the AppFabric Session State Provider for ASP.NET (AppFabric 1.1 Caching)
Configuration Settings for the ASP.NET 4 Caching Session State Provider (AppFabric 1.1 Caching)
Application Configuration Settings (AppFabric 1.1 Caching)
Preparing the Cache Client Development Environment (AppFabric 1.1 Caching)
Managing Security (Windows Server AppFabric Caching)

Wednesday, 30 December 2015

How to Move EF Database First Template .tt File to Another Project

On this post, we will see how to have Entity Framework .tt template file generated by an .edmx file in a different project. By default .tt files are created under the same project where the .edmx file is. Usually this is our data layer project. However, for most of the time, we would want the POCO models that are generated by a model .tt file to be put under a separate project (i.e. domain or model project) for a better practice.

There are a few steps to make this happen (I am using VS 2013 here):
1. Add a new model template .tt file in the other project through 'add a new item' then select EF DbContext Generator file type under 'Data'.


2. Open the new .tt file then change the value of 'inputFile' to point to the .edmx file in the original project.

In this case, my data project is called 'MySolution.Data.StudentBoundedContext'.

3. To ensure that all of the will be generated POCO classes have right namespaces, we need to tell the template file the new namespace to use. Right click the .tt file and select 'Properties' then put the new namespace on 'Custom Tool Namespace' value.


4. Delete the model .tt file on the original project.

5. I prefer to leave the context .Context.tt template file on the data layer project and only move the model .tt file to a domain/model project. Therefore, I will need to tell the context template file to refer to the models in the other project.
To do this:
- add a project reference to the other project (domain/model project)
- open the .Context.tt file and add a 'using' statement referring to the models namespace


6. Regenerate the models and context files by right clicking the template files and selecting 'Run Custom Tool'.

Monday, 14 December 2015

Bulk Insert in Web SQL

Below is a snippet of how to do bulk insert of records in Web SQL:
// db is the database object that is usually initialise with openDatabase() function
db.transaction(function (tx) {  
  // insert each record
  $.each(myArray, function (i, item) {
   tx.executeSql("INSERT INTO MyTable(name, value) VALUES (?, ?)", [item.name, item.value]);
  });   
},
// error
function (error) {
 . . .
},
// success - the transaction() function does not pass any object to its success callback
function () {
 . . .
});

Web SQL does not understand the Standard SQL bulk insert syntax such as
Insert Into tbl (col1, col2) Values ('val1', 'val2'), ('val3', 'val4'), ...
but each insert statement needs to be executed using executeSql() function. A transaction is usually used to wrap these insert commands.

Tuesday, 27 October 2015

A Form Validation Example in AngularJS - Show Error Style After Submitted

Below is a basic example of a form validation in AngularJS that shows error style after the form is submitted.

To do this, we need to use novalidate attribute on the form to avoid browser validating the form but is passed to JavaScript to perform manual validation. In addition, we can utilise ng-submitted class that is added to the form by AngularJS after it is submitted.

The view:
<body ng-app="validationExample">
    <div ng-controller="MyCtrl as vm">
      <form name="myForm" novalidate ng-submit="vm.submitted(myForm, vm.input)">
        <input type="text" name="name" ng-model="vm.input.name" placeholder="please enter text" required/>
        <span ng-show="myForm.name.$error.required == true">*</span>
        <input type='text' name="value" ng-model='vm.input.value' placeholder="a number greater than 0" required ng-pattern='/^([1-9][0-9]*(\.[0-9]+)?|0+\.[0-9]*[1-9][0-9]*)$/'>
        <span ng-show="myForm.value.$error.required == true">*</span>
        <button>submit</button>
      </form>
    </div>
</body>

The script:
var myApp = angular.module('validationExample', [])

myApp.controller('MyCtrl', [function () {
    var vm = this;
    vm.submitted = function(form, input) {
      if(form.$valid) {
        alert('submitted');
      }
    }
} ]);

The stylesheet:
.ng-submitted input.ng-invalid {
  border-color:red;
}

See the example in Plunker.

To read more about form validation, please see my previous post.

Thursday, 1 October 2015

Table with Dynamic Rows Manipulation Example in AngularJS

Below is a code example of building a table with the ability to add, edit and remove rows dynamically with AngularJS. It also makes the corresponding input in focus.

The view:
<html>
  <head>
    <script src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
    <script src="https://code.angularjs.org/1.2.16/angular.js"></script>
    <script src="script.js"></script>
  </head>
  <body ng-app="myApp">
    <div ng-controller="MyCtrl as vm">
      <table>
        <thead>
          <tr>
            <th>Name</th>
            <th>Value</th>
          </tr>
        </thead>
        <tbody>
          <tr ng-repeat="row in vm.rows">
            <td>
              <input type="text" ng-model="row.name" ng-readonly="row.readonly" ng-disabled="row.readonly" on-focus="!row.readonly" />
            </td>
            <td>
              <input type="text" ng-model="row.value" ng-readonly="row.readonly" ng-disabled="row.readonly" />
            </td>
            <td>
              <button ng-click="vm.editRow($index)">{{row.readonly ? "Edit" : "Save" }}</button>
              <button ng-click="vm.removeRow($index)">Remove</button>
            </td>
          </tr>
        </tbody>
      </table>
      <br />
      <input type="button" value="Add New" ng-click="vm.addNewRow('','')" />
    </div>
  </body>
</html>

The script:
angular.module('myApp', [])
.controller('MyCtrl', function () {
    var vm = this;
    vm.rows = [{"name": "aaa", "value" : 50, "readonly": true}, {"name": "bbb", "value" : 70, "readonly": true}];
    
    vm.addNewRow = function(name, value) {
      vm.rows[vm.rows.length - 1].readonly= true;
      vm.rows.push({"name":"", "value":"", "readonly": false})
    }
    
    vm.removeRow = function(index) {
      vm.rows.splice(index, 1);
    }
    
    vm.editRow = function(index) {
      vm.rows[index].readonly = !vm.rows[index].readonly;
    }
})
.directive('onFocus', function($timeout) {
    return function(scope, element, attrs) {
        scope.$watch(attrs.onFocus, function (newValue) {
            if (newValue) {
                $timeout(function () {
                    element.focus();
                }, 0, false);
            }
        }); 
      };    
});

See the example in action on Plunker.