mirror of
https://codeberg.org/redict/redict.git
synced 2025-01-22 08:08:53 -05:00
Fix Read/Write key pattern selector (CVE-2024-51741)
The explanation on the original commit was wrong. Key based access must have a `~` in order to correctly configure whey key prefixes to apply the selector to. If this is missing, a server assert will be triggered later. Cherry-picked and squashed from relevant Valkey changes. Signed-off-by: Madelyn Olson <madelyneolson@gmail.com> Signed-off-by: Drew DeVault <sir@cmpwn.com> Co-authored-by: YaacovHazan <yaacov.hazan@redis.com>
This commit is contained in:
parent
a8edd3f6ac
commit
ba5dcb3b16
@ -1068,19 +1068,24 @@ int ACLSetSelector(aclSelector *selector, const char* op, size_t oplen) {
|
|||||||
int flags = 0;
|
int flags = 0;
|
||||||
size_t offset = 1;
|
size_t offset = 1;
|
||||||
if (op[0] == '%') {
|
if (op[0] == '%') {
|
||||||
|
int perm_ok = 1;
|
||||||
for (; offset < oplen; offset++) {
|
for (; offset < oplen; offset++) {
|
||||||
if (toupper(op[offset]) == 'R' && !(flags & ACL_READ_PERMISSION)) {
|
if (toupper(op[offset]) == 'R' && !(flags & ACL_READ_PERMISSION)) {
|
||||||
flags |= ACL_READ_PERMISSION;
|
flags |= ACL_READ_PERMISSION;
|
||||||
} else if (toupper(op[offset]) == 'W' && !(flags & ACL_WRITE_PERMISSION)) {
|
} else if (toupper(op[offset]) == 'W' && !(flags & ACL_WRITE_PERMISSION)) {
|
||||||
flags |= ACL_WRITE_PERMISSION;
|
flags |= ACL_WRITE_PERMISSION;
|
||||||
} else if (op[offset] == '~' && flags) {
|
} else if (op[offset] == '~') {
|
||||||
offset++;
|
offset++;
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
|
perm_ok = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!flags || !perm_ok) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return C_ERR;
|
return C_ERR;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
flags = ACL_ALL_PERMISSION;
|
flags = ACL_ALL_PERMISSION;
|
||||||
}
|
}
|
||||||
|
@ -123,9 +123,23 @@ start_server {tags {"acl external:skip"}} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
test {Validate read and write permissions format} {
|
test {Validate read and write permissions format} {
|
||||||
catch {r ACL SETUSER key-permission-RW %~} err
|
# Regression tests for CVE-2024-51741
|
||||||
set err
|
assert_error "ERR Error in ACL SETUSER modifier '%~': Syntax error" {r ACL SETUSER invalid %~}
|
||||||
} {ERR Error in ACL SETUSER modifier '%~': Syntax error}
|
assert_error "ERR Error in ACL SETUSER modifier '%': Syntax error" {r ACL SETUSER invalid %}
|
||||||
|
}
|
||||||
|
|
||||||
|
test {Validate key permissions format - empty and omitted pattern} {
|
||||||
|
# Empty pattern results with access to only the empty key
|
||||||
|
r ACL SETUSER key-permission-no-key on nopass %RW~ +@all
|
||||||
|
assert_equal "User key-permission-no-key has no permissions to access the 'x' key" [r ACL DRYRUN key-permission-no-key GET x]
|
||||||
|
assert_equal "OK" [r ACL DRYRUN key-permission-no-key GET ""]
|
||||||
|
# This is incorrect syntax, it should have `~`, but we'll allow it for compatibility since it does something
|
||||||
|
r ACL SETUSER key-permission-omit on nopass %RW +@all
|
||||||
|
assert_equal "User key-permission-omit has no permissions to access the 'x' key" [r ACL DRYRUN key-permission-omit GET x]
|
||||||
|
assert_equal "OK" [r ACL DRYRUN key-permission-omit GET ""]
|
||||||
|
# Assert these two are equivalent
|
||||||
|
assert_equal [r ACL GETUSER key-permission-omit] [r ACL GETUSER key-permission-no-key]
|
||||||
|
}
|
||||||
|
|
||||||
test {Test separate read and write permissions on different selectors are not additive} {
|
test {Test separate read and write permissions on different selectors are not additive} {
|
||||||
r ACL SETUSER key-permission-RW-selector on nopass "(%R~read* +@all)" "(%W~write* +@all)"
|
r ACL SETUSER key-permission-RW-selector on nopass "(%R~read* +@all)" "(%W~write* +@all)"
|
||||||
|
Loading…
Reference in New Issue
Block a user