summaryrefslogtreecommitdiffstats
path: root/meta/recipes-core/dropbear
diff options
context:
space:
mode:
authorMingli Yu <Mingli.Yu@windriver.com>2018-09-06 16:06:33 +0800
committerRichard Purdie <richard.purdie@linuxfoundation.org>2018-09-10 12:13:06 +0100
commit688611a5edd7a90f05f8501bf29f7ba8cf4c07fc (patch)
treeca0b5efaee65ca5838aee40da2e823893f148115 /meta/recipes-core/dropbear
parent8e8d296ea91722ae7a362277abbca64f9ce1fd76 (diff)
downloadpoky-688611a5edd7a90f05f8501bf29f7ba8cf4c07fc.tar.gz
dropbear: Fix CVE-2018-15599
Wait to fail invalid usernames to fix CVE-2018-15599 Rework 0006-dropbear-configuration-file.patch to fix fuzz warnings (From OE-Core rev: f017715120b67ff02f56ed5db131436ee62aeffb) Signed-off-by: Mingli Yu <Mingli.Yu@windriver.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/recipes-core/dropbear')
-rw-r--r--meta/recipes-core/dropbear/dropbear.inc1
-rw-r--r--meta/recipes-core/dropbear/dropbear/0006-dropbear-configuration-file.patch23
-rw-r--r--meta/recipes-core/dropbear/dropbear/CVE-2018-15599.patch236
3 files changed, 254 insertions, 6 deletions
diff --git a/meta/recipes-core/dropbear/dropbear.inc b/meta/recipes-core/dropbear/dropbear.inc
index b634e0e53e..dc24ea71bf 100644
--- a/meta/recipes-core/dropbear/dropbear.inc
+++ b/meta/recipes-core/dropbear/dropbear.inc
@@ -13,6 +13,7 @@ RPROVIDES_${PN} = "ssh sshd"
13DEPENDS += "${@bb.utils.contains('DISTRO_FEATURES', 'pam', 'libpam', '', d)}" 13DEPENDS += "${@bb.utils.contains('DISTRO_FEATURES', 'pam', 'libpam', '', d)}"
14 14
15SRC_URI = "http://matt.ucc.asn.au/dropbear/releases/dropbear-${PV}.tar.bz2 \ 15SRC_URI = "http://matt.ucc.asn.au/dropbear/releases/dropbear-${PV}.tar.bz2 \
16 file://CVE-2018-15599.patch \
16 file://0001-urandom-xauth-changes-to-options.h.patch \ 17 file://0001-urandom-xauth-changes-to-options.h.patch \
17 file://0007-fix-localoptions-search-path.patch \ 18 file://0007-fix-localoptions-search-path.patch \
18 file://init \ 19 file://init \
diff --git a/meta/recipes-core/dropbear/dropbear/0006-dropbear-configuration-file.patch b/meta/recipes-core/dropbear/dropbear/0006-dropbear-configuration-file.patch
index fa4c8d0a67..deed78ffb9 100644
--- a/meta/recipes-core/dropbear/dropbear/0006-dropbear-configuration-file.patch
+++ b/meta/recipes-core/dropbear/dropbear/0006-dropbear-configuration-file.patch
@@ -1,4 +1,7 @@
1Subject: [PATCH 6/6] dropbear configuration file 1From e3a5db1b6d3f6382a15b2266458c26c645a10f18 Mon Sep 17 00:00:00 2001
2From: Mingli Yu <Mingli.Yu@windriver.com>
3Date: Thu, 6 Sep 2018 15:54:00 +0800
4Subject: [PATCH] dropbear configuration file
2 5
3dropbear: Change the path ("/etc/pam.d/sshd" as default) to find a pam configuration file \ 6dropbear: Change the path ("/etc/pam.d/sshd" as default) to find a pam configuration file \
4to "/etc/pam.d/dropbear for dropbear when enabling pam supporting" 7to "/etc/pam.d/dropbear for dropbear when enabling pam supporting"
@@ -7,12 +10,17 @@ Upstream-Status: Inappropriate [configuration]
7 10
8Signed-off-by: Maxin B. John <maxin.john@enea.com> 11Signed-off-by: Maxin B. John <maxin.john@enea.com>
9Signed-off-by: Xiaofeng Yan <xiaofeng.yan@windriver.com> 12Signed-off-by: Xiaofeng Yan <xiaofeng.yan@windriver.com>
13Signed-off-by: Mingli Yu <Mingli.Yu@windriver.com>
10--- 14---
11diff -Naur dropbear-2013.60-orig/svr-authpam.c dropbear-2013.60/svr-authpam.c 15 svr-authpam.c | 2 +-
12--- dropbear-2013.60-orig/svr-authpam.c 2013-10-16 16:34:53.000000000 +0200 16 1 file changed, 1 insertion(+), 1 deletion(-)
13+++ dropbear-2013.60/svr-authpam.c 2013-10-21 17:04:04.969416055 +0200 17
14@@ -211,7 +211,7 @@ 18diff --git a/svr-authpam.c b/svr-authpam.c
15 userData.passwd = password; 19index d201bc9..165ec5c 100644
20--- a/svr-authpam.c
21+++ b/svr-authpam.c
22@@ -223,7 +223,7 @@ void svr_auth_pam(int valid_user) {
23 }
16 24
17 /* Init pam */ 25 /* Init pam */
18- if ((rc = pam_start("sshd", NULL, &pamConv, &pamHandlep)) != PAM_SUCCESS) { 26- if ((rc = pam_start("sshd", NULL, &pamConv, &pamHandlep)) != PAM_SUCCESS) {
@@ -20,3 +28,6 @@ diff -Naur dropbear-2013.60-orig/svr-authpam.c dropbear-2013.60/svr-authpam.c
20 dropbear_log(LOG_WARNING, "pam_start() failed, rc=%d, %s", 28 dropbear_log(LOG_WARNING, "pam_start() failed, rc=%d, %s",
21 rc, pam_strerror(pamHandlep, rc)); 29 rc, pam_strerror(pamHandlep, rc));
22 goto cleanup; 30 goto cleanup;
31--
322.7.4
33
diff --git a/meta/recipes-core/dropbear/dropbear/CVE-2018-15599.patch b/meta/recipes-core/dropbear/dropbear/CVE-2018-15599.patch
new file mode 100644
index 0000000000..912545c957
--- /dev/null
+++ b/meta/recipes-core/dropbear/dropbear/CVE-2018-15599.patch
@@ -0,0 +1,236 @@
1From 256e2abb8150f9fea33cd026597dbe70f0379296 Mon Sep 17 00:00:00 2001
2From: Matt Johnston <matt@ucc.asn.au>
3Date: Thu, 23 Aug 2018 23:43:12 +0800
4Subject: [PATCH] Wait to fail invalid usernames
5
6Wait to fail invalid usernames
7
8Upstream-Status: Backport [https://secure.ucc.asn.au/hg/dropbear/rev/5d2d1021ca00]
9CVE: CVE-2018-15599
10Signed-off-by: Mingli Yu <Mingli.Yu@windriver.com>
11---
12 auth.h | 6 +++---
13 svr-auth.c | 19 +++++--------------
14 svr-authpam.c | 26 ++++++++++++++++++++++----
15 svr-authpasswd.c | 27 ++++++++++++++-------------
16 svr-authpubkey.c | 11 ++++++++++-
17 5 files changed, 54 insertions(+), 35 deletions(-)
18
19diff --git a/auth.h b/auth.h
20index da498f5..98f5468 100644
21--- a/auth.h
22+++ b/auth.h
23@@ -37,9 +37,9 @@ void recv_msg_userauth_request(void);
24 void send_msg_userauth_failure(int partial, int incrfail);
25 void send_msg_userauth_success(void);
26 void send_msg_userauth_banner(const buffer *msg);
27-void svr_auth_password(void);
28-void svr_auth_pubkey(void);
29-void svr_auth_pam(void);
30+void svr_auth_password(int valid_user);
31+void svr_auth_pubkey(int valid_user);
32+void svr_auth_pam(int valid_user);
33
34 #if DROPBEAR_SVR_PUBKEY_OPTIONS_BUILT
35 int svr_pubkey_allows_agentfwd(void);
36diff --git a/svr-auth.c b/svr-auth.c
37index 64d97aa..1f364ca 100644
38--- a/svr-auth.c
39+++ b/svr-auth.c
40@@ -149,10 +149,8 @@ void recv_msg_userauth_request() {
41 if (methodlen == AUTH_METHOD_PASSWORD_LEN &&
42 strncmp(methodname, AUTH_METHOD_PASSWORD,
43 AUTH_METHOD_PASSWORD_LEN) == 0) {
44- if (valid_user) {
45- svr_auth_password();
46- goto out;
47- }
48+ svr_auth_password(valid_user);
49+ goto out;
50 }
51 }
52 #endif
53@@ -164,10 +162,8 @@ void recv_msg_userauth_request() {
54 if (methodlen == AUTH_METHOD_PASSWORD_LEN &&
55 strncmp(methodname, AUTH_METHOD_PASSWORD,
56 AUTH_METHOD_PASSWORD_LEN) == 0) {
57- if (valid_user) {
58- svr_auth_pam();
59- goto out;
60- }
61+ svr_auth_pam(valid_user);
62+ goto out;
63 }
64 }
65 #endif
66@@ -177,12 +173,7 @@ void recv_msg_userauth_request() {
67 if (methodlen == AUTH_METHOD_PUBKEY_LEN &&
68 strncmp(methodname, AUTH_METHOD_PUBKEY,
69 AUTH_METHOD_PUBKEY_LEN) == 0) {
70- if (valid_user) {
71- svr_auth_pubkey();
72- } else {
73- /* pubkey has no failure delay */
74- send_msg_userauth_failure(0, 0);
75- }
76+ svr_auth_pubkey(valid_user);
77 goto out;
78 }
79 #endif
80diff --git a/svr-authpam.c b/svr-authpam.c
81index 05e4f3e..d201bc9 100644
82--- a/svr-authpam.c
83+++ b/svr-authpam.c
84@@ -178,13 +178,14 @@ pamConvFunc(int num_msg,
85 * Keyboard interactive would be a lot nicer, but since PAM is synchronous, it
86 * gets very messy trying to send the interactive challenges, and read the
87 * interactive responses, over the network. */
88-void svr_auth_pam() {
89+void svr_auth_pam(int valid_user) {
90
91 struct UserDataS userData = {NULL, NULL};
92 struct pam_conv pamConv = {
93 pamConvFunc,
94 &userData /* submitted to pamvConvFunc as appdata_ptr */
95 };
96+ const char* printable_user = NULL;
97
98 pam_handle_t* pamHandlep = NULL;
99
100@@ -204,12 +205,23 @@ void svr_auth_pam() {
101
102 password = buf_getstring(ses.payload, &passwordlen);
103
104+ /* We run the PAM conversation regardless of whether the username is valid
105+ in case the conversation function has an inherent delay.
106+ Use ses.authstate.username rather than ses.authstate.pw_name.
107+ After PAM succeeds we then check the valid_user flag too */
108+
109 /* used to pass data to the PAM conversation function - don't bother with
110 * strdup() etc since these are touched only by our own conversation
111 * function (above) which takes care of it */
112- userData.user = ses.authstate.pw_name;
113+ userData.user = ses.authstate.username;
114 userData.passwd = password;
115
116+ if (ses.authstate.pw_name) {
117+ printable_user = ses.authstate.pw_name;
118+ } else {
119+ printable_user = "<invalid username>";
120+ }
121+
122 /* Init pam */
123 if ((rc = pam_start("sshd", NULL, &pamConv, &pamHandlep)) != PAM_SUCCESS) {
124 dropbear_log(LOG_WARNING, "pam_start() failed, rc=%d, %s",
125@@ -242,7 +254,7 @@ void svr_auth_pam() {
126 rc, pam_strerror(pamHandlep, rc));
127 dropbear_log(LOG_WARNING,
128 "Bad PAM password attempt for '%s' from %s",
129- ses.authstate.pw_name,
130+ printable_user,
131 svr_ses.addrstring);
132 send_msg_userauth_failure(0, 1);
133 goto cleanup;
134@@ -253,12 +265,18 @@ void svr_auth_pam() {
135 rc, pam_strerror(pamHandlep, rc));
136 dropbear_log(LOG_WARNING,
137 "Bad PAM password attempt for '%s' from %s",
138- ses.authstate.pw_name,
139+ printable_user,
140 svr_ses.addrstring);
141 send_msg_userauth_failure(0, 1);
142 goto cleanup;
143 }
144
145+ if (!valid_user) {
146+ /* PAM auth succeeded but the username isn't allowed in for another reason
147+ (checkusername() failed) */
148+ send_msg_userauth_failure(0, 1);
149+ }
150+
151 /* successful authentication */
152 dropbear_log(LOG_NOTICE, "PAM password auth succeeded for '%s' from %s",
153 ses.authstate.pw_name,
154diff --git a/svr-authpasswd.c b/svr-authpasswd.c
155index bdee2aa..69c7d8a 100644
156--- a/svr-authpasswd.c
157+++ b/svr-authpasswd.c
158@@ -48,22 +48,14 @@ static int constant_time_strcmp(const char* a, const char* b) {
159
160 /* Process a password auth request, sending success or failure messages as
161 * appropriate */
162-void svr_auth_password() {
163+void svr_auth_password(int valid_user) {
164
165 char * passwdcrypt = NULL; /* the crypt from /etc/passwd or /etc/shadow */
166 char * testcrypt = NULL; /* crypt generated from the user's password sent */
167- char * password;
168+ char * password = NULL;
169 unsigned int passwordlen;
170-
171 unsigned int changepw;
172
173- passwdcrypt = ses.authstate.pw_passwd;
174-
175-#ifdef DEBUG_HACKCRYPT
176- /* debugging crypt for non-root testing with shadows */
177- passwdcrypt = DEBUG_HACKCRYPT;
178-#endif
179-
180 /* check if client wants to change password */
181 changepw = buf_getbool(ses.payload);
182 if (changepw) {
183@@ -73,12 +65,21 @@ void svr_auth_password() {
184 }
185
186 password = buf_getstring(ses.payload, &passwordlen);
187-
188- /* the first bytes of passwdcrypt are the salt */
189- testcrypt = crypt(password, passwdcrypt);
190+ if (valid_user) {
191+ /* the first bytes of passwdcrypt are the salt */
192+ passwdcrypt = ses.authstate.pw_passwd;
193+ testcrypt = crypt(password, passwdcrypt);
194+ }
195 m_burn(password, passwordlen);
196 m_free(password);
197
198+ /* After we have got the payload contents we can exit if the username
199+ is invalid. Invalid users have already been logged. */
200+ if (!valid_user) {
201+ send_msg_userauth_failure(0, 1);
202+ return;
203+ }
204+
205 if (testcrypt == NULL) {
206 /* crypt() with an invalid salt like "!!" */
207 dropbear_log(LOG_WARNING, "User account '%s' is locked",
208diff --git a/svr-authpubkey.c b/svr-authpubkey.c
209index aa6087c..ff481c8 100644
210--- a/svr-authpubkey.c
211+++ b/svr-authpubkey.c
212@@ -79,7 +79,7 @@ static int checkfileperm(char * filename);
213
214 /* process a pubkey auth request, sending success or failure message as
215 * appropriate */
216-void svr_auth_pubkey() {
217+void svr_auth_pubkey(int valid_user) {
218
219 unsigned char testkey; /* whether we're just checking if a key is usable */
220 char* algo = NULL; /* pubkey algo */
221@@ -102,6 +102,15 @@ void svr_auth_pubkey() {
222 keybloblen = buf_getint(ses.payload);
223 keyblob = buf_getptr(ses.payload, keybloblen);
224
225+ if (!valid_user) {
226+ /* Return failure once we have read the contents of the packet
227+ required to validate a public key.
228+ Avoids blind user enumeration though it isn't possible to prevent
229+ testing for user existence if the public key is known */
230+ send_msg_userauth_failure(0, 0);
231+ goto out;
232+ }
233+
234 /* check if the key is valid */
235 if (checkpubkey(algo, algolen, keyblob, keybloblen) == DROPBEAR_FAILURE) {
236 send_msg_userauth_failure(0, 0);