Bug 45801

Summary: SSLRequireSSL with strictrequire and satisfy any does not behave as expected
Product: Apache httpd-2 Reporter: thawn <webmaster>
Component: mod_sslAssignee: Apache HTTPD Bugs Mailing List <bugs>
Status: REOPENED ---    
Severity: normal CC: apachebug, robm, webmaster
Priority: P2    
Version: 2.2.9   
Target Milestone: ---   
Hardware: PC   
OS: Linux   

Description thawn 2008-09-13 13:39:35 UTC
I would like to achieve the following behavior:

On a http server, a subdirectory should only be accessible via https
If http is tried, the user should be automatically redirected to the https page

From the intranet the subtree is accessible without authentication
From the internet the subtree needs authentication

My config:
<Location /opendb>
#   Network Access Control
       Order Deny,Allow
       Deny from all
       Allow from 192.168.0
       Allow from 127.0.0.1

#   Authentication
        AuthType Basic
        AuthName "Open Media Database"
        AuthUserFile /var/svn/conf/svnbackupusers
        Require valid-user

#   Allow Network Access and/or Basic Auth
       Satisfy Any

#   Require HTTPS and redirect if HTTP is used
        SSLRequireSSL
        SSLOptions +StrictRequire
        ErrorDocument 403 /bin/httpsredirect.php
</Location>

The behavior i get is the following:
from the intranet (192.168.0.x) the page behaves as expected, redirecting the user to the https page without authentication

however from the internet, the user is asked to authenticate, but is not redirected to the https page (resulting in plain text transfer of username and password)
Comment 1 Ruediger Pluem 2008-09-13 14:08:17 UTC
This cannot work due to the order how both access checks are processed. The IP address check comes first and if it fails the SSL requirements will not be checked anymore. Thus no redirect happens.
Try the following:

RewriteCond %{HTTPS} =Off
RewriteRule ^/opendb($|/.*) https://yourserver.com/opendb$1

<Location /opendb>
#   Network Access Control
       Order Deny,Allow
       Deny from all
       Allow from 192.168.0
       Allow from 127.0.0.1

#   Authentication
        AuthType Basic
        AuthName "Open Media Database"
        AuthUserFile /var/svn/conf/svnbackupusers
        Require valid-user

#   Allow Network Access and/or Basic Auth
       Satisfy Any

</Location>
Comment 2 Ruediger Pluem 2008-09-13 14:11:34 UTC
(In reply to comment #1)
> This cannot work due to the order how both access checks are processed. The IP
> address check comes first and if it fails the SSL requirements will not be
> checked anymore. Thus no redirect happens.
> Try the following:
> 
> RewriteCond %{HTTPS} =Off
> RewriteRule ^/opendb($|/.*) https://yourserver.com/opendb$1

My fault. It needs to be

RewriteRule ^/opendb($|/.*) https://yourserver.com/opendb$1 [R,L]

of course.


Comment 3 thawn 2008-09-14 05:27:20 UTC
I do not agree that this is a simple misconfiguration. Therefore I disagree with having this bug assigned the status resolved.

Reasons:
1. If I use the suggested configuration, I get double log ins one to the http page and one to the https page. This is absolutely inacceptible because the reason for using https in the first place was to have the authentication transmitted ssl encrypted.
2. I use Satisfy Any, so if the check for the ip address fails, apache should still check for SSL and authentication.
3. The description of SSLOption  StrictRequire says:
"This forces forbidden access when SSLRequireSSL or SSLRequire successfully decided that access should be forbidden. Usually the default is that in the case where a ``Satisfy any'' directive is used, and other access restrictions are passed, denial of access due to SSLRequireSSL or SSLRequire is overridden (because that's how the Apache Satisfy mechanism should work.) But for strict access restriction you can use SSLRequireSSL and/or SSLRequire in combination with an ``SSLOptions +StrictRequire''. Then an additional ``Satisfy Any'' has no chance once mod_ssl has decided to deny access."

Which, to my understanding, means that if StrictRequire is on, it should not be possible to access the page without ssl at all, period. This is a feature which is security sensitive and should not fail to work!

Especially point 3 is, in my opinion a strong argument to reopen the bug.
Comment 4 Liam Morland 2009-06-05 10:53:22 UTC
The desire to redirect from http to https is a common one. Getting it right is important for security. One can use mod_rewrite to do this, but not if SSLRequireSSL is specified. One of the reasons for SSLRequireSSL is "for defending against configuration errors that expose stuff that should be protected". It's handy to have a simple, one-line configuration which provides that security.

My suggestion: create an optional parameter so that one could put in a config file "SSLRequireSSL Redirect". This would issue a redirect to non-SSL connections before any other access controls or authentication would be tested.
Comment 5 Stefan Fritsch 2012-02-03 09:55:53 UTC
I think the bug here is that ssl_hook_Access runs as APR_HOOK_MIDDLE while it should run at APR_HOOK_FIRST (or even REALLYFIRST). ssl_hook_Access provides information (in the ssl-access-forbidden request note) that is used later by other hooks if StrictRequire is set. Therefore it is important that ssl_hook_Access is always run.

Another example: With this test config:

SSLOptions +StrictRequire
<Directory /opt/apache22/htdocs/test/strictrequire>
    AuthBasicProvider       file
    AuthName                "strict require test"
    AuthType                basic
    AuthUserFile            conf/users
    Require user admin
    Satisfy any
    Deny from all
    allow from 10.56.51.0/24
    SSLRequire %{HTTP_REFERER} == "foo"
</Directory>

If I make a request where neither SSLRequire nor the ip restriction is fulfilled, it depends on the load order of mod_ssl and mod_authz_host if I get a "Forbidden" or a "Authorization Required". Different behavior depending on the load order is always a bug, IMHO.

SSLRequire and SSLRequireSSL are equivalent with respect to this bug because they are both checked in ssl_hook_Access.