Views: 7585
Number of votes: 9
Average rating:

Security checklist for Episerver 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. 

  • 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. 

  • Secure edit and admin mode

    For the strongest security, use a separate editor server. If the public server doesn't even have publishing capabilities, it can't be hacked. Check option 2 on the url below:
    http://world.episerver.com/blogs/Chris-Bennett/Dates/2009/12/Server-Architecture-Options-for-EPiServer/

    Shut down edit mode on public web front

    1
    2
    3
    4
    5
    6
    7
    8
    9
    <configuration>
      ...
      <location path="episerver">
        <system.web>
          <authorization>
            <deny users="*" />
          </authorization>
        </system.web>
      </location>

    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.

    1
    2
    3
    4
    5
    6
    7
    <system.webServer>
        <security>
            <ipSecurity allowUnlisted="false" denyAction="NotFound">
                <add allowed="true" ipAddress="123.456.0.0" subnetMast="255.255.0.0"/>
            </ipSecurity>
        </security>
    </system.webServer>
  • Validate user input

    Validate all forms of user input against a whitelist (valid chars) on the server side. I use a reg exp for this to check that string that come from the users can only contain normal charaters. Double check that the My profile page is validating input correctly since this would be my favorite target. LastName<script> anyone? If you need country specific whitelist, store the reg exp as a setting on a multisite.

    A few example of functions that clean user input by regex:

    public static string ToOnlyAlphaNumericInput(this string input)
    {
        if (input == null)
        {
            return null;
        }
        return Regex.Replace(input, @"[^\w]", string.Empty);
    }
    public static string ToOnlyNormalTextInput(this string input)
    {
        if (input == null)
        {
            return null;
        }
        return Regex.Replace(input, @"[^\w\.@!? ,/:+()'´-]", string.Empty);
    }
  • Validate querystring params

    Similar to the one above but easier to forget but equally important. Let's avoid those pesky sql injections and similar...

  • Html encode all output

    Especially important for all data that comes from other systems / user input to avoid javascript cross site scripting (XSS) attacks.

    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.

  • 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

  • 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.

  • 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.

  • Filter your lists for access rights

    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 showing restricted content.

  • 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).

  • 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:

    http://www.iis.net/learn/get-started/planning-for-security/understanding-built-in-user-and-group-accounts-in-iis

  • 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.

  • 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...

  • Double check your caching strategy

    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 VPPs

    Do you check access rights on all folders that you want? Might be that someone switched the flag bypassAccessCheck="false"

  • Secure your scheduled jobs

    The normal situation with these is that they simply don't work on production because you forgot to test to run them automatically. This is because they run as your current user when you press the run-manually key in admin but run as anonymous user when you run them automatically. You can fix this by setting the access right you want.
    http://world.episerver.com/blogs/Magnus-Rahl/Dates/2010/12/Run-a-scheduled-job-as-a-specific-role/
    Just make sure you know what you are doing if you run the job as admin. You might end up sending out restricted information if you are not careful...

  • Performance

    Although performance is a separate issue, bad performance can also be used to kill a website. I've seen major websites that can be shutdown for 10 minutes simply by searching for the letter 'a' in the search field. Check your IIS logs to find all slow pages and optimize them / add load balancing if needed. Remember that this performance issue applies to all components in your solution including SQL server, DNS, SSO etc. You should at least point out to the customer that it's a risk and let them decide if they want to solve it.

  • Email is not a secure channel

    Never send passwords and similar on email. Send a temporary link instead.

  • Remove unused membership providers

    If you don't use your windows membership provider, remove it.

  • Turn off detailed error messages for WCF
    1
    2
    3
    4
    5
    6
    7
    8
    <configuration>
       
        <system.serviceModel>
            ...
            <behaviors>
                <serviceBehaviors>
                    ...
                    <serviceDebug includeExceptionDetailInFaults="false" />
  • 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/

  • 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.

  • Check SSL certificate

    Old versions of protocols and algorithms are vulnerable to attacks. Use for instance:
    https://www.ssllabs.com/ssltest/analyze.html or
    https://cryptoreport.websecurity.symantec.com/checker/views/certCheck.jsp
    to check if you are using the latest and greatest without known security holes.

  • If Troy Hunt says jump
    the proper response is "How high?". Seriously. If a security expert alerts you of a security flaw of your website. Take it to a private channel, ask them to describe the problem, say "Thank you" and fix it. Just using the standard PR response "Don't worry!" won't cut it. Don't let your website get hacked or make the BBC news because of security flaws. If you can't get the funds for security for your website then show the one with money this article
    http://www.bbc.com/news/technology-42353478

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 2017 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. 

Great list Daniel!  This covers many of the OWASP points. 

I'd add to this to remember to secure any plugin URLs you add for custom plugins.  If you have a folder called Plugins for example simply add another Location node in your web.config to secure ~/Plugins

Where did the "Test this websites security" button go? ;-)

They got the message Oerjan :)

Lets leave it at that, sorry for my poor sense of developer humor.

I added your suggestion to the list Janaka. I've seen some admin plugins that wasn't secured correctly so it's definitely something to think about.

Neat list, but regarding validating user input: I'd rather do things properly and protect myself against SQL attacks in other ways than not letting "Dr. Ing. John-Peter Mc'Doe" register with his proper name. And for email-adresses, you can be pretty sure to miss out on something that's actually allowed by using one of the thousands of "email regexes" out there. I know 99% of people will do just fine with just [a-Z] in the name, but for those pesky exceptions, it's going to be a nightmare to use your site.

Protect against SQL injections by using properly protected existing APIs, or parameterized SQL if you're doing that part yourself.

So to sum up Arve:

Yes to using existing API and parameterized SQL

No to storing any user input as name or email or any text field without server validation vs white list of characters. Too risky for XSS if nothing else.

I will also add the possibility to secure the editing part with ip-restrictions so you are only alowing users that are logged in to your own network to access it.

https://www.stokia.com/support/misc/web-config-ip-address-restriction.aspx

Nice list, thanks a lot!

That's a decent cheap solution instead of having a separate server for editors. Definitely a useful option that I'll add to the list, thanks for the input!

Yes, message received.

I've blocked script inclusions in blog posts, at least the most obvious way of doing it. If you used some other trick please don't blog about it - drop us a line at epw@episerver.com. :)

Updated post with a few more items and some examples...

Updated post after my latest PEN test and OWASP test of a new website with some SSL suggestions...PEN test went great btw :)

Updated with some more tools from mr Jones

Hmm, wonder why it was dated to 1st of december 2016 again just because I updated it. Oh well...nm :)

I'd just say "Use HTTPS" regardless of anything. It's cheap and ensures the integrity of your site, even if you have no log-in-functionality. Ever used In flight-WIFI that puts ads on your site? This is in practice a man-in-the-middle-attack, which is not possible if running on HTTPS.

Chrome will get you warnings in your face when site is not running on HTTPS. I would say - that's not recommendation, but demand instead.

Here two pages that can test your site security.

https://www.ssllabs.com/ssltest

https://securityheaders.io

However, verify the implementation on a dev/test/stage environment first, before it is placed at a production environment.

Please login to comment.