Fix: directory traversal in unzip binary

Resolves: RHEL-105822
This commit is contained in:
Jakub Martisko 2025-07-29 16:53:31 +02:00
parent f015ecb883
commit 36bd73419a
2 changed files with 87 additions and 2 deletions

View File

@ -0,0 +1,76 @@
From f65fecf5373d1053dd4d57e87433fd4697203450 Mon Sep 17 00:00:00 2001
From: Jakub Martisko <jamartis@redhat.com>
Date: Tue, 29 Jul 2025 16:02:29 +0200
Subject: [PATCH] new
---
bins/unzip-mem.c | 44 ++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 42 insertions(+), 2 deletions(-)
diff --git a/bins/unzip-mem.c b/bins/unzip-mem.c
index afd546d..6285b8b 100644
--- a/bins/unzip-mem.c
+++ b/bins/unzip-mem.c
@@ -85,16 +85,57 @@ zzip_mem_entry_pipe(ZZIP_MEM_DISK* disk, ZZIP_MEM_ENTRY* entry, FILE* out)
}
}
+#include <zzip/__param.h> /*PATH_MAX*/
+static inline void
+remove_dotdotslash(char *path)
+{
+ /* Note: removing "../" from the path ALWAYS shortens the path, never adds to it! */
+ char *dotdotslash;
+ int warned = 0;
+
+ dotdotslash = path;
+ while ((dotdotslash = strstr(dotdotslash, "../")) != NULL)
+ {
+ /*
+ * Remove only if at the beginning of the pathname ("../path/name")
+ * or when preceded by a slash ("path/../name"),
+ * otherwise not ("path../name..")!
+ */
+ if (dotdotslash == path || dotdotslash[-1] == '/')
+ {
+ char *src, *dst;
+ if (!warned)
+ {
+ /* Note: the first time through the pathname is still intact */
+ fprintf(stderr, "Removing \"../\" path component(s) in %s\n", path);
+ warned = 1;
+ }
+ /* We cannot use strcpy(), as there "The strings may not overlap" */
+ for (src = dotdotslash+3, dst=dotdotslash; (*dst = *src) != '\0'; src++, dst++)
+ ;
+ }
+ else
+ dotdotslash +=3; /* skip this instance to prevent infinite loop */
+ }
+}
+
static void
zzip_mem_entry_make(ZZIP_MEM_DISK* disk, ZZIP_MEM_ENTRY* entry)
{
- FILE* file = fopen(entry->zz_name, "wb");
+ char name_sanitized[PATH_MAX+1];
+
+ strncpy(name_sanitized, entry->zz_name, PATH_MAX);
+ name_sanitized[PATH_MAX]='\0';
+ remove_dotdotslash(name_sanitized);
+
+
+ FILE* file = fopen (name_sanitized, "wb");
if (file) {
zzip_mem_entry_pipe(disk, entry, file);
fclose(file);
return;
}
- perror(entry->zz_name);
+ perror(name_sanitized);
if (status < EXIT_WARNINGS)
status = EXIT_WARNINGS;
}
--
2.50.0

View File

@ -5,11 +5,13 @@
Summary: Lightweight library to easily extract data from zip files
Name: zziplib
Version: 0.13.78
Release: 1%{?dist}
Release: 2%{?dist}
License: LGPL-2.0-or-later OR MPL-1.1
URL: http://zziplib.sourceforge.net/
Source: https://github.com/gdraheim/zziplib/archive/v%{version}.tar.gz
Patch1: CVE-2018-17828-singlez.patch
BuildRequires: make
BuildRequires: gcc
BuildRequires: perl-interpreter
@ -62,8 +64,10 @@ zziplib library.
%prep
%setup -q
%patch 1 -p1
%build
%cmake -B "%{_vpath_builddir}"
%cmake -B "%{_vpath_builddir}" -DZZIP_TESTCVE=OFF
%make_build -C "%{_vpath_builddir}"
@ -91,6 +95,11 @@ zziplib library.
%{_mandir}/man3/*
%changelog
* Tue Jul 29 2025 Jakub Martisko <jamartis@redhat.com> - 0.13.78-2
- Fix directory traversal in unzip binary
- Disable the CVE tests during the check phase - the reproducers for these are downloaded from the github
- Resolves: RHEL-105822
* Fri Jan 31 2025 Jakub Martisko <jamartis@redhat.com> - 0.13.78-1
- Rebase to 0.13.78
- Related: RHEL-45367