]> source.dussan.org Git - nextcloud-server.git/commitdiff
Show warning page when accessing server from an untrusted domain
authorVincent Petry <pvince81@owncloud.com>
Wed, 5 Mar 2014 14:02:05 +0000 (15:02 +0100)
committerVincent Petry <pvince81@owncloud.com>
Thu, 6 Mar 2014 10:51:08 +0000 (11:51 +0100)
Added early check for the requested domain host and show a warning
page if the domain is not trusted.

lib/base.php
lib/private/request.php

index 351b91b7dfa2d145fdffbb364a2785e9710db068..82612a187717c571089ab832bdf748f98f0da641 100644 (file)
@@ -694,6 +694,22 @@ class OC {
                        exit();
                }
 
+               $host = OC_Request::insecureServerHost();
+               // if the host passed in headers isn't trusted
+               if (!OC::$CLI
+                       // overwritehost is always trusted
+                       && OC_Request::getOverwriteHost() === null
+                       && !OC_Request::isTrustedDomain($host)) {
+
+                       header('HTTP/1.1 400 Bad Request');
+                       header('Status: 400 Bad Request');
+                       OC_Template::printErrorPage(
+                               'You are accessing the server from an untrusted domain.',
+                               'Please contact your administrator'
+                       );
+                       return;
+               }
+
                $request = OC_Request::getPathInfo();
                if (substr($request, -3) !== '.js') { // we need these files during the upgrade
                        self::checkMaintenanceMode();
index afd3fda4f2d9ced5d77ec5d1ee2ce2a726948cf1..fb387e83e3ac426b79941634501a74d10c77fc37 100755 (executable)
@@ -25,49 +25,87 @@ class OC_Request {
        }
 
        /**
-        * @brief Checks whether a domain is considered as trusted. This is used to prevent Host Header Poisoning.
+        * @brief Checks whether a domain is considered as trusted from the list
+        * of trusted domains. If no trusted domains have been configured, returns
+        * true.
+        * This is used to prevent Host Header Poisoning.
         * @param string $host
-        * @return bool
+        * @return bool true if the given domain is trusted or if no trusted domains
+        * have been configured
         */
        public static function isTrustedDomain($domain) {
-               $trustedList = \OC_Config::getValue('trusted_domains', array(''));
+               $trustedList = \OC_Config::getValue('trusted_domains', array());
+               if (empty($trustedList)) {
+                       return true;
+               }
                return in_array($domain, $trustedList);
        }
 
        /**
-        * @brief Returns the server host
+        * @brief Returns the unverified server host from the headers without checking
+        * whether it is a trusted domain
         * @returns string the server host
         *
         * Returns the server host, even if the website uses one or more
         * reverse proxies
         */
-       public static function serverHost() {
-               if(OC::$CLI) {
-                       return 'localhost';
-               }
-               if(OC_Config::getValue('overwritehost', '') !== '' and self::isOverwriteCondition()) {
-                       return OC_Config::getValue('overwritehost');
-               }
+       public static function insecureServerHost() {
+               $host = null;
                if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) {
                        if (strpos($_SERVER['HTTP_X_FORWARDED_HOST'], ",") !== false) {
                                $host = trim(array_pop(explode(",", $_SERVER['HTTP_X_FORWARDED_HOST'])));
-                       }
-                       else{
+                       } else {
                                $host = $_SERVER['HTTP_X_FORWARDED_HOST'];
                        }
                } else {
                        if (isset($_SERVER['HTTP_HOST'])) {
                                $host = $_SERVER['HTTP_HOST'];
-                       }
-                       else if (isset($_SERVER['SERVER_NAME'])) {
+                       } else if (isset($_SERVER['SERVER_NAME'])) {
                                $host = $_SERVER['SERVER_NAME'];
                        }
                }
+               return $host;
+       }
+
+       /**
+        * Returns the overwritehost setting from the config if set and
+        * if the overwrite condition is met
+        * @return overwritehost value or null if not defined or the defined condition
+        * isn't met
+        */
+       public static function getOverwriteHost() {
+               if(OC_Config::getValue('overwritehost', '') !== '' and self::isOverwriteCondition()) {
+                       return OC_Config::getValue('overwritehost');
+               }
+               return null;
+       }
+
+       /**
+        * @brief Returns the server host from the headers, or the first configured
+        * trusted domain if the host isn't in the trusted list
+        * @returns string the server host
+        *
+        * Returns the server host, even if the website uses one or more
+        * reverse proxies
+        */
+       public static function serverHost() {
+               if(OC::$CLI) {
+                       return 'localhost';
+               }
+
+               // overwritehost is always trusted
+               $host = self::getOverwriteHost();
+               if ($host !== null) {
+                       return $host;
+               }
+
+               // get the host from the headers
+               $host = self::insecureServerHost();
 
                // Verify that the host is a trusted domain if the trusted domains
                // are defined
                // If no trusted domain is provided the first trusted domain is returned
-               if(self::isTrustedDomain($host) || \OC_Config::getValue('trusted_domains', "") === "") {
+               if (self::isTrustedDomain($host)) {
                        return $host;
                } else {
                        $trustedList = \OC_Config::getValue('trusted_domains', array(''));