第三种master key解析

0x0 前言

        
        Android
系统Master Key漏洞一波未平一波又起,昨天,国外安全研究人员爆料Android系统存在第三个Master Key漏洞,黑客可以通过该漏洞完成控制我们的手机。目前,Google官方已经修复了该漏洞,但是由于Android系统更新的推动力更多的来自于各个设备生产商,因此补丁的推送滞后非常严重。我们在这里提醒大家,下载应用要到正规的市场去下载。


0x1 庖丁解牛

        该漏洞的主要原理是:android在解析Zip包时,没有校验ZipEntry和Header中的FileNameLength是否一致。

 

0x1.1 ZIP格式的文件结构

        在了解漏洞的原理前,先熟悉下zip格式的文件结构。

        如果一个压缩包文件里有多个文件,可以认为每个文件都是被单独压缩,然后再拼成一起。

        一个 ZIP 文件由三个部分组成:压缩源文件数据区+压缩源文件目录区+压缩源文件目录结束标志,如下图:

                       

                                          图 1
1)文件头(压缩源文件目录区)在文件末尾,即图1中的FileHeader,记录了索引段的偏移、大小等等。

2)数据段(压缩源文件数据区)在文件开头,即图1中的Local Header,记录了数据的一些基本信息,可以用来跟File Header中记录的数据进行比较,保证数据的完整性。

3)Local Header还包含了文件被压缩之后的存储区,即图1中的Data区域。

4)图2和图3为Local Header(图2中的ZIPFILERECORD)和File Header(图3中的ZIPDIRENTRY)的数据对比,两者数据是一致的。


                               图2


                              图3

0x1.2 漏洞产生原因

        先来看一下是如何定位到Local Header中的Data数据:


off64_t dataOffset = localHdrOffset +

                             kLFHLen +

                             get2LE(lfhBuf + kLFHNameLen) +

                             get2LE(lfhBuf + kLFHExtraLen);

        Data的偏移是通过Header的起始偏移+Header的大小(固定值)+Extra data的大小+文件名的大小,如图4

                              图4


        回头看一下,java在获取Data偏移的处理,在读取Extra data的长度的时候,它已经预存了文件名在FileHeader中的长度。


// We don't know the entry data's start position. 
// All we have is the position of the entry's local 
// header. At position 28 we find the length of the 
// extra data. In some cases this length differs 
// from the one coming in the central header. 

RAFStream rafstrm = new RAFStream(raf, 
         entry.mLocalHeaderRelOffset + 28); 
 DataInputStream is = new DataInputStream(rafstrm); 
int localExtraLenOrWhatever = 
         Short.reverseBytes(is.readShort()); 
 is.close(); 
// Skip the name and this "extra" data or whatever it is: rafstrm.skip(entry.nameLength + localExtraLenOrWhatever);


        漏洞就在这里产生了,如果Local Header中的FileNameLength被设成一个大数,并且FileName的数据包含原来的数据,File Header中的FileNameLength长度不变,那么底层C++运行和上层Java运行就是不一样的流程。

C++ Header 64k Name Data 
+--------> +----------------------> +----------> 
length=64k classes.dex dex\035\A... dex\035\B... 
+--------> +---------> +----------> 
Java Header 11 Name Data


        如上面所示,底层C++的执行会读取64k的FileName长度,而Java层由于是读取File Header中的数据,FileName的长度依旧是11,于是Java层校验签名通过,底层执行会执行恶意代码。

 

漏洞修复方案:

校验Local Header和File Header中的FileNameLength是否一致

int length = Short.reverseBytes(raf.readShort()) & 0xffff; 
if (length != length.getInt(entry)) 
             throw new ZipException();


0x2 后记

        从Android系统的这3个MasterKey漏洞,我们进行了如下反思:

1、手机厂商的安全意识有待加强

        由于Android系统的开源特性,注定了各大手机产商百花齐放,市面上的Android系统安全性参差不齐。更为严重的是,如果Android系统爆出系统漏洞,由于各大手机产商安全意识薄弱,导致补丁推送速度严重跟不上。因此,国内手机厂商的安全意识有待加强,真真正正用户至上。

2、开发者安全意识有待加强

        从这个3个Master Key漏洞管中窥豹,都是由于开发者的安全意识薄弱,导致产生严重的逻辑漏洞。同时,由于Android系统补丁推送的滞后性,业务需要预备一套应对系统漏洞的应对方案。以这个漏洞为例,业务可以对自己的安装包进行校验,防止被黑客恶意利用。后续我们会在这方面进行改进、完善,并且会与业界进行交流,分享我们的成果。

 

0x3 参考

YetAnother Android Master Key Bug

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Kubernetes(k8s)是一个用于自动化部署、扩展和管理容器化应用程序的开源平台。在k8s集群中,有一个主节点(master node)和多个工作节点(worker node)。主节点负责管理集群中的资源和进行调度决策,而工作节点则负责运行应用程序容器。 在k8s集群中添加多个主节点可以提高集群的可靠性和容错能力。如果某个主节点出现故障,其他主节点可以继续正常工作,确保集群的稳定性和可用性。 下面是详细的步骤和解析,以添加两个主节点为例: 1. 准备环境 确保每个新的主节点都可以访问k8s集群,并且已安装了所需的软件包和依赖项。需要确保主节点上的kubeadm、kubelet、kubectl、容器运行时(如Docker或CRI-O)等软件版本与其他节点相同。 2. 初始化第一个主节点 在集群中选择一个现有的主节点来初始化第一个新主节点。可以使用kubeadm init命令将新主节点纳入集群。 示例命令: ``` $ kubeadm init --control-plane-endpoint=LOAD_BALANCER_DNS_OR_IP --upload-certs ``` 其中,LOAD_BALANCER_DNS_OR_IP是负载均衡器的DNS或IP地址,用于将流量分配到多个主节点。--upload-certs选项将证书上传到新的主节点,以确保其可以加入现有的控制平面。 3. 加入第二个主节点 使用kubeadm join命令将第二个主节点加入集群。要注意的是,需要指定新的主节点的API服务器地址和证书,以便其可以连接到集群。 示例命令: ``` $ kubeadm join LOAD_BALANCER_DNS_OR_IP --token TOKEN --discovery-token-ca-cert-hash SHA256:HASH --control-plane --certificate-key CERTIFICATE_KEY ``` 其中,TOKEN是由第一个主节点生成的加入令牌,HASH是由第一个主节点生成的CA证书哈希值,CERTIFICATE_KEY是第一个主节点生成的证书密钥。 4. 初始化第二个主节点 在第二个主节点上执行与第一个主节点相同的命令,初始化第二个主节点并加入集群。 示例命令: ``` $ kubeadm init --control-plane-endpoint=LOAD_BALANCER_DNS_OR_IP --upload-certs ``` 5. 验证集群状态 使用kubectl命令验证集群状态,确保所有节点都已成功加入集群。可以使用以下命令查看节点状态: ``` $ kubectl get nodes ``` 6. 完成 现在,k8s集群已添加两个主节点,并且可以更好地扩展和管理容器化应用程序。 解析: 添加多个主节点可以提高k8s集群的可靠性和容错能力。多个主节点可以共同管理集群中的资源和进行调度决策,从而确保集群的稳定性和可用性。 在添加新的主节点之前,需要确保每个新的主节点都可以访问k8s集群,并且已安装了所需的软件包和依赖项。需要确保主节点上的kubeadm、kubelet、kubectl、容器运行时(如Docker或CRI-O)等软件版本与其他节点相同。 在添加新的主节点时,需要指定API服务器地址和证书,以便新的主节点可以连接到集群。如果使用负载均衡器将流量分配到多个主节点,需要确保所有主节点的负载均衡器地址相同。 添加多个主节点后,需要使用kubectl命令验证集群状态,确保所有节点都已成功加入集群。可以使用kubectl get nodes命令查看节点状态。 总的来说,添加多个主节点可以提高k8s集群的可靠性和容错能力,使其更适合运行生产环境中的容器化应用程序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值