Protect Your Code With System Accounts and Role Based Code Access Security
In this article I wanted to provide a simple example of how you can meet some of the best practices for secure code implementation and also some best practices in implementing a scalable architecture.
I tried to keep the prototype as simple as I could work it out but it’s still somewhat a more advanced project. Additional steps could/should be taken to further secure the data like the password in the .config file and the system account authentication data while in memory but again I wanted to keep the prototype simple. I should touch some of the data encryption/protection in a future article.
Still the article show some proven techniques that we also apply to the applications our development engineering teams develop under our custom development services.
The best practices I have used in the prototype are:
- Security in depth
Simply put security in depth follows the premise that there isn’t a silver bullet to cyber security. To secure your assets you’ll need to implement multiple layers of security.
Using a web application as an example this could look something like:
- Add a firewall between the web server and your internet access.
- Reduce your attack surface to a minimum by defaulting the firewall configuration to “deny all”. Then open only the port 443 to allow only inbound https traffic.
- Secure the web server by installing a certificate from a known certificate provider.
- Configure your web server to only allow traffic to the https port.
- If you are using a Proxied/NAT firewall and want to be annal about it configure your web server for https on a non standard port like the port 5000 for example. Then configure your firewall to allow inbound traffic on port 443 and then route it to the port 5000 on the web server. Yes, you guessed right I’m the annal kind of guy!
- Most of the servers, Linux or Windows come with a firewall installed and on by default. Even though your web server is in the DMZ and has a firewall in front of it don’t disable the firewall in the server. Keep it on and in this case configure the firewall to allow traffic only on port 5000 which is the port we configured in the web server.
We probably could keep going but you get the picture. Now this is just on the network side. We should follow a similar approach when it comes to protecting the code and the application itself.
Some of the best practices for code security:
- Implement code security from the beginning of the development project.
- Implement authentication using a well established authentication systems like Basic Authentication and https. This can be used in Linux hosted web servers like Apache or Tomcat. I you are hosting your application in IIS on a Windows server you can also use Basic Authentication with https but Microsoft recommends the use of Windows Authentication or preferably Federated Services.
- Secure code access (the focus of the prototype for this article):
- Run your web application under a specific system account.
- Access your middle tier using a different system account.
- Use role authorization for access to the business layer.
- If the application needs access to files in the OS make sure you configure your system account for read only access to the files.
- If the application needs access to data in a database configure another system account with permissions to the specific database only. If you are accessing Linux hosted databases you will need to setup the system account in the database. If you are hosting the database in a SQL Server Microsoft recommends the use of local Windows accounts.
- If you are hosting the web application in a Windows environment Microsoft recommends that all the system accounts be local least privilege Windows accounts. If one of the accounts is hacked the hacker won’t be able to get Admin privilege to the server. With the account being local the damage will be (hopefully) only in that server not to the entire network which would be the risk if you were using a domain system account.
- Validate user inputed data in the web application and again in your business layer. Remember the data is crossing layers and there can be the potential for tempering with it on the wire.
- Don’t store user passwords in the database. Store a hash of the password and use a salt code. During authentication of the user, hash the password the user typed in the application and compare it with the hash stored in the database.
Well, you really are going to have to do some reading but you get the gist. It’s called Security in Depth!
If you look above between securing the network and securing the application you can see the many layers of difficulty we have put in front of anyone trying to hack our environment. That’s the whole point, to make it as hard as possible. If one layer falls we still have many more and hopefully with the same level of difficulty to break into and just make it not worth it the time.
On the infrastructure side, besides the best practices above you can look at tools like for example Sophos Server Endpoint Security like the ones we use in all our servers and the services we provide.
. multi-layered development;
When developing a more complex application a best practice is to separate the different layers of the application. One of the benefits of the layered approach is to decouple the code for the Application layer and user interface from the code that implements the business logic for the business requirements and also the code that handles and manipulates the data.
The other benefit of the layered approach we can see represented in our prototype is that it provides the approach necessary to implement one of the very important security best practices which is multi-layered security or in the technical jargon security in depth.
Another benefit is maintainability of the code and research potential bugs in the code.
The other benefit of the layered architecture is improved performance. You can now independently unit test each layer, measure performance and try to get the best performance out of each of the layers.
If you are an advocate of test driven development (TDD) you can now independently work and unit test each of the layers. If you are working on your data layer you can unit test whatever method you are developing, validate the data the method handles. Once your data layer is tested you can start working on the business layer but at this point you know your data layer is tested and you can focus just on the business layer.
There’s good documentation on the layered approach that you can refer to.
By now you are already asking, “sure but where the heck is that prototype???”!
First you can download the solution here.
Well, if you check the picture to the left of the prototype’s Visual Studio solution it probably makes more sense seeing the 4 projects I have used to build it.
The first project is called DataProtection. This is the .Net implementation of the unmanaged DPAPI Windows library. I’m not going to dive into this library in this article. I’ll just say that we need this library so we can logon with our system account from within our code. I used the WindowsLogon method of this library.
The second project is called SecureMiddleTier.BusinessEntity. Simply put we implement all our business entities in their own assembly. The assembly is referenced by all the other layers to move data up and down the layers.
The third project is called SecureMiddleTier.BusinessLayer. This is where we implement the application’s business logic. In this case I have just one class with one method. To access the class if enforces that the account accessing it be part of the Windows group “QualTech System”. This is where the whole music starts.
You can easily test that this works by removing the system account from the QualTech System Windows group and run the console application in the solution. You’ll get a security exception as soon as you call the method GetItemList.
The account logon information is in the .config file of the console application in the SecureMiddleTier.Console project. You’ll have to create an account with the same name in the Windows Computer Management.
In the Computer Management select Groups and create the group “QualTech System”. Add the ServiceSysAcc account you created. Also make sure you set password that is in the .config file.
Once you are done with these configuration steps you are ready to step through the code and see how it all comes together.
* Get and authenticate the system account
using( windowsIdentity = SysAccountIdentity() )
* impersonate the system account
using( WindowsImpersonationContext windowsImpersonation = windowsIdentity.Impersonate() )
Thread.CurrentPrincipal = new WindowsPrincipal( windowsIdentity );
AppDomain.CurrentDomain.SetPrincipalPolicy( PrincipalPolicy.WindowsPrincipal );
* call the middle tier method
* as the system account
menuItems = ItemBl.GetItemList();
The code above is where everything comes together. The method SysAccountIdentity reads the system account’s user id, domain and password information from the configuration file. It authenticates the account using the DPAPI library and returns the WindowsIdentity object.
Using the WindowsIdentity object we use impersonation to call the business layer in the security context of the system account.
Because the WindowsIdentity and WindowsImpersonationContext are within using statements the code execution will ensure the destruction and disposal of these objects right after the call to the business layer ends to make sure no additional code in the application runs under the impersonation.
When you start executing the application it will start under your user id. You can check this but typing WindowsIdentity.GetCurrent().Name in Visual Studio’s Immediate Window.
After you execute the impersonation and right before calling GetItemList if you check the WindowsIdentity again it will now return the name of the impersonated system account.
Once the code execution exits the using statements the security context is back to your user id.
I hope you find this article useful. As always feel free to leave your comments or contact us at email@example.com with your questions.