CVE-2015-2304 (C, published 2015-03-15T19:59Z)
Description: value: Absolute path traversal vulnerability in bsdcpio in libarchive 3.1.2 and earlier allows remote attackers to write to arbitrary files via a full pathname in an archive.
Severity: MEDIUM (CVSS v3 base score: )
Weakness: CWE-22 \u2014 Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
The product uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the product does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory.
Repository: https://github.com/libarchive/libarchive
Files changed:
cpio/bsdcpio.1
cpio/cpio.c
libarchive/archive.h
libarchive/archive_write_disk.3
libarchive/archive_write_disk_posix.c
libarchive/test/test_write_disk_secure.c
Commit message: Add ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS option

This fixes a directory traversal in the cpio tool.


Vulnerable code:
This allows extraction via symbolic links and path names containing
 * error for an empty path, a trailing '..' or (if _SECURE_NODOTDOT is
 * set) any '..' in the path.
	if (*src == '/')

Fixed code:
This allows extraction via symbolic links, absolute paths,
and path names containing
	cpio->extract_flags |= ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS;
			cpio->extract_flags &= ~ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS;
/* Default: Do not reject entries with absolute paths */
#define ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS (0x10000)
.It Cm ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS
Refuse to extract an absolute path.
The default is to not refuse such paths.
 * error for an empty path, a trailing '..', (if _SECURE_NODOTDOT is
 * set) any '..' in the path or (if ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS
 * is set) if the path is absolute.
	if (*src == '/') {
		if (a->flags & ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS) {
			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
			                  "Path is absolute");
			return (ARCHIVE_FAILED);
		}

	}
	/*
	 * Without security checks, we should be able to
	 * extract an absolute path.
	 */
	assert((ae = archive_entry_new()) != NULL);
	archive_entry_copy_pathname(ae, "/tmp/libarchive_test-test_write_disk_secure-absolute_path.tmp");
	archive_entry_set_mode(ae, S_IFREG | 0777);
	assert(0 == archive_write_header(a, ae));
	assert(0 == archive_write_finish_entry(a));
	assertFileExists("/tmp/libarchive_test-test_write_disk_secure-absolute_path.tmp");
	assert(0 == unlink("/tmp/libarchive_test-test_write_disk_secure-absolute_path.tmp"));

	/* But with security checks enabled, this should fail. */
	assert(archive_entry_clear(ae) != NULL);
	archive_entry_copy_pathname(ae, "/tmp/libarchive_test-test_write_disk_secure-absolute_path.tmp");
	archive_entry_set_mode(ae, S_IFREG | 0777);
	archive_write_disk_set_options(a, ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS);
	failure("Extracting an absolute path should fail here.");
	assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae));
	archive_entry_free(ae);
	assert(0 == archive_write_finish_entry(a));
	assertFileNotExists("/tmp/libarchive_test-test_write_disk_secure-absolute_path.tmp");