Showing posts with label RAZOR. Show all posts
Showing posts with label RAZOR. Show all posts

Tuesday, April 28, 2015

Change Areas folder convention to Plugins in ASP.Net MVC

ASP.Net MVC is mostly about convention. The controllers are inside Controller folder, cshtml files needs to be under views folder, the views are looked up from ActionResult by the action name etc...But whatever conventions are there, all those can be overridden. That is the beauty of MVC framework.

Recently we faced one scenario of overriding convention in one of the MVC projects. It uses MVC Areas to achieve plugin model. We deploy new plugins into the areas folder without recompiling the original framework web application. During one of the demo, there was a suggestion to rename the 'Areas' folder to 'Plugins' for better naming convention and readability. We tried to resist it as it adds unwanted code. But due to the pressure from leadership we decided to change it. It is good in one way that, we gets more chances to look inside the MVC framework.

Initially thought of having custom controller or ViewEngine. But after playing with MVC for some time, it became very easy as adding some lookup folder paths into RazorViewEngine. Files and folder hierarchy under the Plugins folder needs to be done manually. Right click and add area will not put new files into Plugins folder. Code below. The sub folder structure and files can be organized in side the Plugins folder in the same way how its seen in Area's folder.


        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            AddPluginsFolderToAreaLocationFormatsOfRazorViewEngine();
        }

        private static void AddPluginsFolderToAreaLocationFormatsOfRazorViewEngine()
        {
            string[] PluginsLocationFormats = new string
                [] { "~/Plugins/{2}/Views/{1}/{0}.cshtml" };
            var razorEngine = ViewEngines.Engines.OfType<RazorViewEngine>().First();
            razorEngine.AreaMasterLocationFormats = 
                razorEngine.AreaMasterLocationFormats.Concat(PluginsLocationFormats).ToArray();
            razorEngine.AreaViewLocationFormats = 
                razorEngine.AreaViewLocationFormats.Concat(PluginsLocationFormats).ToArray();
        }


If anybody faces issues in getting this run, comment here. I can upload a sample MVC5 project.

http://theshravan.net/blog/configure-the-views-search-locations-in-asp-net-mvc/
http://stackoverflow.com/questions/632964/can-i-specify-a-custom-location-to-search-for-views-in-asp-net-mvc

Tuesday, September 2, 2014

Hosting WCF service in IIS and System.Web.WebPages.Deployment

As per MSDN the System.Web.WebPages,Deployment namespace contains "the classes that are used to confirm the deployment of web applications". It make sense for web applications which contains web pages created using .aspx or Razor. But what is the relation between this System.Web.WebPages.Deployment.dll and WCF service application which hosted inside IIS which is exposed via netNamedPipes ?

As we have seem in my previous post about SSMS and System.Transactions.dll, I got a machine crash and the machine started behaving in its's own way which resulted in problems. Now when I host WCF services inside IIS there are problems. The services, I was able to browse before the crash stopped working with below error message.

Could not load file or assembly 'System.Web.WebPages.Deployment, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The module was expected to contain an assembly manifest

The call stack looks as follows

[BadImageFormatException: Could not load file or assembly 'System.Web.WebPages.Deployment, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The module was expected to contain an assembly manifest.]
   System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks) +0
   System.Reflection.RuntimeAssembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks) +34
   System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName assemblyRef, Evidence assemblySecurity, RuntimeAssembly reqAssembly, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks) +152
   System.Reflection.RuntimeAssembly.InternalLoad(String assemblyString, Evidence assemblySecurity, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean forIntrospection) +77
   System.Reflection.RuntimeAssembly.InternalLoad(String assemblyString, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection) +16
   System.Reflection.Assembly.Load(String assemblyString) +28
   System.Web.Configuration.CompilationSection.LoadAssemblyHelper(String assemblyName, Boolean starDirective) +38

[ConfigurationErrorsException: Could not load file or assembly 'System.Web.WebPages.Deployment, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The module was expected to contain an assembly manifest.]
   System.Web.Configuration.CompilationSection.LoadAssemblyHelper(String assemblyName, Boolean starDirective) +752
   System.Web.Configuration.CompilationSection.LoadAssembly(AssemblyInfo ai) +57
   System.Web.Compilation.BuildManager.GetReferencedAssemblies(CompilationSection compConfig) +170
   System.Web.Compilation.BuildManager.GetPreStartInitMethodsFromReferencedAssemblies() +91
   System.Web.Compilation.BuildManager.CallPreStartInitMethods(String preStartInitListPath) +258
   System.Web.Compilation.BuildManager.ExecutePreAppStart() +135
   System.Web.Hosting.HostingEnvironment.Initialize(ApplicationManager appManager, IApplicationHost appHost, IConfigMapPathFactory configMapPathFactory, HostingEnvironmentParameters hostingParameters, PolicyLevel policyLevel, Exception appDomainCreationException) +516

[HttpException (0x80004005): Could not load file or assembly 'System.Web.WebPages.Deployment, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The module was expected to contain an assembly manifest.]
   System.Web.HttpRuntime.FirstRequestInit(HttpContext context) +9873912
   System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext context) +101
   System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +254


One possibility for BadImageFormatException is the mismatch of runtime. ie if we try to load x86 assembly in x64 application or other way we may get this exception. I tried enabling 32 bit support in the application pool by setting the "Enable 32-Bit Applications" flag in IIS. 

It did't help.

Then looked at all the config files possible such as aspnet.config and machine.config. Nowhere I was able to find any entry to the problematic dll. Then I decided to find out the assembly binding information which is as follows

=== Pre-bind state information ===
LOG: User = NT AUTHORITY\NETWORK SERVICE
LOG: DisplayName = System.Web.WebPages.Deployment, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
 (Fully-specified)
LOG: Appbase = file:///<drive>:/TFS/TestDotNet/WcfService1/
LOG: Initial PrivatePath = <drive>:\TFS\TestDotNet\WcfService1\bin
Calling assembly : (Unknown).
===


Here its clear that the calling assembly is unknown which I assume any framework dll. May be it was earlier getting loaded from GAC and after the crash GAC registration might be broken. So I figured out the location of he dll and registered into GAC.

Location of System.Web.WebPages.Deployment.dll - <Install drive>:\Program Files (x86)\Microsoft ASP.NET\ASP.NET Web Pages\v2.0\Assemblies

But the GACUtil failed with a message as follows.

The module 'System.Web.WebPages.Deployment.dll' was expected to contain an assembly manifest.

Then I tried open the dll in reflector and could see that, it was not able to open as its no more a .net dll and it displayed more detailed error message


File is not a portable executable. DOS header does not contain 'MZ' signature.


This leads to a conclusion that the System.Web.Webpages.Deployment.dll is corrupt. So next option is repair or re-install. So went to appwiz.cpl and re-installed "Microsoft ASP,Net Webpages 2".

It worked!!!

But why WCF hosted in IIS needs System.Web.WebPages.Deployment.dll which is for web page related :-(

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.

Monday, April 7, 2014

Showing different RAZOR Views based on the Model type in ASP.Net MVC

Problem

In real time, there will be scenarios where we need to display different model classes differently in the Views. Normally, if the controller is aware of the Model type and knows the corresponding View, it can return the proper ViewResult object via its Action() methods. But what should we do, if we have an GenericBusinessObject ie an Entity which have its properties in a dictionary or enclosed in XElement and we need to switch the View based on the type of Generic Entity?

My current project have an offline processing feature which is controlled via queues. When somebody needs to process a long running task they put their request into the queue and the queue monitor mechanism dequeue the requests whenever there is space to process that request. This is a general framework where the track developer needs to write code for queuing the request which accepts the parameter in the form of xml. The parameter decide how the processing server process that particular request. The track developer also needs to write code for the actual processing by implementing certain interfaces. Simply saying the queuing system just makes the processing delayed until the processing servers have enough capacity to process the request and the details about how to process and related logic is decoupled from the queue framework as the operation detail is passed as xml.

This system also has monitoring web application as well where the production engineers can see how many queue items are waiting in the queue, how many failed etc...The web site also have provision to see the queue request parameter xml which is viewable only to the application support engineers. A trained application support engineer can identify, what a particular queue request is intended for, by analysing the queue requests parameter. This monitoring site is implemented using ASP.Net MVC 4 with a page to see all queue requests. Things were easy until we get a requirement to display different pages based on the queue request type, so that the application support engineers don't need to analyse the xml to know what is the intention of the queue request.

To understand the issue in a simple scenario, lets take Person object with 2 properties. PersonType and Properties. Definition is given below.

    public class Person
    {
        [Display(Name = "First Name")]
        public string PersonType { get; set; }
        public XElement Properties { get; set; }
    }

The Properties is kept as xml as it is having dynamic schema or in simple words variable number of properties. If the PersonType is Employee the Properties can include FirstName & Company.For Student type it can have FirstName,School & Marks. 
The MVC site is supposed to call a web service to get person  object list and display all the unique person types from the obtained person list. When the user clicks on the PersonType link it should display Person objects corresponding to the person type. If the type is known such as Student display 3 columns and if its unknown just show the Person type. The URL might look like as below
site.com/Person/List?personType=Employee
or
site.com/Person/List?personType=Student

Challenges

  • If we just return the model from Action method, it cannot render as it don't know the View corresponding to the Model.
  • If we put if/switch condition based on the PersonType in the List.cshtml and render the <Table> accordingly the List.cshtml will grow to large size.
  • We can have same if/switch based on PersonType and render partial views which will limit the size of the List.cshtml. But again the partial view need to have logic for parsing the XML and display accordingly.

Solution

The better solution, I could think of is "having an abstraction for parsing the xml to create concrete model classes and give to View for just display" instead of view working on Model to find out what is relevant. So the logic of parsing xml is done in the Action and it returns typed model class object to the corresponding views. When we say abstraction, its just and interface which returns the typed objects and the corresponding view name. The implemented classes will have the logic of parsing the xml to convert to typed objects. Only consideration is about having a base class for view model classes which are returned from the interface methods or properties.

It is not the perfect solution. We can argue on merits of having partial views v/s this provider mechanism. But its worth looking at this provider mechanism as well. Below is the relevant code for this approach.

    public class ViewModelBase
    {
    }
//Typed class for student.It will differ for employee
    public class StudentViewModel:ViewModelBase
    {
        public IEnumerable<StudentModel> Students { get; set; }
    }
    public class StudentModel
    {
        [Display(Name = "First Name")]
        public string FirstName { get; set; }
        [Display(Name = "School")]
        public string School { get; set; }
        [Display(Name = "Marks")]
        public string Marks { get; set; }
    }
    public class DefaultViewModel : ViewModelBase
    {
        //Reuse the Person itself instead of DefaultModel
        public IEnumerable<Person> Persons { get; set; }
    }
/////////////////Classes related to provider model.
    public interface IViewModelProvider
    {
        ViewModelBase GetViewModel(IList<Person> persons);
        string ViewName { get; }
    }
    internal partial class StudentViewModelProvider : IViewModelProvider
    {
        ViewModelBase IViewModelProvider.GetViewModel(IList<Models.Person> persons)
        {
            StudentViewModel studVMList = new StudentViewModel() { };
            studVMList.Students = persons.Select(p=>new StudentModel(){
                FirstName = p.Properties.Attribute("FirstName").Value,
                School = p.Properties.Attribute("School").Value,
                Marks = p.Properties.Attribute("Marks").Value
            });
            return studVMList;
        }
        string IViewModelProvider.ViewName
        {
            get { return "Student"; }
        }
    }
    public class DefaultViewModelProvider : IViewModelProvider
    {
        ViewModelBase IViewModelProvider.GetViewModel(IList<Models.Person> persons)
        {
            DefaultViewModel personVMList = new DefaultViewModel() { };
            personVMList.Persons = persons;
            return personVMList;
        }
        string IViewModelProvider.ViewName
        {
            get { return "Index"; }
        }
    }
/////////////MVC Specific
    public class PersonController : Controller
    {
        public ActionResult List(string personType)
        {
            IEnumerable<Person> persons = DataRepository.GetPersonsByType(personType);
            IViewModelProvider provider = ViewModelProviderFactory.GetProvider(personType);
            ViewModelBase viewModel = provider.GetViewModel(persons.ToList());
            return View(provider.ViewName, viewModel);
        }
    }

Hope this is clear. Sample can be downloaded from the below location.

Monday, January 2, 2012

Creating simple ASP.Net MVC 3 RAZOR application and adding a view to list users

I am really new to Razor the new view engine of ASP.Net MVC and decided to have a look at it during last weekend. First I started with what are the specialties of RAZOR and could see that it is more simple than the traditional ASP.Net view engine. Then I searched for the differences between the asp.net view engine and the Razor in terms of usage which will help me to write Razor view.Also I got the list which says how the Razor view elements are converted to HTML elements.

Seems we are ready to taste RAZOR through a sample application. Again searched for creating simple razor application and got the link which explains how to create a user list with option such as edit,list...
http://www.asp.net/mvc/tutorials/overview/creating-a-mvc-3-application-with-razor-and-unobtrusive-javascript

But it looks little complicated to me as we need to create model and all. So decided to just list down the user list from Membership provider.Steps goes as follows.
  1. Create a new ASP.Net MVC 3 project with default templates which will setup the membership provider and some pages such as the login, create new user etc...
  2. Create a new action in HomeController.cs named "Users". Add the below code to return the MembershipUserCollection.
    public ActionResult Users()
    {
          return View(Membership.GetAllUsers());
    }
  3. Right click on the "Users" Action method definition and select the "Add view".Use the same master page of other views(~/Views/Shared/_Layout.cshtml)
  4. Go to the added view and add the below lines in it.
    @{
        ViewBag.Title = "Users";
        Layout = "~/Views/Shared/_Layout.cshtml";
    }
    <h2>Users</h2>
    @foreach (var user in Model)
    { 
        @user.UserName
    }

  5. Go to master page and add action along with Home and About.
    <li>@Html.ActionLink("Users", "Users", "Home")</li>
Hope the steps are self explanatory. From the Action method in the Controller we are passing the MembershipUserCollection as model and that model is being enumerated in the RAZOR View to display the UserName.

More on ASP.Net MVC 3
http://msdn.microsoft.com/en-us/library/gg416514(v=vs.98).aspx
http://davidhayden.com/blog/dave/archive/2011/01/05/ASPNETMVC3TutorialsIndex.aspx