Thursday, 10 December 2015

securityheaders.io, Public-Key-Pins, IIS and Azure

Testing Web Server Headers

securityheaders.io is a cool site to test the hardening of your web server. I suspect that many sites would score fairly low and although you could debate the relative value of each measure, why not aim for the top and make an attacker's life that much harder.

Well, our test site has just scored A and I hope to increase that to A+ once I have sorted out the Content Security Policy using my cool ASP.Net CSP builder!

Most of the headers are pretty easy. If you only use https for instance, you might as well set Strict-Transport-Security, which is cached for a period of time and tells the browser only to allow access to this site via https. This is cached in the browser and can be un-cached but helps an unwitting user from suffering some kind of downgrade by a MITM talking to our site with https and the victim's browser with http. Anyway, it's easy to add, I do it in Application_BeginRequest in my application.

Most of the others are pretty easy to and can be applied to most of our sites to prevent things like X-Framing and some amount of XSS protection although those that need to be applied to the entire server, rather than just the app, need to be added either manually to IIS via the interface or in Azure, using a startup script and either command-line or PowerShell.

I have these lines in my startup.cmd:

%windir%\system32\inetsrv\APPCMD.EXE set config -section:system.webServer/httpProtocol /+"customHeaders.[name='X-Frame-Options',value='DENY']"
%windir%\system32\inetsrv\APPCMD.EXE set config -section:system.webServer/httpProtocol /-"customHeaders.[name='X-Powered-By']"

Adding the header for denying framing and removing the one that tells the client what version of ASP.Net I am using!

IMPORTANT NOTE: You MUST save your startup.cmd as ASCII, otherwise the unicode header will confuse Windows command and appear as a weird character, which will break the first line of functionality and possibly have knock-on effects depending on its content. Click save-as and on the save button, choose "save with encoding" and I used US-ASCII as the encoding.

Public-Key-Pins

Public-Key-Pins is slightly more complex to carry out because it requires taking signatures of our SSL certificates and giving them to the browser. In a similar way to Strict Transport Security, the browser will remember these signatures for the amount of time we specify and will require that the signature of the SSL certificate match one of those specified in the header. The article here explains the process of signature gathering better than me but I want to then explain how you can do this on Azure using the startup task.

Backup Signatures

It is VERY important that you understand the purpose of back-up signatures. Imagine that you have told the browser to remember your pins for, say, 6 months. 2 months later, your site is hacked and an attacker has obtained the private key to your SSL certificate and now has the ability to decrypt communications between your customers and you. You decide to revoke the SSL certificate and you now need to obtain another one but you cannot use the same private key, because it was compromised, you instead generate a new one, get a new SSL certificate and deploy it. The browser does not know this and will insist that the new certificate matches one of its pinned signatures, which it won't UNLESS you create, say, 2 new CSRs for certs, add their signatures to your list, so that if the cert is compromised, you use one of these CSRs to get your new cert and its signature will already be valid. The linked article describes this, just make sure not to bypass it otherwise you will have irate customers asking how to clear the pin cache on their browser to access your site!

IIS and Azure

It's pretty easy in IIS to add the header that you have creating for your certificate signatures, you just open IIS Manager and choose "Reponse Headers" and add a new one with the correct key and value but in the case of Azure, you will want to automate this and apply it to the entire server, not just the app, so it applies to any resources that are not obtained from the application. This takes us back to our startup task.

Hopefully, you already have one of these to run various things whenever the role is started or restarted (because of this, make sure you don't always reboot after anything, otherwise you will cycle forever). I use something called startup.cmd, which is set to always copy to output in Visual Studio. I then have these lines in my ServiceDefinition.csdef:

<Startup priority="-2">
   <Task commandLine="startup.cmd" executionContext="elevated" taskType="simple" />
</Startup>

This lives under the WebRole section and tells the system to run the task with elevated permissions and simple just means that it runs as you would expect, rather than a foreground or background task.

You can then put whatever you need into it, including calling other scripts if required. I do the following in mine:

  1. Add X-Frame-Options DENY
  2. Remove X-Powered-By
  3. Add my Public-Key-Pins
  4. Add the web IP security IIS feature so I can...
  5. Enable IP security section to be able to dynamically blacklist IPs
  6. Enable dynamic IP security to provide rate-limiting
  7. Replace the default Location header (containing internal IPs) with a named URL
  8. Setup the best-practice for SSL cipher order using a Powershell script
  9. Install a stripheaders module to remove default Server header from IIS
The code for adding the public-key-pins is standard AppCmd stuff but NOTE that the double-quotes in the pin values need to be tripled " => """ so that they escape properly on the command line. This is probably not required in Powershell but I don't know.

%windir%\system32\inetsrv\APPCMD.EXE set config -section:system.webServer/httpProtocol /+"customHeaders.[name='Public-Key-Pins',value='pin-sha256="""wCJKYZwKJ8LcMVKrPHv+0cBua/ndTZ3aUeogjN6S0xI=""";max-age=2592000']"

I have removed two of the pins to make it simpler to read but you should get the idea! The max-age above is 1 month in seconds, which I will use for now.

The link recommends starting with a short max-age so that any problems can be fixed quickly and easily, you can also append "-Report-Only" to the header so that the browser will log any problems but not block you, this is ideal for testing that you have the correct signatures and format for the header. Another reminder to use the backup CSR process so that you can easily reset your SSL cert if a problem arises.

Wednesday, 2 December 2015

Web App Security - Are you doing it wrong?

Another day, another breach, another few million people are at best probably going to end up on a SPAM email list, at worst, they are going to have other accounts attacked with the leaked credentials. One day, we can hope that governments start appropriately punishing people for negligence in the web application security arena but don't hold your breath.

So are YOU doing it wrong?

If you are not using a modern popular framework as the foundation for your site, you are PROBABLY doing it wrong. There are hundreds of ways in which a site can be compromised, some subtle and some more obvious. Many of these vulnerabilities are squashed in popular modern frameworks or are at least harder to accidentally introduce. Pay attention to session, authentication and authorisation and make sure you know how the validation and encoding controls work.

If you don't know whether your site is susceptible to SQL (and other) injection attacks, you are DOING IT WRONG. If you do not have a fundamental way of protection from injection attacks such as stored procedures or parameterized queries YOU ARE DOING IT WRONG. Validation can help you but it is not a strong enough defence because it is easy to forget validation is a single instance, which can open up your whole site. Remember, it doesn't matter if you have 200 strong locked doors on your house, it only takes 1 open one to undermine it.

If you are not validating all input from the user YOU ARE DOING IT WRONG. User input is always untrusted. Not only can attackers bypass any client-side validation or assumptions that you make about correct use, they can do a whole load of things you probably haven't heard of. Your own staff and trusted friends can also accidentally do something incorrectly and that can have bad consequences.

If you have to write things like "Sign in securely" on your buttons, YOU ARE DOING IT WRONG. Teach your users about real markers of security, don't try and convince them you are secure just because you say so. It is meaningless and more importantly, it doesn't teach real security. If you must boast, use commercial badges such as Site Seal or "This site was code reviewed by XYZ Inc.".

If your logout button doesn't immediately log people out YOU ARE DOING IT WRONG. Log out means log out, people are used to hitting it and walking away. Don't ask if people are sure or leave them on a "just before we log you out...." page.

If you allow people to use weak passwords, YOU ARE DOING IT WRONG. You might assume that they are only letting themselves down but that is both untrue and arrogant. If their password is hacked from your site, an attacker could gain access to your system, he could attack other systems and he can potentially get much quicker information about password hashes if he knows you allow weak passwords.

If you store passwords in a reversible format or plain text and if you ever email people passwords YOU ARE DOING IT WRONG. Sure, sending someone a password seems useful but email is insecure and if the system can reverse passwords, there is no way to know if an attacker has accessed that functionality and gained people's passwords that are almost certainly used elsewhere. Give people a reset mechanism involving their email and/or security questions - the stuff you would check on the phone.

If you do not know the openness of your networks both internally and externally, YOU ARE DOING IT WRONG. An attacker might attack via the web application but might also send malware into your company. Do you know that the malware would still not be able to access sensitive data, even if it was running with the permissions of a valid corporate user? Think of it like someone sitting at their PC in your company what can they access? Would you even know? Could you block it easily if it was suspicious? Can you detect large data transfers?

If you store credit card numbers or cvv numbers, YOU ARE DOING IT WRONG. There are approved ways to do whatever you want, please don't think it is OK that you can just side-step those, make up your own rules and assume that your network security is good enough. We have enough proof now that it probably isn't.

If you have to search for security answers on Google, YOU ARE DOING IT WRONG. Most of the web is very hard to verify for correctness or maybe it was best-practice in 1995 but not any more. Get proper training, proper expertise and for goodness sake take it seriously. You would be frightened how many people still use MD5 for password hashes, this has been frowned on for over 10 years. Be wary of programming books also, which are often woefully poor on security techniques.

If you are not familiar with the work of OWASP, YOU ARE DOING IT WRONG. Owasp pool all of the best information from the industry, please don't think that you don't need that. If you read it all and realise you know it all, great, but you will probably be surprised at certain attack vectors that you would never have imagined. Free code-review checklists, free testing utilities - what's not to like?

If your management are not on-board with security, YOU ARE DOING IT WRONG. I suggest you find another job because you've already lost!

If you don't have a go-to person for security related questions, YOU ARE DOING IT WRONG. We can't all be experts but someone needs to be - perhaps you have a contractor or consultant to do this, as long as it's someone. Pooling mutual ignorance is the downfall of many a company.

If you don't perform code reviews and penetration testing of your sites, YOU ARE DOING IT WRONG. Yes, they cost a couple of thousand dollars but they are an awful lot cheaper than damage limitation and probably cost less than one Developer's monthly salary.

If you realise that security is a big and complicated topic and you have the humility to seek out expert help, if you continue to learn over time, if you pay attention to causes of breaches in the news, if you get trained in web application security controls and if you follow convention instead of inventing your own "good ideas" then YOU ARE PROBABLY DOING IT RIGHT!