CVE-2017-13156 Janus 漏洞学习,Android Signature Version 详解

一、CVE-2017-13156 Janus 漏洞学习

Janus漏洞

“Janus”安卓漏洞(漏洞编号:CVE-2017-13156)是Google在2017年12月发布的安卓系统安全公告中披露的一个漏洞。
该漏洞可以绕过安卓系统的signature scheme V1签名机制,使攻击者在不改变原来apk签名的情况下,植入恶意代码。


漏洞简析

漏洞前提1:虚拟机

Janus漏洞出现于Android5.0及以上系统,原因是Android5.0之后Android手机虚拟机由原来的Dalvik转为ART,而ART虚拟机允许执行一个dex文件或者一个包含dex的zip文件(apk文件)。

漏洞前提2:Android签名机制

Android支持两种签名方式,V1签名使用传统JAR签名,这种签名方式对zip文件内的所有entry做校验,可以防止zip打包文件被篡改,但是无法校验整个zip文件是否被篡改。在Android7.0及以上版本Google增加了V2签名机制,可以校验整个apk文件,但是为了兼容性,允许2种签名方式同时存在。

漏洞产生:


一个APK文件头部是dex文件尾部是apk文件,① Android在apk安装时进行签名校验,如果apk只有V1签名,则使用V1签名验证,发现apk内所有entry未进行篡改,签名验证通过;② ART虚拟机执行的时候发现这是一个dex文件,则直接执行,恶意代码被成功执行。

ZIP文件简析:
Android官方文档的图片:


ZIP是一个压缩文件包,其文件结构分为3个部分如上图所示。Contents of ZIP entries 是压缩包内所有entry;Central Directory保存了所有entry的header,而且每个header都是以魔鬼数字0x02014b50开头,每个header的第42-46字节保存的是每个entry的偏移量;End of Central Directory以魔鬼数字0x06054b50开头,第12-16字节保存 Central Directory 的长度,16-20字节保存 Central Directory 的起始位置偏移量。

因此只要偏移量正确,通过End of Central Directory可以确定Central Directory,再通过 Central Directory可以找到对应的entry,那么这就是一个合法的zip文件。而V1签名只能保证Contents of ZIP entries部分不被篡改,因此修改偏移量并不会影响V1签名。我们只要通过流将DEX文件加到APK头部,并且修改Central Directory和 End of Central Directory部分的偏移量使其保持一个合法的ZIP结构,即可绕过Android V1签名,并且执行我们自己的代码DEX文件。


JAVA版合并代码(仅供学习使用)


github地址 :https://github.com/xyzAsian/Janus-CVE-2017-13156

Android V2签名

注:最新签名机制V2签名,并不存在这个漏洞,原因是由于V2签名校验整个ZIP文件,包括了Central Directory和 End of Central Directory部分,因此只要修改了偏移量,V2签名校验就会失败。

漏洞分析参考资料

CVE-2017-13156漏洞分析(上): https://shunix.com/janus-one/

CVE-2017-13156漏洞分析(中)https://shunix.com/janus-two/


二、Android  Signature Version 详解

CVE-2017-13156 Janus 漏洞学习,Android Signature Version 详解_第1张图片
 

问题描述(v1和v2)

Android 7.0中引入了APK Signature Scheme v2,v1是jar Signature来自JDK
V1:应该是通过ZIP条目进行验证,这样APK 签署后可进行许多修改 - 可以移动甚至重新压缩文件。
V2:验证压缩文件的所有字节,而不是单个 ZIP 条目,因此,在签名后无法再更改(包括 zipalign)。正因如此,现在在编译过程中,我们将压缩、调整和签署合并成一步完成。好处显而易见,更安全而且新的签名可缩短在设备上进行验证的时间(不需要费时地解压缩然后验证),从而加快应用安装速度。


解决方案一

v1和v2的签名使用
1)只勾选v1签名并不会影响什么,但是在7.0上不会使用更安全的验证方式
2)只勾选V2签名7.0以下会直接安装完显示未安装,7.0以上则使用了V2的方式验证
3)同时勾选V1和V2则所有机型都没问题

解决方案二
在app的build.gradle的android标签下加入如下

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. signingConfigs {  
  2.     debug {  
  3.         v1SigningEnabled true  
  4.         v2SigningEnabled true  
  5.     }  
  6.     release {  
  7.         v1SigningEnabled true  
  8.         v2SigningEnabled true  
  9.     }  
  10. }  

官方解释:
CVE-2017-13156 Janus 漏洞学习,Android Signature Version 详解_第2张图片
  • 个人建议:

这是一个从Android7.0系统出现的新的签名机制,这个新机制使得apk的签名方式更加安全,首先我们应该尝试把V1和V2两个选项全部勾选,并尽可能的去使用他们,但是如果全部勾选完毕出现了问题,那么我们可以忽略这种新的签名机制,只勾选第一个选项(V1),依旧使用我们之前老的签名机制。




你可能感兴趣的:(android安全与逆向)