“Game of Rars” – Exploring a New Remote Code Execution Vulnerability in WinRAR with Proof-of-Concept (CVE-2023-40477) –

Wild Pointer > Security Research  > “Game of Rars” – Exploring a New Remote Code Execution Vulnerability in WinRAR with Proof-of-Concept (CVE-2023-40477) –

“Game of Rars” – Exploring a New Remote Code Execution Vulnerability in WinRAR with Proof-of-Concept (CVE-2023-40477) –


Executive Summary

  • WinRAR, 500+ million users, is exposed to new vulnerabilities (CVE-2023-40477, CVE-2023-38831).
  • Today, we present for the first-time: A PoC for CVE-2023-40477 (At time of writing)
  • Although considered RCE & assumed to be exploitable, its’ impact in reality doesn’t look promising because of numerous reasons.
  • We present here thorough technical research: its impact, exploitable scenarios and mitigations.
  • The vulnerability was fixed in recent Winrar v6.23, we give another mitigations possibility here as well



CVE-2023-40477: Technical Overview & Proof-of-Concept


It is Mid-August, Winrar 6.23 is out with some vague alerts about critical vulnerabilities.

All we know is – The vulnerability (CVE-2023-40477) is fixed and this information:

Armed with BinDiff, IDA & Notepad, Let’s dive in.


Diffing Binaries


We know 6.23 is fixed, let’s try finding minimal version before and after the fixed so we can observe just it. I’ve downloaded both portable winrar-v6.23 + winrar-v6.22 and observed it:

Winrar directory structure & interesting files


One can immediately observe that winrar.exe is probably just a GUI and if a vulnerability in extraction – it will probably be also in “unrar.exe”. Diffing 6.23 & 6.22 gave me following diffs (ignore comments ;)):

First Bindiff output

Going through flow graphs gave me couple of interesting additions in 6.23 (in big function graph – seemingly looks like the main extraction):

Highlevel bindiff additions in extract

Looking carefully seems like these are additional checks!

Bindiff’s x86 interesting additional blocks



This looks promising! we see here additional checks that some var < 255 !! Interesting. looks like overflow checks rights here.
So, time to go for a trigger (i.e change bytes to maximal values).

I have looked over RAR format, We know from the description this is related to RAR4 (vol3?) recovery volumes,
so I generated RAR4 with these features, it gave me a list of files like the following:

  • RAR_FILE.rar
  • RAR_FILE.r00
  • RAR_FILE00.rev
  • RAR_FILE.r01
  • RAR_FILE01.rev


I have tried to bruteforce the contents of any “byte-like” value in “.rev” & “rXX” volumes without success. it hasn’t triggered or changed anything.
Then, I tried to Google some “unrar” source-code – maybe it exists as a part of some other project?!
Success! I’ve found this old repository: https://github.com/aawc/unrar

Looking now in the source-code, We see multiple “255” const-checks, espcially in “recvol3.cpp”, They appear also in the original 6.22 source-code, so maybe they added extra ones because of … an overflow?
Let’s check, Diving deeper, I’ve found the security checks actually related to 0xff / 255.

The Vulnerability

 

CVE-2023-40477 inside recvol3.cpp


Here, P[i]’s are extracted from the “.rev” files themselves. they are inside the end of files.
These P[i]’s are used to determine which recovery volume they represent and what FileNumber they suit to.
FileNumber is retrieved from them as well in P[2].
Right after, File* is allocated and placed in an index we control in array of size 256! (line 241).
That explains the 255 checks.
Becuase the index is actually equals to:P[2]+P[0]-1. We can almost arbitrarily control it with “rev” volumes contents.
So, after all, we get to overwrite that buffer with pointers (pointing to File structures), they are overwriting the next properties in the current object.

PoC Writeup

To trigger that vulnerability, we found “Restore()” needed to be called in recvol3.cpp.
We found out we also need the reconstruction step to happen, so something will be done with the overwrite of pointers.

For that to happen, one needs to have some missing volumes of rar (.r00 missing), and .rev volumes available.
Also, we need to make sure crc32 checksums are correct, this concluded to just couple of lines to trigger.
For our ease, We have used the original rar4 recovery volumes we generated with the GUI, but this can surely be much smaller and a more efficient trigger with probably up to 2-3 files at most.

# 1. re-generate malformed recovery vols.
data = open('%s01.rev' % ARCHIVE_NAME, 'rb').read() # just use the first and malform it up.
names = ['%s%s.rev' % (ARCHIVE_NAME, str(i).zfill(2)) for i in range(256)]
# "destroy" the P[i]'s
datas = [data[:-7] + bytes([0xf0, 0x00, i]) + calc_crc(data[:-7] + bytes([0xf0, 0x00, i])) for i in range(256)]

# 2. overwrite malformed recovery vols.
for i in range(256):
	fname = names[i]
	data = datas[i]
	open(fname, 'wb').write(data)

Our PoC @ https://github.com/wildptr-io/Winrar-CVE-2023-40477-POC/



Shortly after finding it, We’ve also seen https://www.rarlab.com/vuln_rev3_names.html in rar-labs site, confirming in high probability our findings.


Using that, we have successfully crashed winrar / unrar in couple of scenarios:

  1. Memset overwrite with zeroes to invalid memory (probably after the buffer):

    Crash while using winrar’s unrar.exe – on memset of Buf



    from source-code – the memset of Buf


  2. Heap overflow possible scenario in winrar.exe when using “extract to”

    Heap Overflow in winrar.exe – possible scenario


Exploitable?

To determine exploitability, let’s look at structures we override after the 256-array.
Let’s determine how attackers can use this primitive to gain RCE & what mitigations exists.

// RecVolume3 struct - that gets overflowed
class RecVolumes3
{
  private:
    File *SrcFile[256]; // overflow in here with File* pointers.
    Array Buf;

#ifdef RAR_SMP
    ThreadPool *RSThreadPool;
#endif
  public:
    RecVolumes3(CommandData *Cmd,bool TestOnly);
    ~RecVolumes3();
    void Make(CommandData *Cmd,wchar *ArcName);
    bool Restore(CommandData *Cmd,const wchar *Name,bool Silent);
    void Test(CommandData *Cmd,const wchar *Name);
};
...
...
// Array template class:
template  class Array
{
  private:
    T *Buffer;
    size_t BufSize;
    size_t AllocSize;
    size_t MaxSize;
  public:
    Array();
    Array(size_t Size);
    Array(const Array &Src); // Copy constructor.
    ~Array();

So, after all, We overflow “Buffer” object with “File*” pointers.
That’s nice, but not enough, one would probably need to bypass many defenses enabled here.
Fortunately, Many protections are inside: ASLR, CFG, Stack-Cookie & DEP.

That is also without mentioning the binary differences between winrar versions. All of that makes exploitation possible but not so probable for the average threat-actor.


Impact


Despite its high-severity CVE rating, the complexity required for successful exploitation suggests a low likelihood of widespread abuse, unlike, for example, the widely exploited Log4j RCE vulnerability.

Interestingly, Chromium appears to utilize the unrar library as well:https://chromium.googlesource.com/chromium/src/+/6ff23b0604e2edbe7ef282564ea340f5c72ab91a%5E%21/.

It’s plausible that the unrar library is incorporated into Chrome OS as a third-party dependency, although code references suggesting its usage are absent.

 

Mitigations

In terms of mitigation strategies, there are several feasible options to consider: