Return-Path: X-Original-To: apmail-httpd-dev-archive@www.apache.org Delivered-To: apmail-httpd-dev-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 403BE178F0 for ; Wed, 22 Oct 2014 03:30:10 +0000 (UTC) Received: (qmail 55171 invoked by uid 500); 22 Oct 2014 03:30:09 -0000 Delivered-To: apmail-httpd-dev-archive@httpd.apache.org Received: (qmail 55098 invoked by uid 500); 22 Oct 2014 03:30:09 -0000 Mailing-List: contact dev-help@httpd.apache.org; run by ezmlm Precedence: bulk Reply-To: dev@httpd.apache.org list-help: list-unsubscribe: List-Post: List-Id: Delivered-To: mailing list dev@httpd.apache.org Received: (qmail 55088 invoked by uid 99); 22 Oct 2014 03:30:09 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 22 Oct 2014 03:30:09 +0000 X-ASF-Spam-Status: No, hits=1.5 required=5.0 tests=HTML_MESSAGE,RCVD_IN_DNSWL_LOW,SPF_PASS X-Spam-Check-By: apache.org Received-SPF: pass (nike.apache.org: domain of graham.dumpleton@gmail.com designates 209.85.216.181 as permitted sender) Received: from [209.85.216.181] (HELO mail-qc0-f181.google.com) (209.85.216.181) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 22 Oct 2014 03:29:42 +0000 Received: by mail-qc0-f181.google.com with SMTP id r5so2017013qcx.26 for ; Tue, 21 Oct 2014 20:29:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:sender:in-reply-to:references:date:message-id:subject :from:to:content-type; bh=8CdBOqnGRLBxM+ImSc6gA3WXPk4dMoutfjMTwwDhBcM=; b=GD4TMKIookKMgH3mz2bs6JumuoXOX8cwvPGs4nmfbfqP4iWolSnpbAj6DcR3j++CY4 MPdlVb2da7VErlQfA2kn7NpMee2aNjqWdJ9KDI8WpydZ+leJPincfAMUpEJudwN1tIk2 CCDAb49j8WSYKIG8OKtVpJidOQcGn507Amlj+QgnTJEGhKWrXso/RwTfXIAgrpTuxrG2 QkPxvN1VkN/eSStbzypzGOnF/GVyhfPhufbCPTBtLKc1phhflL6H1ik14uuVZzkihVLx RP1wb2QAwS8JydipR0XHx7TmEfYZMKqNM1G4lpcd0m7VOXYEGrHvX9h/cEyF9wVQdBTu CdsA== MIME-Version: 1.0 X-Received: by 10.224.103.200 with SMTP id l8mr52064431qao.52.1413948581353; Tue, 21 Oct 2014 20:29:41 -0700 (PDT) Sender: graham.dumpleton@gmail.com Received: by 10.140.20.3 with HTTP; Tue, 21 Oct 2014 20:29:41 -0700 (PDT) In-Reply-To: References: <5236F207.6010906@thelounge.net> <542C3464.4040708@thelounge.net> Date: Wed, 22 Oct 2014 14:29:41 +1100 X-Google-Sender-Auth: yk3GY4CwuYaUIa4bDPA4J9MRyzU Message-ID: Subject: Re: MAJOR SECURITY-PROBLEM Apache 2.4.6 From: Graham Dumpleton To: "dev@httpd.apache.org" Content-Type: multipart/alternative; boundary=001a1132e9d2ec24920505fa8ec4 X-Virus-Checked: Checked by ClamAV on apache.org --001a1132e9d2ec24920505fa8ec4 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable On 22 October 2014 13:51, Yehuda Katz wrote: > On Wed, Oct 1, 2014 at 2:19 PM, Eric Covener wrote: > >> >> On Wed, Oct 1, 2014 at 2:16 PM, Eric Covener wrote: >> >>> To me, this does not exonerate mod_php, it implicates it. I suspect >>> your source code is served because PHP swallowed the LimitRequestBody= =E2=80=8B and >>> then passed control back to Apache. I'm fairly certain I responded to = you >>> privately with similar information already. >> >> >> =E2=80=8BI should add that I don't understand your scenario completely, = where the >> file is not processed.=E2=80=8B I think my own test result was the same = as Yehuda >> ITT which is not the same as what I just described with the default hand= ler >> taking over. >> > > 1. Is this result (PHP executed) still a bug (could be in mod_php)? If a > 413 comes up, shouldn't no other content be returned? > I am considering setting up a new VM to do some testing, but I want to > make sure this is not the expected behavior (whether the PHP is executed = or > not). > > 2. Is there another module that hooks in with a similar way to mod_php > that might also show this behavior (mod_lua for example)? > FWIW, I noted similar behaviour in implementing mod_wsgi many years ago. Since then I have code in mod_wsgi in the handler before anything is done which specifically does: /* * Check to see if the request content is too large if the * Content-Length header is defined then end the request here. We do * this as otherwise it will not be done until first time input data * is read in by the application. Problem is that underlying HTTP * output filter will also generate a 413 response and the error * raised from the application will be appended to that. The call to * ap_discard_request_body() is hopefully enough to trigger sending * of the 413 response by the HTTP filter. */ lenp =3D apr_table_get(r->headers_in, "Content-Length"); if (lenp) { char *endstr; apr_off_t length; if (wsgi_strtoff(&length, lenp, &endstr, 10) || *endstr || length < 0) { wsgi_log_script_error(r, apr_psprintf(r->pool, "Invalid Content-Length header value of '%s' was " "supplied.", lenp), r->filename); return HTTP_BAD_REQUEST; } limit =3D ap_get_limit_req_body(r); if (limit && limit < length) { ap_discard_request_body(r); return OK; } } So in the case of mod_wsgi it wasn't that the source code was being appended, but that any error response from the hosted Python WSGI application, generated in reaction to the reading of the request content failing because of the length check by the input filter, that got appended to the end of the 413 error response that the HTTP filter had already caused to be delivered back. Graham --001a1132e9d2ec24920505fa8ec4 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable


On 22 October 2014 13:51, Yehuda Katz <yehuda@ymkatz.net> wrote:
On Wed, Oct 1, 2014 at 2:19= PM, Eric Covener <covener@gmail.com> wrote:

On Wed, Oct 1, 2014 at 2:16 PM, Eric Covener <covener@gmail.com&g= t; wrote:
To me, this does not exonerate mod_php= , it implicates it.=C2=A0 I suspect your source code is served because PHP = swallowed the LimitRequestBody=E2=80=8B and then passed control back to Apa= che.=C2=A0 I'm fairly certain I responded to you privately with similar= information already.

=E2=80=8BI should add that I don't understand your scenario completely= , where the file is not processed.=E2=80=8B I think my own test result was = the same as Yehuda ITT which is not the same as what I just described with = the default handler taking over.

1. Is this result (PHP executed) still a bug (could be = in mod_php)? If a 413 comes up, shouldn't no other content be returned?=
I am considering setting up a new VM to do some testing, but I w= ant to make sure this is not the expected behavior (whether the PHP is exec= uted or not).

2. Is there another module that = hooks in with a similar way to mod_php that might also show this behavior (= mod_lua for example)?

=C2=A0FWIW, I noted similar behaviour in implementing mod_wsgi many year= s ago. Since then I have code in mod_wsgi in the handler before anything is= done which specifically does:

=C2=A0 =C2=A0 = /*
=C2=A0 =C2=A0 =C2=A0* Check to see if the request content is t= oo large if the
=C2=A0 =C2=A0 =C2=A0* Content-Length header is de= fined then end the request here. We do
=C2=A0 =C2=A0 =C2=A0* this= as otherwise it will not be done until first time input data
=C2= =A0 =C2=A0 =C2=A0* is read in by the application. Problem is that underlyin= g HTTP
=C2=A0 =C2=A0 =C2=A0* output filter will also generate a 4= 13 response and the error
=C2=A0 =C2=A0 =C2=A0* raised from the a= pplication will be appended to that. The call to
=C2=A0 =C2=A0 = =C2=A0* ap_discard_request_body() is hopefully enough to trigger sending
=C2=A0 =C2=A0 =C2=A0* of the 413 response by the HTTP filter.
=
=C2=A0 =C2=A0 =C2=A0*/

=C2=A0 =C2=A0 lenp =3D= apr_table_get(r->headers_in, "Content-Length");
=C2=A0 =C2=A0 if (lenp) {
=C2=A0 =C2=A0 =C2=A0 =C2=A0= char *endstr;
=C2=A0 =C2=A0 =C2=A0 =C2=A0 apr_off_t length;

=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (wsgi_strtoff(&leng= th, lenp, &endstr, 10)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 || *endstr || length < 0) {

=C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 wsgi_log_script_error(r, apr_psprintf(r->poo= l,
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 "Invalid Content-Length header value of '%s' was "= ;
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 "supplied.", lenp), r->filename);

<= div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return HTTP_BAD_REQUEST;
=C2=A0 =C2=A0 =C2=A0 =C2=A0 }

=C2=A0 =C2=A0 = =C2=A0 =C2=A0 limit =3D ap_get_limit_req_body(r);

= =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (limit && limit < length) {
=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ap_discard_request_body(r);<= /div>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return OK;
= =C2=A0 =C2=A0 =C2=A0 =C2=A0 }
=C2=A0 =C2=A0 }
So in the case of mod_wsgi it wasn't that the source code w= as being appended, but that any error response from the hosted Python WSGI = application, generated in reaction to the reading of the request content fa= iling because of the length check by the input filter, that got appended to= the end of the 413 error response that the HTTP filter had already caused = to be delivered back.

Graham
--001a1132e9d2ec24920505fa8ec4--