Bug 52774

Summary: RewriteRules within outgoing proxy no longer work
Product: Apache httpd-2 Reporter: Jerome Grandjanny <jerome.grandjanny>
Component: mod_proxyAssignee: Apache HTTPD Bugs Mailing List <bugs>
Status: RESOLVED FIXED    
Severity: regression CC: g.russell, jerome.grandjanny, petr.sumbera, timmyf
Priority: P2 Keywords: FixedInTrunk
Version: 2.2.22   
Target Milestone: ---   
Hardware: PC   
OS: Linux   
Attachments: Example of possible fix.
Patch for CVE-2011-4317 effecting only rewriterule proxy
Patch v2 for CVE-2011-4317 effecting only rewriterule proxy

Description Jerome Grandjanny 2012-02-26 20:11:19 UTC
This kind of configuration is for an outgoing proxy which filters advertisments requests. It worked in 2.2.13 but not in 2.2.14 :

Listen 127.0.0.1:81
<VirtualHost 127.0.0.1:81>
    ProxyRequests On
    RewriteEngine On
    RewriteRule /advertising/ - [forbidden]
    ... other generic ads filtering rules ...
</VirtualHost>

In 2.2.14, it seems that mod_proxy processes the request before mod_rewrite can even do its job and RewriteRules are not processed at all. In previous versions, RewriteRules were processed first, then, the request was processed by mod_proxy if it passed all the ads filtering rules.
Comment 1 Eric Covener 2012-02-26 20:41:20 UTC
Not seeing any relevant changes.  per-vhost scope rewriterules should have taken precedence for the full life of 2.2.  Can you post a verbatim configuration and evidence that you're hitting the right vhost (custom log, RewriteLog, etc)
Comment 2 Jerome Grandjanny 2012-02-29 20:26:07 UTC
Yes, here is a verbatim minimal configuration file allowing to show the issue :

    ServerRoot "/etc/apache2"
    User  www-data
    Group www-data

    LoadModule proxy_module /usr/lib/apache2/modules/mod_proxy.so
    LoadModule proxy_http_module /usr/lib/apache2/modules/mod_proxy_http.so
    LoadModule rewrite_module /usr/lib/apache2/modules/mod_rewrite.so

    ErrorLog /var/log/apache2/error.log
    LogLevel debug
    CustomLog /var/log/apache2/access.log "%h %l %u %t \"%r\" %>s %b"
    RewriteLog /var/log/apache2/rewrite.log
    RewriteLogLevel 9

    Listen 127.0.0.1:81
    ServerName localhost
    ProxyRequests On
    RewriteEngine On
    RewriteRule /ads/ - [forbidden]

This is intended to be an outgoing proxy which blocks any request having the string /ads/ in the URL.

1) Expected behavior :
   -------------------
     Request 1 : GET http://pubs.lemonde.fr/RealMedia/ads/click_lx.ads/INTERNATIONAL-LEMONDE/articles_international/exclu/tall/L50/L50/306065288/x21/OasDefault/lm_ysl_06010_rg02_sp/ibm_emagazine_rg01_sp.html/576879454745394f676c554142765042 HTTP/1.0
     Response 1 : HTTP/1.1 403 Forbidden

     Request 2 : GET http://www.hpmuseum.org HTTP/1.O
     Response 2 : HTTP/1.1 200 Ok

     Explanation : when the request contains the string /ads/, the RewriteRule immediately rejects it. For any other request, the RewriteRule is not triggered and the request is proxyied by mod_proxy.

2) Actual behavior :
   -----------------
     Request 1 : Same as below
     Response 1 : HTTP/1.1 302 Found
     Content of access.log : 127.0.0.1 - - [29/Feb/2012:20:56:36 +0100] "GET http://pubs.lemonde.fr/RealMedia/ads/click_lx.ads/INTERNATIONAL-LEMONDE/articles_international/exclu/tall/L50/L50/306065288/x21/OasDefault/lm_ysl_06010_rg02_sp/ibm_emagazine_rg01_sp.html/576879454745394f676c554142765042 HTTP/1.0" 302 399
     Content of rewrite.log : empty

3) Verification with the line "ProxyRequests On" commented out :
   -------------------------------------------------------------
     Request 1 : Same as below
     Response 1 : HTTP/1.1 403 Forbidden
     Content of access.log : 127.0.0.1 - - [29/Feb/2012:20:57:56 +0100] "GET http://pubs.lemonde.fr/RealMedia/ads/click_lx.ads/INTERNATIONAL-LEMONDE/articles_international/exclu/tall/L50/L50/306065288/x21/OasDefault/lm_ysl_06010_rg02_sp/ibm_emagazine_rg01_sp.html/576879454745394f676c554142765042 HTTP/1.0" 403 398
     Content of rewrite.log :
        127.0.0.1 - - [29/Feb/2012:20:57:56 +0100] [pubs.lemonde.fr/sid#203f78e8][rid#2047d960/initial] (2) init rewrite engine with requested uri /RealMedia/ads/click_lx.ads/INTERNATIONAL-LEMONDE/articles_international/exclu/tall/L50/L50/306065288/x21/OasDefault/lm_ysl_06010_rg02_sp/ibm_emagazine_rg01_sp.html/576879454745394f676c554142765042
        127.0.0.1 - - [29/Feb/2012:20:57:56 +0100] [pubs.lemonde.fr/sid#203f78e8][rid#2047d960/initial] (3) applying pattern '/ads/' to uri '/RealMedia/ads/click_lx.ads/INTERNATIONAL-LEMONDE/articles_international/exclu/tall/L50/L50/306065288/x21/OasDefault/lm_ysl_06010_rg02_sp/ibm_emagazine_rg01_sp.html/576879454745394f676c554142765042'
        127.0.0.1 - - [29/Feb/2012:20:57:56 +0100] [pubs.lemonde.fr/sid#203f78e8][rid#2047d960/initial] (2) forcing responsecode 403 for /RealMedia/ads/click_lx.ads/INTERNATIONAL-LEMONDE/articles_international/exclu/tall/L50/L50/306065288/x21/OasDefault/lm_ysl_06010_rg02_sp/ibm_emagazine_rg01_sp.html/576879454745394f676c554142765042

This show that, in the first configuration, rewrite_mod doesn't have a chance to process the request before mod_proxy. In the "verification" configuration, we see that the RewriteRule works perfectly when mod_proxy is not sollicited.

In the real life, I use this kind of configuration with a bunch of RewriteRules and RewriteConds to eliminate advertisments from my navigations. It was working nice for years and years on many systems until my Ubuntu updated Apache Httpd to 2.2.14 and then it was broken.

Thanks for your time,
Best regards,
Jerome.
Comment 3 Kaspar Brand 2012-03-03 08:48:36 UTC
(In reply to comment #0)
> This kind of configuration is for an outgoing proxy which filters advertisments
> requests. It worked in 2.2.13 but not in 2.2.14 :

(In reply to comment #2)
> and RewriteConds to eliminate advertisments from my navigations. It was working
> nice for years and years on many systems until my Ubuntu updated Apache Httpd
> to 2.2.14 and then it was broken.

Thanks for the test case.

Were you really using 2.2.13 before, or just the version which Ubuntu previously provided?

And when saying "2.2.14", are you referring to a vanilla httpd 2.2.14 deployment, or actually something like 2.2.14-5ubuntuXYZ?
Comment 4 Jerome Grandjanny 2012-03-05 19:48:12 UTC
(In reply to comment #3)
> (In reply to comment #0)
> > This kind of configuration is for an outgoing proxy which filters advertisments
> > requests. It worked in 2.2.13 but not in 2.2.14 :
> 
> (In reply to comment #2)
> > and RewriteConds to eliminate advertisments from my navigations. It was working
> > nice for years and years on many systems until my Ubuntu updated Apache Httpd
> > to 2.2.14 and then it was broken.
> 
> Thanks for the test case.
> 
> Were you really using 2.2.13 before, or just the version which Ubuntu
> previously provided?
> 
> And when saying "2.2.14", are you referring to a vanilla httpd 2.2.14
> deployment, or actually something like 2.2.14-5ubuntuXYZ?

Yes, indeed, I was not aware that Ubuntu did its own cooking with Apache versions.

when I type :
        apache2ctl -v
I get :
        Server version: Apache/2.2.14 (Ubuntu)
        Server built:   Feb 14 2012 18:09:18

And when I type :
        cd /root/.synaptic/log
        fgrep 'apache2 ' *.log
I get :
        2010-10-05.192601.log:apache2 (2.2.14-5ubuntu8.2)
        2010-10-28.115159.log:apache2 (2.2.14-5ubuntu8.2) to 2.2.14-5ubuntu8.3
        2010-11-27.173910.log:apache2 (2.2.14-5ubuntu8.3) to 2.2.14-5ubuntu8.4
        2011-09-02.191300.log:apache2 (2.2.14-5ubuntu8.4) to 2.2.14-5ubuntu8.6
        2011-11-14.190709.log:apache2 (2.2.14-5ubuntu8.6) to 2.2.14-5ubuntu8.7
        2012-02-20.111132.log:apache2 (2.2.14-5ubuntu8.7) to 2.2.14-5ubuntu8.8

Obviously, my configuration broke on 2012-02-20.
Comment 5 Kaspar Brand 2012-03-07 08:21:36 UTC
(In reply to comment #4)
>         2012-02-20.111132.log:apache2 (2.2.14-5ubuntu8.7) to 2.2.14-5ubuntu8.8
> 
> Obviously, my configuration broke on 2012-02-20.

The reason is most likely this (from http://changelogs.ubuntu.com/changelogs/pool/main/a/apache2/apache2_2.2.14-5ubuntu8.8/changelog):

  * SECURITY UPDATE: another mod_proxy reverse proxy exposure
    - debian/patches/216_CVE-2011-4317.dpatch: validate additional URIs in
      modules/mappers/mod_rewrite.c, modules/proxy/mod_proxy.c,
      server/protocol.c.
    - CVE-2011-4317

I'm tentatively setting the version to 2.2.22, as this is the official release with the fix for CVE-2011-4317 (see r1235443).
Comment 6 Rainer Jung 2012-03-24 11:28:20 UTC
I can confirm the behaviour for a vanilla 2.2.22. Since the URL does not start with a "/", we return DECLINED in hook_uri2file().

This was added as part of a fix for CVE-2011-4317 in r1235443.
Comment 7 Petr Sumbera 2012-04-05 15:30:21 UTC
Created attachment 28547 [details]
Example of possible fix.

In original fix for CVE-2011-3368 there was following note:

From RFC -    /* RFC 2616:
     *   Request-URI    = "*" | absoluteURI | abs_path | authority

But in both fixes for CVE-2011-3368 and CVE-2011-4317 there was no code allowing 
absoluteURI which is used in case of poxing.

Please see attached diff file which in my case solved this issue (probably the same fix should go also into mod_proxy.c).

Any comments?
Comment 8 Jerome Grandjanny 2012-05-10 19:48:58 UTC
Hello,

I installed a fresh vanilla Apache 2.2.22 with Petr's patch and now it works as I expected.
Thanks to Petr.
Comment 9 Rainer Jung 2012-05-26 13:00:41 UTC
*** Bug 53286 has been marked as a duplicate of this bug. ***
Comment 10 Gordon 2012-05-26 16:35:29 UTC
Bug 53286 is about http CONNECT not proxy:, and the diff patch here seems to only help proxy not CONNECT. It certainly doesn't seem to help in my bug. 
The only link I can see between these bugs is that they relate to the same code change in 2.2.22. In CONNECT the uri does not start with http or https, but it can be still perfectly valid. 

Joining the bugs together just seems really confusing to me. 

However if joining them means we get nearer a fix then I am all for it!

I also note Rainer's comments in apache devel. I don't subscribe to that list. But note my bug report has nothing to do with the [p] option so using that as a test would not help.  You probably need a global modrewrite flag as another user suggested in order for the average user to feel safe while being flexible for the experienced user. 

So if you want to join the bugs that's fine but do read the other bug report and don't forget the CONNECT method in your fix. 

Thanks.
Comment 11 Gordon 2012-05-26 16:55:07 UTC
Very sorry Rainer. On second thoughts checking the uri only on a [P] rather than every time would indeed fix 53286. It would also fix this report and seems to me to be a better fix for CVE-2011-3368. Vote +1 if I am allowed to vote... Put up a patch and I will happily test it in my config.
Comment 12 Gordon 2012-05-28 12:18:18 UTC
Created attachment 28842 [details]
Patch for CVE-2011-4317 effecting only rewriterule proxy

I had a few hours spare today and wrote a patch on 2.2.22.
This would appear to allow both continued use of rewriterule in proxy and connect conditions, while enforcing a rule for [P] type modrewrite.

Unfortunately I could not test the problems of CVE-2011-4317 in these changes as they seem for me to be blocked early in the process (perhaps due to me using an rpms from fedora). Could someone validate that the problem URIs are still blocked?

The previous CVE-2011-4317 fix ignored modrewrite when the URI was invalid, and this caused my config to allow requests which would have otherwise been blocked (as I use [F] rewriterule for security). I think this patch is better as it make the request FORBIDDEN if a [p] rule was the one that matched and the URI is not safe.

The previous rule ignored proxy in .htaccess files. I assume this was already thought through? As per the previous fix I ignore this.

I had to add an extra flag to one of the functions to indicate that a proxy modrewrite was used. Just using a match on "proxy:" incorrectly trapped simple rewrite rules involving the CONNECT method.

I hope this is useful to you...
Comment 13 Gordon 2012-05-28 16:11:47 UTC
Created attachment 28843 [details]
Patch v2 for CVE-2011-4317 effecting only rewriterule proxy

Had another little play, and this patch is another approach by extending ACTION_ to include ACTION_FORBIDDEN. Less parameters and cleaner, but only if you dont mind ACTION being extended in this way.

Added it into .htaccess too.

Again, I have been unable to test to see if this actually does block the CVE issue, but I cannot see any reason why it wouldnt deal with the issue. Maybe someone can check and amend as necessary? I am not a mod_rewrite.c expert so this patch could have side-effects, but it seems ok and works for me.
Comment 14 Joe Orton 2012-07-02 13:26:17 UTC
See list discussion here:

http://comments.gmane.org/gmane.comp.apache.devel/48357

I have added a new RewriteOption, "AllowAnyURI", in r1356115 which IMO resolves this issue.  Other opinions are available! :)
Comment 15 Petr Sumbera 2012-07-11 12:39:29 UTC
(In reply to comment #14)
> I have added a new RewriteOption, "AllowAnyURI", in r1356115 which IMO
> resolves this issue.  Other opinions are available! :)

Doesn't mean "AllowAnyURI" option actually "allow CVE-2011-3368/CVE-2011-4317"?

And is following statement correct?

"Declining, request-URI 'http://blahblah' is not a URL-path"

I believe http://blahblah is valid URL path.

And what is problem with the patch I proposed? Is it vulnerable for CVE-2011-3368/CVE-2011-4317? I hope not.

I think I just don't understand it.. :-)
Comment 16 Eric Covener 2012-07-11 12:46:34 UTC
(In reply to comment #15)
> (In reply to comment #14)
> > I have added a new RewriteOption, "AllowAnyURI", in r1356115 which IMO
> > resolves this issue.  Other opinions are available! :)
> 
> Doesn't mean "AllowAnyURI" option actually "allow
> CVE-2011-3368/CVE-2011-4317"?

If you write a rule that captures/substitutes unsafely, and opts into non-path arguments, yes.

> 
> And is following statement correct?
> 
> "Declining, request-URI 'http://blahblah' is not a URL-path"
> 
> I believe http://blahblah is valid URL path.

The path is 1 component of a URL, we use the term "URL-path" for that component.

> And what is problem with the patch I proposed? Is it vulnerable for
> CVE-2011-3368/CVE-2011-4317? I hope not.
> 
> I think I just don't understand it.. :-)

IMO it is too narrow and does not force the user to opt in to the input sometimes not being a URL path (as it had been documented)
Comment 17 Rainer Jung 2012-08-21 16:28:53 UTC
Applied to 2.4.x in r1359687.
Released with 2.4.3.
Applied to 2.2.x with r1375113.