Showing posts with label C#. Show all posts
Showing posts with label C#. Show all posts

Monday, December 8, 2014

The news RSS Webjob

For the news.sleepysecurity.ninja I decided to build a webjob that would handle the reading of the RSS feeds and putting that data into a database that I could then mine.  Being relatively new to using the SyndicationFeed class in .net, and to webjobs, my code went through a few iterations.

After creating my solution and subsequent website project, I added a webjob using the built in mechanism to Visual Studio 2013, by right clicking on the web project, going to add, and selecting New Azure Webjob Project.

New Azure WebJob Project menu selection

 After running through a small wizard, a project is created for you with a 2 main code files.

class Program
{
  static void Main(){
    var host = new JobHost();
    host.Call(typeof(Functions).GetMethod("ManualTrigger"),new {value = 20});
  }
}
 
The other one is the functions file that contains a definition for ManualTrigger.  The JobHost is part of the Azure WebJobs SDK and provides the following services out of the box:
  1. Get azure account strings from your app.config  (the strings can also be passed in directly to the ctor).
  2. Reflect over your code to find C# methods with the SimpleBatch attributes. (much like how WebAPI discovers controllers)
  3. Listen for new blobs that match the [BlobInput] pattern.
  4. when a blob is found, invoke the function
  5. automatically log the invocation so that you can view the results in a separate dashboard. 
So basically, although you can create and run almost any program as a WebJob, by creating one using the JobHost, it provides some special helpers to deal with interacting with other Azure services.  Pretty neat.  The last point above (the dashboard) is super handy for monitoring the webjobs and getting some quick debugging information.  I will get to that later.

One key thing to note is that I had to add two connection strings to my website config in order to get the dashboard to work correctly.



Another interesting thing is the way that the function is called.  It's a static method that is called via reflection.  Interesting.  This makes it hard to do DI or anything like that.  I guess the design pattern here is that a webjob should really do only one thing, and therefore, you shouldn't need to reuse a bunch of the code.

Okay moving on, since I was just fooling around and not following TDD, this is the first version of code that I wrote.  Ewwwww.  I didn't even want to show it.

I know the above is a picture.  Don't copy it, it sucks.  Firstly, I built a webjob that runs on a schedule.  This is different to a continuous webjob, or one that is called via external trigger.  In order for the JobHost to find this method properly, you have to annotate it with the [NoAutomaticTrigger] function.  I figured that I would update my data every hour, so I set that to be the initial schedule.

There are several things bad about the above code, but most importantly, it isn't testable.  I need this function to follow some logic:

  • Read feed and get the latest info
  • Read the database for all posts from that feed
  • If the feed contains new posts, add them, else, continue on

Although it seems easy to read the above, I want to be able to make it testable.  Furthermore, I don't like how this functions class knows about the database, etc. After some refactoring, here is what the code looks like.


        [NoAutomaticTrigger]
        public static void GetFeedData(TextWriter log, IDataService dataService, IRssService rssService)
        {
            var feeds = dataService.GetAllFeeds();
            foreach (var feed in feeds)
            {
                Console.WriteLine("Processing " + feed.Name);
                var posts = dataService.GetAllPostsFor(feed);

                var newPosts = rssService.ReadRssFeed(feed);

                var postsToAdd = newPosts.Where(x => !posts.Any(y => y.PostId.Equals(x.PostId))).ToList();

                postsToAdd.ForEach(x => dataService.InsertPost(Post.CreateFrom(x, feed)));
                
            }
        }

After some refactoring and moving some core components out into services, I can now test the code.  I used Moq in another test project (which I won't show here).  One interesting thing about webjobs, is that any Console.Writeline messages actually get piped to the output and easily viewed.


Pretty cool.  The last thing I needed to do is add in some error handling and event logging.  It turns out that websites and webjobs use the built in Trace mechanism and log to a log source of your choice automatically.  You can find out more about what those options are at this link

Tuesday, April 15, 2014

Some thoughts on Secure File Uploads (MVC / C#)

Recently, I was asked to take a look at a solution that involves receiving file uploads via an MVC application that would then be later processed by an internal system.  MVC already has built in functionality to receive files, so that was no problem.  But what about the security aspects of doing something like this?  Before I dive into some of the things you can do to secure your file transfer, I want to touch on a couple of things.

1)  Verifying files and file types is hard!  There is a project that is available that tries to keep track of the magic numbers for each file type.  A quick scroll through there and you will notice that in some cases, multiple extensions use the same magic numbers.  In other cases, different versions of the application use different file types and magic numbers.  It is a mess!

2)  The verifying that can be done in the application often isn't enough.  We have to remember that we cannot rely on the MVC application to solve all problems.  Even the server side checks that can be implemented are not full proof.  Furthermore, this only verifies that a file is of the type it claims to be (or that you are looking for).  One would still have the problem of ensuring the file was actually "safe" for consumption by the target application.  At the outset, this seems more of a problem for IDS/IPS/Virus Scan than it does the MVC application.

3)  This type of functionality should have already gone through some sort of security review well before it reaches the development team.  The risk of uploading files should be pointed out as well as all the compensating controls that are in place to help mitigate that risk.  For example, is this page authenticated?  Is there sufficient logging?  Is there and IDS/IPS in the network?  Do the files get virus scanned before being consumed?  Can the files be "detonated" on a segregated machine before being given to end users?

As usual, OWASP has a great write-up on this.  They cover a lot of the key points you would want to look at when building your application.

First thing is first, you have build your form/app to receive files.  This is easily done.  MVC4 has the concept of HttpPostedFileBase which is the type the file shows up as.  A couple of notes, you must make sure that the name of your input field matches that of the parameter input to your controller method.  Secondly, you must set the enctype of the form to multipart/form-data.  See this post for more info.

One last thing, the checks below take into account a lot of assumptions about the types of files you want to accept.  You will most probably tailor them to your specific example.  In my case, I am focusing on docx or xlsx files.

Check 1:  Is a file actually there?
Basically this is the equivalent to the ModelState.IsValid() method.  You want to make sure you are actually processing a file.

  if (file == null){
   return View("Error");
  }

Check 2:  File Size
One of the first checks you are going to want to do is around file size.  You can use the request limits feature of request filtering to limit the maximum size you would like to handle.  A couple of notes is that this setting is a global setting, and not page specific.  Further to this, you cannot set a "minimum" size.  You could check for file size in the code (just call length on the input stream), and this might be a valid check in your case.

Check 3:  File Name
We have to remember here that the interpreted file name and content type is actually passed directly from the http request.  This means that it is untrusted client side input and must be validated.  You may want to run a series of checks, but the basics would be length of the file name and a regular expression match.  Here you will want to make some assumptions about the types of files/file names you will be getting.

  if (file.FileName.Length > 255)
  {
    return View("Error");
  }

  var regex = new Regex(@"^[\d\w -]+\.[\w]{4}");
  if (!regex.IsMatch(file.FileName))
  {
    return View("Error");
  }

  var acceptedExtensions = new List() {".docx", ".xlsx"};
  var fileExtension = Path.GetExtension(file.FileName);
  if (acceptedExtensions.All(x => !x.Equals(fileExtension)))
  {
    return View("Error");
  }


In my case, I am looking specifically for docx and xlsx files.  So I can take those assumptions and work with the code.

Check 4:  Content Type
Generally, content type is generated from extension present on the file name.  This behavior varies between browsers and potentially across OS platforms.  Never-the-less, it is information we can look at as a first check.  In the code below, I just compare it to a white-list.  You could take this farther by keeping a mapping of extension to accepted content type.

            var acceptedContentTypes = new List()
            {
                "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
                "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
            };
            if (acceptedContentTypes.All(x => !x.Equals(file.ContentType)))
            {
                return View("Error");
            }

Check 5:  FindMimeFromData Call
Windows has a built in call that does a static check to determine 26 different mime types.  The problems with this are that you have to use interop.  This is the same check that is done in internet explorer, but the benefit is that server side you can control what parameters you call the program with. 

There are a few steps here to using this.  First you have to add the call definition to your code.


        [DllImport(@"urlmon.dll", CharSet = CharSet.Auto)]
        private extern static System.UInt32 FindMimeFromData(
            System.UInt32 pBC,
            [MarshalAs(UnmanagedType.LPStr)] System.String pwzUrl,
            [MarshalAs(UnmanagedType.LPArray)] byte[] pBuffer,
            System.UInt32 cbSize,
            [MarshalAs(UnmanagedType.LPStr)] System.String pwzMimeProposed,
            System.UInt32 dwMimeFlags,
            out System.UInt32 ppwzMimeOut,
            System.UInt32 dwReserverd
        );

Next you have to get the header and call the function. This is a rough idea of what you would do.
            var buf = new byte[265];
            file.InputStream.Seek(0, SeekOrigin.Begin);
            if (file.InputStream.Length > 256)
            {
                file.InputStream.Read(buf, 0, 256);
            }
            else
            {
                file.InputStream.Read(buf, 0, (int)file.InputStream.Length);
            }

            System.UInt32 mimetype;
            var result = (int)FindMimeFromData(0, null, buf, 256, null, 0, out mimetype, 0);
            if (result != 0)
            {
                return View("Error");
            }
            var mimeTypePointer = new IntPtr(mimetype);
            var mimeType = Marshal.PtrToStringUni(mimeTypePointer);
            Marshal.FreeCoTaskMem(mimeTypePointer);

            if (mimeType == null || !mimeType.Equals("application/x-zip-compressed"))
            {
                return View("Error");
            }
In the case of open-xml format, the file that actually gets sent is a Zip file.  So you can look for it there.  There are some alternatives to calling out to the interop.  You could figure out the header bits for a zip file and code the check manually.  See mimedetector or filetypedetective.

So at this point, let us recap.  We have done some basic file name checks.  We have also done some basic content type checks, but this data is built from the file name, so it can't be trusted.  We have run a sever side check and from the header, we can determine that it is in fact a zip file.  Pretty weak!

At this point, we could now rip open the zip file and start to have a look at what is inside.

Check 6:  Zip Verification

The code would look something like this.

            var isValid = false;
            using (var archive = new ZipArchive(file.InputStream,ZipArchiveMode.Read))
            {
                foreach (var entry in archive.Entries)
                {
                    if (!entry.Name.Equals("[Content_Types].xml"))
                    {
                        continue;
                    }

                    using (var contentTypeFile = entry.Open())
                    {
                        var xElement = XElement.Load(contentTypeFile);
                        var elements = xElement.Elements();
                        
                        foreach (var element in elements)
                        {
                            if (element.FirstAttribute.Value.StartsWith("/word/") ||
                                element.FirstAttribute.Value.StartsWith("/xl/"))
                            {
                                isValid = true;
                                break;
                            }
                        }
                    }
                }
            }

            if (!isValid)
            {
                return View("Error");
            }
In .net 4.5, they finally introduced the ZipFile/ZipArchive functionality.  You can use it to open up a stream and check what is inside.  All I am doing in the code above looking for a specific file and checking that file for an attribute that I know needs to be there (as per the standard).  If you think about it, all I am doing is verifying that I have received a zip file (that I can open) and it has a file with some key words in it.  Once again, pretty weak stuff!

Conclusion

Where do you stop? It really depends on the needs of your application.  There is no good way to handle this.  We can start to decrease the risk by adding all of these extra checks, but we can't mitigate it completely.  The entire solution needs to take file upload into consideration.

Saturday, October 29, 2011

Hoppity Solution

I recently stumbled upon the facebook engineering puzzles located here and decided to try and do a few myself.  Hoppity is the first and easiest one, but I thought I'd take a stab at it here.  I'm not really sure what facebook would be looking for in order to get a job interview, but it would be have been cool to be able to view the submissions that got jobs. Please note that I didn't bother with the file reading code, but you can easily add it yourself.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace HoppitySolution
{
    class Program
    {
        private const string DIV_3 = "Hoppity";
        private const string DIV_5 = "HopHop";
        private const string DIV_3_AND_5 = "Hop";

        static void Main(string[] args)
        {
            var maximumInt = GetMaximumIntFrom(args);
            Enumerable.Range(1, maximumInt).ToList().ForEach(x => ProcessHop(x));
        }

        private static void ProcessHop(int i)
        {
            if(DivisibleBy3And5(i))
            {
                Console.WriteLine(DIV_3_AND_5);
                return;
            }

            if (DivisibleBy5(i))
            {
                Console.WriteLine(DIV_5);
                return;
            }

            if (DivisibleBy3(i))
            {
                Console.WriteLine(DIV_3);
                return;
            }
        }

        private static bool DivisibleBy5(int i)
        {
            return i % 5 == 0;
        }

        private static bool DivisibleBy3(int i)
        {
            return i % 3 == 0;
        }

        private static bool DivisibleBy3And5(int i)
        {
            return DivisibleBy5(i) && DivisibleBy3(i);
        }

        private static int GetMaximumIntFrom(string[] args)
        {
            // Add File Read Code here.....
            return 15;
        }
    }
}

Saturday, April 30, 2011

MVC3 Validation Oddities

I had created a post to demonstrate an example for how to do validation in MVC 3. I worked off of an assumption that is now proving to be false.

1) All validation attributes are run, even if one of them fails.

My initial assumption was that if one of the validation attributes were to fail (say Required) that no other attributes would run. In my post, I didn't add a null check to my custom validator based on this assumption. In fact, according to the debugger, all validation attributes are run.

I decided to play around with this a bit to see what the logic was behind this. My colleague mentioned that when you validate, you would probably want to get all the errors back at once, as opposed to only one. This made sense at the time, but was still a little big confusing. Obviously, if you enter a null value for something like username, you probably only want the one error message (User name is required). I can understand where my colleague is coming from , however. Lets say that the username is not null. You would probably want an error message if the length is too small, or doesn't contain the correct characters.

The first thing I tried was to add two custom validators, and see what would happen. It turns out that although both attributes are run, only the error message from one is actually displayed.

[Address]
        [Address2]
        public string Address { get; set; }

It seems (at least for me) that Address2 was the error message that always came up. It did not matter on ordering. I found that one of the methods you can override is IsDefaultAttribute. I found that even setting that didn't change which message gets sent back to the client.


public class AddressAttribute : ValidationAttribute
    {
        public AddressAttribute()
        {
            ErrorMessage = "Address attribute failed";
        }

        public override bool IsDefaultAttribute()
        {
            return true;
        }

        public override bool IsValid(object value)
        {
           
            var address = value as string;

            return false;
        }
    }

I even tried this using the built in validators that come with MVC2. Same result, only one error message made it back to the form.

I know for a fact that when client side validation is turned on, you seem to get all the error messages displayed back. With that being said, it is interesting that you don't get all the error messages displayed if you are just doing simple, no js dependent, error checking. What is also interesting, is that you have to do things like a null check in all of your custom validators, otherwise they will blow up.

I decided as one last final step, to go take a look at some of the source code to see if I could make sense of all of this. Without resharper (or a a full VS at home) it was pretty hard to piece things together. What I did find was the RegularExpressionValidator in Sys.Mvc.

2) Included Validators seem to be dependent on each other.

I'm not sure where this is used, but the implementation of this seems to depend on the the RequiredValidator. A quick test of this yields that a null will pass through the regular expression attribute no problem!

namespace Sys.Mvc {
    using System;

    public sealed class RegularExpressionValidator {

        private readonly string _pattern;

        public RegularExpressionValidator(string pattern) {
            _pattern = pattern;
        }

        public static Validator Create(JsonValidationRule rule) {
            string pattern = (string)rule.ValidationParameters["pattern"];
            return new RegularExpressionValidator(pattern).Validate;
        }

        public object Validate(string value, ValidationContext context) {
            if (ValidationUtil.StringIsNullOrEmpty(value)) {
                return true; // let the RequiredValidator handle this case
            }

            RegularExpression regExp = new RegularExpression(_pattern);
            string[] matches = regExp.Exec(value);
            return (!ValidationUtil.ArrayIsNullOrEmpty(matches) && matches[0].Length == value.Length);
        }

    }
}

I'm sorry this post was a little bit of a ramble, I guess I am just confused on the implementation of validation in MVC 3.

Monday, April 18, 2011

c#: Custom Validation Example

Validation is a big thing for any application.  I am currently working on implementing validation in my WCF layer that doesn't rely on me checking each operation and then hardcoding validation logic into a gigantic class.  I really like the way WCF does model validation, so I decided to start trying to reproduce it to figure out how they did it.

It turns out that it is pretty simple as the following code suggests.  I created a base attribute called Validation Attribute.  I created a BaseModel that has a validate method on it.  That method does some simple reflection to get all the attributes for all the properties in the given class.  It just calls IsValid on those attributes to run the specified logic. 

Check it out.


    public class BaseModel
    {
        public bool Validate()
        {
            var result = true;

            foreach (var property in this.GetType().GetProperties())
            {
                foreach (var attribute in property.GetCustomAttributes(true))
                {
                    if (attribute is ValidationAttribute)
                    {
                        try
                        {
                            var attr = (ValidationAttribute)attribute;
                            result = result && attr.IsValid(property.GetValue(this, null));
                        }
                        catch (Exception)
                        {
                            result = false;
                        }
                    }
                }
            }

            return result;
        }
    }


    public class LoginModel : BaseModel
    {
        [UserNameValidation]
        public string UserName { get; set; }
    }

    [System.AttributeUsage(System.AttributeTargets.Property)]
    public class ValidationAttribute : Attribute
    {
        public virtual bool IsValid(object obj)
        {
            return false;
        }
    }

    public class UserNameValidationAttribute : ValidationAttribute
    {
        private const string USER_NAME_REGEX = @"^\w+$";

        public override bool IsValid(object obj)
        {
            if (obj == null)
            {
                return false;
            }

            var value = obj as string;
            
            if (Regex.IsMatch(value, USER_NAME_REGEX))
            {
                return true;
            }

            return false;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var loginModel = new LoginModel();
            loginModel.UserName = "UserName";
            Console.WriteLine(loginModel.Validate());
        }
    }

Sunday, April 10, 2011

Self Updating WCF Service

Recently I was in a meeting where my idea of a self-updating WCF service was laughed at. This post will contain a very rough proof of concept that the idea is possible. The solution is pretty simple.

1) Self hosted WCF service has a file watcher looking for a file to be created.
2) WCF service has an "update" method where it creates a file to trigger an update
3) Self hosted service reloads the new assembly by way of reflection.

I have skipped over a lot of the details in this proof of concept. Things to look at would be:

1) How does the update file get there (could be via WCF Service)
2) File watcher is not the only way to do this. Maybe nServiceBus? I would have to look into it more.
3) DLL Needs to be verified somehow before it is just loaded automatically. Could be done via signed dll's, or another method? Open to suggestions.

Anyways, here is the code.

WCF Service
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.IO;

namespace WCFSelfUpdater
{
    public class Service1 : IService1
    {
        private string versionNumber = "1.1";

        /// 
        /// Version number in original program is 1.0.  Changed to 1.1
        /// If you want to reproduce this, you need to create 2 dll's each with a different 
        /// version number.
        /// 
        /// 
        public string GetVersionNumber()
        {
            return versionNumber;
        }

        /// 
        /// Method could write the stream out to the disk and then move it (atomic operation)
        /// to where it needs to be.  In this case I just skipped over all of the implementation'
        /// details to just show that the idea was possible.
        /// 
        ///         /// 
        public bool Update(Stream stream)
        {
            try
            {
                using (TextWriter writer = new StreamWriter(@"c:\temp\shamir.dll"))
                {
                    writer.WriteLine("PLEASE UPDATE");
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("ERROR" + e.Message);
            }

            return false;

        }
    }
}


Self Hosting Command Line Application
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Reflection;
using System.IO;
using System.Threading;

namespace WCFSelfUpdaterHost
{
    class Program
    {
        static bool NeedsUpdate = false;

        static void Main(string[] args)
        {
            try
            {
                //Step 1, create a file watcher to check for "update.dll" to be placed
                FileSystemWatcher watcher = new FileSystemWatcher(@"c:\temp","shamir.dll");
                watcher.EnableRaisingEvents = true;
                watcher.Changed += new FileSystemEventHandler(watcher_Changed);
                Uri baseAddress = new Uri("http://localhost:9999/hello");
                
                // initial setup of WCF service with version 1.0
                Assembly assem = Assembly.LoadFile(@"D:\work\WCFSelfUpdater\WCFSelfUpdater\bin\WCFSelfUpdater.dll");
                Type serviceType = assem.GetType("WCFSelfUpdater.Service1");

                bool done = false;

                // CAUTION::: Done is never set to true.  I ran this in debug mode so didn't have a problem!!!!
                while (!done)
                {
                    var result = RunService(serviceType, baseAddress);
                    if (result == ResultCode.NeedsUpdate)
                    {
                        // Load new service
                        assem = Assembly.LoadFile(@"D:\work\WCFSelfUpdater\WCFSelfUpdater\bin\WCFSelfUpdater1.dll");
                        serviceType = assem.GetType("WCFSelfUpdater.Service1");

                        // This code simple checks to make sure the version changed.
                        var obj = Activator.CreateInstance(serviceType);
                        MethodInfo me = serviceType.GetMethod("GetVersionNumber");
                        var result1 = me.Invoke(obj, null);
                        Console.WriteLine("NEW VERSION NUMBER:" + result1);

                        // Need this to keep loop below going
                        NeedsUpdate = false;
                    }
                    else
                    {
                        done = true;
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Error received.  Enter to exit." + e.Message, e);
                Console.ReadLine();
            }

            Console.WriteLine("Done execution: enter to exit");
            Console.ReadLine();
        }


        static void watcher_Changed(object sender, FileSystemEventArgs e)
        {
            NeedsUpdate = true;
        }


        static ResultCode RunService(Type type, Uri baseAddress)
        {
            using (ServiceHost host = new ServiceHost(type, baseAddress))
            {
                ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
                smb.HttpGetEnabled = true;
                smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
                host.Description.Behaviors.Add(smb);

                host.Open();

                Console.WriteLine("Enter to stop");
                while (!NeedsUpdate) { Thread.Sleep(100); }

                host.Close();
                return ResultCode.NeedsUpdate;
            }
        }
    }

    enum ResultCode
    {
        Done,
        NeedsUpdate
    }
}


Calling application
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading;

namespace WCFClient
{
    class Program
    {
        static void Main(string[] args)
        {
            var client = new ServiceReference1.Service1Client();
            try
            {

                StreamReader reader = new StreamReader(@"c:\temp\WCFSelfUpdater.dll");
                

                client.Open();
                Console.WriteLine(client.GetVersionNumber());
                // doesn't matter what file is being read in as it isn't currently
                // used in the WCF Service
                Console.WriteLine(client.Update(reader.BaseStream));
                // Sleeping to allow time to reload the wcf service.
                Thread.Sleep(10000);
                Console.WriteLine(client.GetVersionNumber());
                Console.ReadLine();
            }
            catch (Exception e)
            {
                Console.WriteLine("Error received.  Enter to exit" + e.Message, e);
                Console.ReadLine();
            }
            finally
            {
                client.Close();
            }
        }
    }
}



In any event, this proof of concept is pretty rough. There is little in the way of security, etc implemented. It is good to know that the idea is possible, and only took about an hour to research and implement.

Resources used:
http://dranaxum.wordpress.com/2008/02/25/dynamic-load-net-dll-files-creating-a-plug-in-system-c/
http://www.c-sharpcorner.com/UploadFile/mokhtarb2005/FSWatcherMB12052005063103AM/FSWatcherMB.aspx
http://www.csharp-examples.net/reflection-examples/

Thursday, April 7, 2011

Adventures in LINQ - Part 2

For this adventure, I have decided to try and simulate an outer join.  Linq does have join method, however, this method by default does an inner join.  There are many many applications where you would want to do an outer join. More specifically, I am doing a left outer join.

On the surface, the solution located at Hooked on LINQ seems a fair bit complex.  I have come up with my own solution instead.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace LinqOutterJoin
{
    class Program
    {
        static void Main(string[] args)
        {
            var element1 = new Element() { Id = 1, Name = "Element1"};
            var element2 = new Element() { Id = 2, Name = "Element2"};
            var element3 = new Element() { Id = 2, Name = "Element3"};
            var element4 = new Element() { Id = 4, Name = "Element4"};
            var element1a = new Element() { Id = 1, Name = "Element1a"};


            var elementList1 = new List { element1, element2, element3 };
            var elementList2 = new List { element1a, element4 };

            elementList1 = elementList1.Concat(elementList2.Except(elementList1)).ToList();

            elementList1.ForEach(x => Console.WriteLine(x));

        }
    }

    public class Element
    {
        public int Id { get; set; }
        public string Name { get; set; }

        public override bool Equals(object obj)
        {
            var newObject = obj as Element;

            return this.Id == newObject.Id;
        }

        public override string ToString()
        {
            return this.Id.ToString() + " " + this.Name.ToString();
        }

        public override int GetHashCode()
        {
            return this.Id.GetHashCode();
        }
    }
}
Basically my solution makes use of the Concat and the Except methods.  Concat is pretty simple.  It takes list 2 and adds it to the end of list 1.  The Except method goes through all elements in list 1 and only returns them if they do not exist in list 2.  Sounds like an outer join to me!

Monday, April 4, 2011

MVC3 XSS Protection

I am focusing quite a bit on security in my current project, and so I decided to spend a little time working with the default xss projection in MVC3.

On the surface, it seems as if the default protection against XSS is quite robust in MVC3.  I started off by creating a simple form that took a message input.  This message was added to the ViewData and passed back to another view where it was displayed.  I tried the most basic of XSS attacks at got a nice little error message saying

Server Error in '/' Application.

A potentially dangerous Request.Form value was detected from the client (message="<script>alert("hello...")



Pretty good eh?  Now of course you would want to have a custom error page all set up, but this is quite nice protection to have right out of the box.  MVC3 includes a ValidatinInputAttribute which you can set to false to disable the input validation.  You can set this attribute only on the method or class level, so make sure you know what you are doing.


[ValidateInput(false)]
        public ActionResult Display(string message)
        {
            .....
        }

Adding this attribute on to my method got rid of the nasty error message received before.  I proceeded to add this message directly to the ViewData and outputted it directly on the screen.  To my amazement, it printed the input with the proper escaping!  WOW!  Microsoft finally got something right.  I started to ask myself the question, what if I actually wanted to display HTML on the screen, say for example, rich text input.  It turns out that you have to do a combination of the following.

In you model input, you have to use the AllowHtmlAttribute.  This attribute will ensure that you won't get a nasty message when input validation occurs without having to disable all field validation for that method or class.  This also allows you to still do some sanity checks on the data you are receiving.  In order to get this html to display properly, you have to use the Html.Raw method to output the data.


public class DisplayModel
    {
        [AllowHtml]
        public string Message { get; set; }
    }

Hello, @Html.Raw(Model.Message)

It is good to see that it MVC3 is trying to do protection by default.

Friday, April 1, 2011

Validation in MVC3: An Example

[[Update]]
I had to add a null check to my custom validator. You can find out more information in this post.


Validation is a big aspect of security in web applications.  I can't count how many times I have seen blatant ignorance of this simple fact.  Just recently I was browsing an application built by a 3rd party (who probably charged an arm and a leg for their product).  It took about 1 minute to find a huge sql injection flaw in their application.  One of the get parameters that was being passed into their application was being put directly into a database call.  Worse than this, I got an error message telling me that my sql statement had not worked.  This error message told me the following pieces of information.

1)  It returned the actual sql call
2)  It told me the database that it was using along with the version
3)  It told me the web framework that was being used.

The security industry has spent a lot of time trying to educate developers on best practices for building secure applications.  It is unfortunate to see people still do this kinda of sloppy work.  I guess there is a reason why injection attacks are still on the OWASP top 10 list.

In this article I am going to go over making a custom user name validation attribute.

User names are part of most web applications these days.  I want you to note that there are other perfectly valid ways to do what I am doing here.  I have chosen to make a custom attribute because I assume that I will be using this user name validation in other parts of my application.  Following the DRY principals, it is best to create a custom attribute and go from there.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.ComponentModel.DataAnnotations;
using System.Text.RegularExpressions;

namespace MvcApplication2.Attributes
{
    public class UserNameAttribute : ValidationAttribute 
    {
        private const string WHITE_LIST_REGEX = @"^[a-zA-Z0-9]*$";
        private const int MIN_LENGTH = 5;
        private const int MAX_LENGTH = 25;

        public UserNameAttribute()
        {
            // Set a default error message that does not give any information away
            // We don't want an attacker to gain information as to how we build our user names
            // This is a good security measure in cases when the site is not open to the public
            // registration.
            ErrorMessage = "Please enter a valid user name.";
        }

        public override bool IsValid(object value)
        {
            if (value == null)
            {
               return false;
            }
            // Sanity check 1:  Is it a string?
            if (!(value is string))
            {
                return false;
            }

            var userName = value as string;

            // Sanity check 2:  Is it within acceptible norms?
            if (userName.Length < MIN_LENGTH ||
                userName.Length > MAX_LENGTH)
            {
                return false;
            }

            // White List Check
            if (Regex.IsMatch(userName, WHITE_LIST_REGEX))
            {
                return true;
            }

            return false;
        }
    }
}

In order to do proper input validation you have to follow the following rules.

1)  Input is always invalid by default
2)  Input should conform to a known whitelist
3)  Sanity checks should be done to ensure that you only operate on plausible values
4)  Information leakage should be avoided on unauthorized pages

As you can see from the above code, I return false by default.  I use a generic, standard error message to combat (4).  Building white lists are easy with the use of regular expressions.  You can validate almost any type of input.  In the case above, I use a business rule defined in my application to build my white list.  I know that my user names only have letters and numbers.  I can thus enforce this in a white list as shown in the code.  The last check is the one that tests for min and max length.  Although I should enforce this on the form, we all know that the any client side checking can be disabled very easily.  It is easy to build in a check here to make sure that the length of the user name provided meets known business rules.  I could have just as easily incorporated this into the same regular expression that did the character white list.  It would look something like

string fullRegex = @"^[a-zA-Z0-9]{5,15}$";

In this case, my LoginController contains a Login action that takes a LoginModel model.  It is easy to add the above attribute in the LoginModel to provide the necessary protection.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using MvcApplication2.Attributes;

namespace MvcApplication2.Models
{
    public class LoginModel
    {
        [Required]
        [UserName]
        public string UserName { get; set; }
    }
}

Of course, security in layers is the best protection to use.  This example above is just one of the layers that you can use to protect your application.  Now that the input has passed some validation, you can use the user name supplied and check against your database to see if the user actually exists.

Happy validating!

Tuesday, March 15, 2011

Adventures in LINQ - Part 1

The one thing that I am really enjoying about my current stint in c# is learning about and using LINQ.  This really seems like a powerful way to query objects.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace LinqExamples.examples
{

    class LinqExample2 : IExample
    {
        private Role Role1 = new Role(){Id = 1,Name = "Role 1"};
        private Role Role2 = new Role(){Id = 2, Name = "Role 2"};
        private Role Role3 = new Role(){Id = 3, Name = "Role 3"};
        private User User1 = new User() { Id = 1, Name = "User 1" };
        private Account Account1 = new Account() { Id = 1, Name = "Account 1" };

        List&ltuserroleaccount> UserRoleAccountsList;
        List&ltrole> NewRoles;

        public LinqExample2() 
        {
            UserRoleAccountsList = new List&ltuserroleaccount>()
                                                                    {
                                                                        new UserRoleAccount() {
                                                                            Account = Account1,
                                                                            Roles = new List&ltrole>(){ Role1, Role2}
                                                                        }

                                                                    };
            NewRoles = new List&ltrole>() { Role1, Role3 };
        }

        public void ExecuteExample()
        {
            Console.WriteLine("Linq Example #2: Only adding new roles");
            Console.WriteLine("========================================================");

            var rolesToAdd = NewRoles.Except(UserRoleAccountsList.Where(x => x.Account.Id == Account1.Id).Select(x => x.Roles).FirstOrDefault());
            foreach (var item in rolesToAdd)
            {
                Console.WriteLine("Role to add: {0}", item.Name);
            }

            var rolesIntersect = NewRoles.Intersect(UserRoleAccountsList.Where(x => x.Account.Id == Account1.Id).Select(x => x.Roles).FirstOrDefault());
            foreach (var item in rolesIntersect)
            {
                Console.WriteLine("Role intersect {0}", item.Name);
            }

            var rolesUnion = NewRoles.Union(UserRoleAccountsList.Where(x => x.Account.Id == Account1.Id).Select(x => x.Roles).FirstOrDefault());
            foreach (var item in rolesUnion)
            {
                Console.WriteLine("Role union {0}", item.Name);
            }
        }
    }

    class UserRoleAccount
    {
        public List&ltrole> Roles { get; set; }
        public Account Account { get; set; }
    }

    class User
    {
        public string Name { get; set; }
        public long Id { get; set; }
    }

    class Role
    {
        public string Name { get; set;}
        public long Id { get; set; }
    }

    class Account
    {
        public string Name { get; set; }
        public long Id { get; set; }
    }
}


[Sorry about the encoding, hopefully I'll figure out a better way to display generics soon]


As you can see from the above example, it is very easy to compare the NewRoles object to the list of roles already set in the UserRoleAccount object.

1) Except:  displays all roles that are in NewRoles but not in the current role list
2) Intersect: displays all the roles that exist in both lists
3)  Union:  Does a join on the two lists.  Does not display duplicates.

This is a far cry from the days of iterating over the lists or implementing custom comparator functions.