Security checklist for Optimizely or .NET website
So you have built a great website for your customer, but is it secure? Code review your solution for these top issues.
Added some levels to indicate in what order I would do them in.
- Level A - Most important fixes / low effort that all sites should have yesterday.
- Level AA - Important / medium effort
- Level AAA - If you complete these you are probably top 1% of the sites out there in terms of security.
- Use Https
Without https you are wide open for a whole bunch of man-in-the-middle (MITM) attacks. Don't release a site without it. Use it on the entire site and not only on the logged in part. Check that you are using at least TLS 1.2 and disallow older versions
You can also add the following to global.asax for older .NET versions (4.5) for application start to force all outgoing requests to use TLS 1.2
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
- Secure edit and admin mode
For the strongest security, use a separate editor server node. If the public server doesn't even have publishing capabilities, that part is much more secure. Check option 2 on the url below:
Shut down edit mode on public web front123456789
If you can't afford it, at least choose hard-to-guess custom urls for util and cms and force your editors to use strong passwords.
Another cheaper option instead of a separate editor server is to use ip restrictions for the relevant directories to lock the server down.1234567
- Secure cookies
For an https site, your session cookies and authentication cookies should be marked as secure. Small fix to web.config required. Might need to have a few lines of code in the end request event in global.asax to handle the authentication cookie as well. See http://stackoverflow.com/questions/3428556/authcookie-not-secure-in-global-asax
<configuration> <system.web> <httpCookies requireSSL="true" />
- Turn off detailed errors and set compilation mode to release
Easily done in web.config. https://www.owasp.org/index.php/ASP.NET_Misconfigurations
- Avoid click jacking attacks
Add a response header for X-Frame-Options.
<system.webServer> <httpProtocol> <customHeaders> <add name="X-Frame-Options" value="SAMEORIGIN" /> </customHeaders> </httpProtocol>
- Restrict editors
Give them the least access rights needed and avoid making shared accounts. If something goes wrong, you want to know who did what. Use WebEditors to give access to edit mode only and a separate role to give access to the part of the content tree "Editors_Sweden, Editors_Norway" or similar.
- Remove test users
Especially all admin accounts to EPiServer and similar that was used during development needs to be deleted before launch.
- Use a service account for scheduled jobs and similar
It happens that the developer uses his own account instead of creating a separate service account to run scheduled jobs. Don't.
- Check that your search result page (SRP) never displays secured content.
Depending on search solution, this can be a problem. I've seen it a couple of times that excerps are shown on the SRP of secured content to the anonymous user. Double check that pages in waste basket isn't shown.
- Check that pages in waste basket is not shown / crashes site
If you list content in any way by using GetChildren / FindPagesByCriteria in the background, make sure you filter your list for access rights before displaying them. EPiServer controls do this out-of-the-box but if you use custom code to render your lists/menus you will have to solve this problem to avoid any issue. Test by sending some content to wastebasket and check that they are handled correctly. They should not be visible in menus or in search results for instance.
- Move your log files
Having your log files in web root is not a good idea from a security point of view. EPiServer has log4net as logging tool and by default they end up in webroot if you turn on logging. They should ideally be on a separate harddrive (since it happens that too large log files crash the website).
- IIS File access rights
Double check that your file access rights are correct and that noone added full access rights for everyone when they were troubleshooting something. Check this url if you are unsure:
- Email is not a secure channel
Never send passwords and similar on email. Send a temporary link instead.
- Remove unused membership providers (CMS 11 and earlier)
If you don't use your windows membership provider, remove it.
- Turn off detailed error messages for WCF
- Check vulnerabilities in used frameworks node modules / nuget
Check nuget packages with tools like Audit.Net visual studio plugin. Locking external packages to a specific version to avoid automatic upgrades by build servers is a good idea. Using signed packages if possible is another, especially for secondary feeds like a private feed. Beware of private package high jacking detailed below if you are using multiple package sources.
- Avoid leaking user data to countries you do not trust with frontend scripts (GDPR)
Some scripts like google analytics and hotjar provide great functionality but is also a security risk that needs to be discussed. How much user data from your site are you willing to let someone else in another country control? You can easily see to which country you are sending user data to using running this script in your google chrome console window
- Require strong passwords
Long passwords beat complex passwords. A minimum of 9 characters is recommended. Preferably more if your users don't start screaming too loud. This is easy to configure on your membership provider in web.config. Make it possible to copy passwords to enable password managers to work well.
- Use 2 factor authentication (2FA) for login
This will help secure your site against brute force attacks guessing passwords and also make it less sensitive if an email account is hacked. Many federated login services has support for 2FA.
- Check SSL certificate
Old versions of protocols and algorithms are vulnerable to attacks. Use for instance:
to check if you are using the latest and greatest without known security holes.
- Prevent cross site forgery
Do use the [ValidateAntiForgeryToken] attribute in MVC controller for post actions and @Html.AntiForgeryToken() in your views. Check out some nasty example on http://blog.stevensanderson.com/2008/09/01/prevent-cross-site-request-forgery-csrf-using-aspnet-mvcs-antiforgerytoken-helper/
- Have a company security feedback process
If Troy Hunt says jump the proper response is "How high?". Seriously though. You need to have a feedback function on your website where people can report security issues in a safe way. The proper response to someone reporting a security issue is "Thank you. We will look into it."
If you fail on this it might mean that someone decides to report the issue to the local paper instead to warn of an unsafe site. You don't want that
- Double check your content caching strategies
Make sure you never cache non-public content. E.g. if you cache the menu (that is filtered on access rights) and you then surf around with an admin user followed by an anonymous user you might show menu items that only admins should see to the anonymous user. Normally you don't need to cache EPiServer content lists if you just use GetChildren. EPiServer does that for you.
- Secure your data layer
Make sure you use an ORM like EF that doesn't allow SQL injections and that you never ever string concat an SQL statement together. If you run SQL stored procedures it might be worth checking those for string concatenation as well. I've seen some ugly code hidden there as well...
- Secure your service layer
For websites that are more application oriented, it's wise to secure your service layer so that some functions are only available to certain roles e.g. delete user can only be run by someone logged in as administrator. It's easy to solve this by simply hiding the button for this in the presentation layer but a more secure way is to add it above your service layer. I use custom attributes and AOP for this but the exact implementation is less important.
- Lock down webservices and handlers
It's easy to get lazy when EPiServer is handling security for content out-of-the-box. Check through your solution for other access points that the solution uses like webservices, web api, handlers etc and secure them / validate all input.
- Lock down plugins and other .NET files
Check if you have admin/editor plugins, regular aspx files and similar and secure them. This can normally be done easily by adding a location tag in web.config and restrict it to a certain role
- Validate querystring parameters and api input
Similar to the one above but easier to forget but equally important. Let's avoid those pesky sql injections and similar.
If a user sends a customerId, does that user actually have access to that customerId?
- Server side request forgery (SSRF)
With SSRF, the attacker can trick the backend itself to do requests to harmful urls. Example: Imagine you have a report generator that lists names of users in system, creates an html file and then generates a report based on that html. Now one user changes their name to <img src="http://badsite.com" />. That means that when server lists users and renders that html in backend it will try to get that image and send a request to that server. The user has tricked that backend to issue a request to a url it really shouldn't.
Clean all input from users and avoid letting users use html if possible.
Whitelist allowed characters. If possible also have a whitelist in firewall of allowed outgoing domains and ips.
- Html encode all output (XSS)
For webforms, check that you are using webcontrols that support htmlencoding or the
<span class="label label-info"><%#: Item.QuestionNumber %></span>
If you are using MVC, use the standard Model. syntax and stay away from Html.Raw as much as possible.
- Reverse tab nabbing
For external links that open in a new window, also set the rel attribute to noopener to protect against reverse tab nabbing attack
<a href="some-external-link" rel="noopener" target="_blank">Some External Website</a>
- Use my performance checklist to protect vs DDoS attacks
Link to performance checklist
- Enable HSTS
This is used to secure https one step furter to disallow any http requests whatsoever. If you only use a http => https redirect it leaves a security hole where a man-in-the-middle can hijack the request.
- Protect vs XXE (Xml Extended Elements)
Read more here. Part of OWASP top 10 list.
Avoid using XmlTextReader at all and make sure you have .NET version 4.6 or higher and you should be pretty safe.
If you have to use XmlTextReader use
XmlTextReader myReader = new XmlTextReader(new StringReader(xml)); myReader.DtdProcessing = DtdProcessing.Prohibit;
- Use Content Security Policy, CSP to protect against XSS attacks
- Use a single package source for nuget / node packages
If you don't you will likely be vulnerable to supply chain attacks. If you decide to use multiple sources like an additional private package source you will need to add extra security measures. This is because it's possible to create a new version of your private package on the public package source which will then be downloaded instead. Having a single package source protects against this. Signed packages and locking down versions to a specific version to avoid automatic upgrades on CI server also helps reducing risk.
- Use external PEN test to test security on your site
A bit expensive but worth it for sites that need higher security
If you went through this checklist you will hopefully have a more secure site than you had before. Do check out the OWASP top 10 for official recommendations as well. Nothing is unbreakable of course but let's avoid the obvious security holes at least. Ending up in the news because your website got hacked is not fun.