type
status
date
slug
summary
tags
category
icon
password
0x01 引言
这道题目利用的是
Parcel MisMatch进行漏洞利用,和直接在系统上通过AddAcount利用造成LaunchAnyWhere原理一样,但是有些细节还是不太一样,需要记录一下。0x02 题目分析
1. Parcel MisMatch 点
存在
Parcel MisMatch 问题的Parcelable 位于MainActivity类中,作为一个子类存在,这个点需要注意,因为如果是这种情况,在构造序列化数据时parcelable数据的数据类名应当为com.de1ta.broadcasttest.MainActivity$Message 而不能将$改为. 问题主要出在
this.rttSpread = in.readLong(); 和dest.writeInt((int) this.rttSpread); 类型不匹配,导致在两次序列化和两次反序列化过程中出现问题。2. 三个广播接收器
题目中有三个继承自
BroadcastReceiver 的接收器,其中只有MyReceiver1 是导出的,并且action为com.de1ta.receiver1 ,另外两个均为非导出,仅能构造恶意序列化数据,构成MyReceiver1.onReceive->MyReceiver2.onReceive->MyReceiver3.onReceive 的调用顺序,在MyReceiver2.onReceive 中绕过对command的检测,在MyReceiver3.onReceive 中使得command = getflag从而拿到flag。3. 两次序列化两次反序列化
这里需要格外注意题目中关于序列化和反序列化点的分析
- 第一次序列化是攻击者构造恶意
Bundle并且将其序列化的过程,实际上可以直接简化为构造parcel序列化数据的过程,构造完成后通过base64传入第一个广播接收器
- 第一次反序列化 是在
MyReceiver2中String command = bundle.getString("command");时进行的,而非在MyReceiver1的时进行bundle.readFromParcel(dest);,实际上在readFromParcel时仅仅将序列化数据放入Bundle实例的mParcelledData中,直到此时序列化数据并未被反序列化,而当getString时需要读取实际的数据而非序列化数据,所以才会取出mParcelledData中数据反序列化并且将反序列化结果(一个map数据结构)放入Bundle实例的mMap中。
- 第二次序列化 是在
MyReceiver2的sendBroadcast时进行,因为在MyReceiver2通过command校验后需要再次将数据广播,但是实际上在进程间传递的信息只能是序列化数据,所以此时需要进行序列化操作,将mMap中的数据再次进行序列化以进行信息传递。
- 第二次反序列化 是在
MyReceiver3的getString时进行,和第一次反序列化类似。
0x03 解题
关于这种漏洞的利用方法,之前已经写blog记录过了,详细的方法和细节请看之前的文章
Android反序列化漏洞-Bundle风水,因此在这里不再赘述,直接给出poc。原理就是第一次反序列化时会读取两个四字节Long,但是第二次序列化会写入一个四字节Int,第二次反序列化又会读取两个四字节Long,中间有四个字节的差,造成偏移后能够隐藏后面的数据。给出第一次反序列化时被攻击APP的视角,发现第二个键值对中隐藏了command,第三个键值对给了假的command绕过,第二个键值对通过字节数组类型绕过

给出第二次反序列化时被攻击APP的视角,发现第三个键值对中出现了
command = getflag,第四个键值对不再读取,因为mapSize = 3 ,和上面的图对比发现就是0xD8位置的07 00 00 00 被吞掉,造成解析偏移。
0x04 总结
其实关键点还是分析两次序列化两次反序列化的具体位置信息,分析出来然后配合着调试就很容易做。构造方法不止一种,可以自己尝试。
0x05 题目
官方在Github上传了题目原件和对应的Docker环境以及WP,有兴趣可以复现
- 作者:LLeaves
- 链接:https://lleavesg.top//article/De1CTF-2020-Pwn-BroadCastTest
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
相关文章








