Android安全开发之ZIP文件目录遍历



1、ZIP文件目录遍历简介

因为ZIP压缩包文件中允许存在“../”的字符串,攻击者可以利用多个“../”在解压时改变ZIP包中某个文件的存放位置,覆盖掉应用原有的文件。如果被覆盖掉的文件是动态链接so、dex或者odex文件,轻则产生本地拒绝服务漏洞,影响应用的可用性,重则可能造成任意代码执行漏洞,危害用户的设备安全和信息安全。比如近段时间发现的“寄生兽”漏洞、海豚浏览器远程命令执行漏洞、三星默认输入法远程代码执行漏洞等都与ZIP文件目录遍历有关。

阿里聚安全的应用漏洞扫描服务,可以检测出应用的ZIP文件目录遍历风险。另外我们发现日本计算机应急响应小组(JPCERT)给出的修复方案存在缺陷。如果使用不当(它提供的示例文档就使用错误),可能起不到防止ZIP文件目录遍历的作用,并且国内有修复方案参考了此方案。

2、漏洞原理和风险示例

2.1 漏洞原理

在Linux/Unix系统中“../”代表的是向上级目录跳转,有些程序在当前工作目录中处理到诸如用“../../../../../../../../../../../etc/hosts”表示的文件,会跳转出当前工作目录,跳转到到其他目录中。 
Java代码在解压ZIP文件时,会使用到ZipEntry类的getName()方法,如果ZIP文件中包含“../”的字符串,该方法返回值里面原样返回,如果没有过滤掉getName()返回值中的“../”字符串,继续解压缩操作,就会在其他目录中创建解压的文件。

如我们构造的ZIP文件中有如下文件:


进行解压的代码如下,没有对getName进行过滤:


解压操作时的日志:


此ZIP文件存放在SD卡中,想让解压出来的所有文件也存在SD卡中,但是a_poc.txt文件却存在了应用的数据目录中:


2.2 风险示例

以海豚浏览器远程代码执行漏洞为例。 
海豚浏览器的主题设置中允许用户通过网络下载新的主题进行更换,主题文件其实是一个ZIP压缩文件。通过中间人攻击的方法可以替换掉这个ZIP文件。替换后的ZIP文件中有重新编译过的libdolphin.so。此so文件重写了JNI_OnLoad()函数:


此so文件以“../../../../../../../../../../data/data/mobi.mgeek.TunnyBrowser/files/libdolphin.so”的形式存在恶意ZIP文件中。海豚浏览器解压恶意ZIP文件后,重新的libdolphin.so就会覆盖掉原有的so文件,重新运行海豚浏览器会弹出Toast提示框:


能弹出Toast说明也就可以执行其他代码。

这里分析下此漏洞产生的原因是: 
1、主题文件其实是一个ZIP压缩包,从服务器下载后进行解压,但是解压时没有过滤getName()返回的字符串中是否有“../”:


2、动态链接库文件libdolphin.so,并没有放在应用数据的lib目录下,而是放在了files目录中:


加载使用的地方是com.dolphin.browser.search.redirect包中的SearchRedirector:


应用使用的是System.load()来加载libdolphin.so而非System.loadLibrary(),在Android中,System.loadLibrary()是从应用的lib目录中加载.so文件,而System.load()是用某个.so文件的绝对路径加载,这个.so文件可以不在应用的lib目录中,可以在SD卡中,或者在应用的files目录中,只要应用有读的权限目录中即可。

在files目录中,应用具有写入权限,通过网络中间人攻击,同时利用ZIP文件目录遍历漏洞,替换掉文件libdolphin.so,达到远程命令执行的目的。

应用的lib目录是软链接到了/data/app-lib/应用目录,如果libdolphin.so文件在lib目录下就不会被覆盖了,第三方应用在执行时没有写入/data/app-lib目录的权限:


3、JPCERT修复方案的研究

在研究中我们发现JPCERT提供的修复方案存在缺陷。它是利用Java的File类提供的getCanonicalPath()方法过滤掉zipEntry.getName()返回的字符串中所包含的“../”,然后检查这个字符串是否是以要解压到的目标目录字符串为开头,如果是,返回getCanonicalPath()获取到的字符串,如果不是,则抛出异常:


但是在JPCERT给出的示例代码中,对validateFilename()的调用对于APP来说不会达到防止任意目录遍历的目的:


其使用“.”,作为要解压到的目的目录,“.”表示当前目录,经测试APP进程的当前工作目录是根目录“/”:


查看进程状态,得到的APP进程的当前工作目录cwd是链接到了根目录:


如下的Demo,如果采用JPCERT示例中validateFilename(entry.genName(), “.”)的调用方式,还是会产生目录遍历读到系统配置文件:


读到的hosts文件内容:


正确的调用validateFilename()形式是传入的要解压到的目的目录不要用“.”,而是指定一个绝对路径。


4、阿里聚安全对开发者建议

1 对重要的ZIP压缩包文件进行数字签名校验,校验通过才进行解压。 
2 检查Zip压缩包中使用ZipEntry.getName()获取的文件名中是否包含”../”或者”..”,检查”../”的时候不必进行URI Decode(以防通过URI编码”..%2F”来进行绕过),测试发现ZipEntry.getName()对于Zip包中有“..%2F”的文件路径不会进行处理。 
3 在应用上线前使用阿里聚安全的安全扫描服务,尽早发现应用的安全风险。


阿里聚安全扫描器建议修复方案: 
在使用java.util.zip包中ZipInputStream类的进行解压操作时,进行检查,示例如下:


也可以使用java.util.zip包中的ZipFile类,直接读取Zip包中的所有entries,然后检查getName()的返回值是否包含“../”:


5、参考

[1] https://www.jpcert.or.jp/present/2014/20140910android-sc.pdf 

[2] 《海豚浏览器与水星浏览器远程代码执行漏洞详解》http://drops.wooyun.org/mobile/8293 
[3] 《影响数千万APP的安卓APP“寄生兽”漏洞技术分析》http://drops.wooyun.org/mobile/6910 
[4] 《三星默认输入法远程代码执行》http://drops.wooyun.org/papers/6632 
[5] http://www.oracle.com/technetwork/articles/java/compress-1565076.html 
[6] http://stackoverflow.com/questions/1099300/whats-the-difference-between-getpath-getabsolutepath-and-getcanonicalpath 

[7] http://stackoverflow.com/questions/7016391/difference-between-system-load-and-system-loadlibrary-in-java


6、Android安全开发系列


目录

Android安全开发之Provider组件安全
Android安全开发之浅谈密钥硬编码

Android安全开发之浅谈网页打开APP

Android应用安全开发之浅谈加密算法的坑


作者:伊樵、呆狐、舟海@阿里聚安全,更多安全技术文章,请访问阿里聚安全博客

本页内容版权归属为原作者,如有侵犯您的权益,请通知我们删除。

浅谈Android中的MVP - 2016-06-24 17:06:24

转载请标明出处: http://blog.csdn.net/hai_qing_xu_kong/article/details/51745798 本文出自: 【顾林海的博客】 前言 为什么使用MVP,网上有很多说法,最主要就是减轻了Activity的责任,相比于MVC中的Activity承担的责任太多,因此有必要讲讲MVP。 MVP入门 在MVC框架中,View是可以直接读取Model模型中的数据的,Model模型数据发生改变是会通知View数据显示发生相应的改变。而在MVP中Model和View之间的没有
阅读此文前请先阅读 Retrofit+okhttp网络框架介绍 从上文中我们已经了解通过如下代码即可得到返回给我们call 以及 response对象,今天我们通过源码来分析这个过程是如何实现的。 /** * 获取天气数据 * @param cityname * @param key * @return */ @GET ( "/weather/index" ) CallWeatherData getWeatherData( @Query ( "format" ) String format, @Query
一、Block 的类型 根据 Block 在内存中的位置分 为三种类型 NSGlobalBlock , NSStackBlock, NSMallocBlock 。 NSGlobalBlock :类似函数,位于 text 段; NSStackBlock :位于 栈内存,函数返回后 Block 将无效; NSMallocBlock :位于堆内存。 二、Block 的 copy 、 retain 、 release 操作   不同于 NSObjec 的 copy 、 retain 、 release 操作: B
前言 module 怎能少得了动画呢~ 代码解读 weex code API 接口 transition (node, options, callback) Arguments 参数node(Node):将要动画的元素。options( object ):操作选项styles( object ):指定要应用的过渡效果的样式的名称和值。color( string ):色彩的元素时,animaiton完成。transform( object ):变换函数被应用到元素。支持下列值。translate/ tran
目录 概述 这是一个关于 RecycleView 滑动事件的辅助类,该辅助类可以检测 RecycleView 滑动到顶部或者底部的状态. 可用于实现 RecycleView 加载更多或者刷新(虽然刷新可以直接用 SwipeRefreshLayout ).也可用于某些滑动相关的需求,如 FloatingActionButton 的隐藏与显示之类的. 关于 RecycleView 的滑动监听 RecycleView 本身已经提供了滑动的监听接口, OnScrollListener ,这个接口包含了以下的方法.
这个小案例建议在手机上运行。 package com.example.camera;import java.io.File;import android.net.Uri;import android.os.Bundle;import android.os.Environment;import android.provider.MediaStore;import android.app.Activity;import android.content.Intent;import android.view.Me
简介 NSScanner是一个类,用于在字符串中扫描指定的字符,尤其是把它们翻译/转换为数字和别的字符串。可以在创建NSScaner时指定它的string属性,然后scanner会按照你的要求从头到尾地扫描这个字符串的每个字符。 NSScanner官方文档 NSScanner类是一个类簇的抽象父类,该类簇为一个从NSString对象扫描值的对象提供了程序接口。 NSScanner对象把NSString 对象的的字符解释和转化成 number和string 类型的值。在创建NSScanner对象的时候为它分
目录 概述 StickHeaderItemDecoration 是用于显示固定头部的item装饰类,扩展来自系统的 ItemDecoration .本文参考了一部分 sticky-headers-recyclerview 原理 绘制头部 固定头部的 ItemDecoration 本质是在 RecycleView 上覆盖一个界面.该界面没有随着滑动变动所以看起来就像一个固定的头部. 绘制item间隔 ItemDecoration 也可以实现每个item之间的间隔的绘制(比如分隔线之类的),这种情况下就不是在
android中网络请求回来数据之后,我们要对其解析。请求的返回的结果格式如果不是自定义协议;那么返回的数据通常是xml,json,html形式的数据了。 下面就是针对上面3种格式进行解析。 xml解析使用工具:在android中推荐使用pull解析,还有其他的dom,sax解析。 json解析使用工具:推荐使用Fastjson,由阿里提供。还有其他的如JackSon,Gson解析。 html解析使用工具:推荐使用Jsoup,还有其他的如HtmlParser;关于使用这个,网络上的爬虫就是这样子的。 1.
一个SpriteKit项目在其他设备上运行都无问题(无论是真机或是模拟器),但是在iPhone6 Plus上会出现精灵对象纹理被过度放大的现象: 从上图中大家可以看到无论是主角或是道具球都过大了. 看了一下精灵图片是放在atlas纹理集文件夹中的: 可以看到PowerUp和Player都有对应缩放的版本:Player.png,Player@2x.png以及Player@3x.png. 在各个图片的属性中检查图片的尺寸也都正确,看不出神马问题… 找到SKSpriteNode对象初始化的代码看看: let o