Hardening and Security Guidance

Introduction

ownCloud aims to ship with secure defaults that do not need to get modified by administrators. However, in some cases some additional security hardening can be applied in scenarios were the administrator has complete control over the ownCloud instance. This page assumes that you run ownCloud Server on Apache2 in a Linux environment.

ownCloud will warn you in the administration interface if some critical security-relevant options are missing. However, it is still up to the server administrator to review and maintain system security.

Limit on Password Length

ownCloud uses the bcrypt algorithm. It only verifies the first 72 characters of passwords. This applies to all passwords you use in ownCloud: user passwords, passwords on link shares and passwords on external shares.

Rate Limiting

Currently ownCloud deliberately does not provide any form of rate-limiting (though it does provide brute-force protection). This is because ownCloud needs to integrate in to a diverse range of environments and infrastructure, which often already provide specialized rate-limiting solutions, e.g., Apache, HAProxy, and F5.

If you are yet to implement a rate-limiting solution for your ownCloud instance, start by retrieving a list of all active routes. This information is obtained by running occ’s security:routes command, as in the following example.

sudo -u www-data ./occ security:routes

It should print a list of all the routes as in the following truncated example.

+-----------------------------------------------------------+-----------------+
| Path                                                      | Methods         |
+-----------------------------------------------------------+-----------------+
| /apps/encryption/ajax/adminRecovery                       | POST            |
| /apps/encryption/ajax/changeRecoveryPassword              | POST            |
| /apps/encryption/ajax/getStatus                           | GET             |
| /apps/encryption/ajax/setEncryptHomeStorage               | POST            |
| /apps/encryption/ajax/updatePrivateKeyPassword            | POST            |
| /apps/encryption/ajax/userSetRecovery                     | POST            |
| /apps/federatedfilesharing/                               | GET             |
| /apps/federatedfilesharing/notifications                  | POST            |
+-----------------------------------------------------------+-----------------+

With this information, you can begin customizing a rate-limiting solution specific to your ownCloud installation.

Operating system

Enable hardening modules such as SELinux

We also recommend to enable hardening modules such as SELinux where possible. See SELinux Configuration to learn more about SELinux.

Deployment

Place data directory outside of the web root

A simple but efficient way to increase the security of your data is to place your data directory outside of the Web root (i.e. outside of /var/www), ideally at the time of installation.

Disable preview image generation

ownCloud is able to generate preview images of common file types such as images or text files. By default, the preview generation for some file types that we consider secure enough for deployment is enabled. However, administrators should be aware that these previews are generated using PHP libraries written in C which might be vulnerable to attack vectors.

For high security deployments, we recommend disabling the preview generation by setting the enable_previews switch to false in config.php. As administrator you are also able to manage which preview providers are enabled by modifying the enabledPreviewProviders option switch.

Use HTTPS

Using ownCloud without an encrypted HTTPS connection opens up your server to a man-in-the-middle (MITM) attack and risks the interception of user data and passwords. It is a best practice, and highly recommended, to always use HTTPS on production servers and to never allow unencrypted HTTP.

For information on how to setup HTTPS, consult the documentation of your Web server. The following examples apply to Apache.

Redirect all unencrypted traffic to HTTPS

To redirect all HTTP traffic to HTTPS, administrators are encouraged to issue a permanent redirect using the 301 status code. Using Apache, this can be achieved by adding a setting such as the following in the Apache VirtualHosts configuration containing the <VirtualHost *:80> entry:

Redirect permanent / https://example.com/

Enable HTTP Strict Transport Security

While redirecting all traffic to HTTPS is good, it may not completely prevent man-in-the-middle attacks. Therefore we recommend setting the HTTP Strict Transport Security header, which instructs browsers to not allow any connection to the ownCloud instance using HTTP, and it attempts to prevent site visitors from bypassing invalid certificate warnings.

This can be achieved by adding the following settings in the Apache VirtualHost file containing the <VirtualHost *:443> entry:

<IfModule mod_headers.c>
  Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains"
</IfModule>

If you don’t have access to your Apache configuration, it is also possible to add this to the main .htaccess file shipped with ownCloud. Make sure you’re adding it below the line:

#### DO NOT CHANGE ANYTHING ABOVE THIS LINE ####

This example configuration will make all subdomains only accessible via HTTPS. If you have subdomains not accessible via HTTPS, remove includeSubDomains.

This requires the mod_headers extension in Apache.

Proper SSL configuration

Default SSL configurations by Web servers are often not state-of-the-art and require fine-tuning for an optimal performance and security. The available SSL ciphers and options depend completely on your environment, therefore we can’t provide a general recommendation.

However, We do recommend using the Mozilla SSL Configuration Generator to generate a configuration suitable for your environment, and the free Qualys SSL Labs Tests gives good guidance on whether your SSL server is correctly configured.

Also ensure that HTTP compression is disabled to mitigate the BREACH attack.

Use a dedicated domain for ownCloud

Administrators are encouraged to install ownCloud on a dedicated domain such as cloud.domain.tld instead of domain.tld to benefit from the same-origin policy.

Ensure that your ownCloud instance is installed in a DMZ

As ownCloud supports features such as Federated File Sharing, we do not consider Server Side Request Forgery (SSRF) a threat. Given all our external storage adapters, this can be considered a feature and not a vulnerability.

This means that a user on your ownCloud instance could probe whether other hosts are accessible from the ownCloud network. If you do not want this, you need to ensure that your ownCloud is installed in a segregated network and proper firewall rules are in place.

Basic security headers are provided by ownCloud already in a default environment. These include:

X-Content-Type-Options: nosniff

Instructs some browsers to not sniff the MIME type of files. This is used for example to prevent browsers from interpreting text files as JavaScript.

X-XSS-Protection: 0

The cross-site scripting filter is deprecated and not used in modern browsers anymore.

X-Robots-Tag: none

Instructs search engines to not index these pages.

X-Frame-Options: SAMEORIGIN

Prevents embedding of the ownCloud instance within an iframe on other domains to prevent clickjacking and similar attacks.

These headers are hard-coded into the ownCloud server and need no intervention by the server administrator.

For optimal security, administrators are encouraged to let the Web server deliver these HTTP headers. To do this, configure Apache to use the .htaccess file and enable the following Apache modules:

  • mod_headers

  • mod_env

Verify this security change by accessing a static resource and check the above mentioned security headers are delivered.

Use Fail2ban

Another approach to hardening ownCloud server is to use an intrusion detection system. An excellent one is Fail2ban. Fail2ban is designed to protect servers from brute force attacks. It works by scanning log files (such as those for ssh, web, mail, and log servers) for certain patterns, specific to each server, and taking actions should those patterns be found.

Actions include banning the IP from which the detected actions originate. This makes the process more difficult and prevents DDOS-style attacks. However, after a predefined time period, the banned IP is usually unbanned again.

This helps if the login attempts were genuine, so that users don’t lock themselves out permanently. An example of such an action is users attempting to brute force log in to a server via ssh. In this case, Fail2ban would look for something similar to the following in /var/log/auth.log:

Mar 15 11:17:37 yourhost sshd[10912]: input_userauth_request: invalid user audra [preauth]
Mar 15 11:17:37 yourhost sshd[10912]: pam_unix(sshd:auth): check pass; user unknown
Mar 15 11:14:51 yourhost sshd[10835]: PAM 2 more authentication failures; logname= uid=0 euid=0 tty=ssh ruser= rhost=221.194.44.231  user=root
Mar 15 11:14:57 yourhost sshd[10837]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=221.194.44.231  user=root
Mar 15 11:14:59 yourhost sshd[10837]: Failed password for root from 221.194.44.231 port 46838 ssh2
Mar 15 11:15:04 yourhost sshd[10837]: message repeated 2 times: [ Failed password for root from 221.194.44.231 port 46838 ssh2]
Mar 15 11:15:04 yourhost sshd[10837]: Received disconnect from 221.194.44.231: 11:  [preauth]
If you’re not familiar with what’s going on, this snippet highlights a number of failed login attempts.

Using Fail2ban to secure an ownCloud login

On Ubuntu, you can install Fail2ban using the following commands:

apt update && apt upgrade
apt install fail2ban

Fail2ban installs several default filters for Apache and various other services, but none for ownCloud. Given that, we have to define our own filter. To do so, you first need to make sure that ownCloud uses your local timezone for writing log entries; otherwise, fail2ban cannot react appropriately to attacks. To do this, edit your config.php file and add the following line:

'logtimezone' => 'Europe/Berlin',
Adjust the timezone to the one that your server is located in, based on PHP’s list of supported timezones.

This change takes effect as soon as you save config.php. You can test the change by:

  1. entering false credentials at your ownCloud login screen, then

  2. checking the timestamp of the resulting entry in ownCloud’s log file.

Next, define a new Fail2ban filter rule for ownCloud. To do so, create a new file called /etc/fail2ban/filter.d/owncloud.conf, and insert the following configuration:

[Definition]
failregex={.*Login failed: \'.*\' \(Remote IP: \'<HOST>\'\)"}
ignoreregex =

This filter needs to be loaded when Fail2ban starts, so a further configuration entry is required to be added in /etc/fail2ban/jail.d/defaults-debian.conf, which you can see below:

[owncloud]
enabled = true
port = 80,443
protocol = tcp
filter = owncloud
maxretry = 3
bantime = 10800
logpath = /var/owncloud_data/owncloud.log

This configuration:

  1. Enables the filter rules for TCP requests on ports 80 and 443.

  2. Bans IPs for 10800 seconds (3 hours).

  3. Sets the path to the log file to analyze for malicious logins

The most important part of the configuration is the logpath parameter. If this does not point to the correct log file, Fail2ban will either not work properly or refuse to start.

After saving the file, restart Fail2ban by running the following command:

service fail2ban restart

To test that the new ownCloud configuration has been loaded, use the following command:

fail2ban-client status

If "owncloud" is listed in the console output, the filter is both loaded and active. If you want to test the filter, run the following command, adjusting the path to your owncloud.log if necessary:

fail2ban-regex /var/owncloud_data/owncloud.log /etc/fail2ban/filter.d/owncloud.conf

The output will look similar to the following if you had one failed login attempt:

fail2ban-regex /var/www/owncloud_data/owncloud.log /etc/fail2ban/filter.d/owncloud.conf

Running tests
=============

Use   failregex file : /etc/fail2ban/filter.d/owncloud.conf
Use         log file : /var/www/owncloud_data/owncloud.log

Results
=======

Failregex: 1 total
|-  #) [# of hits] regular expression
|   1) [1] {.*Login failed: \'.*\' \(Remote IP: \'<HOST>\'\)"}
`-

Ignoreregex: 0 total

Date template hits:
|- [# of hits] date format
|  [40252] ISO 8601
`-

Lines: 40252 lines, 0 ignored, 1 matched, 40251 missed

The Failregex counter increases in increments of 1 for every failed login attempt. To unban an IP locked either during testing or unintentionally, use the following command:

fail2ban-client set owncloud unbanip <IP>

You can check the status of your ownCloud filter with the following command:

fail2ban-client status owncloud

This will produce an output similar to this:

Status for the jail: owncloud
|- filter
|  |- File list:    /var/www/owncloud_data/owncloud.log
|  |- Currently failed: 1
|  `- Total failed: 7
`- action
   |- Currently banned: 0
   |  `- IP list:
   `- Total banned: 1