What a proper way to implement strong authentication security?

What a proper way to implement strong authentication security?

Old forum URL: forums.lhotka.net/forums/t/12061.aspx


sash_kr posted on Friday, July 05, 2013

Let's imagine next situation:
I'm a manager in big organization. That organization uses WinForms application (3 tier) written with CSLA framework. I have some skills in programming.
At one day, I open exe/dll of that application in tools like "ILSpy" or "Reflector" and export it to "csproj". I'm opening that "csproj" in Visual Studio and rewrite "Login" method:
this:

      public static void Login(string username, string password)
      {
            var identity = Library.CustomIdentity.GetCustomIdentity(username, password);
            Csla.ApplicationContext.User = new CustomPrincipal(identity);
      }

I change like this:

     public static void Login(string username, string password)
      {
            var identity = Library.CustomIdentity.GetCustomIdentity("admin");
            Csla.ApplicationContext.User = new CustomPrincipal(identity);
      }

I compile it back and load my modified application. In authentication window I enter any name, any password and voila - I'm working with "admin" rights.
Is it true?

JonnyBee replied on Friday, July 05, 2013

If your identity object expose a method to get the identity without supplying the password AND has unsigned assemblies - then yes you can do it. 

In your post you wil NOT have loaded roles tho'.

sash_kr replied on Friday, July 05, 2013

"In your post you wil NOT have loaded roles tho'."

 Why?

Let's see "ProjectTracker" sample:

    internal static PTIdentity GetPTIdentity(string username)
    {
        return DataPortal.Fetch<PTIdentity>(username);
    }

    private void DataPortal_Fetch(string username)
    {
        ProjectTracker.Dal.UserDto data = null;
        using (var ctx = ProjectTracker.Dal.DalFactory.GetManager())
        {
            var dal = ctx.GetProvider<ProjectTracker.Dal.IUserDal>();
            try
            {
                data = dal.Fetch(username);
            }
            catch (ProjectTracker.Dal.DataNotFoundException)
            {
                data = null;
            }
            LoadUser(data);
          }
      }

      private void LoadUser(ProjectTracker.Dal.UserDto data)
      {
            if (data != null)
            {
                  base.Name = data.Username;
                  base.IsAuthenticated = true;
                  base.AuthenticationType = "Membership";
                  base.Roles = new Csla.Core.MobileList<string>(data.Roles);
            }
            else
            {
                  base.Name = string.Empty;
                  base.IsAuthenticated = false;
                  base.AuthenticationType = string.Empty;
                  base.Roles = new Csla.Core.MobileList<string>();
            }
      }

 

So, roles list are loaded!

Quote from "Using CSLA 4" book:

"There is a cost to serializing the principal and including its data in the byte stream that flows
from client to server. Sometimes it can be cheaper to recreate the principal on the server for each
data portal request."

That's why we have a method with "username" parameter only. That is recommendation from book.

Everyone know how to make signed assembly - unsigned, with no problem.

 

So what's next?

 

 

JonnyBee replied on Sunday, July 07, 2013

The simple and recommended soluion by Microsoft is to use Windows Authentication - especially for computers that are registered in your domain.

So long as there is access to your assemblies on the client - any good hacker can look into the code - decompile or even inject IL-code drectly into the assembly. You should sign all your assemblies. However when you intall the app into your computer you are most likely running in full thrust but you can apply attributes to make the app run in partial thrust (sandboxed). 

Some good links:

Security Changes in .NET: http://msdn.microsoft.com/en-us/library/dd233103.aspx

Writing Secure Class Libraries ; http://msdn.microsoft.com/en-us/library/e942ksxt.aspx

Secure Coding Guidelines: http://msdn.microsoft.com/en-us/library/8a3x2b7f.aspx

 

 

sash_kr replied on Sunday, July 07, 2013

Thank you  JonnyBee  for the hard help.

Unfortunately, Windows Authentication are not always suitable.

To be honest, I know the answer to my question. But still wanted to hear the opinion of Rockford on this issue.So here is my solution of the situation.

First of all, we really need to get rid of a method that accepts a username  parameter only and leave a technique that takes name and password. At the end of this method we should remember password value in  ClientContext:

      public static void Login(string username, string password)
      {
            var identity = Library.CustomIdentity.GetCustomIdentity(username, password);
            Csla.ApplicationContext.User = new CustomPrincipal(identity);
            Csla.ApplicationContext.ClientContext["Password"] = password;
      }

 

Then, on the server-side, implementation of the interface IAuthorizeDataPortal:

    public class AuthorizeDataPortal : IAuthorizeDataPortal 
    {
        public void Authorize(AuthorizeRequest clientRequest)
        {
            if (Csla.ApplicationContext.LocalContext["FirstRun"] == null &&
                Csla.ApplicationContext.AuthenticationType == "Windows")
            {
                Csla.ApplicationContext.LocalContext["FirstRun"] = false;

                var username = (string)Csla.ApplicationContext.ClientContext["Username"];
                var password = (string)Csla.ApplicationContext.ClientContext["Password"];
                if (string.IsNullOrWhiteSpace(username))
                    Csla.ApplicationContext.User = new UnauthenticatedPrincipal();
                else
                    CustomPrincipal.Login(username, password); 
            }
        }
     }

 

Up to now I was unable to test this method but I think this is the only possible solution to the problem.

What do you think?

 

P.S.

Rockford's books are usually very detailed and describe a variety of situations. And there seemed to be a very sensitive subject and Rockford does not notice that matched his proposed method is not ideal and can lead to adverse consequences. And while not offering any solutions. For me it is very strange and so I just wanted to hear his answer.

JonnyBee replied on Sunday, July 07, 2013

A better solution would be to use a GUID similar to a session id in a web application - assign it on login (or a unique identifier for the user) and load the user principal information based on that. 

This is similar to Windows Authenticaion - where you basically have the users SID (Security Identifiier) being sent over the wire and the actual user data is loaded from AD. So you only have the username/password for the first login method. and after that use the GUID as a shared identifier. 

sash_kr replied on Sunday, July 07, 2013

Smile I think it's a good idea. Thanks.

I just would like to suggest Rockford to describe this problem and this solution in his next "Using CSLA X" book.

I'm new to CSLA and 3-tier architecture. So it was wierd to me recommendation of Rockford about "Load" user identity by only username.

RockfordLhotka replied on Monday, July 08, 2013

Security is always a cost/benefit trade-off. Anyone who's done any security work will tell you that it is critical to do threat analysis and then make a business decision about which threats are cost effective to address.

If you are honestly worried about someone decompiling, hacking, and rewriting your client-side code then you are in a very difficult place and must expect to fight a permanent running (and expensive) battle against the hackers to whom you are providing your software. The best example of this scenario is the online gaming world (where I spend a lot of time), and the constant give and take between game creators and hackers. Some of the best games in history (like CounterStrike, or Battlefield 2142) were utterly destroyed by hackers because the game creators couldn't afford the cost of the ongoing battle. More recently things have gotten a little better thanks to tools like PunkBuster and others.

If your threat analysis indicates that you really need to worry about that type of hacking then I can't recommend that you use .NET, much less CSLA. You should probably use C or assembly so as to make your code as unfriendly to humans as possible, and frankly even that won't be enough. So (assuming you aren't building a game) your best bet is to run your app on Citrix (or equivalent) servers so the users have no direct access to your software.

Copyright (c) Marimer LLC