Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use after free in ntfs_uppercase_mbs() of libntfs-3g #84

Closed
jeffbencteux opened this issue Jun 13, 2023 · 6 comments
Closed

Use after free in ntfs_uppercase_mbs() of libntfs-3g #84

jeffbencteux opened this issue Jun 13, 2023 · 6 comments
Assignees

Comments

@jeffbencteux
Copy link

I believe there is a use after free in ntfs_uppercase_mbs() when following a specific code path:

*t = 0;

It can be triggered if the call to utf8_to_unicode() in the function fails with n = -1:

                        n = utf8_to_unicode(&wc, s);

https://github.com/tuxera/ntfs-3g/blob/1565b01e215c74e5c5f83f3ecde1ed682637dc5a/libntfs-3g/unistr.c#LL1166C1-L1166C32

Execution then do not get into the branch checking for n value being positive, breaks out of the loop (for the same reason) and then the following branch is entered:

                if (n < 0) {
                        free(upp);
                        upp = (char*)NULL;
                        errno = EILSEQ;
                }

Next, an access to t is made:

                *t = 0;

Because t = upp and upp is being freed, access *t = 0; is using memory that has been freed.

I suggest removing line 1193 completely as a fix as I cannot find a legit use of it in the code.

@unsound
Copy link
Member

unsound commented Jun 13, 2023

Seems like you're right, but wouldn't removing *t = 0; mean the string isn't guaranteed to be NULL-terminated?
In that case I think a better solution is to enclose it in an else block:

-                *t = 0;
+                else {
+                        *t = 0;
+                }

@unsound unsound self-assigned this Jun 13, 2023
@jeffbencteux
Copy link
Author

Oh yes, forgot that. Your version fix it much better.

unsound added a commit that referenced this issue Jun 14, 2023
If 'utf8_to_unicode' throws an error due to an invalid UTF-8 sequence,
then 'n' will be less than 0 and the loop will terminate without storing
anything in '*t'. After the loop the uppercase string's allocation is
freed, however after it is freed it is unconditionally accessed through
'*t', which points into the freed allocation, for the purpose of NULL-
terminating the string. This leads to a use-after-free.
Fixed by only NULL-terminating the string when no error has been thrown.

Thanks for Jeffrey Bencteux for reporting this issue:
#84
@unsound
Copy link
Member

unsound commented Jun 14, 2023

Closing this as the discussed change is in HEAD now: 75dcdc2

@unsound unsound closed this as completed Jun 14, 2023
secuflag pushed a commit to odroid-dev/android_external_ntfs-3g that referenced this issue Jul 1, 2023
If 'utf8_to_unicode' throws an error due to an invalid UTF-8 sequence,
then 'n' will be less than 0 and the loop will terminate without storing
anything in '*t'. After the loop the uppercase string's allocation is
freed, however after it is freed it is unconditionally accessed through
'*t', which points into the freed allocation, for the purpose of NULL-
terminating the string. This leads to a use-after-free.
Fixed by only NULL-terminating the string when no error has been thrown.

Thanks for Jeffrey Bencteux for reporting this issue:
tuxera/ntfs-3g#84
@Pastea
Copy link

Pastea commented Jun 5, 2024

@unsound I think that could be worth if this bug gets assigned a CVE so the community is aware of it, what do you think about?

@unsound
Copy link
Member

unsound commented Jun 5, 2024

@Pastea If there's a way to exploit this as a security issue then that would make sense, but all this use-after-free does is write a 0 byte to an area that was just freed a few instructions earlier and likely hasn't been reallocated during the course of calling 'free' (depends on the implementation details of 'free' in the libc of course, but it sounds unlikely).
I'm willing to be proven wrong, but I don't see an exploitable security issue.

@Pastea
Copy link

Pastea commented Jun 12, 2024

Yeah, the exploitation time window is very narrow due to the fact that the pointer is used only in some instruction below so forcing an allocation in that space in the meantime is quite challenging.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants