Skip to content

Fix RAR5 NTFS alt-stream check bypassing Zone.Identifier / overwriting default stream#235

Open
matiasdante wants to merge 1 commit into
ip7z:mainfrom
matiasdante:fix/rar5-ntfs-ads-motw-bypass
Open

Fix RAR5 NTFS alt-stream check bypassing Zone.Identifier / overwriting default stream#235
matiasdante wants to merge 1 commit into
ip7z:mainfrom
matiasdante:fix/rar5-ntfs-ads-motw-bypass

Conversation

@matiasdante

Copy link
Copy Markdown

Summary

CVE-2026-58052.

Is_ZoneId_StreamName() in CPP/7zip/UI/Common/ArchiveExtractCallback.cpp compared an archive-supplied NTFS alt-stream name against the literal string "Zone.Identifier" only.

A RAR5 archive can define an NTFS stream (STM) record whose name is ":Zone.Identifier:$DATA" (or carries an extra leading :). NTFS canonicalizes that to the same real Zone.Identifier stream, but the exact-string guard doesn't recognize it, so the archive's own alt-stream content is written through — overwriting the extracted file's Zone.Identifier stream and clearing the Mark-of-the-Web that was otherwise correctly propagated from the (internet-zone) archive. This lets a crafted RAR5 defeat SmartScreen/MotW warnings on extracted files.

A record named "::$DATA" similarly resolves to the file's unnamed/default data stream; without a check, an "alt stream" item could overwrite the extracted file's main content.

Fix

  • Added Normalize_AltStreamName_For_Ntfs(), which strips a trailing ":$DATA" suffix (case-insensitive) and any leading : before the name is used in security-relevant comparisons — mirroring NTFS's own canonicalization.
  • Is_ZoneId_StreamName() now normalizes before comparing, closing the bypass.
  • Added Is_DefaultDataStream_Name(); if an alt-stream item normalizes to an empty name (i.e. refers to the default data stream), extraction of that stream is unconditionally skipped.

Both checks run in CArchiveExtractCallback::GetStream(), before GetExtractStream()/CreateFileW — the same point where the original guard lived — so no other extraction code paths needed to change.

Testing

Verified against real Windows binaries (7zz.exe, built from this branch vs. the unpatched tree via MinGW cross-compilation), using hand-crafted RAR5 archives with STM records patched at the byte level to carry the exact vulnerable names:

  • ":Zone.Identifier:$DATA" — unpatched binary overwrote the extracted file's Zone.Identifier stream (MotW cleared to ZoneId=0); patched binary preserves the propagated ZoneId=3 and does not extract the malicious stream.
  • "::$DATA" — unpatched binary overwrote the extracted file's main content with the alt-stream's payload; patched binary leaves the file's real content untouched and does not extract the stream.

…riting default stream

Is_ZoneId_StreamName() compared an archive-supplied alt-stream name against
the literal "Zone.Identifier" only. A RAR5 STM record can name the stream
":Zone.Identifier:$DATA" (or with an extra leading colon), which NTFS
canonicalizes to the same real stream but doesn't match the exact-string
check, letting the archive overwrite the extracted file's Zone.Identifier
stream and clear the propagated Mark-of-the-Web. A record named "::$DATA"
similarly refers to the file's unnamed/default data stream and could
overwrite the extracted file's main content.

Normalize the alt-stream name (strip a trailing ":$DATA" suffix and any
leading ':') before comparing against "Zone.Identifier", and reject any
alt-stream item that normalizes to the default data stream outright.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 16, 2026 16:33

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Addresses CVE-2026-58052 by hardening Windows NTFS alternate data stream (ADS) name handling during extraction so crafted RAR5 STM records can’t bypass Zone.Identifier protections or target the unnamed/default $DATA stream.

Changes:

  • Added Normalize_AltStreamName_For_Ntfs() to canonicalize ADS names for security-sensitive comparisons (strip leading : and a trailing :$DATA).
  • Updated Is_ZoneId_StreamName() to compare against the normalized name.
  • Added Is_DefaultDataStream_Name() and used it in CArchiveExtractCallback::GetStream() to skip extraction of ADS entries that resolve to the unnamed/default stream.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +170 to +171
while (!s.IsEmpty() && s[0] == ':')
s.DeleteFrontal(1);
Comment on lines +1713 to +1716
{
if (Is_DefaultDataStream_Name(_item.AltStreamName))
return S_OK;
if (ZoneBuf.Size() != 0
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.

2 participants