winrar CVE-2023-38831 vulnerability
Hi again,
In the recent week, we saw that a new vulnerability was published by Group-IB from Winrar.
I decided to analyze it in detail and find out why this type of vulnerability which is very very simple, should occur in such essential software like Winrar.
At first look, I thought that this vulnerability was a toy that was created by a child.
However, after going in deep, I found out that there is a logical and dumb problem in the usage of a Windows API. But I don’t know if this is a Winrar programmer mistake or a bug in that Windows API. Additionally, Winrar makes a mistake that is the root cause of this vulnerability.
Let’s dive in to find out what happened.
thanks to b1tg for his/her POC.
How does the vulnerability work?
In Windows OS, you can’t have two files with the same name in a directory. also, you can’t have a directory and a file with the same name. But this is possible in compression software like WinRar/7zip. In a compressed file, no matter whether you have files with the same name, the files are written in a special structure.
So you can have two objects (File/Dir) with the same name in a ZIP/RAR file.
As described, when you have a file and a directory with the same name, in an archive file and want to open the file temporarily, by double-clicking on it(target file) in the opened archive file, the Winrar extracts this file for you, Also extracts all files that have the same name as the target file. All of them has wrote in a temporary directory in the %tmp% path. This behavior of Winrar is unknown to me because I tested this scenario with 7Zip and it didn’t do this. So let’s test it manually.
In practice, you can’t put two objects with the same name in one archive file in the Winrar. In this case, I used 7Zip to make a zip file.
The Scenario:
I have a directory named “new” and a file1.txt and file2.txt in it.
The content of these files is different:
I used 7Zip Cli to create an archive file.
Now we have an archive file that contains two files: file1.txt and file2.txt
Now I want to change the name of the file2.txt to file1.txt.
in this case, I’ll have two files with the same name in one archive file. I used “rn” switch of 7Zip command to rename an object in the archive file.
We made it:
Two file with the same name but different in the size. one of them is 17 bytes, another is 5 bytes.
Now let’s open one of these text files from the archive file and see what will happen.
I open the archive and open the first file1.txt which has 17 bytes in size.
As you see when I opened the first, Winrar showed me a prompt for replacing a file. after that, I clicked on Yes, and it opened to me the second file1.txt.
What happened?
The Winrar first creates a temporary folder in the temp directory and then extracts the first file1.txt. now in the tmp directory, we have the first file1. But after that try to extract also second file1. Because in Windows we can’t have two files with the same name in a directory, Winrar prompts us on what should do with this new file, and if you press Yes, the second file overwrites the first file and so you see the contents of the second file.
When I debugged the Winrar, I saw that Winrar in a function checks all files and directories name in the archive with the targeted file. If one of them has a name the same as the file that wants to be extracted(target file), it returns 1. I don’t know what is the reason for this behavior, but I also test this file with 7Zip. the 7zip just extracts the file that you want to open.
As you see in this loop, the function checks two file’s names, letter by letter to find out whether they are equal or not. There we have two files with the same name. both of them are “file1.txt”.
In this archive file, we have two files. when you want to extract a file from them temporarily, the Winrar checks the target file name with all object names that exist in the archive. for example, if we have five files in the archive and we want to extract one of them, Winrar checks this file’s name with all other four files.
Now if these files’ name was equal, the function checks another thing.
Imagine we want to extract fileA and we have another file in the archive, “fileB” and also a directory named “data” which in it, we have another file named “fileC”.
When you click on fileA to extract it, the Winrar checks that the fileA name is equal to which another file or directory. if any file name matches with the fileA name, it is added to the extraction list. Also if a directory name matches with fileA name, Then Winrar checks files in that directory with fileA name. if any of them match, then is pushed in the extraction list.
The below pseudo-code clarifies the process of checking for you:
# pseudo code of winrar checking file names
i=0
extraction_list[]
extraction_list[i]= target_file
i++
//check files
for file in files
{
if(strcmp(target_file.name, file.name)==0) // same name
{
extraction_list[i]= file // add file to extraction list
i++
}
}
for dir in directories
{
if(strcmp(target_file.name ,dir.name)==0)
{
for file in dir.files
{
if(strcmp(target_file.name, file.name)==0) //same name
{
extraction_list[i]= file // add file to extraction list
i++
}
}
}
}
As you can see after the function that checks names, now This function checks if File B has “\” or “/” in its name. This function returns 1, if the file name is equal, or the File B is a directory.
So if we have a file or directory whose name equals the file that wants to be extracted, the function returns 1, and then Winrar also extracts those files.
Tip: I used a yellow highlight to show space in file names.
Now let’s analyze a vulnerable sample.
In the malicious sample, we have a file which is the main file, with a “ ” (space) at the end of its name.
Also, we have a directory with the same name as the main file and a “ ” at the end of its name.
In the directory, we have another file with the same name as the main file and a “ ” at the end of its name and then a “.cmd”. This file contains an attack payload.
file.pdf
|
|
–> file.pdf .cmd
file.pdf
I created the malicious archive with 7Zip Cli as before.
Now I open the archive file and open the “A.txt ” file. As seen before, Winrar compares all files in the archive to find files/directories that have the same name as “A.txt “.
So based on our pseudo-code, when Winrar compares the name of the “A.txt ” file with the “A.txt ” directory, they are equal, and also “A.txt ” is a directory. So Winrar continues to check files under the directory and it finds that the file “A.txt .cmd” is the same as the target file, so put it in the extraction list. Now our extraction list is:
File name | Extraction path |
A.txt <–target file clicked on it | C:\Users\sik\AppData\Loca\Temp\Rar$DIa8432.13968\ |
A.txt .cmd <– the file in directory | C:\Users\sik\AppData\Loca\Temp\Rar$DIa8432.13968\ |
Tip: The path of temporary directory is different in my images and samples. this is because I took them in different runs.
Now the Winrar wants to extract these files. The first file is our target file (The file that clicked on to extract and open).
But I should tell you that Windows removes any spaces at the beginning and end of the file name when it wants to create the file.
From Microsoft site:
If a file is saved as ‘ Foo.txt’, where the leading character(s) is an ASCII Space (0x20), it will be saved to the file system as ‘Foo.txt’.
If a file is saved as ‘Foo.txt ‘, where the trailing character(s) is an ASCII Space (0x20), it will be saved to the file system as ‘Foo.txt’.
The Winrar handles this problem. It has a preprocessing phase that checks the file name and removes some special characters that Windows doesn’t accept.
As you can see in the above function, Winrar tries to scan the string of the file path of the “A.txt ” to find if, at the end of the file name, it is a space char(0x20) and replaces it with a NULL(0x00). So after this check, we have a target file without space at the end, “A.txt”.
Ok after this phase Winrar writes “A.txt” and “A.txt .cmd” files in the temp directory in a temporary folder. In the below images, you can see the process of writing files using the “CreateFile” API.
After A.txt, Winrar writes other files of the extraction list:
Now we have a temporary directory in temp like this:
The Final Phase:
Now the process of extraction is finished and Winrar wants to open the target file for us. the target file is the file that we clicked on, so it is “A.txt” and is a text file.
But the Winrar doesn’t know how to open our file, for example, if our target file was a pdf file, the Winrar doesn’t know how to open it and with which program, or in our case, Winrar doesn’t know what application is used to open text files on my Windows. In these cases, applications use Windows APIs like ShellExecute.
From Microsoft site:
ShellExecuteExW Performs an operation on a specified file.
ShellExecute is used to open, edit, explore, and some other operations on a file and Winrar uses this function to open target files for us.
Let’s see how the ShellExecute works.
This function just gets an argument named SHELLEXECUTEINFO, which is a structure.
As you see this structure has many fields. but two of them are important for us.
lpVerb and lpFile.
What is lpVerb? let’s see on the Microsoft site
From Microsoft site:
Type: LPCTSTR
A string, referred to as a verb, that specifies the action to be performed. The set of available verbs depends on the particular file or folder. Generally, the actions available from an object’s shortcut menu are available verbs. This parameter can be NULL, in which case the default verb is used if available. If not, the “open” verb is used. If neither verb is available, the system uses the first verb listed in the registry. The following verbs are commonly used:
edit: Launches an editor and opens the document for editing. If lpFile is not a document file, the function will fail.
explore: Explores the folder specified by lpFile.
find: Initiates a search starting from the specified directory.
open: Opens the file specified by the lpFile parameter. The file can be an executable file, a document file, or a folder.
print: Prints the document file specified by lpFile. If lpFile is not a document file, the function will fail.
properties: Displays the file or folder’s properties.
runas: Launches an application as Administrator. User Account Control (UAC) will prompt the user for consent to run the application elevated or enter the credentials of an administrator account used to run the application.
The highlighted part is very important. It says that if you set the LpVerb to NULL, ShellExecuteExA uses the default verb if available, if not, it performs the “open” verb. And the “open” verb, opens or executes the file.
the following parameter is lpFile.
From Microsoft site:
Type: LPCTSTR
The address of a null-terminated string that specifies the name of the file or object on which ShellExecuteEx will perform the action specified by the lpVerb parameter.
The lpFile is the path of the file that is used in ShellExecuteExA to perform the verb.
Now let’s see these parameters in Winrar.
The structure address is in “eax” and we can see that the verb value is NULL, so the ShellExecuteExA performs a default verb or performs an open verb.
But the surprise is in the lpFile parameter. This is the address of the file path. If we examine it, see the file path string.
As you can see, the file path is for the “A.txt” file which is our target file and should open.
But wait a second. Wooooo
If you remember, we talked about Winrar removing spaces that are at the end of the file name and then writing them on disk. But here if pay attention, you see the space char(0x20) at the end of the file path. 😀
The vulnerability is here. Winrar removed space from the file name at write time but forgot to commit this change to the extraction list. So the target file name didn’t change and the space is still in the file name.
This file path goes to ShellExecuteExA.
But let’s review the problem:
We have two files in the temp directory, one of them is “A.txt” which is our target file for opening.
The next one is “A.txt .cmd” which is the malicious payload with a .cmd extension.
The ShellExecuteExA API wants to open a file with this path :
“C:\Users\sik\AppData\Loca\Temp\Rar$DIa8432.13968\A.txt ”
but in the tmp directory, we have these files :
“C:\Users\sik\AppData\Loca\Temp\Rar$DIa8432.13968\A.txt” –> without space
“C:\Users\sik\AppData\Loca\Temp\Rar$DIa8432.13968\A.txt .cmd“
Now the question is, we haven’t a file named “A.txt ” but how does the ShellExecuteExA opens the “A.txt .cmd” when we pass it a full path of the file?
To answer this question first we should try some things in Windows.
In a folder in Windows I created a simple batch file and named it “calc .bat” that launches “notepad.exe”. I just put a space between the extension and the name. Then opened the “run” window and put the full path of my batch file with its space but without the “.bat” extension and ran it. The batch file was executed successfully.
So the extension of the file doesn’t matter for ShellExecuteExA. But what happens if we have two files with the same name but different extensions in a folder?
Let’s try it:
I copied the calc.exe file in my test folder and changed its name to “calc .exe“. Open the “Run” windows again and open the “calc ” file. This time, it ran the calculator.
As you can see we just pass the name of our file without extension, but the ShellExecuteExA opens one of them. It is accidental? No, it is based on priorities that are defined in the registry for file types.
Now we can find out the answer to our question of how the ShellExecuteExA opens the “A.txt .cmd” file. the “.cmd” doesn’t matter for ShellExecuteExA and it just runs a file with the “A.txt ” name in that path.
In this way, the vulnerability works.
Conclusion
Here the process of analyzing vulnerability is finished. Now I wanna talk about ShellExecuteExA.
The problem is that Winrar extracts another files with the same name and in the patched version, resolved this problem. But this vulnerability has another side.
I think another side of this vulnerability is ShellExecuteExA. Why is it not considered the extension of the file path? in this way, many other programs can be vulnerable if they are using ShellExecuteExA.
For example, if ShellExecuteExA consider full path of the file, the problem doesn’t occurred and this bug doesn’t get convert to a vulnerability.
But I don’t know, maybe this is a feature of Windows or maybe a Bug 😀
Winrar CVE-2023-38831 Vulnerability
Hi,
Thank you for the detailed analysis.
I am also trying to learn the reversing. Can you please help and let me know how you attached rar file in ollydbg? I tried but since it is not a executable it did not worked.
When i tried attaching the rar.exe file and ran poc. I could not understand where I should add bp hence whole poc ran and nothing happened.
Please help me understand the process.
Thanks for your attention. 🙂
Once you want find out how to debug a program, you can run it in usual way then open the task manager and see the command line of that process. In this way you can enter the command line in your debugger. Advice: don’t use ollydbg due to it is a legacy debugger and may hasn’t compatibility with new OS.You can use x64dbg instead
But about the location of bp. You should try many times as you can until find the hot spot. But this is based on your experiences. So you should try and try until find it.
Hi Ali. Thanks for your good description. It was so understandable and it was so useful for me. I just have suggestion for your blog UI, Is it possible to change font color from green to another color. It is hard to read texts in green. Thank you :))
Thanks for your attention 🙂
Hi Alee. After re-analyzing this bug, I found that this statement may not be accurate
“Also, if a directory name matches with fileA name, Then Winrar checks files in that directory with fileA name. if any of them match, then is pushed in the extraction list. ”
If a directory name matches with fileA name, the corresponding dirEntries are pushed into the extraction list, which does not depend on files in that directory.
If there is a zip with 7 entries like this
– Bir
– Dir
– Dir/
– Dir/a1.txt
– Dir/a2.txt
– Eir
– Eir/e1.txt
If you click on the file “Dir”, the matched entries are:
– Dir
– Dir/
– Dir/a1.txt
– Dir/a2.txt
And 3 corresponding files will released (a1.txt, a2.txt, Dir)
Hi b1tg
Yes, it is correct. after a while publishing my blog post, I tested it again and found out that all files in the directory were extracted, But I forgot to edit them in blog.
thank you for your attention and your POC 🙂
Hi Alee, I appreciate a lot your analysis on this amazing Winrar problem. It helps me to understand this problem a lot better thanks to your explanation.
I saw that the problem is handled from the version 6.23 onward. Do you have any idea how did they patch this problem?
Hi kevin,
Thank you. I didn’t check the fixed version.
I was suggested this blog by my cousin. I’m not sure whether this
post is written by him as nobody else know such detailed about
my trouble. You are incredible! Thanks!