iOS应用安全 —— ZipperDown漏洞

简介

ZipperDown是盘古实验室公布的一个由目录穿越导致RCE的漏洞,根据盘古的检测,发现约10%的iOS应用可能受此漏洞的影响。经过手工分析,确认微博、陌陌、网易云音乐、QQ音乐、快手等流行应用受影响。

漏洞原理

  • iOS平台没有提供官方解压类库,所以开发中往往引用第三方库来实现解压功能;
  • 由于现有的iOS App基本上采用SSZipArchive或Ziparchive来实现解压,因此漏洞是来自使用第三方Zip库解压Zip文件的过程中没有对Zip内文件名做校验导致的;
  • 例如 SSZipArchive解压时会吧文件名直接拼接到目标路径后面,如果文件名中含有“../”则可以实现目录的上一级跳转,从而实现应用内任意目录的跳转,进一步可以实现文件覆盖;
  • 如果把App的热修复hotpatch文件覆盖替换了,可以达到执行黑客指定指令,从而按照黑客的意图实现任意应用内攻击。

攻击条件

  • 使用了SSZipArchive或Ziparchive第三方解压库;
  • Zip包在解压时没有做完整性校验;
  • 文件名中包含../等路径特殊符号,解压时没有对文件名过滤处理;
  • 使用了JSPatch或其他热修复库,且本地脚本没有加密等安全处理;
  • 连接不可靠的WIFI热点或者网络被人劫持。

漏洞分析

iOS平台的两个解压缩库(SSZipArchive和ZipArchive)在解压缩过程中没有考虑到文件名中包含”../”的情况,造成了文件释放过程中路径穿越,导致恶意Zip文件可以在App沙盒范围内,覆盖任意可写文件。具体代码如下:

ZipArchive相关代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
-(BOOL) UnzipFileTo:(NSString*) path overWrite:(BOOL) overwrite
{
[...]
// check if it contains directory
NSString* strPath = [NSString stringWithCString:filename encoding:NSUTF8StringEncoding];
BOOL isDirectory = NO;
if( filename[fileInfo.size_filename-1]=='/' || filename[fileInfo.size_filename-1]=='\\')
isDirectory = YES;
free( filename );
if( [strPath rangeOfCharacterFromSet:[NSCharacterSetcharacterSetWithCharactersInString:@"/\\"]].location!=NSNotFound )
{
// contains a path
strPath = [strPath stringByReplacingOccurrencesOfString:@"\\" withString:@"/"];
}
NSString* fullPath = [path stringByAppendingPathComponent:strPath];
[...]
}

SSZipArchive相关代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
+ (BOOL)unzipFileAtPath:(NSString *)path
toDestination:(NSString *)destination
preserveAttributes:(BOOL)preserveAttributes
overwrite:(BOOL)overwrite
nestedZipLevel:(NSInteger)nestedZipLevel
password:(nullable NSString *)password
error:(NSError **)error
delegate:(nullable id)delegate
progressHandler:(void (^_Nullable)(NSString *entry, unz_file_info zipInfo, long entryNumber, long total))progressHandler
completionHandler:(void (^_Nullable)(NSString *path, BOOL succeeded, NSError * _Nullable error))completionHandler{
[...]
if ([strPath rangeOfCharacterFromSet:[NSCharacterSetcharacterSetWithCharactersInString:@"/\\"]].location != NSNotFound) {
strPath = [strPath stringByReplacingOccurrencesOfString:@"\\" withString:@"/"];
}
NSString *fullPath = [destination stringByAppendingPathComponent:strPath];
[...]
}

基于以上漏洞原理,漏洞利用条件的核心即如何使目标App解压不可信Zip文件,iOS应用的主要解压场景如下:

  1. App直接接收不可信Zip文件,并使用SSZipArchive/ZipArchive(或其它存在路径穿越问题的代码)解压。例如聊天应用、文件管理应用中可能存在这类业务场景。
  2. App通过HTTP下载Zip文件,使用SSZipArchive/ZipArchive(或其它存在路径穿越问题的代码)解压。在这种场景下,攻击者可以通过流量劫持等途径,将正常Zip文件替换为恶意Zip文件,在App中实现文件覆盖。

完成文件覆盖后,一些特殊场景可以实现RCE,例如:

  1. 覆盖了热补丁文件,APP加载恶意热补丁实现RCE
  2. 覆盖了APP的核心文件,实现钓鱼、拒绝服务等

先前的微信、企业微信等都是因为存在ZipperDown问题,导致最后账户被克隆。

另外,由于iOS沙盒保护,ZipperDown的破坏范围仅限在App环境中。

参考资料:

  1. ZipperDown https://zipperdown.org/
  2. https://github.com/muzipiao/ZipperDownDemo