1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-14 01:57:53 +03:00

CVE-2021-20251 s4-rpc_server: Use user privileges for SAMR password change

We don't (and shouldn't) need system prvileges to perform the password
change, so drop to the privileges of the user by setting
DSDB_SESSION_INFO. We need to reuse the same sam_ctx: creating a new one
with only user privileges would not work, because any database
modifications would be blocked by the transaction taken out on the
original context.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=14611

Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
Reviewed-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
(cherry picked from commit f74f92aea164af40d9177b332778a76d7ecabcbd)
This commit is contained in:
Joseph Sutton 2022-08-02 14:39:06 +12:00 committed by Jule Anger
parent b8c123d02d
commit 7b28bd1080
2 changed files with 31 additions and 6 deletions

View File

@ -4091,7 +4091,8 @@ static NTSTATUS dcesrv_samr_SetUserInfo(struct dcesrv_call_state *dce_call, TALL
sam_ctx,
a_state->account_dn,
a_state->domain_state->domain_dn,
&r->in.info->info31.password);
&r->in.info->info31.password,
DSDB_PASSWORD_RESET);
if (!NT_STATUS_IS_OK(status)) {
goto done;
}
@ -4244,7 +4245,8 @@ static NTSTATUS dcesrv_samr_SetUserInfo(struct dcesrv_call_state *dce_call, TALL
a_state->sam_ctx,
a_state->account_dn,
a_state->domain_state->domain_dn,
&r->in.info->info32.password);
&r->in.info->info32.password,
DSDB_PASSWORD_RESET);
}
else IFSET(SAMR_FIELD_LM_PASSWORD_PRESENT)
{
@ -4255,7 +4257,8 @@ static NTSTATUS dcesrv_samr_SetUserInfo(struct dcesrv_call_state *dce_call, TALL
a_state->sam_ctx,
a_state->account_dn,
a_state->domain_state->domain_dn,
&r->in.info->info32.password);
&r->in.info->info32.password,
DSDB_PASSWORD_RESET);
}
if (!NT_STATUS_IS_OK(status)) {
goto done;

View File

@ -134,6 +134,8 @@ NTSTATUS dcesrv_samr_ChangePasswordUser4(struct dcesrv_call_state *dce_call,
.data = cdk_data,
.length = sizeof(cdk_data),
};
struct auth_session_info *call_session_info = NULL;
struct auth_session_info *old_session_info = NULL;
NTSTATUS status = NT_STATUS_WRONG_PASSWORD;
int rc;
@ -219,14 +221,33 @@ NTSTATUS dcesrv_samr_ChangePasswordUser4(struct dcesrv_call_state *dce_call,
goto done;
}
/* Drop to user privileges for the password change */
old_session_info = ldb_get_opaque(sam_ctx, DSDB_SESSION_INFO);
call_session_info = dcesrv_call_session_info(dce_call);
rc = ldb_set_opaque(sam_ctx, DSDB_SESSION_INFO, call_session_info);
if (rc != LDB_SUCCESS) {
ldb_transaction_cancel(sam_ctx);
status = NT_STATUS_INVALID_SYSTEM_SERVICE;
goto done;
}
status = samr_set_password_aes(dce_call,
mem_ctx,
&cdk,
sam_ctx,
dn,
NULL,
r->in.password);
r->in.password,
DSDB_PASSWORD_CHECKED_AND_CORRECT);
BURN_DATA(cdk_data);
/* Restore our privileges to system level */
if (old_session_info != NULL) {
ldb_set_opaque(sam_ctx, DSDB_SESSION_INFO, old_session_info);
}
if (!NT_STATUS_IS_OK(status)) {
ldb_transaction_cancel(sam_ctx);
status = NT_STATUS_WRONG_PASSWORD;
@ -741,7 +762,8 @@ NTSTATUS samr_set_password_aes(struct dcesrv_call_state *dce_call,
struct ldb_context *sam_ctx,
struct ldb_dn *account_dn,
struct ldb_dn *domain_dn,
struct samr_EncryptedPasswordAES *pwbuf)
struct samr_EncryptedPasswordAES *pwbuf,
enum dsdb_password_checked old_password_checked)
{
DATA_BLOB pw_data = data_blob_null;
DATA_BLOB new_password = data_blob_null;
@ -779,7 +801,7 @@ NTSTATUS samr_set_password_aes(struct dcesrv_call_state *dce_call,
domain_dn,
&new_password,
NULL,
DSDB_PASSWORD_RESET,
old_password_checked,
NULL,
NULL);
TALLOC_FREE(new_password.data);