[RESEND][PATCH] fix masking of malicious path traversals in archive content listings
Prevent unprintable bytes including terminal escapes being printed when listing tar file contents in a terminal as this can be used to hide malicious archive content from users prior to unpacking a file. Re #16018 Also added bb_safe_dump_str() to include/libbb.h --- archival/libarchive/header_list.c | 3 ++- archival/libarchive/header_verbose_list.c | 14 +++--- include/libbb.h | 8 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/archival/libarchive/header_list.c b/archival/libarchive/header_list.c index 0621aa406..9ee69aae2 100644 --- a/archival/libarchive/header_list.c +++ b/archival/libarchive/header_list.c @@ -8,5 +8,6 @@ void FAST_FUNC header_list(const file_header_t *file_header) { //TODO: cpio -vp DIR should output "DIR/NAME", not just "NAME" */ - puts(file_header->name); + bb_safe_dump_str(stdout, file_header->name); + bb_putchar('\n'); } diff --git a/archival/libarchive/header_verbose_list.c b/archival/libarchive/header_verbose_list.c index a575a08a0..956589a1b 100644 --- a/archival/libarchive/header_verbose_list.c +++ b/archival/libarchive/header_verbose_list.c @@ -29,7 +29,7 @@ void FAST_FUNC header_verbose_list(const file_header_t *file_header) /*sprintf(gid, "%u", (unsigned)file_header->gid);*/ group = utoa(file_header->gid); } - printf("%s %s/%s %9"OFF_FMT"u %4u-%02u-%02u %02u:%02u:%02u %s", + printf("%s %s/%s %9"OFF_FMT"u %4u-%02u-%02u %02u:%02u:%02u ", bb_mode_string(modestr, file_header->mode), user, group, @@ -39,14 +39,13 @@ void FAST_FUNC header_verbose_list(const file_header_t *file_header) ptm->tm_mday, ptm->tm_hour, ptm->tm_min, - ptm->tm_sec, - file_header->name); + ptm->tm_sec); #else /* !FEATURE_TAR_UNAME_GNAME */ localtime_r(&file_header->mtime, ptm); - printf("%s %u/%u %9"OFF_FMT"u %4u-%02u-%02u %02u:%02u:%02u %s", + printf("%s %u/%u %9"OFF_FMT"u %4u-%02u-%02u %02u:%02u:%02u ", bb_mode_string(modestr, file_header->mode), (unsigned)file_header->uid, (unsigned)file_header->gid, @@ -56,14 +55,15 @@ void FAST_FUNC header_verbose_list(const file_header_t *file_header) ptm->tm_mday, ptm->tm_hour, ptm->tm_min, - ptm->tm_sec, - file_header->name); + ptm->tm_sec); #endif /* FEATURE_TAR_UNAME_GNAME */ + bb_safe_dump_str(stdout, file_header->name); /* NB: GNU tar shows "->" for symlinks and "link to" for hardlinks */ if (file_header->link_target) { - printf(" -> %s", file_header->link_target); + printf(" -> "); + bb_safe_dump_str(stdout, file_header->link_target); } bb_putchar('\n'); } diff --git a/include/libbb.h b/include/libbb.h index 01cdb1bdc..3222fac8b 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -2524,6 +2524,14 @@ static ALWAYS_INLINE unsigned char bb_ascii_tolower(unsigned char a) #define isgraph_asciionly(a) ((unsigned)((a) - 0x21) <= 0x7e - 0x21) #define isprint_asciionly(a) ((unsigned)((a) - 0x20) <= 0x7e - 0x20) +/* Print msg to a file-descriptor, replacing any unprintable and terminal escape bytes with '?' if fd is a TTY */ +static ALWAYS_INLINE void bb_safe_dump_str(FILE* fd, const char* msg) { + int fdno = fileno(fd); + if (isatty(fdno)) { +msg = printable_string(msg); + } + fprintf(fd, "%s", msg); +} /* Simple unit-testing framework */ -- 2.20.1 Any email and files/attachments transmitted with it are intended solely for the use of the individual or entity to whom they are addressed. If this message has been sent to you in error, you must not copy, distribute or disclose of the information it contains. Please notify Entrust immediately and delete the message from your system. Wellbeing Notice: Receiving this email outside of normal working hours? Managing work and life responsibilities is unique for everyone. I have sent this email at a time that works for me. Unless this email is specifically marked urgent, please respond at a time that works for you. ___ busybox mailing list busybox@busybox.net http://lists.busybox.net/mailman/listinfo/busybox
Re: [EXTERNAL] [RESEND(4) PATCH] archival: disallow path traversals (CVE-2023-39810)
FYI, This seems also related to https://bugs.busybox.net/show_bug.cgi?id=16018 (my patch for fixing that seems to have got lost in the mailing list noise) From: busybox on behalf of Peter Kaestle Date: Wednesday 2 October 2024 at 09:12 To: "busybox@busybox.net" , Denys Vlasenko Cc: "martin.schob...@pentagrid.ch" , Peter Kaestle , Samuel Sapalski Subject: [EXTERNAL] [RESEND(4) PATCH] archival: disallow path traversals (CVE-2023-39810) Create new configure option for archival/libarchive based extractions to disallow path traversals. As this is a paranoid option and might introduce backward incompatibiltiy, default it to no. Fixes: CVE-2023-39810 Signed-off-by: Peter Kaestle Create new configure option for archival/libarchive based extractions to disallow path traversals. As this is a paranoid option and might introduce backward incompatibiltiy, default it to no. Fixes: CVE-2023-39810 Signed-off-by: Peter Kaestle Reviewed-by: Samuel Sapalski --- archival/Config.src| 7 +++ archival/libarchive/data_extract_all.c | 22 ++ testsuite/cpio.tests | 18 ++ 3 files changed, 47 insertions(+) diff --git a/archival/Config.src b/archival/Config.src index 6f4f30c43..ac9d3db95 100644 --- a/archival/Config.src +++ b/archival/Config.src @@ -35,4 +35,11 @@ config FEATURE_LZMA_FAST This option reduces decompression time by about 25% at the cost of a 1K bigger binary. +config FEATURE_PATH_TRAVERSAL_PROTECTION + bool "enable path traversal protection" + default n + help + This option will disallow extraction of files outside of the + destination directory. + endmenu diff --git a/archival/libarchive/data_extract_all.c b/archival/libarchive/data_extract_all.c index 049c2c156..cb5d5c4ca 100644 --- a/archival/libarchive/data_extract_all.c +++ b/archival/libarchive/data_extract_all.c @@ -66,6 +66,28 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle) } #endif +#if ENABLE_FEATURE_PATH_TRAVERSAL_PROTECTION + if (strstr(dst_name, "../")) { +char *resolved_dst_path, *cwd; + +cwd = getcwd(NULL, 0); + +resolved_dst_path = xmalloc_realpath_coreutils(dst_name); +if (resolved_dst_path) { +if (strncmp(cwd, resolved_dst_path, strlen(cwd))) { + errno = 0; /* suppress missleading error prints */ + free(resolved_dst_path); + bb_perror_msg_and_die("path traversal detected: %s", + dst_name); +} +free(resolved_dst_path); +} else { +bb_perror_msg_and_die("cannot allocate memory for real path: %s", + dst_name); +} + } +#endif + if (archive_handle->ah_flags & ARCHIVE_CREATE_LEADING_DIRS) { char *slash = strrchr(dst_name, '/'); if (slash) { diff --git a/testsuite/cpio.tests b/testsuite/cpio.tests index 85e746589..1c0b75297 100755 --- a/testsuite/cpio.tests +++ b/testsuite/cpio.tests @@ -154,6 +154,24 @@ testing "cpio -R with extract" \ " "" "" SKIP= +optional FEATURE_PATH_TRAVERSAL_PROTECTION +rm -rf cpio.testdir +mkdir -p cpio.testdir/prepare/inner +echo "file outside of destination was written" > cpio.testdir/prepare/dont_write +echo "data" > cpio.testdir/prepare/inner/to_extract +mkdir -p cpio.testdir/extract +testing "cpio extract file outside of destination" \ +"(cd cpio.testdir/prepare/inner && echo -e '../dont_write\nto_extract' | cpio -H newc --create) | +(cd cpio.testdir/extract && cpio -vi 2>&1); +echo \$?; +ls cpio.testdir/dont_write 2>&1" \ +"\ +cpio: path traversal detected: ../dont_write +1 +ls: cpio.testdir/dont_write: No such file or directory +" "" "" +SKIP= + # Clean up rm -rf cpio.testdir cpio.testdir2 2>/dev/null -- 2.42.0 ___ busybox mailing list busybox@busybox.net https://urldefense.com/v3/__http://lists.busybox.net/mailman/listinfo/busybox__;!!FJ-Y8qCqXTj2!dv3Uoeo_xECehdxW2TOtpmp-ONDwsssh0Tl72I5vnwfii2WIcR71lUIMVSJb44L4bKG4Eg6HpK5s3-Bv4ph0xWY$