Skip to content

Commit f11b8fa

Browse files
authored
fix unarchive vulnerability
- avoid malicious record name being able to write to system files - address imports for unit tests
1 parent ac88119 commit f11b8fa

File tree

7 files changed

+33
-20
lines changed

7 files changed

+33
-20
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
## History
44

5+
### 1.11.2 (September 4, 2018) - Nolan O'Brien
6+
- Fix vulnerability when zip archive provides malicious output file name
7+
58
### 1.11.1 (August 14, 2018) - Nolan O'Brien
69

710
- Update Brotli (v1.0.5) and ZStandard (v1.3.5)

ZipUtilities.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Pod::Spec.new do |s|
22
s.name = "ZipUtilities"
3-
s.version = "1.11.1"
3+
s.version = "1.11.2"
44
s.summary = "Zip Archiving, Unarchiving and Utilities in Objective-C"
55
s.description = <<-DESC
66
ZipUtilities, prefixed with NOZ for Nolan O'Brien ZipUtilities, is a library of zipping and unzipping utilities for iOS and Mac OS X.

ZipUtilities/NOZDecompress.m

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -301,20 +301,20 @@ - (NSError *)private_unzipAllEntries
301301

302302
NSError *innerError = nil;
303303
[self->_unzipper saveRecord:record
304-
toDirectory:self->_sanitizedDestinationDirectoryPath
305-
options:(overwrite) ? NOZUnzipperSaveRecordOptionOverwriteExisting : NOZUnzipperSaveRecordOptionsNone
306-
progressBlock:^(int64_t totalBytes,
307-
int64_t bytesComplete,
308-
int64_t byteWrittenThisPass,
309-
BOOL *abort) {
310-
if (self.isCancelled) {
311-
stackError = kCancelledError;
312-
*abort = YES;
313-
} else {
314-
[self private_didDecompressBytes:byteWrittenThisPass];
315-
}
316-
}
317-
error:&innerError];
304+
toDirectory:self->_sanitizedDestinationDirectoryPath
305+
options:(overwrite) ? NOZUnzipperSaveRecordOptionOverwriteExisting : NOZUnzipperSaveRecordOptionsNone
306+
progressBlock:^(int64_t totalBytes,
307+
int64_t bytesComplete,
308+
int64_t byteWrittenThisPass,
309+
BOOL *abort) {
310+
if (self.isCancelled) {
311+
stackError = kCancelledError;
312+
*abort = YES;
313+
} else {
314+
[self private_didDecompressBytes:byteWrittenThisPass];
315+
}
316+
}
317+
error:&innerError];
318318

319319
if (!stackError) {
320320
if (innerError) {

ZipUtilities/NOZUnzipper.m

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -347,8 +347,9 @@ - (BOOL)saveRecord:(NOZCentralDirectoryRecord *)record
347347
}
348348
});
349349

350-
BOOL overwrite = (options & NOZUnzipperSaveRecordOptionOverwriteExisting) != 0;
351-
BOOL followIntermediatePaths = !(options & NOZUnzipperSaveRecordOptionIgnoreIntermediatePath);
350+
destinationRootDirectory = [destinationRootDirectory stringByStandardizingPath];
351+
const BOOL overwrite = (options & NOZUnzipperSaveRecordOptionOverwriteExisting) != 0;
352+
const BOOL followIntermediatePaths = !(options & NOZUnzipperSaveRecordOptionIgnoreIntermediatePath);
352353

353354
NSFileManager *fm = [NSFileManager defaultManager];
354355
NSString *destinationFile = nil;
@@ -358,7 +359,13 @@ - (BOOL)saveRecord:(NOZCentralDirectoryRecord *)record
358359
destinationFile = [[destinationRootDirectory stringByAppendingPathComponent:record.nameNoCopy.lastPathComponent] stringByStandardizingPath];
359360
}
360361

362+
if (![destinationFile hasPrefix:destinationRootDirectory]) {
363+
stackError = [NSError errorWithDomain:NSPOSIXErrorDomain code:EBADF userInfo:nil];
364+
return NO;
365+
}
366+
361367
if (![fm createDirectoryAtPath:[destinationFile stringByDeletingLastPathComponent] withIntermediateDirectories:YES attributes:nil error:error]) {
368+
stackError = [NSError errorWithDomain:NSPOSIXErrorDomain code:EACCES userInfo:nil];
362369
return NO;
363370
}
364371

ZipUtilitiesTests/NOZCoderTests.m

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@
1010
#import "NOZXBrotliCompressionCoder.h"
1111
#import "NOZXZStandardCompressionCoder.h"
1212

13+
#import "ZipUtilities.h"
14+
1315
@import XCTest;
14-
@import ZipUtilities;
1516

1617
#define NOZCompressionMethodZStandard (100)
1718
#define NOZCompressionMethodZStandard_D128 (101)

ZipUtilitiesTests/NOZCompressTests.m

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,10 @@
2525
// SOFTWARE.
2626
//
2727

28+
#import "ZipUtilities.h"
29+
2830
@import Foundation;
2931
@import XCTest;
30-
@import ZipUtilities;
3132

3233
//#define TESTLOG(...) NSLog(__VA_ARGS__)
3334
#define TESTLOG(...) ((void)0)

ZipUtilitiesTests/NOZDecompressTests.m

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,10 @@
2525
// SOFTWARE.
2626
//
2727

28+
#import "ZipUtilities.h"
29+
2830
@import Foundation;
2931
@import XCTest;
30-
@import ZipUtilities;
3132

3233
//#define TESTLOG(...) NSLog(__VA_ARGS__)
3334
#define TESTLOG(...) ((void)0)

0 commit comments

Comments
 (0)