From f100bd2f2e4f047942002a992c99104227a17f81 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 10 Jul 2020 15:09:33 -0700 Subject: [PATCH 1/6] s4: torture: Add smb2.notify.handle-permissions test. Add knownfail entry. CVE-2020-14318 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14434 Signed-off-by: Jeremy Allison --- .../smb2_notify_handle_permissions | 2 + source4/torture/smb2/notify.c | 80 +++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 selftest/knownfail.d/smb2_notify_handle_permissions diff --git a/selftest/knownfail.d/smb2_notify_handle_permissions b/selftest/knownfail.d/smb2_notify_handle_permissions new file mode 100644 index 00000000000..c0ec8fc8153 --- /dev/null +++ b/selftest/knownfail.d/smb2_notify_handle_permissions @@ -0,0 +1,2 @@ +^samba3.smb2.notify.handle-permissions + diff --git a/source4/torture/smb2/notify.c b/source4/torture/smb2/notify.c index d8aa44f5d4c..79096394130 100644 --- a/source4/torture/smb2/notify.c +++ b/source4/torture/smb2/notify.c @@ -2649,6 +2649,83 @@ done: return ok; } +/* + Test asking for a change notify on a handle without permissions. +*/ + +#define BASEDIR_HPERM BASEDIR "_HPERM" + +static bool torture_smb2_notify_handle_permissions( + struct torture_context *torture, + struct smb2_tree *tree) +{ + bool ret = true; + NTSTATUS status; + union smb_notify notify; + union smb_open io; + struct smb2_handle h1 = {{0}}; + struct smb2_request *req; + + smb2_deltree(tree, BASEDIR_HPERM); + smb2_util_rmdir(tree, BASEDIR_HPERM); + + torture_comment(torture, + "TESTING CHANGE NOTIFY " + "ON A HANDLE WITHOUT PERMISSIONS\n"); + + /* + get a handle on the directory + */ + ZERO_STRUCT(io.smb2); + io.generic.level = RAW_OPEN_SMB2; + io.smb2.in.create_flags = 0; + io.smb2.in.desired_access = SEC_FILE_READ_ATTRIBUTE; + io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY; + io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL; + io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ | + NTCREATEX_SHARE_ACCESS_WRITE; + io.smb2.in.alloc_size = 0; + io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE; + io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS; + io.smb2.in.security_flags = 0; + io.smb2.in.fname = BASEDIR_HPERM; + + status = smb2_create(tree, torture, &io.smb2); + CHECK_STATUS(status, NT_STATUS_OK); + h1 = io.smb2.out.file.handle; + + /* ask for a change notify, + on file or directory name changes */ + ZERO_STRUCT(notify.smb2); + notify.smb2.level = RAW_NOTIFY_SMB2; + notify.smb2.in.buffer_size = 1000; + notify.smb2.in.completion_filter = FILE_NOTIFY_CHANGE_NAME; + notify.smb2.in.file.handle = h1; + notify.smb2.in.recursive = true; + + req = smb2_notify_send(tree, ¬ify.smb2); + torture_assert_goto(torture, + req != NULL, + ret, + done, + "smb2_notify_send failed\n"); + + /* + * Cancel it, we don't really want to wait. + */ + smb2_cancel(req); + status = smb2_notify_recv(req, torture, ¬ify.smb2); + /* Handle h1 doesn't have permissions for ChangeNotify. */ + CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); + +done: + if (!smb2_util_handle_empty(h1)) { + smb2_util_close(tree, h1); + } + smb2_deltree(tree, BASEDIR_HPERM); + return ret; +} + /* basic testing of SMB2 change notify */ @@ -2682,6 +2759,9 @@ struct torture_suite *torture_smb2_notify_init(TALLOC_CTX *ctx) torture_smb2_notify_rmdir3); torture_suite_add_2smb2_test(suite, "rmdir4", torture_smb2_notify_rmdir4); + torture_suite_add_1smb2_test(suite, + "handle-permissions", + torture_smb2_notify_handle_permissions); suite->description = talloc_strdup(suite, "SMB2-NOTIFY tests"); -- 2.17.1 From f43ecce46a89c6380317fbb5f2ae38f48d3d42c8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 7 Jul 2020 18:25:23 -0700 Subject: [PATCH 2/6] s3: smbd: Ensure change notifies can't get set unless the directory handle is open for SEC_DIR_LIST. Remove knownfail entry. CVE-2020-14318 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14434 Signed-off-by: Jeremy Allison --- selftest/knownfail.d/smb2_notify_handle_permissions | 2 -- source3/smbd/notify.c | 8 ++++++++ 2 files changed, 8 insertions(+), 2 deletions(-) delete mode 100644 selftest/knownfail.d/smb2_notify_handle_permissions diff --git a/selftest/knownfail.d/smb2_notify_handle_permissions b/selftest/knownfail.d/smb2_notify_handle_permissions deleted file mode 100644 index c0ec8fc8153..00000000000 --- a/selftest/knownfail.d/smb2_notify_handle_permissions +++ /dev/null @@ -1,2 +0,0 @@ -^samba3.smb2.notify.handle-permissions - diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index b36a4c0003a..68553686fa2 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -289,6 +289,14 @@ NTSTATUS change_notify_create(struct files_struct *fsp, char fullpath[len+1]; NTSTATUS status = NT_STATUS_NOT_IMPLEMENTED; + /* + * Setting a changenotify needs READ/LIST access + * on the directory handle. + */ + if (!(fsp->access_mask & SEC_DIR_LIST)) { + return NT_STATUS_ACCESS_DENIED; + } + if (fsp->notify != NULL) { DEBUG(1, ("change_notify_create: fsp->notify != NULL, " "fname = %s\n", fsp->fsp_name->base_name)); -- 2.17.1 From f17967ad73e9c1d2bd6e0b7c181f08079d2a8214 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 9 Jul 2020 21:49:25 +0200 Subject: [PATCH 3/6] CVE-2020-14323 winbind: Fix invalid lookupsids DoS A lookupsids request without extra_data will lead to "state->domain==NULL", which makes winbindd_lookupsids_recv trying to dereference it. Reported by Bas Alberts of the GitHub Security Lab Team as GHSL-2020-134 Bug: https://bugzilla.samba.org/show_bug.cgi?id=14436 Signed-off-by: Volker Lendecke --- source3/winbindd/winbindd_lookupsids.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source3/winbindd/winbindd_lookupsids.c b/source3/winbindd/winbindd_lookupsids.c index d28b5fa9f01..a289fd86f0f 100644 --- a/source3/winbindd/winbindd_lookupsids.c +++ b/source3/winbindd/winbindd_lookupsids.c @@ -47,7 +47,7 @@ struct tevent_req *winbindd_lookupsids_send(TALLOC_CTX *mem_ctx, DEBUG(3, ("lookupsids\n")); if (request->extra_len == 0) { - tevent_req_done(req); + tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); return tevent_req_post(req, ev); } if (request->extra_data.data[request->extra_len-1] != '\0') { -- 2.17.1 From d0ca2a63aaedf123205337aaa211426175ffcebf Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 9 Jul 2020 21:48:57 +0200 Subject: [PATCH 4/6] CVE-2020-14323 torture4: Add a simple test for invalid lookup_sids winbind call We can't add this test before the fix, add it to knownfail and have the fix remove the knownfail entry again. As this crashes winbind, many tests after this one will fail. Reported by Bas Alberts of the GitHub Security Lab Team as GHSL-2020-134 Bug: https://bugzilla.samba.org/show_bug.cgi?id=14436 Signed-off-by: Volker Lendecke --- source4/torture/winbind/struct_based.c | 27 ++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/source4/torture/winbind/struct_based.c b/source4/torture/winbind/struct_based.c index 9745b621ca9..71f248c0d61 100644 --- a/source4/torture/winbind/struct_based.c +++ b/source4/torture/winbind/struct_based.c @@ -1110,6 +1110,29 @@ static bool torture_winbind_struct_lookup_name_sid(struct torture_context *tortu return true; } +static bool torture_winbind_struct_lookup_sids_invalid( + struct torture_context *torture) +{ + struct winbindd_request req = {0}; + struct winbindd_response rep = {0}; + bool strict = torture_setting_bool(torture, "strict mode", false); + bool ok; + + torture_comment(torture, + "Running WINBINDD_LOOKUP_SIDS (struct based)\n"); + + ok = true; + DO_STRUCT_REQ_REP_EXT(WINBINDD_LOOKUPSIDS, &req, &rep, + NSS_STATUS_NOTFOUND, + strict, + ok=false, + talloc_asprintf( + torture, + "invalid lookupsids succeeded")); + + return ok; +} + struct torture_suite *torture_winbind_struct_init(TALLOC_CTX *ctx) { struct torture_suite *suite = torture_suite_create(ctx, "struct"); @@ -1132,6 +1155,10 @@ struct torture_suite *torture_winbind_struct_init(TALLOC_CTX *ctx) torture_suite_add_simple_test(suite, "getpwent", torture_winbind_struct_getpwent); torture_suite_add_simple_test(suite, "endpwent", torture_winbind_struct_endpwent); torture_suite_add_simple_test(suite, "lookup_name_sid", torture_winbind_struct_lookup_name_sid); + torture_suite_add_simple_test( + suite, + "lookup_sids_invalid", + torture_winbind_struct_lookup_sids_invalid); suite->description = talloc_strdup(suite, "WINBIND - struct based protocol tests"); -- 2.17.1 From 2d7d1dff7d20d5b06ff50452e7f714af9f6a109e Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Fri, 21 Aug 2020 17:10:22 +1200 Subject: [PATCH 5/6] CVE-2020-14383: s4/dns: Ensure variable initialization with NULL. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Based on patches from Francis Brosnan Blázquez and Jeremy Allison BUG: https://bugzilla.samba.org/show_bug.cgi?id=14472 BUG: https://bugzilla.samba.org/show_bug.cgi?id=12795 Signed-off-by: Douglas Bagnall Reviewed-by: Jeremy Allison (based on commit 7afe449e7201be92bed8e53cbb37b74af720ef4e) --- .../rpc_server/dnsserver/dcerpc_dnsserver.c | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/source4/rpc_server/dnsserver/dcerpc_dnsserver.c b/source4/rpc_server/dnsserver/dcerpc_dnsserver.c index b6389f2328a..ec610168266 100644 --- a/source4/rpc_server/dnsserver/dcerpc_dnsserver.c +++ b/source4/rpc_server/dnsserver/dcerpc_dnsserver.c @@ -1759,15 +1759,17 @@ static WERROR dnsserver_enumerate_records(struct dnsserver_state *dsstate, TALLOC_CTX *tmp_ctx; char *name; const char * const attrs[] = { "name", "dnsRecord", NULL }; - struct ldb_result *res; - struct DNS_RPC_RECORDS_ARRAY *recs; + struct ldb_result *res = NULL; + struct DNS_RPC_RECORDS_ARRAY *recs = NULL; char **add_names = NULL; - char *rname; + char *rname = NULL; const char *preference_name = NULL; int add_count = 0; int i, ret, len; WERROR status; - struct dns_tree *tree, *base, *node; + struct dns_tree *tree = NULL; + struct dns_tree *base = NULL; + struct dns_tree *node = NULL; tmp_ctx = talloc_new(mem_ctx); W_ERROR_HAVE_NO_MEMORY(tmp_ctx); @@ -1850,9 +1852,9 @@ static WERROR dnsserver_enumerate_records(struct dnsserver_state *dsstate, } } - talloc_free(res); - talloc_free(tree); - talloc_free(name); + TALLOC_FREE(res); + TALLOC_FREE(tree); + TALLOC_FREE(name); /* Add any additional records */ if (select_flag & DNS_RPC_VIEW_ADDITIONAL_DATA) { @@ -1870,14 +1872,14 @@ static WERROR dnsserver_enumerate_records(struct dnsserver_state *dsstate, LDB_SCOPE_ONELEVEL, attrs, "(&(objectClass=dnsNode)(name=%s)(!(dNSTombstoned=TRUE)))", encoded_name); - talloc_free(name); + TALLOC_FREE(name); if (ret != LDB_SUCCESS) { continue; } if (res->count == 1) { break; } else { - talloc_free(res); + TALLOC_FREE(res); continue; } } @@ -1892,8 +1894,8 @@ static WERROR dnsserver_enumerate_records(struct dnsserver_state *dsstate, select_flag, rname, res->msgs[0], 0, recs, NULL, NULL); - talloc_free(rname); - talloc_free(res); + TALLOC_FREE(rname); + TALLOC_FREE(res); if (!W_ERROR_IS_OK(status)) { talloc_free(tmp_ctx); return status; -- 2.17.1 From 425c31a599bb96c7d01273fc50b682bc42dbed57 Mon Sep 17 00:00:00 2001 From: Douglas Bagnall Date: Fri, 21 Aug 2020 17:23:17 +1200 Subject: [PATCH 6/6] CVE-2020-14383: s4/dns: do not crash when additional data not found MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Found by Francis Brosnan Blázquez . BUG: https://bugzilla.samba.org/show_bug.cgi?id=14472 BUG: https://bugzilla.samba.org/show_bug.cgi?id=12795 Signed-off-by: Douglas Bagnall Reviewed-by: Jeremy Allison Autobuild-User(master): Douglas Bagnall Autobuild-Date(master): Mon Aug 24 00:21:41 UTC 2020 on sn-devel-184 (based on commit df98e7db04c901259dd089e20cd557bdbdeaf379) --- source4/rpc_server/dnsserver/dcerpc_dnsserver.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/source4/rpc_server/dnsserver/dcerpc_dnsserver.c b/source4/rpc_server/dnsserver/dcerpc_dnsserver.c index ec610168266..88efc01f154 100644 --- a/source4/rpc_server/dnsserver/dcerpc_dnsserver.c +++ b/source4/rpc_server/dnsserver/dcerpc_dnsserver.c @@ -1859,8 +1859,8 @@ static WERROR dnsserver_enumerate_records(struct dnsserver_state *dsstate, /* Add any additional records */ if (select_flag & DNS_RPC_VIEW_ADDITIONAL_DATA) { for (i=0; izones; z2; z2 = z2->next) { char *encoded_name; @@ -1877,6 +1877,7 @@ static WERROR dnsserver_enumerate_records(struct dnsserver_state *dsstate, continue; } if (res->count == 1) { + msg = res->msgs[0]; break; } else { TALLOC_FREE(res); @@ -1892,7 +1893,7 @@ static WERROR dnsserver_enumerate_records(struct dnsserver_state *dsstate, } status = dns_fill_records_array(tmp_ctx, NULL, DNS_TYPE_A, select_flag, rname, - res->msgs[0], 0, recs, + msg, 0, recs, NULL, NULL); TALLOC_FREE(rname); TALLOC_FREE(res); -- 2.17.1