Package: release.debian.org
Severity: normal
Tags: bookworm security
X-Debbugs-Cc: 7...@packages.debian.org, t...@security.debian.org, 
yokota.h...@gmail.com
Control: affects -1 + src:7zip
User: release.debian....@packages.debian.org
Usertags: pu


[ Reason ]
Fix CVE-2023-52168 (buffer overflow) and CVE-2023-52169 (buffer over-read)

[ Impact ]
Some vulnerabilities are unfixed.

[ Tests ]
Very trivial NTFS disk image file test was passed.
* list files
* extract files

[ Risks ]
Upstream dose not provide fix patch.
So I extract fix patch from CVE reporter's blog entry.
> https://dfir.ru/2024/06/19/vulnerabilities-in-7-zip-and-ntfs3/

I think the fix patch will works, but not confirmed by upstream
because upstream dose not provides fix patch files.

[ Checklist ]
  [x] *all* changes are documented in the d/changelog
  [x] I reviewed all changes and I approve them
  [x] attach debdiff against the package in (old)stable
  [x] the issue is verified as fixed in unstable

[ Changes ]
Add fix-ups to NTFS extractor.

[ Other info ]
CVE Reporter's blog entry:
> https://dfir.ru/2024/06/19/vulnerabilities-in-7-zip-and-ntfs3/

Debdiff can be examine from online:
> https://salsa.debian.org/debian/7zip/-/tree/bookworm-update
>
https://salsa.debian.org/debian/7zip/-/commits/33950db8e8c9130ac6718fde10515c74f9c6cecc

Roger Shimizu <r...@debian.org> provides bookworm-backports package
7zip:24.08+dfsg-1~bpo12+1.
7zip 24.08 already fixed the vulnerabilities by upstream since 24.05.

--
YOKOTA Hiroshi
diff -Nru 7zip-22.01+dfsg/debian/changelog 7zip-22.01+dfsg/debian/changelog
--- 7zip-22.01+dfsg/debian/changelog    2022-12-18 21:09:42.000000000 +0900
+++ 7zip-22.01+dfsg/debian/changelog    2024-10-06 11:40:03.000000000 +0900
@@ -1,3 +1,9 @@
+7zip (22.01+dfsg-8+deb12u1) bookworm; urgency=medium
+
+  * Fix CVE-2023-52168 and CVE-2023-52169
+
+ -- YOKOTA Hiroshi <yokota.h...@gmail.com>  Sun, 06 Oct 2024 11:40:03 +0900
+
 7zip (22.01+dfsg-8) unstable; urgency=medium
 
   * Upgrade Debian standards
diff -Nru 
7zip-22.01+dfsg/debian/patches/0009-Fix-CVE-2023-52168-and-CVE-2023-52169.patch 
7zip-22.01+dfsg/debian/patches/0009-Fix-CVE-2023-52168-and-CVE-2023-52169.patch
--- 
7zip-22.01+dfsg/debian/patches/0009-Fix-CVE-2023-52168-and-CVE-2023-52169.patch 
    1970-01-01 09:00:00.000000000 +0900
+++ 
7zip-22.01+dfsg/debian/patches/0009-Fix-CVE-2023-52168-and-CVE-2023-52169.patch 
    2024-10-06 11:40:03.000000000 +0900
@@ -0,0 +1,146 @@
+From: YOKOTA Hiroshi <yokota.h...@gmail.com>
+Date: Wed, 2 Oct 2024 12:09:49 +0900
+Subject: Fix CVE-2023-52168 and CVE-2023-52169
+
+Bug-Debian: https://security-tracker.debian.org/tracker/CVE-2023-52168
+Bug-Debian: https://security-tracker.debian.org/tracker/CVE-2023-52169
+Forwarded: not-needed
+
+This patch was extracted from reporter's blog and
+upstream/23.01..upstream/24.05 diff.
+> https://dfir.ru/2024/06/19/vulnerabilities-in-7-zip-and-ntfs3/
+---
+ CPP/7zip/Archive/NtfsHandler.cpp | 89 +++++++++++++++++++++++++---------------
+ 1 file changed, 57 insertions(+), 32 deletions(-)
+
+diff --git a/CPP/7zip/Archive/NtfsHandler.cpp 
b/CPP/7zip/Archive/NtfsHandler.cpp
+index 0b9ee29..39a1299 100755
+--- a/CPP/7zip/Archive/NtfsHandler.cpp
++++ b/CPP/7zip/Archive/NtfsHandler.cpp
+@@ -71,6 +71,7 @@ struct CHeader
+ {
+   unsigned SectorSizeLog;
+   unsigned ClusterSizeLog;
++  unsigned MftRecordSizeLog;
+   // Byte MediaType;
+   UInt32 NumHiddenSectors;
+   UInt64 NumSectors;
+@@ -156,14 +157,47 @@ bool CHeader::Parse(const Byte *p)
+ 
+   NumClusters = NumSectors >> sectorsPerClusterLog;
+ 
+-  G64(p + 0x30, MftCluster);
++  G64(p + 0x30, MftCluster);   // $MFT.
+   // G64(p + 0x38, Mft2Cluster);
+-  G64(p + 0x48, SerialNumber);
+-  UInt32 numClustersInMftRec;
+-  UInt32 numClustersInIndexBlock;
+-  G32(p + 0x40, numClustersInMftRec); // -10 means 2 ^10 = 1024 bytes.
+-  G32(p + 0x44, numClustersInIndexBlock);
+-  return (numClustersInMftRec < 256 && numClustersInIndexBlock < 256);
++  G64(p + 0x48, SerialNumber); // $MFTMirr
++
++  /*
++    numClusters_per_MftRecord:
++    numClusters_per_IndexBlock:
++    only low byte from 4 bytes is used. Another 3 high bytes are zeros.
++      If the number is positive (number < 0x80),
++          then it represents the number of clusters.
++      If the number is negative (number >= 0x80),
++          then the size of the file record is 2 raised to the absolute value 
of this number.
++          example: (0xF6 == -10) means 2^10 = 1024 bytes.
++  */
++  {
++    UInt32 numClusters_per_MftRecord;
++    G32(p + 0x40, numClusters_per_MftRecord);
++    if (numClusters_per_MftRecord >= 0x100 || numClusters_per_MftRecord == 0)
++      return false;
++    if (numClusters_per_MftRecord < 0x80)
++    {
++      const int t = GetLog(numClusters_per_MftRecord);
++      if (t < 0)
++        return false;
++      MftRecordSizeLog = (unsigned)t + ClusterSizeLog;
++    }
++    else
++      MftRecordSizeLog = 0x100 - numClusters_per_MftRecord;
++    // what exact MFT record sizes are possible and supported by Windows?
++    // do we need to change this limit here?
++    const unsigned k_MftRecordSizeLog_MAX = 12;
++    if (MftRecordSizeLog > k_MftRecordSizeLog_MAX)
++      return false;
++    if (MftRecordSizeLog < SectorSizeLog)
++      return false;
++  }
++  {
++    UInt32 numClusters_per_IndexBlock;
++    G32(p + 0x44, numClusters_per_IndexBlock);
++    return (numClusters_per_IndexBlock < 0x100);
++  }
+ }
+ 
+ struct CMftRef
+@@ -266,8 +300,8 @@ bool CFileNameAttr::Parse(const Byte *p, unsigned size)
+   G32(p + 0x38, Attrib);
+   // G16(p + 0x3C, PackedEaSize);
+   NameType = p[0x41];
+-  unsigned len = p[0x40];
+-  if (0x42 + len > size)
++  const unsigned len = p[0x40];
++  if (0x42 + len * 2 > size)
+     return false;
+   if (len != 0)
+     GetString(p + 0x42, len, Name);
+@@ -1730,26 +1764,22 @@ HRESULT CDatabase::Open()
+  
+   SeekToCluster(Header.MftCluster);
+ 
+-  CMftRec mftRec;
+-  UInt32 numSectorsInRec;
+-
++  // we use ByteBuf for records reading.
++  // so the size of ByteBuf must be >= mftRecordSize
++  const size_t recSize = (size_t)1 << Header.MftRecordSizeLog;
++  const size_t kBufSize = MyMax((size_t)(1 << 15), recSize);
++  ByteBuf.Alloc(kBufSize);
++  RINOK(ReadStream_FALSE(InStream, ByteBuf, recSize))
++  {
++    const UInt32 allocSize = Get32(ByteBuf + 0x1C);
++    if (allocSize != recSize)
++      return S_FALSE;
++  }
++  // MftRecordSizeLog >= SectorSizeLog
++  const UInt32 numSectorsInRec = 1u << (Header.MftRecordSizeLog - 
Header.SectorSizeLog);
+   CMyComPtr<IInStream> mftStream;
++  CMftRec mftRec;
+   {
+-    UInt32 blockSize = 1 << 12;
+-    ByteBuf.Alloc(blockSize);
+-    RINOK(ReadStream_FALSE(InStream, ByteBuf, blockSize));
+-    
+-    {
+-      UInt32 allocSize = Get32(ByteBuf + 0x1C);
+-      int t = GetLog(allocSize);
+-      if (t < (int)Header.SectorSizeLog)
+-        return S_FALSE;
+-      RecSizeLog = t;
+-      if (RecSizeLog > 15)
+-        return S_FALSE;
+-    }
+-
+-    numSectorsInRec = 1 << (RecSizeLog - Header.SectorSizeLog);
+     if (!mftRec.Parse(ByteBuf, Header.SectorSizeLog, numSectorsInRec, 0, 
NULL))
+       return S_FALSE;
+     if (!mftRec.IsFILE())
+@@ -1768,11 +1798,6 @@ HRESULT CDatabase::Open()
+   if ((mftSize >> 4) > Header.GetPhySize_Clusters())
+     return S_FALSE;
+ 
+-  const size_t kBufSize = (1 << 15);
+-  const size_t recSize = ((size_t)1 << RecSizeLog);
+-  if (kBufSize < recSize)
+-    return S_FALSE;
+-
+   {
+     const UInt64 numFiles = mftSize >> RecSizeLog;
+     if (numFiles > (1 << 30))
diff -Nru 7zip-22.01+dfsg/debian/patches/series 
7zip-22.01+dfsg/debian/patches/series
--- 7zip-22.01+dfsg/debian/patches/series       2022-12-18 21:09:42.000000000 
+0900
+++ 7zip-22.01+dfsg/debian/patches/series       2024-10-06 11:40:03.000000000 
+0900
@@ -6,3 +6,4 @@
 0006-Disable-local-echo-display-when-in-input-passwords-C.patch
 0007-Manually-de-reference-pointers.patch
 0008-Remove-unwanted-hack-for-object-files.patch
+0009-Fix-CVE-2023-52168-and-CVE-2023-52169.patch

Reply via email to