Skip to content

fix path traversal bug in unshield.c#172

Open
eqawasm wants to merge 1 commit intotwogood:mainfrom
eqawasm:eqawasm-patch-1
Open

fix path traversal bug in unshield.c#172
eqawasm wants to merge 1 commit intotwogood:mainfrom
eqawasm:eqawasm-patch-1

Conversation

@eqawasm
Copy link

@eqawasm eqawasm commented May 17, 2023

fix path traversal bug

fix path traversal bug
@eqawasm eqawasm changed the title Update unshield.c fix path traversal bug in unshield.c May 17, 2023
@twogood
Copy link
Owner

twogood commented May 18, 2023

Resolves #171

@twogood
Copy link
Owner

twogood commented May 27, 2023

@kratz00 What do you think?

/* use GNU extension to return non-existing files to real_output_directory */
realpath(output_directory, real_output_directory);
realpath(filename, real_filename);
strncat(real_output_directory, "/", PATH_MAX);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this could overflow real_output_directory as strncat will add a terminating null-character.

If I see it correctly this PR is intended to fix CVE-2015-1386, therefor it might make sense to clean-up/review the existing code which supposedly should already address it and most importantly double check the test in https://github.com/twogood/unshield/tree/main/test/v5/CVE-2015-1386

This is just shooting from the hip, I will have a deeper look as soon as possible.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So it's the same CVE? I didn't notice. Strange that the old test case passes.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Saw this and throwing in my two cents.

Looks like it should be strncat(..., PATH_MAX - 1) to avoid the null character causing an off-by-one.

Regarding CVE-2015-1386, #171 looks like a corner case that the original fix missed. In the PoC @eqawasm provided, they appear to be exploiting a common prefix between the real paths: /tm. Suffixing / to real_output_directory prevents the directory name from being misinterpreted as a file name.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@carter-yagemann summed it up quite nicely 👍

I think the proposed patch for this corner case is not sufficient, even when fixing the off-by-one issue, here is why.
The reproductions steps in #171 can be simplified and do not even require root permissions:

git clone git@github.com:twogood/unshield.git
cd unshield
cmake -B build
cmake --build build
./build/src/unshield -d /tmp x test/v5/CVE-2015-1386/data1.cab
Cabinet: test/v5/CVE-2015-1386/data1.cab
  extracting: /tmp/Bovine_Files/../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../tmp/moo
 --------  -------
          1 files

real_filename will be always /tmp/moo, in case of this manipulated cabinet file.
For the strncmp call (see https://github.com/twogood/unshield/blob/main/src/unshield.c#L496), we only need to make sure to match the first four bytes at most by influencing the real_output_directory, this can be easily done by using the -d command line option.

In the /tn case adding the slash would work to solve the issue but not for the /tmp case.

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

Successfully merging this pull request may close these issues.

4 participants