安卓应用漏洞学习case8–CVE-2020-6828

安卓应用漏洞学习case8–CVE-2020-6828

前期回顾

漏洞免费实战部分-安卓应用层getLastPathSegment函数问题

漏洞实战部分2-安卓应用ZipEntry对象问题实战

漏洞实战部分3-ContentProvider组件的openFile接口问题

漏洞学习之PWN-easyheap分析

漏洞学习之PWN-HITCON_CTF_2016:Secret Holder

漏洞学习之PWN-绿城杯uaf_pwn 分析

漏洞学习之PWN-ASIS_CTF_2016_b00ks

漏洞学习之PWN-lctf2016:pwn200 堆利用

安卓应用漏洞学习-Content Provider组件的自定义权限

漏洞免费实战部分-安卓应用漏洞学习case5

漏洞免费实战部分-安卓应用漏洞学习case6

漏洞免费实战部分-安卓应用漏洞学习case7

安卓应用漏洞学习case8–CVE-2020-6828

CVE-2020-6828 Firefox Android 任意文件写漏洞,我们模拟学习这个漏洞原理。首先创建case8应用代替Firefox应用,case8需要能被外部调用,且为隐式调用。

为了方便区分,这里创建一个名为 MainActivity2的组件,要满足隐式调用和MIME需要增加intent-filter标签和data数据标签。如下:

image1

image1

Intent 的显式(explicitly)和隐式(implicitly)

显式:

在构造Intent对象时就指定接收者

Intent intent = new Intent(MainActivity.this,targetActivity.class);

startActivity(intent);

隐式:

在构造Intent对象时,不知道接收对象。这种有利于降低开发的耦合度。

Intent intent = new Intent();

intent.setAction(Intent.ACTION_VIEW);

intent.setPackage(“com.targetname”);

startActivity(intent);

隐式的匹配规则:

主要是查找已注册在AndroidManifest.xml 文件中所有的IntentFilter,来找到匹配的Intent。通过action、type、category三个属性标签判断。隐式调用至少有一个category(“android.intent.category.DEFAULT”),不然Intent的匹配就会失败,报错说找不到匹配的组件。

  • action的匹配

隐式调用必须设置action标签,调用者构造Intent时必须指定action变量,且值必须与被调用组件声明的一直。如:

<intent-filter>
<action android:name="android.intent.action.VIEW"/>
</intent-filter>

调用者:

Intent intent = new Intent();
intent.setAction("android.intent.action.VIEW");
startActivity(intent);

  • data的匹配

和action一样,只要Intent的data和目标组件在IntentFilter中声明data完全相同,则data匹配成功。

data有两部分:mimetype、URI

mimeType是指类型例如:image/jpeg,auto/*,text/html.等。可表图片、文本、媒体等格式。

URI是指协议和地址如:scheme、host、port、path、pathPattern、pathPrefix等组成。

<scheme>://<host>:<port>/[path|pathPattern|pathPrefix]

具体在xml中:

<intent-filter>
<data android:scheme="http"
android:host="case8"
android:port="xxxx"
android:path="xxxx"
android:pathPattern="xxxx"
android:pathPrefix="xxxx"
android:mimeType="text/html"
/>
</intent-filter>

  • category的匹配规则

这个特殊,构造Intent时不设置category的话,系统会默认带上”android.intent.category.DEFAULT”,它必须保证和过滤规则中的一个category相同。不强制要求Intent设置category。

配置好隐式调用后,MainActivity2组件实现接收外部传入的Intent,并将intent中的uri提取出来使用。模拟Firefox 的逻辑,Firefox使用接收的uri调用query获取文件名,代码如下:

image2

image2

查数据得到文件名后,没有判断文件是否包含”../“特殊符号,直接与contentUri目录拼接写入文件。

image3

image3

FileUtils.copy是读取uri指向的文件,写入到file2创建的新文件中。

image4

image4

File 对象本身不检查带特殊符号”../“的路径。

case8模拟这个逻辑,代码如下:

image5

image5

MainActivity2组件接收外部传入的Intent并取出uri,使用query读取uri指向的poc8提供的Content Provider组件。

image6

image6

这里会返回poc8提供的文件名,文件名可控能携带’../’特殊字符。没有做任何校验,直接返回与this.getCacheDir()拼接并创建文件,随后调用copy函数将uri指向的文件拷贝到新创建的文件中。

image8

image8

this.getContentResolver().openInputStream(uri)会调用poc8中的openFile重载函数,也可被控制。

poc8只需要实现query函数和openFile函数,即可对cae8沙箱内任意文件写入。

image9

image9

MatrixCursor 是一种虚表,父类继承Cursor 所以可以当返回值用。

image10

image10

image11

image11

image

image

openFile实现:

image13

image13

这里读取创建好的poc8.txt文件。文件是在poc8启动时创建,写入”hello poc8”字符串。创建路径为: “/storage/emulated/0/Android/data/com.test.poc8/cache/poc8.txt”

image14

image14

准备好所有调用函数之后,执行poc调用case8进行文件写入,poc代码:

image15

image15

添加包名、隐式启动需要action进行匹配,不设置category系统会默认增加”android.intent.category.DEFAULT”,addFlags增加临时读写权限,在Intent中要同时设置Data和Type属性就只能调用setDataAndType函数,如果是单独setData、setType会互相抵消。

image16

image16

image17

image17

完成所有代码后运行查看效果。

image18

image18

image19

image19

poc8执行之前当前case8沙箱内文件:

image20

image20

poc8执行之后当前case8沙箱内文件:

image21

image21

打破了安卓沙箱隔离机制,poc8的文件写入到了case8内,当然如果case8内有加载的插件,那么poc8提供插件覆盖这个case8的插件,重启case8应用执行加载这个插件就可以在case8中执行代码了。原漏洞CVE-2020-6828是覆写了profile.ini文件和增加user.js文件,profile.ini文件指向加载js的路径,poc修改为指向同目录下文件也就是user.js。user.js内部执行设置代理的逻辑,将所有流量转向攻击者提供的ip地址和端口。

CVE-2020-6828演示视频:

https://drive.google.com/open?id=1q6IQP8SCcpqtUTZ-Wb6z73Y8vWcFdLzM

CVE-2020-6828补丁修复也简单,在 query查询完之后,只获取文件名。:

--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/FileUtils.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/FileUtils.java
@@ -319,17 +319,17 @@ public class FileUtils {
try (Cursor metaCursor = cr.query(uri, projection, null, null, null);) {
if (metaCursor.moveToFirst()) {
fileName = metaCursor.getString(0);
}
} catch (Exception e) {
e.printStackTrace();
}

- return fileName;
+ return canonicalizeFilename(fileName);
}


 



 

 

关注微信公众号或者可以直接加作者微信:

 

 

 

 

posted @ 2023-02-06 20:10  syscallwww  阅读(80)  评论(0编辑  收藏  举报