HomeDev GuideAPI Reference
Dev GuideAPI ReferenceUser GuideGitHubNuGetDev CommunitySubmit a ticketLog In
GitHubNuGetDev CommunitySubmit a ticket

Security checklist

Describes common security issues for websites.

(Thanks to Daniel Ovaska for providing the foundation for this checklist.)

This topic provides an overview of common security issues to be aware of when building websites.

Background

Optimizely provides a flexible and granular user/role-based authorization security model, which reflects best practice approaches widely employed by enterprise-level platforms. Individual access can be controlled through Optimizely's standard authentication and authorization mechanisms.

User and role permissions can be enforced to any section of the website, and also to all levels of content, including products, pages, and content blocks. It is also possible to secure standard CMS navigation and UI elements based on user/group permissions.

Using the Optimizely user interface, administrators can create users, groups, and roles to grant permissions to content items, pages, types of pages, blocks, media, properties, files, folders, and language variations. The platform can also inherit roles and permissions from a role membership provider such as Microsoft's Membership and Role Provider model. 

Access to editing is administered by Optimizely Content Management System (CMS) admin users who can then define what groups are given access to editing. In addition to this, permissions can be associated with properties to ensure that only the allowed tabs and properties can be filled in by authors during the editing experience.

Optimizely enables templates to be shared across sites including styles and branding if desired. Once created templates can be applied with permissions to only be visible to certain users/groups of the CMS. See Security for more details.

Checklist

Consider the suggestions below to make your site as secure as possible.

  • Use HTTPS
    Without HTTPS you are wide open for a whole bunch of man-in-the-middle (MITM) attacks. Do not release a site without it. Use it on the entire site and not only on the logged-in part.
  • Secure edit and admin views
    For the strongest security, use a separate editor server. If the public server does not even have publishing capabilities, it cannot be hacked. See option 2 in the blog post Server Architecture Options for Optimizely .
    Shut down edit mode on public web front:
<configuration> 
          ...
          <location path="episerver">
            <system.web>
              <authorization>
                <deny users="*"/>
              </authorization>
            </system.web>
          </location>
If you cannot have a separate editor server, at least choose hard-to-guess custom URLs for _util_ and _cms_ and force your editors to use strong passwords.  

Another option instead of a separate editor server is to use IP restrictions for the relevant directories to lock the server down:
<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 (with valid characters) on the server side. You can, for example, use a regular expression to check that the string that comes from the users only contain normal characters. If you are using user profile pages, double-check that these are validating input correctly since they may targeted. If you need country-specific whitelists, store the regular expression as a setting on a multi site.
    A few examples of functions that clean up the 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 parameters
    Similar to the one above; however, easier to forget but no less important.
  • HTML encode all output
    This is especially important for all data that come from other systems/user input to avoid JavaScript cross-site scripting (XSS) attacks.
    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
    Optimizely is handling security for content out-of-the-box, but you should check your solution for other access points such as web services, web API, and handlers, and secure them or 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 restricting it to a certain role.
  • Secure cookies
    For an HTTPS site, your session cookies and authentication cookies should be marked as secure. This requires a small change in the web.config and you may 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 (debug="false" in web.config)
    This is easily done in web.config, set clientResources debug to false in the <episerver.framework> section.
  • 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 creating shared accounts. If something goes wrong, you want to know who did what.
  • Remove test users
    Especially all admin accounts used during development need 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, use a specific service account for tasks like these instead.
  • Check that your search result page (SRP) never displays secured content
    Make sure that excerpts of secured content are not displayed to anonymous users on the search result page.
  • 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. The CMS controls do this out-of-the-box but if you use custom code to render your lists or menus, you have to solve this problem to avoid showing restricted content.
  • Move your log files
    Having your log files in the web root is not a good idea from a security point of view. CMS has log4net as its logging tool and by default log files end up in the web root if you turn on logging. Ideally, they should be on a separate hard drive (because too large log files may crash the website).
  • File access rights
    Double-check that your file access rights are correct and that noone has added full access rights for everyone when troubleshooting. Check this URL if you are unsure: Understanding Built-In User and Group Accounts in IIS 7.
  • Secure your service layer
    For websites that are more application oriented, it is wise to secure your service layer so that some functions are only available to certain roles, for example, delete user can only be run by someone logged in as administrator. It is easy to simply hide the button for this in the presentation layer but a more secure way is to add it above your service layer. One way of implementing this is using custom attributes and AOP.
  • Secure your data layer
    Make sure you use an Object/Relational Mapping (ORM) framework like Entity Framework (EF) that does not allow SQL injections and that you never string concatenate an SQL statement together. If you run SQL stored procedures, it might be worth checking those for string concatenation as well.
  • Double-check your caching strategy
    Make sure you never cache non-public content. For example, if you cache a menu (filtered on access rights) and you then navigate the site with an admin user followed by an anonymous user, you may display menu items to the anonymous user that only admins should see. Normally, you do not need to cache Optimizely content lists if you just use GetChildren; Optimizely does that for you.
  • Secure your Virtual Path Providers (VPPs)
    Do you check access rights on all folders that you want? Someone might have switched the flag bypassAccessCheck="false".
  • Secure your scheduled jobs
    If you find that your scheduled jobs do not work on your production site, it may be because scheduled jobs run as your current user when you press Start manually in admin view, but as anonymous user when you run them automatically. If the anonymous access rights are not enough, you have to log in programmatically to execute the job as a specific user.
    See Magnus Rahl's blog post 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. Check your IIS logs to find all slow pages, and optimize them and add load balancing if needed. Remember that this performance issue applies to all components in your solution including the SQL server, DNS, SSO etc. 
  • Email is not a secure channel
    Never send passwords and similar on email. Send a temporary link instead.
  • Remove unused membership providers
    Remove your Windows membership provider if you do not use it.
  • Turn off detailed error messages for Windows Communication Foundation (WCF)
<configuration>
            …
            <system.serviceModel>
                ... 
                <behaviors>
                    <serviceBehaviors>
                        ...
                        <serviceDebug includeExceptionDetailInFaults="false"/>
  • Prevent cross-site forgery
    Use the [ValidateAntiForgeryToken] attribute in the MVC controller for post actions and the @Html.AntiForgeryToken() in your views. For more information, see this blog post: Prevent Cross-Site Request Forgery (CSRF) using ASP.NET MVC’s AntiForgeryToken() helper.
  • Require strong passwords
    Long passwords beat complex passwords. A minimum of 9 characters is recommended. Preferably more if your users do not start screaming too loud. The password rules are easy to configure on your membership provider in web.config. See Authentication and authorization.
  • Check your SSL certificate
    Old versions of protocols and algorithms are vulnerable to attacks. Use SSL Server Test (for instance) to check if you are using the latest versions without known security holes.