Thursday, November 6, 2014

Simple Security Tips for .Net Developers

Intro
As developers, it is our responsibility to make sure our code is secure. If you haven't coded with security in mind before, a good place to start is by learning. So, today we'll see a few small tips you can start using right away to make your code more secure. Eventually you might end up designing security into your systems from the get-go, but let's start simple and see a few practical tips.

Use HTTPS

Information transmitted over the web is generally done on port 80 (HTTP), or 443 (HTTPS). Information transmitted via HTTP is insecure; HTTPS is encrypted using keys. If you have sensitive information including personally identifiable information, authentication information such as passwords, sensitive financial information, or anything else you want to protect, get an SSL certificate for your domain. This allows HTTPS traffic, and you can then force clients to use HTTPS instead of HTTP.

Http Header: X-Frame-Options

Have you ever heard of clickjacking? It's a form of attack where the user sitting at a web browser performs actions on one site when they think they are performing actions on another. Picture this: You have a site that allows users to enter and remove widgets. You have a "delete all widgets" button on your website. Someone else, who is just a malicious chode, puts your site in an iframe on their website. They then cover the stuff on your site with their own html elements using sneaky CSS and/or JavaScript, so that the user thinks they're clicking on a button that says "give me a free ipad" on one site, when in reality they're clicking your button that says "delete all widgets". Oops! It turns out this attack is pretty easy to thwart, just set an http header named x-frame-options to a value of "deny". You can do this in IIS, or my preferred method is to do so in code in your global.asax:

void Application_BeginRequest(object sender, EventArgs e)
{
    HttpContext.Current.Response.AddHeader("x-frame-options", "DENY");
}

This simply prevents browsers from rendering your website within a frame or iframe. You may still have to worry about older browsers, but consider this an opportunity for research on your own :)


Meta Tag: Charset

Would you believe that people can attack your website by passing it information using a character set other than what you expect? For example, if you expect users to type in utf-8 information, which is fairly standard, but they enter in utf-8 character sequences, they just might be able to sneak some JavaScript into your entries. Such an attack is called a Cross Site Scripting attack, or CSS or XSS for short. The good news is that this is also quite easy to get around. My preferred method of preventing this type of attack is done within the html of each of your pages, as per the following:

<html>
  <head>
    <meta charset="UTF-8">
  </head>
</html>

This tells the browser not to accept any form of input from the client unless it is UTF-8.


Restrict Access

This is just a general security tip which is useful in many situations: Restrict access by default, and give access only as necessary for a person to get done what needs doing. Don't give more access or rights than are necessary. If someone asks if you want to do the bare minimum, proudly exclaim "yes!". It's more secure.

Sql Parameters

Many .Net developers don't realize just how easy it is to hack the database behind a website using the website to do the dirty work. This is called a SQL Injection attack. I could go into a lot more detail showing you how to make such an attack, but hey, I have a wedding to attend this weekend so my time is gold this evening. Here is some code that will do a pretty good job of preventing such issues, and bonus: your code is cleaner than if you just concatenated the whole query together.

public void DoStuff()
{
  using (var conn = new SqlConnection("some conn string"))
  {
    var command = new SqlCommand("select * from SomeTable where SomeCol = @SomeCol", conn);
    command.Parameters.Add(new SqlParameter("@SomeCol", Request.QueryString["someval"]));
    command.Connection.Open();
    command.ExecuteNonQuery();
  }
}

In this example we are running a query which is based off a value the user typed into the querystring of the request. Using a SqlParameter in the command's Parameters list, we have ensured that the data passed to the database is safe and will not allow the caller to use SQL Injection.

Validate Info Entered/Imported

This is another general bit of information: Validate all information that is input into your system, whether it's from a user, another system, a file, a database, or other. If it's going through your system, validate! You never can tell what type of data might get tossed your way, so be prepared and prevent it from taking your system down by validating it's of the type and size you expect, and possibly within a range of valid values you might expect.

Encrypt Sensitive Data

This might seem like a bit of a no-brainer but I feel it needs mentioning. If you have sensitive information such as passwords, Personally Identifiable Information, sensitive financial information, or other info you don't want unauthorized people to get hold of, encrypt the data. There are many ways to do this in both .Net and in database platforms including SQL Server, you'll have to research this part on your own. Or hey, give me a buzz and I'll help out! I just don't have the time or space on this blog to give examples at the moment, as it can get pretty complex. Good, strong encryption is not for the faint of heart, but it's necessary for many things.

1-Way Encryption for Auth Passwords

Speaking of encryption, passwords! When setting up your authentication system you can take it a step further by creating a 1-way encryption of the passwords of your users. Why do that? Even if an attacker somehow gets hold of your database, they still won't be able to decrypt the passwords in order to use the logins of others. You may be wondering how you can then authenticate your users...the concept is simple, even if the encryption code is more complex: You just make sure that any given input value encrypts to the same value. So for example, I have a user named "bob" whose password is "hi!" The encrypted version of this password is "1234asdlfkj214o2i;;". When bob logs in he types in "hi!", so I then encrypt the typed in value and check to make sure it's the same as the encrypted value stored in my database.

Strong Passwords

So that prior example with a password of "hi!" isn't exactly a great password. Why not? The longer a password is, and the more nonsensical, the less vulnerable it is to something called a brute force attack (more specifically, a dictionary attack) where the attacker has a program try to randomly guess your password. They try words from the dictionary, including 1337-speek. So, make your users use better passwords. Instead of "hi!", suggest "124ksdfAAA!!~x@". This is not going to be vulnerable to a dictionary attack specifically, and makes it less vulnerable to a brute force attack in general. Don't carry this too far though; the stronger password enforcement you have in place, the more likely the user is to rebel and write that super-secure password on a post-it note stuck to their monitor. Backfire-city!

2-Factor Auth

Lately a concept called 2-factor authentication has been gaining steam. It's a simple concept: use more than 1 form of authenticating a specific user. Popular choices include a mobile app with a pseudo-randomly generated code ala World of Warcraft, a text message with a specific code sent to the user's mobile phone, fingerprint analysis, voice recognition, and others. In the world of websites this generally means you have your standard id and password along with some special code that you acquire elsewhere. Neat huh? Simple concept, but the coding might take a bit.

Validate Email Addresses

My last tip of the day: If you make users sign up to your system using their email address, and this is the email address they'll use for password reset and other such administrative features, validate the user actually owns the email address when the account is created. This is usually as simple as sending the user a unique activation link to the email address on the account as soon as the account is created, making sure the user can't login to the account until they activate it via the link you emailed. Once they click said link, the account is usable. 

What's Next?

Clearly there are many more good security tips out there, many more vulnerabilities to discuss, and all of the above topics could use a lot more detail. Spend some time on your own researching a few things.

Do you have a simple secure coding tip to share? Say so in the comments below!

Resources

Clickjacking Defense Cheat Sheet
Html Meta Charset

No comments:

Post a Comment