1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-22 22:04:08 +03:00
Douglas Bagnall f89767bea7 CVE-2020-27840 ldb_dn: avoid head corruption in ldb_dn_explode
A DN string with lots of trailing space can cause ldb_dn_explode() to
put a zero byte in the wrong place in the heap.

When a DN string has a value represented with trailing spaces,
like this

     "CN=foo   ,DC=bar"

the whitespace is supposed to be ignored. We keep track of this in the
`t` pointer, which is NULL when we are not walking through trailing
spaces, and points to the first space when we are. We are walking with
the `p` pointer, writing the value to `d`, and keeping the length in
`l`.

     "CN=foo   ,DC= "       ==>       "foo   "
            ^  ^                             ^
            t  p                             d
                                       --l---

The value is finished when we encounter a comma or the end of the
string. If `t` is not NULL at that point, we assume there are trailing
spaces and wind `d and `l` back by the correct amount. Then we switch
to expecting an attribute name (e.g. "CN"), until we get to an "=",
which puts us back into looking for a value.

Unfortunately, we forget to immediately tell `t` that we'd finished
the last value, we can end up like this:

     "CN=foo   ,DC= "       ==>        ""
            ^      ^                    ^
            t      p                    d
                                        l=0

where `p` is pointing to a new value that contains only spaces, while
`t` is still referring to the old value. `p` notices the value ends,
and we subtract `p - t` from `d`:

     "CN=foo   ,DC= "       ==>  ?     ""
            ^       ^            ^
            t       p            d
                                      l ~= SIZE_MAX - 8

At that point `d` wants to terminate its string with a '\0', but
instead it terminates someone else's byte. This does not crash if the
number of trailing spaces is small, as `d` will point into a previous
value (a copy of "foo" in this example). Corrupting that value will
ultimately not matter, as we will soon try to allocate a buffer `l`
long, which will be greater than the available memory and the whole
operation will fail properly.

However, with more spaces, `d` will point into memory before the
beginning of the allocated buffer, with the exact offset depending on
the length of the earlier attributes and the number of spaces.

What about a longer DN with more attributes? For example,
"CN=foo     ,DC= ,DC=example,DC=com" -- since `d` has moved out of
bounds, won't we continue to use it and write more DN values into
mystery memory? Fortunately not, because the aforementioned allocation
of `l` bytes must happen first, and `l` is now huge. The allocation
happens in a talloc_memdup(), which is by default restricted to
allocating 256MB.

So this allows a person who controls a string parsed by ldb_dn_explode
to corrupt heap memory by placing a single zero byte at a chosen
offset before the allocated buffer.

An LDAP bind request can send a string DN as a username. This DN is
necessarily parsed before the password is checked, so an attacker does
not need proper credentials. The attacker can easily cause a denial of
service and we cannot rule out more subtle attacks.

The immediate solution is to reset `t` to NULL when a comma is
encountered, indicating that we are no longer looking at trailing
whitespace.

Found with the help of Honggfuzz.

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

Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
2021-03-19 08:52:23 +01:00
..
2020-04-23 21:53:38 +00:00
2021-01-14 13:29:35 +00:00

compression - Various compression algorithms (MSZIP, lzxpress)
popt - Command-line option parsing library
replace - Provides replacements for standard (POSIX, C99) functions 
          not provided by the host platform.
subunit - Utilities and bindings for working with the Subunit test result 
          reporting protocol.
talloc - Hierarchical pool based memory allocator 
tdb - Simple but fast key/value database library, supporting multiple writers
torture - Simple unit testing helper library