mirror of
https://github.com/samba-team/samba.git
synced 2024-12-22 13:34:15 +03:00
lib/fuzzing: add fuzz_sddl_access_check
This fuzzer parses SDDL into a security descriptor and runs an access check on it using a known security token. This is purely for crash detection -- we don't know enough to assert whether the check should succeed or not. The seed strings used are compatible with those of fuzz_sddl_parse -- anything found by fuzz_sddl_parse is worth trying as a seed here, and vice versa. Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abartlet@samba.org>
This commit is contained in:
parent
3ed1ba6fed
commit
5ad28bd760
125
lib/fuzzing/fuzz_sddl_access_check.c
Normal file
125
lib/fuzzing/fuzz_sddl_access_check.c
Normal file
@ -0,0 +1,125 @@
|
||||
/*
|
||||
Fuzz access chcek using SDDL strings and a known token
|
||||
Copyright (C) Catalyst IT 2023
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "replace.h"
|
||||
#include "libcli/security/security.h"
|
||||
#include "lib/util/attr.h"
|
||||
#include "librpc/gen_ndr/ndr_security.h"
|
||||
#include "lib/util/bytearray.h"
|
||||
#include "fuzzing/fuzzing.h"
|
||||
|
||||
|
||||
static struct security_token token = {0};
|
||||
|
||||
static struct dom_sid dom_sid = {0};
|
||||
|
||||
/*
|
||||
* For this one we initialise a security token to have a few SIDs. The fuzz
|
||||
* strings contain SDDL that will be tested against this token in
|
||||
* se_access_check() or sec_access_check_ds() -- supposing they compile.
|
||||
*
|
||||
* When we introduce conditional ACEs and claims (soon!), we'll also add some
|
||||
* claims and device SIDs to the token.
|
||||
*/
|
||||
|
||||
int LLVMFuzzerInitialize(int *argc, char ***argv)
|
||||
{
|
||||
size_t i;
|
||||
bool ok;
|
||||
TALLOC_CTX *mem_ctx = talloc_new(NULL);
|
||||
struct dom_sid *sid = NULL;
|
||||
|
||||
const char * user_sids[] = {
|
||||
"S-1-333-66",
|
||||
"S-1-16-8448",
|
||||
"S-1-9-8-7",
|
||||
};
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(user_sids); i++) {
|
||||
sid = dom_sid_parse_talloc(mem_ctx, user_sids[i]);
|
||||
if (sid == NULL) {
|
||||
abort();
|
||||
}
|
||||
add_sid_to_array(mem_ctx, sid,
|
||||
&token.sids,
|
||||
&token.num_sids);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int LLVMFuzzerTestOneInput(uint8_t *input, size_t len)
|
||||
{
|
||||
TALLOC_CTX *mem_ctx = NULL;
|
||||
struct security_descriptor *sd = NULL;
|
||||
NTSTATUS status;
|
||||
uint32_t access_desired;
|
||||
uint32_t access_granted;
|
||||
const char *sddl;
|
||||
ssize_t i;
|
||||
if (len < 5) {
|
||||
return 0;
|
||||
}
|
||||
access_desired = PULL_LE_U32(input + len - 4, 0);
|
||||
|
||||
/*
|
||||
* check there is a '\0'.
|
||||
*
|
||||
* Note this allows double-dealing for the last 4 bytes: they are used
|
||||
* as the access_desired mask (see just above) but also *could* be
|
||||
* part of the sddl string. But this doesn't matter, for three
|
||||
* reasons:
|
||||
*
|
||||
* 1. the desired access mask doesn't usually matter much.
|
||||
*
|
||||
* 2. the final '\0' is rarely the operative one. Usually the
|
||||
* effective string ends a long time before the end of the input, and
|
||||
* the tail is just junk that comes along for the ride.
|
||||
*
|
||||
* 3. Even if there is a case where the end of the SDDL is part of the
|
||||
* mask, the evolution stategy is very likely to try a different mask,
|
||||
* because it likes to add junk on the end.
|
||||
*
|
||||
* But still, you ask, WHY? So that the seeds from here can be shared
|
||||
* back and forth with the fuzz_sddl_parse seeds, which have the same
|
||||
* form of a null-terminated-string-with-trailing-junk. If we started
|
||||
* the loop at `len - 5` instead of `len - 1`, there might be
|
||||
* interesting seeds that are valid there that would fail here. That's
|
||||
* all.
|
||||
*/
|
||||
for (i = len - 1; i >= 0; i--) {
|
||||
if (input[i] != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
sddl = (const char *)input;
|
||||
mem_ctx = talloc_new(NULL);
|
||||
|
||||
sd = sddl_decode(mem_ctx, sddl, &dom_sid);
|
||||
if (sd == NULL) {
|
||||
goto end;
|
||||
}
|
||||
status = se_access_check(sd, &token, access_desired, &access_granted);
|
||||
end:
|
||||
talloc_free(mem_ctx);
|
||||
return 0;
|
||||
}
|
@ -42,6 +42,11 @@ bld.SAMBA_BINARY('fuzz_nmblib_parse_packet',
|
||||
deps='fuzzing libsmb afl-fuzz-main',
|
||||
fuzzer=True)
|
||||
|
||||
bld.SAMBA_BINARY('fuzz_sddl_access_check',
|
||||
source='fuzz_sddl_access_check.c',
|
||||
deps='fuzzing samba-security afl-fuzz-main',
|
||||
fuzzer=True)
|
||||
|
||||
bld.SAMBA_BINARY('fuzz_regfio',
|
||||
source='fuzz_regfio.c',
|
||||
deps='fuzzing samba3-util smbconf REGFIO afl-fuzz-main',
|
||||
|
Loading…
Reference in New Issue
Block a user