X-Received: by 10.13.244.2 with SMTP id d2mr1887465ywf.34.1434478107679; Tue, 16 Jun 2015 11:08:27 -0700 (PDT) X-BeenThere: rubyonrails-security@googlegroups.com Received: by 10.182.130.168 with SMTP id of8ls173102obb.54.gmail; Tue, 16 Jun 2015 11:08:17 -0700 (PDT) X-Received: by 10.182.65.164 with SMTP id y4mr1833274obs.26.1434478097667; Tue, 16 Jun 2015 11:08:17 -0700 (PDT) Return-Path: Received: from mail-pa0-f54.google.com (mail-pa0-f54.google.com. [209.85.220.54]) by gmr-mx.google.com with ESMTPS id ct6si220749pdb.1.2015.06.16.11.08.17 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 16 Jun 2015 11:08:17 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.220.54 is neither permitted nor denied by best guess record for domain of aa...@tenderlovemaking.com) client-ip=209.85.220.54; Authentication-Results: gmr-mx.google.com; spf=neutral (google.com: 209.85.220.54 is neither permitted nor denied by best guess record for domain of aa...@tenderlovemaking.com) smtp.mail=aa...@tenderlovemaking.com Received: by mail-pa0-f54.google.com with SMTP id yx8so17402645pac.2 for ; Tue, 16 Jun 2015 11:08:17 -0700 (PDT) X-Gm-Message-State: ALoCoQmYDh8kdjbrYLcXfMoIqEWsvwKrOzFfhS5GFA/1DvIbi/d1+UJSzG9v4SYcDyokAxTyixjb X-Received: by 10.68.68.175 with SMTP id x15mr2755431pbt.91.1434478097533; Tue, 16 Jun 2015 11:08:17 -0700 (PDT) Return-Path: Received: from TC.local (c-66-235-2-11.sea.wa.customer.broadstripe.net. [66.235.2.11]) by mx.google.com with ESMTPSA id ux6sm2136237pab.24.2015.06.16.11.08.15 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 16 Jun 2015 11:08:16 -0700 (PDT) Sender: Aaron Patterson Date: Tue, 16 Jun 2015 11:08:13 -0700 From: Aaron Patterson To: secu...@suse.de, rubyonrail...@googlegroups.com, oss-se...@lists.openwall.com, ruby-sec...@googlegroups.com Subject: [CVE-2015-3224] IP whitelist bypass in Web Console Message-ID: <20150616180813.GE28496@TC.local> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="g3RkK9jYN81zD2N+" Content-Disposition: inline User-Agent: Mutt/1.5.23 (2014-03-12) --g3RkK9jYN81zD2N+ Content-Type: multipart/mixed; boundary="GBuTPvBEOL0MYPgd" Content-Disposition: inline --GBuTPvBEOL0MYPgd Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable IP whitelist bypass in Web Console There is a remote code execution vulnerability in Web Console. This vulnerability has been assigned the CVE identifier CVE-2015-3224. Versions Affected: All Not affected: Environments inaccessible from remote IPs, or without W= eb Console enabled Fixed Versions: 2.1.3 Impact=20 ------=20 Specially crafted remote requests can spoof their origin, bypassing the IP = whitelist, in any environment where Web Console is enabled (development and= test, by default). Users whose application is only accessible from localhost (as is the defaul= t behaviour in Rails 4.2) are not affected, unless a local proxy is involve= d. All affected users should either upgrade or use one of the work arounds imm= ediately.=20 Releases=20 --------=20 The 2.1.3 release is available at the normal locations.=20 Workarounds=20 -----------=20 To work around this issue, turn off web-console in all environments, by rem= oving/commenting it from the application's Gemfile. Patches=20 -------=20 To aid users who aren't able to upgrade immediately we have provided patche= s for the two supported release series. They are in git-am format and cons= ist of a single changeset.=20 * 2-1-ip-whitelist.patch - Patch for 2.1 series=20 Please note that only the 2.1.x series is supported at present. Users of e= arlier unsupported releases are advised to upgrade as soon as possible. Credits=20 -------=20 This vulnerability was reported by both joernchen of Phenoelit and Ben Murp= hy. Thanks to each of them for reporting the issue to us and verifying the= fix. --=20 Aaron Patterson http://tenderlovemaking.com/ --GBuTPvBEOL0MYPgd Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="2-1-ip-whitelist.patch" Content-Transfer-Encoding: quoted-printable From 4e47681e7b3bb92fad73660832eb91a62e148f87 Mon Sep 17 00:00:00 2001 From: Matthew Draper Date: Sun, 12 Apr 2015 08:29:28 +0930 Subject: [PATCH] Always apply Web Console's stricter whitelist to remote IP= s --- lib/web_console/request.rb | 21 ++++++++++++++++++++- test/web_console/request_test.rb | 24 ++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/lib/web_console/request.rb b/lib/web_console/request.rb index f48aec6..d7a8a72 100644 --- a/lib/web_console/request.rb +++ b/lib/web_console/request.rb @@ -15,7 +15,12 @@ module WebConsole # For a request to hit Web Console features, it needs to come from a w= hite # listed IP. def from_whitelited_ip? - whitelisted_ips.include?(remote_ip) + whitelisted_ips.include?(strict_remote_ip) + end + + # Determines the remote IP using our much stricter whitelist. + def strict_remote_ip + GetSecureIp.new(env, whitelisted_ips).to_s end =20 # Returns whether the request is from an acceptable content type. @@ -26,5 +31,19 @@ module WebConsole def acceptable_content_type? content_type.blank? || content_type.in?(acceptable_content_types) end + + class GetSecureIp < ActionDispatch::RemoteIp::GetIp + def initialize(env, proxies) + @env =3D env + @check_ip =3D true + @proxies =3D proxies + end + + def filter_proxies(ips) + ips.reject do |ip| + @proxies.include?(ip) + end + end + end end end diff --git a/test/web_console/request_test.rb b/test/web_console/request_te= st.rb index 93b466b..3fd953a 100644 --- a/test/web_console/request_test.rb +++ b/test/web_console/request_test.rb @@ -18,6 +18,30 @@ module WebConsole assert req.from_whitelited_ip? end =20 + test '#from_whitelisted_ip? is truthy for whitelisted IPs via whitelis= ted proxies' do + req =3D request('http://example.com', 'REMOTE_ADDR' =3D> '127.0.0.1'= , 'HTTP_X_FORWARDED_FOR' =3D> '127.0.0.0') + + assert req.from_whitelited_ip? + end + + test '#from_whitelisted_ip? is falsy for blacklisted IPs via whitelist= ed proxies' do + req =3D request('http://example.com', 'REMOTE_ADDR' =3D> '127.0.0.1'= , 'HTTP_X_FORWARDED_FOR' =3D> '0.0.0.0') + + assert_not req.from_whitelited_ip? + end + + test '#from_whitelisted_ip? is falsy for lying blacklisted IPs via whi= telisted proxies' do + req =3D request('http://example.com', 'REMOTE_ADDR' =3D> '127.0.0.1'= , 'HTTP_X_FORWARDED_FOR' =3D> '10.0.0.0, 127.0.0.0') + + assert_not req.from_whitelited_ip? + end + + test '#from_whitelisted_ip? is falsy for whitelisted IPs via blacklist= ed proxies' do + req =3D request('http://example.com', 'REMOTE_ADDR' =3D> '10.0.0.0',= 'HTTP_X_FORWARDED_FOR' =3D> '127.0.0.0') + + assert_not req.from_whitelited_ip? + end + test '#acceptable_content_type? is truthy for explicit HTML content ty= pe' do html =3D request('http://example.com', 'CONTENT_TYPE' =3D> 'text/htm= l') xhtml =3D request('http://example.com', 'CONTENT_TYPE' =3D> 'applica= tion/xhtml+xml') --=20 2.3.2 (Apple Git-55) --GBuTPvBEOL0MYPgd-- --g3RkK9jYN81zD2N+ Q29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi9wZ3Atc2lnbmF0dXJlDQoNCi0tLS0tQkVHSU4gUEdQ IFNJR05BVFVSRS0tLS0tDQoNCmlRRWNCQUVCQWdBR0JRSlZnR1lOQUFvSkVKVXhjTHkwLzYvRzlI c0gvakkzZXRzQnJ1L3Nycm9sY2RIcDZHV1ENClhHdS9yRVllTk95YmoreGI0cGZiWDdFempQc1pV Zkl0UVVrMWg3aHFRQ0RKNGFQZGFva2FOek1vdXFJemJEdFgNCi92M1psQ0l6TG5rUDVJUWpQa05h TVpIVzhpVzZPdzJ4NitmenJjLzNHUjAvRUhCOWdNdXUrMHUyclBDVTVVWkINCjgxTExORzdjNkNR QXhndzh1OHB5TEIvQmlEc3FhdlFwczg3TG9Bd0tnekdBS2oya09acnQyQjB2VjJaNEVjL0QNCmFW Y3ExT21wZklRMzN2SzB1ZFpOMmRaNUpBUE9CWTF0cm1TclhjNERUL1JqeDZDelhaQjZmczNvWjVl MFk2VGkNCk9Kbk9tSk10QmRtMkhkNXNZV0FKVklwOFZCc3FLT0ZJZTRseWdodENzMTRmWkgvbk1I aVE4T21VRmYvYUVxRT0NCj1BaE0zDQotLS0tLUVORCBQR1AgU0lHTkFUVVJFLS0tLS0NCg== --g3RkK9jYN81zD2N+--