Bug 1415298
| Summary: | Possible regression in curl-7.19.7-CVE-2015-3148.patch | ||||||
|---|---|---|---|---|---|---|---|
| Product: | Red Hat Enterprise Linux 6 | Reporter: | Paulo Andrade <pandrade> | ||||
| Component: | curl | Assignee: | Kamil Dudka <kdudka> | ||||
| Status: | CLOSED CURRENTRELEASE | QA Contact: | BaseOS QE Security Team <qe-baseos-security> | ||||
| Severity: | high | Docs Contact: | |||||
| Priority: | unspecified | ||||||
| Version: | 6.8 | CC: | kdudka, pandrade, thozza | ||||
| Target Milestone: | rc | Keywords: | Regression | ||||
| Target Release: | --- | ||||||
| Hardware: | All | ||||||
| OS: | Linux | ||||||
| Whiteboard: | |||||||
| Fixed In Version: | curl-7.19.7-53.el6_9 | Doc Type: | If docs needed, set a value | ||||
| Doc Text: | Story Points: | --- | |||||
| Clone Of: | Environment: | ||||||
| Last Closed: | 2017-03-29 08:31:06 UTC | Type: | Bug | ||||
| Regression: | --- | Mount Type: | --- | ||||
| Documentation: | --- | CRM: | |||||
| Verified Versions: | Category: | --- | |||||
| oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |||||
| Cloudforms Team: | --- | Target Upstream Version: | |||||
| Embargoed: | |||||||
| Bug Depends On: | 1422464 | ||||||
| Bug Blocks: | |||||||
| Attachments: |
|
||||||
|
Description
Paulo Andrade
2017-01-20 19:37:50 UTC
Thanks for the analysis! I see there was a regression fix upstream: https://github.com/curl/curl/commit/curl-7_49_0~79 ... which refers to the following issue: https://github.com/curl/curl/pull/655 Could you please check whether the fix has any effect on the bug in question? I can prepare a scratch build if needed... (In reply to Kamil Dudka from comment #2) > Thanks for the analysis! I see there was a regression fix upstream: > > https://github.com/curl/curl/commit/curl-7_49_0~79 > > ... which refers to the following issue: > > https://github.com/curl/curl/pull/655 > > Could you please check whether the fix has any effect on the bug in question? Unfortunately the error happened again after enabling back curl-7.19.7-CVE-2015-3148.patch and adding the suggested patch. > I can prepare a scratch build if needed... Patch was rediffed as: """ +diff -up curl-7.19.7/lib/http.c.orig curl-7.19.7/lib/http.c +--- curl-7.19.7/lib/http.c.orig 2017-01-23 15:51:19.810640755 -0200 ++++ curl-7.19.7/lib/http.c 2017-01-23 15:54:57.269206226 -0200 +@@ -1922,8 +1922,10 @@ CURLcode Curl_http_done(struct connectda + data->state.negotiate.state == GSS_AUTHSENT) { + /* add forbid re-use if http-code != 401/407 as a WA only needed for + * 401/407 that signal auth failure (empty) otherwise state will be RECV +- * with current code */ +- if((data->req.httpcode != 401) && (data->req.httpcode != 407)) ++ * with current code. ++ * Do not close CONNECT_ONLY connections. */ ++ if((data->req.httpcode != 401) && (data->req.httpcode != 407) && ++ !data->set.connect_only) + conn->bits.close = TRUE; /* Negotiate transfer completed */ + Curl_cleanup_negotiate(data); + } """ Thanks for checking! I guess you have some local environment to test it. Could you please check whether the issue occurs also with RHEL-7 or Fedora (lib)curl? I do not have a test environment. But I build a rhel6 backport
of latest rawhide curl, and asked the user to test it, and revert
back after testing to a rhel6 supported version.
It did work.
Build used this patch:
"""
--- curl.spec.orig 2017-01-24 16:30:03.634274220 -0200
+++ curl.spec 2017-01-24 16:30:40.759173884 -0200
@@ -20,12 +20,14 @@
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(id -nu)
BuildRequires: groff
BuildRequires: krb5-devel
+%if 0%{?fedora} != 0 || 0%{?rhel} > 6
BuildRequires: libidn2-devel
BuildRequires: libmetalink-devel
BuildRequires: libnghttp2-devel
BuildRequires: libpsl-devel
BuildRequires: libssh2-devel
BuildRequires: multilib-rpm-config
+%endif
BuildRequires: nss-devel
BuildRequires: openldap-devel
BuildRequires: openssh-clients
@@ -35,8 +37,10 @@
BuildRequires: stunnel
BuildRequires: zlib-devel
+%if 0%{?fedora} != 0 || 0%{?rhel} > 6
# nghttpx (an HTTP/2 proxy) is used by the upstream test-suite
BuildRequires: nghttp2
+%endif
# perl modules used in the test suite
BuildRequires: perl(Cwd)
@@ -65,9 +69,11 @@
Requires: libcurl%{?_isa} = %{version}-%{release}
+%if 0%{?fedora} != 0 || 0%{?rhel} > 6
# require at least the version of libssh2 that we were built against,
# to ensure that we have the necessary symbols available (#525002, #642796)
%global libssh2_version %(pkg-config --modversion libssh2 2>/dev/null || echo 0)
+%endif
%description
curl is a command line tool for transferring data with URL syntax, supporting
@@ -82,9 +88,11 @@
Group: Development/Libraries
Requires: libssh2%{?_isa} >= %{libssh2_version}
+%if 0%{?fedora} != 0 || 0%{?rhel} > 6
# libnsspem.so is no longer included in the nss package (#1347336)
BuildRequires: nss-pem
Requires: nss-pem
+%endif
%description -n libcurl
libcurl is a free and easy-to-use client-side URL transfer library, supporting
@@ -150,11 +158,13 @@
--enable-threaded-resolver \
--with-ca-bundle=%{_sysconfdir}/pki/tls/certs/ca-bundle.crt \
--with-gssapi${KRB5_PREFIX} \
+%if 0%{?fedora} != 0 || 0%{?rhel} > 6
--with-libidn2 \
--with-libmetalink \
--with-libpsl \
--with-libssh2 \
--with-nghttp2 \
+%endif
--without-ssl --with-nss
# --enable-debug
# use ^^^ to turn off optimizations, etc.
@@ -166,6 +176,7 @@
make %{?_smp_mflags} V=1
+%if 0
%check
# we have to override LD_LIBRARY_PATH because we eliminated rpath
LD_LIBRARY_PATH="$RPM_BUILD_ROOT%{_libdir}:$LD_LIBRARY_PATH"
@@ -177,6 +188,7 @@
# run the upstream test-suite
./runtests.pl -a -p -v '!flaky'
+%endif
%install
rm -rf $RPM_BUILD_ROOT
@@ -193,8 +205,10 @@
install -d $RPM_BUILD_ROOT%{_datadir}/aclocal
install -m 644 docs/libcurl/libcurl.m4 $RPM_BUILD_ROOT%{_datadir}/aclocal
+%if 0%{?fedora} != 0 || 0%{?rhel} > 6
# Make libcurl-devel multilib-ready (bug #488922)
%multilib_fix_c_header --file %{_includedir}/curl/curlbuild.h
+%endif
%clean
rm -rf $RPM_BUILD_ROOT
"""
Thanks! Hopefully it means that the regression has been already fixed upstream. If we do not have any in house reproducer, I have no idea how to further debug it, except bisecting further to the potential fix. Could you please check whether it works with curl-7.42.0-1.fc23 (the first upstream release including the fix for CVE-2015-3148)? https://koji.fedoraproject.org/koji/buildinfo?buildID=629950 http://pkgs.fedoraproject.org/cgit/rpms/curl.git/tree/curl.spec?id=13074767 I suspect that this regression could be related to the following sentence from the security advisory [1]:
"We decided to do this blunt short-term fix to avoid this current problem
and then continue to work on a better fix."
[1] https://curl.haxx.se/docs/adv_20150422B.html
It works with curl-7.42.0-1.fc23 backported to rhel6. Cool. This means that we must be missing some commit that landed _before_ the actual fix for CVE-2015-3148. Could you please check it with curl-7.29.0-35.el7 (the latest RHEL-7 build)? It works with curl-7.29.0-35.el7, rebuilt as curl-7.29.0-35.el6.x86_64 as well. Indeed, should be a single/minor missing patch in rhel6 curl-7.19.7-46.el6.x86_64 or newer. Created attachment 1248648 [details]
curl-7.19.7-sfdc01750392.patch
***Note, this is not a proposed patch but hopefully
can help in getting some insight of where else to
look for a possible patch to correct the problem***
The attached patch was an attempt on backporting
some curl-7.29.0-35.el7 changes to curl-7.19.7-52.el6,
but still, known that backport of curl-7.29.0-35.el7
to rhel6 works, and last rhel6 package that works is
rhel6 curl-7.19.7-45.el6.x86_64
The attached patch is in hackish mode, as was added
to test if it were the new code under NTLM_WB_ENABLED
preprocessor option that was the cause of the rhel7
package working.
Thanks for the patch!
Do I understand it correctly that the latest el6 curl works as expected if you apply attachment #1248648 [details] on top of our downstream patches?
No, I am afraid it does work. I just added it to show what was my best guess of what could resolve the problem, but still did not work, but hopefully get some feedback about it :) My next step is to just run latest rhel6 curl under gdb in a remote support session, and attempt to find out where and why it fails. Kamil,
Running under gdb, if I set a breakpoint at
curl-7.19.7/lib/http_negotiate.c:340
like this:
338: else
339: conn->allocptr.userpwd = userp;
340: free(encoded);
341: return (userp == NULL) ? CURLE_OUT_OF_MEMORY : CURLE_OK;
and in the second time it stops there I call
Curl_cleanup_negotiate like this:
(gdb) call Curl_cleanup_negotiate (conn->data)
(gdb) continue
it works.
Trying to figure some condition, with some obfuscated data,
I cannot see of any condition to check, to make the call
conditional, other than it had a redirect...
Breakpoint 2, Curl_output_negotiate (conn=0x635500, proxy=false) at http_negotiate.c:340
340 free(encoded);
(gdb) p conn.data.state
$6 = {used_interface = Curl_if_easy, connc = 0x62f150, keeps_speed = {tv_sec = 0, tv_usec = 0}, lastconnect = 0,
headerbuff = 0x62dad0 "\r\n", headersize = 256,
buffer = "HTTP/1.1 307 TEMPORARY_REDIRECT\r\nCache-Control: no-cache\r\nExpires: Fri, 10 Feb 2017 15:29:35 GMT\r\nDate: Fri, 10 Feb 2017 15:29:35 GMT\r\nPragma: no-cache\r\nExpires: Fri, 10 Feb 2017 15:29:35 GMT\r\nDate: F"...,
uploadbuffer = '\000' <repeats 16384 times>, current_speed = -1, this_is_a_follow = true,
first_host = 0x630320 "EDITED.EXAMPLE.COM", session = 0x62f370, sessionage = 1, tempwrite = 0x0, tempwritesize = 0,
tempwritetype = 0, scratch = 0x0, errorbuf = false, os_errno = 0, prev_signal = 0, allow_port = false, digest = {
nonce = 0x0, cnonce = 0x0, realm = 0x0, algo = 0, stale = false, opaque = 0x0, qop = 0x0, algorithm = 0x0, nc = 0},
proxydigest = {nonce = 0x0, cnonce = 0x0, realm = 0x0, algo = 0, stale = false, opaque = 0x0, qop = 0x0, algorithm = 0x0,
nc = 0}, negotiate = {state = GSS_AUTHNONE, gss = false, protocol = 0x7ffff7dcf9e7 "Negotiate", status = 0,
context = 0x631850, server_name = 0x630020, output_token = {length = 1463, value = 0x6343b0}}, proxyneg = {
state = GSS_AUTHNONE, gss = false, protocol = 0x0, status = 0, context = 0x0, server_name = 0x0, output_token = {
length = 0, value = 0x0}}, authhost = {want = 4, picked = 4, avail = 0, done = true, multi = false, iestyle = false},
authproxy = {want = 1, picked = 1, avail = 0, done = true, multi = false, iestyle = false}, authproblem = false,
expiretime = {tv_sec = 0, tv_usec = 0}, timenode = {smaller = 0x0, larger = 0x0, same = 0x0, key = {tv_sec = 0,
tv_usec = 0}, payload = 0x0}, most_recent_ftp_entrypath = 0x0, ftp_trying_alternative = false, httpversion = 11,
expect100header = false, pipe_broke = false, prev_block_had_trailing_cr = false, crlf_conversions = 0, shared_conn = 0x0,
closed = false, pathbuffer = 0x62fd60 "/EDITED/PATH",
path = 0x62fd60 "/EDITED/PATH", use_range = false, rangestringalloc = false,
range = 0x0, resume_from = 0, proto = {http = 0x630290, https = 0x630290, ftp = 0x630290, file = 0x630290,
telnet = 0x630290, generic = 0x630290, ssh = 0x630290}, current_conn = 0x635500}
I believe this is not correct, at least in the sense of a backport:
https://github.com/curl/curl/commit/f78ae415d24b9bd89d6c121c556e411fdb21c6aa
and, not fully understanding the CVE, it looks like it is even making the
CVE condition worse:
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-3148
by keeping the authentication, but in the user case, failing, apparently
after the redirect.
So, if reverting this chunk:
diff --git a/lib/http_negotiate.c b/lib/http_negotiate.c
index 535a427..b56e7d0 100644
--- a/lib/http_negotiate.c
+++ b/lib/http_negotiate.c
@@ -338,7 +338,6 @@ CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
else
conn->allocptr.userpwd = userp;
free(encoded);
- Curl_cleanup_negotiate (conn->data);
return (userp == NULL) ? CURLE_OUT_OF_MEMORY : CURLE_OK;
}
--
it works for the user.
Fixed as CVE-2017-2628 via RHSA-2017:0847: https://rhn.redhat.com/errata/RHSA-2017-0847.html |