Android Security Bulletin Index 2021

  • 由于本人水平有限,所以框架相关漏洞分析的会较详细,很多媒体和短距的漏洞,写的较为简略,有兴趣的读者可以自行阅读原始patch,还请理解。

2021-12-01 security patch level vulnerability details

Framework

CVE-2021-0955

  • MediaProvider中的FuseDaemon存在UAF漏洞,只影响Android 11。
    
     if (size < 0)
         fuse_reply_err(req, -size);
     else {
  • fuse_reply_write(req, size);
  • // Execute Record before fuse_reply_write to avoid the following ordering:
  • // fuse_reply_write -> pf_release (destroy handle) -> Record (use handle after free)
    fuse->fadviser.Record(h->fd, size);
  • fuse_reply_write(req, size);
    }
    }

  • 影响版本:11
  • 致谢信息:Mitch Phillips using GWP-ASan

CVE-2021-0970

  • GpsNavigationMessage的序列化错误
  • if (parcel.dataAvail() >= Integer.SIZE) {
  • int status = parcel.readInt();
  • navigationMessage.setStatus((short) status);
  • } else {
  • navigationMessage.setStatus(STATUS_UNKNOWN);
  • }
  • int status = parcel.readInt();
  • navigationMessage.setStatus((short) status);
  • API中的readInt会一路调用到Parcel.cpp中的readAligned

    // frameworks/native/libs/binder/Parcel.cpp
    template<class T>
    status_t Parcel::readAligned(T *pArg) const {
    static_assert(PAD_SIZE_UNSAFE(sizeof(T)) == sizeof(T));
    
    if ((mDataPos+sizeof(T)) <= mDataSize) {
        if (mObjectsSize > 0) {
            status_t err = validateReadData(mDataPos + sizeof(T));
            if(err != NO_ERROR) {
                // Still increment the data position by the expected length
                mDataPos += sizeof(T);
                return err;
            }
        }
    
        const void* data = mData+mDataPos;
        mDataPos += sizeof(T);
        *pArg =  *reinterpret_cast<const T*>(data);
        return NO_ERROR;
    } else {
        return NOT_ENOUGH_DATA;
    }
    }
  • 这是一个模板函数,当readInt的时候会传入int32_t作为模板类型,然后可以看到这个函数里面的validateReadData是可以保证不会出现读越界的。
  • GpsNavigationMessage中的代码本意也是做这个判断,担心dataAvail不够一个int的长度,然而判断用的是Integer.SIZE,这个值实际上是32。而dataAvail返回的是字节数(如果用Integer.BYTE可能还好点)。
    size_t Parcel::dataAvail() const
    {
    size_t result = dataSize() - dataPosition();
    if (result > INT32_MAX) {
        LOG_ALWAYS_FATAL("result too big: %zu", result);
    }
    return result;
    }
  • 所以这个操作不仅多此一举,而且还判断错了。补丁就是去掉没用的检查代码
  • 影响版本:9, 10, 11, 12
  • 致谢信息:MyTyrannosaurusBuddy

CVE-2021-0704

  • AccountManagerService中改了一下帐号请求通知(account request notification)的字符串,看起来是里面带上了请求权限的应用名字。
  • 影响版本:9, 10, 11
  • 致谢信息:Edward Cunningham of Google

Media Framework

CVE-2021-0967

  • external/tremolo中的漏洞,在Android 9上面可以远程利用。
  • 影响版本:9, 10, 11, 12
  • 致谢信息:无

CVE-2021-0964

  • C2SoftMp3Dec软解里面的数值计算问题,后续导致越界写入。
    
     mConfig->inputBufferCurrentLength = (inSize - inPos);
     mConfig->inputBufferMaxLength = 0;
     mConfig->inputBufferUsedLength = 0;
  • mConfig->outputFrameSize = (calOutSize – outSize);
  • mConfig->outputFrameSize = (calOutSize – outSize) / sizeof(int16_t);
    mConfig->pOutputBuffer = reinterpret_cast<int16_t *> (wView.data() + outSize);

  • 影响版本:9, 10, 11, 12
  • 致谢信息:无

System

CVE-2021-0968

  • 蓝牙组件内存分配器的问题,防止无符号的size高位为1,也就是整数溢出中将负数当作size_t传入osi_malloc或者osi_calloc来分配超大内存的情况,现在就不能再分配了。
    
    void* osi_malloc(size_t size) {
  • CHECK(static_cast<ssize_t>(size) >= 0);
    size_t real_size = allocation_tracker_resize_for_canary(size);
    void* ptr = malloc(real_size);
    CHECK(ptr);

    
    ```diff
    void* osi_calloc(size_t size) {</code></pre></li>
    <li>CHECK(static_cast<ssize_t>(size) >= 0);
    size_t real_size = allocation_tracker_resize_for_canary(size);
    void* ptr = calloc(1, real_size);
    CHECK(ptr);
    <pre><code></code></pre></li>
    <li>影响版本:9, 10, 11, 12</li>
    <li>致谢信息:Vijay Prakash and Ruian Duan, Palo Alto Networks Inc</li>
    </ul>
    <h4>CVE-2021-0956</h4>
    <ul>
    <li>NFC组件中的越界写
    <pre><code class="language-diff">
    if (mTechListTail < (MAX_NUM_TECHNOLOGY - 1)) {
     mNumTechList = mTechListTail;</code></pre></li>
    <li>} else {</li>
    <li>LOG(ERROR) << StringPrintf("%s: exceed max=%d", fn, MAX_NUM_TECHNOLOGY);</li>
    <li>android_errorWriteLog(0x534e4554, "189942532");</li>
    <li>goto TheEnd;
    }
    <pre><code></code></pre></li>
    <li>影响版本:11, 12   </li>
    <li>致谢信息:Nguyễn Hoàng Thạch (d4rkn3ss) of STAR Labs</li>
    </ul>
    <h4>CVE-2021-0953</h4>
    <ul>
    <li>QuickSearchBox组件中的SearchWidgetProvider存在不安全的PendingIntent。由于OEM的定制,这个漏洞可能不影响部分OEM的系统。
    <pre><code class="language-diff">
     private void setOnClickActivityIntent(Context context, RemoteViews views, int viewId,
             Intent intent) {</code></pre></li>
    <li>intent.setPackage(context.getPackageName());
    PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
    views.setOnClickPendingIntent(viewId, pendingIntent);
    }
    <pre><code></code></pre></li>
    <li>影响版本:9, 10, 11, 12</li>
    <li>致谢信息:无</li>
    </ul>
    <h4>CVE-2021-0954</h4>
    <ul>
    <li>com.android.internal.app.ResolverActivity的点击劫持问题,添加SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS标志。</li>
    <li>影响版本:10, 11</li>
    <li>致谢信息:无</li>
    </ul>
    <h4>CVE-2021-0963</h4>
    <ul>
    <li>com.android.keychain.KeyChainActivity的点击劫持问题,添加SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS标志并使用setFilterTouchesWhenObscured(true)。</li>
    <li>影响版本:9, 10, 11, 12</li>
    <li>致谢信息:Tianyi Hu (胡天易) of Bytedance Wuheng Lab</li>
    </ul>
    <h4>CVE-2021-0965</h4>
    <ul>
    <li>防止恶意应用调用com.android.settings.bluetooth.BluetoothPairingDialog来伪造蓝牙配对窗口,添加android.permission.BLUETOOTH_PRIVILEGED权限来保护。</li>
    <li>影响版本:9, 10, 11, 12</li>
    <li>致谢信息:Yu-Cheng Lin (林禹成) (@AndroBugs)</li>
    </ul>
    <h4>CVE-2021-0952</h4>
    <ul>
    <li>通讯录应用选联系人头像并编辑的AttachPhotoActivity,限制只调用系统应用来进行联系人头像编辑,防止第三方应用在没有权限的情况下从Intent中读取到通讯录。由于OEM的定制,这个漏洞可能不影响部分OEM的系统。
    <pre><code class="language-java">private ResolveInfo getIntentHandler(Intent intent) {
    final List<ResolveInfo> resolveInfos = getPackageManager()
            .queryIntentActivities(intent,
                    PackageManager.MATCH_DEFAULT_ONLY | PackageManager.MATCH_SYSTEM_ONLY);
    return (resolveInfos != null && resolveInfos.size() > 0) ? resolveInfos.get(0) : null;
    }</code></pre></li>
    <li>影响版本:9, 10, 11, 12</li>
    <li>致谢信息:Sithija</li>
    </ul>
    <h4>CVE-2021-0966</h4>
    <ul>
    <li>在编译AIDL文件的时候,如果enum没有默认值,则用0进行填充。</li>
    <li>影响版本:11, 12</li>
    <li>致谢信息:Jann Horn of Google Project Zero</li>
    </ul>
    <h4>CVE-2021-0958</h4>
    <ul>
    <li>KeyStore 2.0中km_compat的问题,TBD。<code>https://android.googlesource.com/platform/system/security/+/b7f303146fecc166260aced8de677dfc7322f7a3</code></li>
    <li>影响版本:11, 12</li>
    <li>致谢信息:无</li>
    </ul>
    <h4>CVE-2021-0969</h4>
    <ul>
    <li>AP名称为空会导致NPE
    <pre><code class="language-diff">
    public String getTitle() {</code></pre></li>
    <li>if (isPasspoint()) {</li>
    <li>if (isPasspoint() && !TextUtils.isEmpty(mConfig.providerFriendlyName)) {
    return mConfig.providerFriendlyName;</li>
    <li>} else if (isPasspointConfig()) {</li>
    <li>} else if (isPasspointConfig() && !TextUtils.isEmpty(mProviderFriendlyName)) {
    return mProviderFriendlyName;</li>
    <li>} else if (isOsuProvider()) {</li>
    <li>} else if (isOsuProvider() && !TextUtils.isEmpty(mOsuProvider.getFriendlyName())) {
    return mOsuProvider.getFriendlyName();</li>
    <li>} else {</li>
    <li>} else if (!TextUtils.isEmpty(getSsidStr())) {
    return getSsidStr();</li>
    <li>} else {</li>
    <li>return "";
    }
    }
    <pre><code></code></pre></li>
    <li>影响版本:10, 11</li>
    <li>致谢信息:无</li>
    </ul>
    <h2>2021-12-05 security patch level vulnerability details</h2>
    <h2>2021-11-01 security patch level vulnerability details</h2>
    <h3>Framework</h3>
    <h4>CVE-2021-0799</h4>
    <ul>
    <li>在ActivityThread中,使用ArrayMap来管理ProviderKey,而不是使用SparseArray,因为ArrayMap可以更好的处理Hash碰撞场景。ActivityThread是位于应用进程中,不太清楚这个漏洞的具体利用场景。</li>
    <li>影响版本:12</li>
    <li>致谢信息:Makoto Onuki of Google</li>
    </ul>
    <h4>CVE-2021-0921</h4>
    <ul>
    <li>
    <p>跨进程传递ParsingPackage的时候,传递复杂对象,先写入长度再写入内容,这里传递的是一个<code>Map<String, ArraySet<PublicKey>></code>嵌套类型</p>
    <pre><code class="language-java">
    /**
    * Writes the keyset mapping to the provided package. {@code null} mappings are permitted.
    */
    public static void writeKeySetMapping(@NonNull Parcel dest,
        @NonNull Map<String, ArraySet<PublicKey>> keySetMapping) {
    if (keySetMapping == null) {
        dest.writeInt(-1);
        return;
    }
    
    final int N = keySetMapping.size();
    dest.writeInt(N);
    
    for (String key : keySetMapping.keySet()) {
        dest.writeString(key);
        ArraySet<PublicKey> keys = keySetMapping.get(key);
        if (keys == null) {
            dest.writeInt(-1);
            continue;
        }
    
        final int M = keys.size();
        dest.writeInt(M);
        for (int j = 0; j < M; j++) {
            dest.writeSerializable(keys.valueAt(j));
        }
    }
    }</code></pre>
    </li>
    </ul>
    <p>/**</p>
    <ul>
    <li>Reads a keyset mapping from the given parcel at the given data position. May return</li>
    <li>
    <p>{@code null} if the serialized mapping was {@code null}.
    */
    @NonNull
    public static ArrayMap<String, ArraySet<PublicKey>> readKeySetMapping(@NonNull Parcel in) {
    final int N = in.readInt();
    if (N == -1) {
    return null;
    }</p>
    <p>ArrayMap<String, ArraySet<PublicKey>> keySetMapping = new ArrayMap<>();
    for (int i = 0; i < N; ++i) {
    String key = in.readString();
    final int M = in.readInt();
    if (M == -1) {
    keySetMapping.put(key, null);
    continue;
    }</p>
    <pre><code>ArraySet<PublicKey> keys = new ArraySet<>(M);
    for (int j = 0; j < M; ++j) {
        PublicKey pk = (PublicKey) in.readSerializable();
        keys.add(pk);
    }
    
    keySetMapping.put(key, keys);</code></pre>
    <p>}</p>
    <p>return keySetMapping;
    }</p>
    <pre><code>
    - 影响版本:11
    - 致谢信息:Zinuo Han (weibo.com/ele7enxxh) of Amber Security Lab, OPPO Mobile Telecommunications Corp. Ltd.</code></pre>
    </li>
    </ul>
    <h4>CVE-2021-0923</h4>
    <ul>
    <li>当Internal类型的权限所有者变更时,收回权限
    <pre><code class="language-diff"></code></pre></li>
    <li>if (permission.isRuntime() && (ownerChanged || wasNonRuntime)) {</li>
    <li>// If this is a runtime permission and the owner has changed, or this wasn't a runtime</li>
    <li>// permission, then permission state should be cleaned up</li>
    <li>if ((permission.isInternal() && ownerChanged)</li>
    <li>|| (permission.isRuntime() && (ownerChanged || wasNonRuntime))) {</li>
    <li>// If this is an internal/runtime permission and the owner has changed, or this wasn't a</li>
    <li>// runtime permission, then permission state should be cleaned up.
    permission.mDefinitionChanged = true;
    }
    <pre><code></code></pre></li>
    <li>ownerChanged的条件是,系统应用重新定义了非系统权限的时候,这种场景应该非常少,可能是一个非系统应用在OTA升级之后变成了系统应用
    <pre><code class="language-java">@NonNull
    public static Permission createOrUpdate(@Nullable Permission permission,
        @NonNull PermissionInfo permissionInfo, @NonNull AndroidPackage pkg,
        @NonNull Collection<Permission> permissionTrees, boolean isOverridingSystemPermission) {
    // Allow system apps to redefine non-system permissions
    boolean ownerChanged = false;
    if (permission != null && !Objects.equals(permission.mPermissionInfo.packageName,
            permissionInfo.packageName)) {
        if (pkg.isSystem()) {
            if (permission.mType == Permission.TYPE_CONFIG && !permission.mReconciled) {
                // It's a built-in permission and no owner, take ownership now
                permissionInfo.flags |= PermissionInfo.FLAG_INSTALLED;
                permission.mPermissionInfo = permissionInfo;
                permission.mReconciled = true;
                permission.mUid = pkg.getUid();
            } else if (!isOverridingSystemPermission) {
                Slog.w(TAG, "New decl " + pkg + " of permission  "
                        + permissionInfo.name + " is system; overriding "
                        + permission.mPermissionInfo.packageName);
                ownerChanged = true;
                permission = null;
            }
        }
    }
    //...
    }</code></pre></li>
    <li>影响版本:12</li>
    <li>致谢信息:Xianlin Wu(吴宪林) of OPPO Amber Security Lab</li>
    </ul>
    <h4>CVE-2021-0926</h4>
    <ul>
    <li>限制第三方应用调用NfcImportVCardActivity,增加android.permission.DISPATCH_NFC_MESSAGE权限管控</li>
    <li>影响版本:9, 10, 11, 12</li>
    <li>致谢信息:Yu-Cheng Lin (林禹成) (@AndroBugs)</li>
    </ul>
    <h4>CVE-2021-0933</h4>
    <ul>
    <li>CompanionDeviceActivity中潜在的XSS问题,使用<code>Html.escapeHtml</code>对显示名称进行过滤。</li>
    <li>影响版本:9, 10, 11, 12</li>
    <li>致谢信息:无</li>
    </ul>
    <h4>CVE-2020-13871</h4>
    <ul>
    <li>sqlite漏洞 CVE-2020-15358 and CVE-2020-13871修复</li>
    <li>影响版本:11</li>
    <li>致谢信息:无</li>
    </ul>
    <h4>CVE-2021-0653</h4>
    <ul>
    <li>NetworkPolicyManagerService中的<code>com.android.server.net.action.SNOOZE_WARNING</code>广播增加接收者,防止第三方应用收到该广播</li>
    <li>影响版本:9, 10, 11</li>
    <li>致谢信息:Yu-Cheng Lin (林禹成) (@AndroBugs)</li>
    </ul>
    <h4>CVE-2021-0922</h4>
    <ul>
    <li>INTERACT_ACROSS_PROFILE这个appop是授予给了package,但是如果有两个packages使用了shareUserId的话,允许只有一个package有此权限,此时enforceCrossUserOrProfilePermission接口校验会出现问题,因为其底层调用的是getPackagesForUid接口,但是对于shareUserId的场景,会返回随机的一个package,因为有多个package对应同一个uid。解决方案是将这个appop授予给一个uid,而不是package,因为Android应用沙箱本质上是保护的uid,而不是package。</li>
    <li>影响版本:11</li>
    <li>致谢信息:Khouloud Mansouri of Google</li>
    </ul>
    <h3>Media Framework</h3>
    <h4>CVE-2021-0928</h4>
    <ul>
    <li>在向Android Camera 2接口传递OutputConfiguration等对象时存在不正确的异常捕获,会导致返回空对象</li>
    <li>共有四个对象存在此问题
    <ul>
    <li>OutputConfiguration</li>
    <li>VendorTagDescriptor</li>
    <li>VendorTagDescriptorCache</li>
    <li>SessionConfiguration</li>
    </ul></li>
    <li>影响版本:9, 10, 11</li>
    <li>致谢信息:Michał Bednarski (michalbednarski)</li>
    </ul>
    <h4>CVE-2021-0650</h4>
    <ul>
    <li>sonivox组件的WT_InterpolateNoLoop中存在越界读</li>
    <li>影响版本:9, 10, 11</li>
    <li>致谢信息:无</li>
    </ul>
    <h3>System</h3>
    <h4>CVE-2021-0918</h4>
    <ul>
    <li>GATT远程代码执行漏洞</li>
    <li>影响版本:12</li>
    <li>致谢信息:Xianfeng Lu(卢先锋) and Lei Ai(艾磊) of OPPO Amber Security Lab</li>
    </ul>
    <h4>CVE-2021-0930</h4>
    <ul>
    <li>NFC的pn8x实现中,phNxpNciHal_process_ext_rsp函数存在越界写入
    <pre><code class="language-diff"></code></pre></li>
    <li>if (*p_len <= (p_ntf[2] + 2)) {</li>
    <li>android_errorWriteLog(0x534e4554, "181660091");</li>
    <li>NXPLOG_NCIHAL_E("length error!");</li>
    <li>return NFCSTATUS_FAILED;</li>
    <li>}
    <pre><code></code></pre></li>
    <li>影响版本:9, 10, 11, 12</li>
    <li>致谢信息:Chaoyuan Peng (@ret2happy)</li>
    </ul>
    <h4>CVE-2021-0434</h4>
    <ul>
    <li>更改了蓝牙权限授予中不清晰的警告文本,防止钓鱼欺骗</li>
    <li>影响版本:9, 10, 11</li>
    <li>致谢信息:Christophe Devine, ANSSI</li>
    </ul>
    <h4>CVE-2021-0649</h4>
    <ul>
    <li>VpnManagerService中的stopVpnProfile() & startVpnProfile函数,没有对调用者进行校验,导致可以关闭其他应用开启的VPN。
    <pre><code class="language-diff">
    @Override
    public void startVpnProfile(@NonNull String packageName) {</code></pre></li>
    <li>final int user = UserHandle.getUserId(mDeps.getCallingUid());</li>
    <li>final int callingUid = Binder.getCallingUid();</li>
    <li>verifyCallingUidAndPackage(packageName, callingUid);</li>
    <li>final int user = UserHandle.getUserId(callingUid);
    synchronized (mVpns) {
    throwIfLockdownEnabled();
    mVpns.get(user).startVpnProfile(packageName);
    //...
    @Override
    public void stopVpnProfile(@NonNull String packageName) {</li>
    <li>final int user = UserHandle.getUserId(mDeps.getCallingUid());</li>
    <li>final int callingUid = Binder.getCallingUid();</li>
    <li>verifyCallingUidAndPackage(packageName, callingUid);</li>
    <li>final int user = UserHandle.getUserId(callingUid);
    synchronized (mVpns) {
    mVpns.get(user).stopVpnProfile(packageName);
    }
    //...
    <pre><code></code></pre></li>
    <li>影响版本:11</li>
    <li>致谢信息:Aman Pandey of bugsmirror</li>
    </ul>
    <h4>CVE-2021-0932</h4>
    <ul>
    <li>SystemUI中的NavigationModeController存在不安全的PendingIntent
    <pre><code class="language-diff">
                       .setStyle(new Notification.BigTextStyle())
                       .setSmallIcon(R.drawable.ic_info)
                       .setAutoCancel(true)</code></pre></li>
    <li>.setContentIntent(PendingIntent.getActivity(context, 0, new Intent(), 0));</li>
    <li>.setContentIntent(PendingIntent.getActivity(context, 0, new Intent(),</li>
    <li>PendingIntent.FLAG_IMMUTABLE));
    context.getSystemService(NotificationManager.class).notify(TAG, 0, builder.build());
    }
    <pre><code></code></pre></li>
    <li>影响版本:10</li>
    <li>致谢信息:Yu-Cheng Lin (林禹成) (@AndroBugs)</li>
    </ul>
    <h4>CVE-2021-0925</h4>
    <ul>
    <li>NFC t4t中cc_file_rsp_len初始化时被赋值为0,实际应该是T4T_CC_FILE_MIN_LEN,应该是会导致越界读。</li>
    <li>影响版本:12</li>
    <li>致谢信息:Android Security Red Team</li>
    </ul>
    <h4>CVE-2021-0931</h4>
    <ul>
    <li>BluetoothDevice中获取远端设备别名时过滤换行符,防止文本折断。</li>
    <li>影响版本:9, 10, 11, 12</li>
    <li>致谢信息:无</li>
    </ul>
    <h4>CVE-2021-0919</h4>
    <ul>
    <li>libbinder中uptimeMillis的精度丢失,应为int64_t,该问题会导致设备正常时间约为1个月,不是很清楚会导致什么。</li>
    <li>影响版本:9, 10, 11</li>
    <li>致谢信息:无</li>
    </ul>
    <h2>2021-11-05 security patch level vulnerability details</h2>
    <h3>Android TV</h3>
    <h4>CVE-2021-0889</h4>
    <ul>
    <li>该漏洞允许远程攻击者静默配对一个电视并且实现远程代码执行,漏洞代码补丁还没有发布。</li>
    </ul>
    <h4>CVE-2021-0927</h4>
    <ul>
    <li>TvInputManagerService中的requestChannelBrowsable函数,在<code>Binder.clearCallingIdentity()</code>之后调用了<code>Binder.getCallingUid()</code>,导致权限绕过</li>
    </ul>
    <h2>2021-10-01 security patch level vulnerability details</h2>
    <h3>Android runtime</h3>
    <h4>CVE-2021-0703</h4>
    <h3>Framework</h3>
    <h4>CVE-2021-0652</h4>
    <ul>
    <li>VectorDrawable中的条件竞争问题</li>
    </ul>
    <h4>CVE-2021-0705</h4>
    <ul>
    <li>利用通知实现后台限制绕过,细节待分析</li>
    </ul>
    <h4>CVE-2021-0708</h4>
    <ul>
    <li>同上个月公告的CVE-2021-0683,不知道为何又放了一遍</li>
    </ul>
    <h4>CVE-2020-15358</h4>
    <ul>
    <li>sqlite的两个漏洞CVE-2020-15358和CVE-2020-13871</li>
    </ul>
    <h4>CVE-2021-0702</h4>
    <h4>CVE-2021-0651</h4>
    <h3>Media Framework</h3>
    <h4>CVE-2021-0483</h4>
    <h3>System</h3>
    <h4>CVE-2021-0643</h4>
    <ul>
    <li>SubscriptionManager.getAllActiveSubscriptionInfoList接口会泄露ICCID</li>
    </ul>
    <h4>CVE-2021-0706</h4>
    <ul>
    <li>SystemUI中的DISABLE_PLUGIN动态广播接收器添加权限
    <pre><code class="language-diff">
     filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
     filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
     filter.addAction(Intent.ACTION_PACKAGE_REMOVED);</code></pre></li>
    <li>filter.addDataScheme("package");</li>
    <li>mContext.registerReceiver(this, filter);
    filter.addAction(PLUGIN_CHANGED);
    filter.addAction(DISABLE_PLUGIN);
    filter.addDataScheme("package");</li>
    <li>mContext.registerReceiver(this, filter, PluginInstanceManager.PLUGIN_PERMISSION, null);
    mContext.registerReceiver(this, filter);
    filter = new IntentFilter(Intent.ACTION_USER_UNLOCKED);
    mContext.registerReceiver(this, filter);
    <pre><code></code></pre></li>
    </ul>
    <h2>2021-10-05 security patch level vulnerability details</h2>
    <h3>System</h3>
    <h4>CVE-2021-0870</h4>
    <h2>2021-09-01 security patch level vulnerability details</h2>
    <h3>Framework</h3>
    <h4>CVE-2021-0687</h4>
    <ul>
    <li>Layout导致的远程拒绝服务漏洞,具体细节仍在调查中(与发现者交流)</li>
    </ul>
    <h4>CVE-2021-0595</h4>
    <h4>CVE-2021-0683</h4>
    <ul>
    <li>am命令的dumpheap功能存在任意文件删除漏洞,会以system_server的身份删除攻击者指定文件名的文件
    <pre><code class="language-java">int runTraceIpcStop(PrintWriter pw) throws RemoteException {
    final PrintWriter err = getErrPrintWriter();
    String opt;
    String filename = null;
    while ((opt=getNextOption()) != null) {
        if (opt.equals("--dump-file")) {
            filename = getNextArgRequired();
        } else {
            err.println("Error: Unknown option: " + opt);
            return -1;
        }
    }
    if (filename == null) {
        err.println("Error: Specify filename to dump logs to.");
        return -1;
    }
    File file = new File(filename);
    file.delete();
    //...
    }</code></pre></li>
    </ul>
    <h4>CVE-2021-0684</h4>
    <h4>CVE-2021-0685</h4>
    <ul>
    <li>移除了ParsedIntentInfo的Parcelable Creator,避免在Parcel传递数组时的size不匹配导致的错误。</li>
    </ul>
    <h4>CVE-2021-0688</h4>
    <ul>
    <li>锁定屏幕的lockNow和updateLockscreenTimeout存在条件竞争,可能导致在lockNow执行后未立即锁屏,而是锁屏超时时间被updateLockscreenTimeout的结果覆盖。</li>
    </ul>
    <h4>CVE-2021-0686</h4>
    <ul>
    <li>getDefaultSmsPackage接口添加跨用户检查。</li>
    </ul>
    <h3>Media Framework</h3>
    <h4>CVE-2021-0689</h4>
    <h4>CVE-2021-0690</h4>
    <h3>System</h3>
    <h4>CVE-2021-0598</h4>
    <ul>
    <li>NFC的确认连接界面ConfirmConnectActivity增加SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS标志</li>
    </ul>
    <h4>CVE-2021-0692</h4>
    <ul>
    <li>对FirstScreenBroadcast的PendingIntent设置FLAG_IMMUTABLE标志</li>
    </ul>
    <h4>CVE-2021-0428</h4>
    <ul>
    <li>SubscriptionController和SubscriptionInfo中多个接口存在标识符泄露漏洞,包括以下接口:
    <ul>
    <li>SubscriptionInfo.getCardString</li>
    <li>SubscriptionInfo.getIccId</li>
    <li>SubscriptionController.getSubscriptionInfoListFromCacheHelper</li>
    </ul></li>
    </ul>
    <h4>CVE-2021-0644</h4>
    <ul>
    <li>SubscriptionInfo的mGroupUUID字段可被仅有READ_PHONE_STATE权限的应用用于不可重置的标识符,要求具有READ_DEVICE_IDENTIFIERS的权限才能访问此字段。</li>
    </ul>
    <h4>CVE-2021-0682</h4>
    <h4>CVE-2021-0693</h4>
    <ul>
    <li>Shell应用(com.android.shell)的HeapDumpProvider对外暴露,会导致在开发者选项中点击“收集堆转储信息”后,被第三方应用直接读取到dump文件。
    <pre><code class="language-diff">
         <provider android:name=".HeapDumpProvider"
                   android:authorities="com.android.shell.heapdump"
                   android:grantUriPermissions="true"</code></pre></li>
    <li>android:exported="true" /></li>
    <li>android:exported="false" />
    <pre><code></code></pre></li>
    </ul>
    <h4>CVE-2021-0691</h4>
    <ul>
    <li>在Android 11的SEPolicy中错误地允许了system_app标签写入apk_data_file标签文件,这将导致本地文件写入转化为代码执行,通过写入<code>/data/app</code>中某应用的<code>base.apk</code>或者<code>lib64</code>下的动态库文件可实现。
    <pre><code class="language-diff">
    # Settings need to access app name and icon from asec
    allow system_app asec_apk_file:file r_file_perms;</code></pre></li>
    </ul>
    <h2>-# Allow system_app (adb data loader) to write data to /data/incremental
    -allow system_app apk_data_file:file write;</h2>
    <h2>-# Allow system app (adb data loader) to read logs
    -allow system_app incremental_control_file:file r_file_perms;</h2>
    <h1>Allow system apps (like Settings) to interact with statsd</h1>
    <p>binder_call(system_app, statsd)</p>
    <pre><code>
    ## 2021-08-01 security patch level vulnerability details
    ### Framework
    #### CVE-2021-0640
    - statsd中noteAtomLogged函数,atomId参数可以传入负值,导致整数溢出以及越界写
    ```diff
     void StatsdStats::noteAtomLogged(int atomId, int32_t timeSec) {
         lock_guard<std::mutex> lock(mLock);
    
    -    if (atomId <= kMaxPushedAtomId) {
    +    if (atomId >= 0 && atomId <= kMaxPushedAtomId) {
             mPushedAtomStats[atomId]++;
         } else {
    +        if (atomId < 0) {
    +            android_errorWriteLog(0x534e4554, "187957589");
    +        }
             if (mNonPlatformPushedAtomStats.size() < kMaxNonPlatformPushedAtoms) {
                 mNonPlatformPushedAtomStats[atomId]++;
             }

    CVE-2021-0645

    • 对于ExternalStorageProvider,不允许访问/sdcard/Android中的文件。

    CVE-2021-0646

    • sqlite中使用精度大于2147483647的浮点数会导致缓冲区溢出,通过编译时限制浮点数最大精度为100000000来解决。测试代码:
      select (printf('%.2147483647G',0.01));

    Media Framework

    CVE-2021-0519

    System

    CVE-2021-0591

    • 在系统设置中,BluetoothPermissionActivity是一个导出组件,接受用户传入的Intent并发送广播,而Intent中可以指定广播的接收者,从而实现以system uid发送广播给任意未导出的或带有权限的广播接收器,但攻击者无法决定其他参数。
      // packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothPermissionActivity.java
      mReturnPackage = i.getStringExtra(BluetoothDevice.EXTRA_PACKAGE_NAME);
      mReturnClass = i.getStringExtra(BluetoothDevice.EXTRA_CLASS_NAME);
      //...
      if (mReturnPackage != null && mReturnClass != null) {
      intent.setClassName(mReturnPackage, mReturnClass);
      }
      //...
      sendBroadcast(intent, android.Manifest.permission.BLUETOOTH_ADMIN);
    • 利用此漏洞可实现越权恢复出厂设置,只需要将组件指定为:
      android/com.android.server.MasterClearReceiver

    CVE-2021-0593

    • 在系统设置中,DevicePickerFragment是导出组件DevicePickerActivity的一部分,接受了用户传入给DevicePickerActivity的Intent,并发送广播,同样地Intent中可以指定广播的接收者,从而实现system uid发送广播给任意未导出的或带有权限的广播接收器,但攻击者无法决定其他参数。
      // packages/apps/Settings/src/com/android/settings/bluetooth/DevicePickerFragment.java
      mLaunchPackage = intent.getStringExtra(BluetoothDevicePicker.EXTRA_LAUNCH_PACKAGE);
      mLaunchClass = intent.getStringExtra(BluetoothDevicePicker.EXTRA_LAUNCH_CLASS);
      //...
      if (mLaunchPackage != null && mLaunchClass != null) {
      intent.setClassName(mLaunchPackage, mLaunchClass);
      }
      getActivity().sendBroadcast(intent, Manifest.permission.BLUETOOTH_ADMIN);
    • 利用此漏洞可实现越权恢复出厂设置,只需要将组件指定为:
      android/com.android.server.MasterClearReceiver

    CVE-2021-0584

    • Parcel内存布局的一个问题,比较复杂需要些时间去研究,原始内容:
      
      verify embedded buffer matches address in parent

    Below is a diagram showing what scatter gather would look like where we
    have one reference to a buffer, and then we have a single embedded
    buffer. For instance, 'a1' might be the hidl_vec object and 'a2' might
    be the data pointer in this object. In practice, there might be
    arbitrarily many levels (this happens when structures contain vectors
    which contain structures etc…).

    legend:
    "…." – random data we don't care about
    "|" – some position in the data
    "<a#>" – some constant address

    offsets into Parcel's mData:
    …..
    ….<a1>…. ….. ….<a2>…. …..
    ^ ^ ^ ^
    – 'buffer' field of structure
    (binder object structure)
    – mObjects[child]
    – binder object structure 'buffer' field
         \- mObjects[parent] (binder object structure)
    
    kernel-owned ro buffer @ address a1 ('parent' buffer)
      .......<a3>....................
             ^
             \- parent buffer as address + parent offset
                (in the example, this would be the data field
                 of hidl_vec. This should be a2).
    
    kernel-owned ro buffer @ address a2 ('child' buffer)
      ............................
             (any random data)

    What was happening here was that by maliciously constructing
    mObjects[child] to be null, there would be no child object, so the
    kernel wouldn't know to fixup the embedded buffer (<a3>) and it
    would be unchanged.

    
    #### CVE-2021-0641
    - getAvailableSubscriptionInfoList接口仍旧使用READ_PHONE_STATE权限保护,存在问题,应改为由READ_PRIVILEGED_PHONE_STATE特许权限保护。
    
    #### CVE-2021-0642
    - 为CONFIGURE_VOICEMAIL这个intent-filter提高优先级,设为1000。
    
    ## 2021-08-05 security patch level vulnerability
    
    ## 2021-07-01 security patch level vulnerability details
    ### Framework
    #### CVE-2021-0441
    - 允许MediaProvier权限弹框显示超过两行的文本。
    
    #### CVE-2021-0486
    - 当应用降级到API 28以下或者在API 29中申请完全存储权限时(回退场景),撤销已授予的存储权限。
    - 因为在Scoped Storage的模式下,已授予的存储权限只限于媒体目录的访问,这时在回退场景之后如果存储权限保留,会导致应用直接可以访问全部外部存储,修改后需要用户重新进行授权。
    - Scoped Storage:[https://source.android.google.cn/devices/storage/scoped](https://source.android.google.cn/devices/storage/scoped)
    
    ### Media Framework
    #### CVE-2021-0587
    #### CVE-2021-0601
    
    ### System
    #### CVE-2020-0417
    - GpsNetIniticatedHandler的Notification中写入了不必要的PendingIntent,且PendingIntent没有指定包名,会导致经典PendingIntent劫持攻击。
    
    #### CVE-2021-0585
    - 检查libfmq中,对MessageQueue进行读写操作时,长度是否对齐
    ```diff
         auto writePtr = mWritePtr->load(std::memory_order_relaxed);
    +    if (writePtr % sizeof(T) != 0) {
    +        hardware::details::logError(
    +                "The write pointer has become misaligned. Writing to the queue is no longer "
    +                "possible.");
    +        return false;
    +    }
         size_t writeOffset = writePtr % mDesc->getSize();</code></pre>
    <pre><code class="language-diff">     auto readPtr = mReadPtr->load(std::memory_order_relaxed);
    +    if (writePtr % sizeof(T) != 0 || readPtr % sizeof(T) != 0) {
    +        hardware::details::logError(
    +                "The write or read pointer has become misaligned. Reading from the queue is no "
    +                "longer possible.");
    +        return false;
    +    }
    
         if (writePtr - readPtr > mDesc->getSize()) {
             mReadPtr->store(writePtr, std::memory_order_release);</code></pre>
    <h4>CVE-2021-0586</h4>
    <ul>
    <li>为蓝牙设备选择界面DevicePickerActivity添加SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS,防止悬浮窗覆盖。</li>
    </ul>
    <h4>CVE-2021-0589</h4>
    <ul>
    <li>蓝牙btm_acl中的数组越界写入,这个问题是从本地触发的。
    <pre><code class="language-diff">
    bool BTM_TryAllocateSCN(uint8_t scn) {
    /* Make sure we don't exceed max port range.
    * Stack reserves scn 1 for HFP, HSP we still do the correct way.
    */</code></pre></li>
    <li>if ((scn >= BTM_MAX_SCN) || (scn == 1)) return false;</li>
    <li>if ((scn >= BTM_MAX_SCN) || (scn == 1) || (scn == 0)) return false;
    /<em> check if this port is available </em>/
    if (!btm_cb.btm_scn[scn - 1]) {
    btm_cb.btm_scn[scn - 1] = true;
    return true;
    }
    return (false); /<em> Port was busy </em>/
    }
    <pre><code>
    ```diff
    bool BTM_FreeSCN(uint8_t scn) {
    BTM_TRACE_DEBUG("BTM_FreeSCN ");
  • if (scn <= BTM_MAX_SCN) {
  • if (scn <= BTM_MAX_SCN && scn > 0) {
    btm_cb.btm_scn[scn – 1] = false;
    return (true);
    } else {
    return (false); / Illegal SCN passed in /
    }
    }

    
    #### CVE-2021-0594
  • NFC确认连接的界面,处理NDFF消息中的蓝牙设备名称字段存在CRLF注入,导致对话框文本换行,使用户无法准确看到蓝牙设备名称。
  • String btExtraName = launchIntent.getStringExtra(BluetoothDevice.EXTRA_NAME);
    String confirmString = String.format(res.getString(R.string.confirm_pairing),
  • launchIntent.getStringExtra(BluetoothDevice.EXTRA_NAME));
  • "\"" + btExtraName.replaceAll("\r|\n", "") + "\"");

CVE-2021-0600

  • 设备管理员请求界面存在HTML注入,导致界面显示异常。
  • mAddMsgText = getIntent().getCharSequenceExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION);
  • final CharSequence addMsgCharSequence = getIntent().getCharSequenceExtra(
  • DevicePolicyManager.EXTRA_ADD_EXPLANATION);
  • if (addMsgCharSequence != null) {
  • mAddMsgText = addMsgCharSequence.toString();
  • }

CVE-2021-0602

  • 在访客模式下,不允许编辑Wi-Fi详细设置,而是显示一个阻止的页面。

CVE-2021-0588

  • 发送蓝牙MAP客户端消息广播时,要求接收者必须有RECEIVE_SMS权限,并且如果有默认的短信应用,则仅发给默认短信应用。
  • mService.sendBroadcast(intent);
  • // Only send to the current default SMS app if one exists
  • String defaultMessagingPackage = Telephony.Sms.getDefaultSmsPackage(mService);
  • if (defaultMessagingPackage != null) {
  • intent.setPackage(defaultMessagingPackage);
  • }
  • mService.sendBroadcast(intent, android.Manifest.permission.RECEIVE_SMS);

CVE-2021-0590

  • 移除了android.net.conn.NETWORK_CONDITIONS_MEASURED广播,防止预置应用可获取到SSID和BSSID。

CVE-2021-0596

  • phNciNfc_RecvMfResp中的越界读取
  • if (2 > RspBuffInfo->wLen) {
  • android_errorWriteLog(0x534e4554, "181346550");
  • return NFCSTATUS_FAILED;
  • }
    uint8_t rspAck = RspBuffInfo->pBuff[RspBuffInfo->wLen – 2];

    
    ```diff
  • <li>if ((PHNCINFC_EXTNID_SIZE + PHNCINFC_EXTNSTATUS_SIZE) ></li>
    <li>RspBuffInfo->wLen) {</li>
    <li>android_errorWriteLog(0x534e4554, "181346550");</li>
    <li>return NFCSTATUS_FAILED;</li>
    <li>}
    /<em> DataLen = TotalRecvdLen – (sizeof(RspId) + sizeof(Status)) </em>/
    wPldDataSize = ((RspBuffInfo->wLen) –
    (PHNCINFC_EXTNID_SIZE + PHNCINFC_EXTNSTATUS_SIZE));
    <pre><code></code></pre></li>
    </ul>
    <h4>CVE-2021-0597</h4>
    <ul>
    <li>对VoIP模块中的SIP广播添加<code>USE_SIP</code>权限
    <pre><code class="language-diff"></code></pre></li>
    <li>mContext.sendBroadcast(intent);</li>
    <li>mContext.sendBroadcast(intent, android.Manifest.permission.USE_SIP);
    <pre><code></code></pre></li>
    </ul>
    <h4>CVE-2021-0599</h4>
    <ul>
    <li>对于通知超时广播的PendingIntent添加接收者,防止经典PendingIntent攻击。
    <pre><code class="language-diff">
    final PendingIntent pi = PendingIntent.getBroadcast(getContext(),
    REQUEST_CODE_TIMEOUT,
    new Intent(ACTION_NOTIFICATION_TIMEOUT)</code></pre></li>
    <li>.setPackage(PackageManagerService.PLATFORM_PACKAGE_NAME)
    .setData(new Uri.Builder().scheme(SCHEME_TIMEOUT)
    .appendPath(record.getKey()).build())
    .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
    <pre><code></code></pre></li>
    </ul>
    <h4>CVE-2021-0604</h4>
    <ul>
    <li>不允许蓝牙分享文件功能从<code>MmsFileProvider</code>分享文件
    <pre><code class="language-diff">
    // This will allow more 3rd party applications to share files via
    // bluetooth
    if ("content".equals(scheme)) {</code></pre></li>
    <li>if (fromExternal && BluetoothOppUtility.isForbiddenContent(uri)) {</li>
    <li>EventLog.writeEvent(0x534e4554, "179910660", -1, uri.toString());</li>
    <li>Log.e(TAG, "Content from forbidden URI is not allowed.");</li>
    <li>return SEND_FILE_INFO_ERROR;</li>
    <li>}</li>
    <li>
    <pre><code> contentType = contentResolver.getType(uri);</code></pre>
    <pre><code></code></pre>
    </li>
    </ul>
    <pre><code class="language-diff">+ static boolean isForbiddenContent(Uri uri) {
    + if ("com.android.bluetooth.map.MmsFileProvider".equals(uri.getHost())) {
    + return true;
    + }
    + return false;
    + }
    +</code></pre>
    <h2>2021-07-05 security patch level vulnerability</h2>
    <h3>Framework</h3>
    <h4>CVE-2020-0368</h4>
    <ul>
    <li>通话记录数据库中的SQL注入,由于该数据库中语音信箱的内容受<code>READ_VOICEMAIL</code>权限保护,如果攻击者仅有<code>READ_CALL_LOG</code>权限,但没有<code>READ_VOICEMAIL</code>权限,那么不允许通过SQL注入等方式读取语音信箱的信息。
    <pre><code class="language-diff">
    /**</code></pre></li>
    <li>
    <ul>
    <li>Form of {@link #CONTENT_URI} which limits the query results to a single result.</li>
    </ul>
    </li>
    <li>*/</li>
    <li>private static final Uri CONTENT_URI_LIMIT_1 = CONTENT_URI.buildUpon()</li>
    <li>.appendQueryParameter(LIMIT_PARAM_KEY, "1")</li>
    <li>.build();</li>
    <li>
    </li>
    <li>/**
    <pre><code>
    “`diff
    c = resolver.query(

  • CONTENT_URI,
  • CONTENT_URI_LIMIT_1,
    new String[] {NUMBER},
    TYPE + " = " + OUTGOING_TYPE,
    null,
  • DEFAULT_SORT_ORDER + " LIMIT 1");
  • DEFAULT_SORT_ORDER);
    
    ```diff
  • <li>final SQLiteQueryBuilder qb = new SQLiteQueryBuilder();</li>
    <li>qb.setTables(Tables.CALLS);</li>
    <li>qb.setProjectionMap(sCallsProjectionMap);</li>
    <li>qb.setStrict(true);</li>
    <li>// If the caller doesn't have READ_VOICEMAIL, make sure they can't</li>
    <li>// do any SQL shenanigans to get access to the voicemails. If the caller does have the</li>
    <li>// READ_VOICEMAIL permission, then they have sufficient permissions to access any data in</li>
    <li>// the database, so the strict check is unnecessary.</li>
    <li>if (!mVoicemailPermissions.callerHasReadAccess(getCallingPackage())) {</li>
    <li>qb.setStrictGrammar(true);</li>
    <li>}
    <pre><code></code></pre></li>
    </ul>
    <h3>System</h3>
    <h4>CVE-2021-0514</h4>
    <h4>CVE-2021-0515</h4>
    <ul>
    <li>将V8升级到8.8.278.14版本</li>
    </ul>
    <h4>CVE-2021-0603</h4>
    <ul>
    <li>为联系人选择界面ContactSelectionActivity添加
    SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS,防止悬浮窗覆盖。</li>
    </ul>
    <h2>2021-06-01 security patch level vulnerability details</h2>
    <h3>Android runtime</h3>
    <h4>CVE-2021-0511</h4>
    <h3>Framework</h3>
    <h4>CVE-2021-0521</h4>
    <ul>
    <li>PackageManagerService中的getAllPackages()接口没有权限保护,可以不受用户、InstantApp和包可见性限制来读取所有已安装应用的包名。该问题由</li>
    <li>Android 11中的软件包可见性:<a href="https://developer.android.google.cn/about/versions/11/privacy/package-visibility">https://developer.android.google.cn/about/versions/11/privacy/package-visibility</a></li>
    <li>Instant App的软件包可见性限制:<a href="https://source.android.google.cn/compatibility/cts/cts-instant#restrictions">https://source.android.google.cn/compatibility/cts/cts-instant#restrictions</a></li>
    </ul>
    <h3>Media Framework</h3>
    <h4>CVE-2021-0508</h4>
    <h4>CVE-2021-0509</h4>
    <h4>CVE-2021-0510</h4>
    <h4>CVE-2021-0520</h4>
    <ul>
    <li>四个都是DRM组件中的内存漏洞</li>
    </ul>
    <h3>System</h3>
    <h4>CVE-2021-0507</h4>
    <ul>
    <li>蓝牙avrc_ctrl_pars_vendor_cmd中的越界写入,可导致远程代码执行。</li>
    </ul>
    <h4>CVE-2021-0516</h4>
    <h4>CVE-2021-0505</h4>
    <ul>
    <li>防止从管理员配置的VPN中断开,逻辑漏洞</li>
    <li>Android 7.0中的始终开启VPN:<a href="https://developer.android.google.cn/guide/topics/connectivity/vpn#always-on">https://developer.android.google.cn/guide/topics/connectivity/vpn#always-on</a></li>
    </ul>
    <h4>CVE-2021-0506</h4>
    <ul>
    <li>为ActivityPicker界面(隐式Intent启动Activity时候的选择窗口)添加SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS,防止悬浮窗覆盖。</li>
    </ul>
    <h4>CVE-2021-0523</h4>
    <ul>
    <li>为WifiScanModeActivity界面添加SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS,防止悬浮窗覆盖。</li>
    </ul>
    <h4>CVE-2021-0504</h4>
    <ul>
    <li>蓝牙avrc_pars_browse_rsp中的越界读取,可导致信息泄露。</li>
    </ul>
    <h4>CVE-2021-0517</h4>
    <ul>
    <li>
    </li>
    </ul>
    <h4>CVE-2021-0522</h4>
    <ul>
    <li>蓝牙AVRCP中使用SdpCb时,错误地将RawAddress的引用而不是值本身当作参数,导致地址泄露。</li>
    </ul>
    <h2>2021-06-05 security patch level vulnerability details</h2>
    <h2>2021-05-01 security patch level vulnerability details</h2>
    <h3>Framework</h3>
    <h4>CVE-2021-0472</h4>
    <ul>
    <li>LockTaskController的shouldLockKeyguard方法中,调用了LockPatternUtils的isSecure方法,该方法接受的userId参数必须是实际的userId,不能接受UserHandle.USER_CURRENT,定义如下:
    <pre><code class="language-java">// frameworks/base/core/java/android/os/UserHandle.java
    /** @hide A user id to indicate the currently active user **/
    @UnsupportAppUsage
    public static final @UserIdInt int USER_CURRENT = -2;
    //…</code></pre></li>
    <li>从UserHandle的源码可以看出,USER_CURRENT的值实际上是-2,这个值只有在创建UserHandle的时候才有效,直接使用-2作为userId显然是不正确的。该漏洞由Google的Edward Cunningham发现。</li>
    </ul>
    <h4>CVE-2021-0485</h4>
    <ul>
    <li>SystemUI组件会限制画中画窗口最小大小为48dp(防止1dp画中画保活?)。关于Android画中画功能请参阅<a href="https://source.android.google.cn/devices/tech/display/pip">https://source.android.google.cn/devices/tech/display/pip</a>
    <pre><code class="language-xml"><!–
    The overridable minimal size of a PiP task, in both dimensions.
    Different from default_minimal_size_pip_resizable_task, this is to limit the dimension
    when the pinned stack size is overridden by app via minWidth/minHeight.
    –>
    <dimen name="overridable_minimal_size_pip_resizable_task">48dp</dimen></code></pre></li>
    <li>该漏洞由Cognizant的Dimitrios Valsamaras发现。</li>
    </ul>
    <h4>CVE-2021-0487</h4>
    <ul>
    <li>为CalendarDebugActivity界面 (话说这个界面是干嘛的?) 配置HIDE_NON_SYSTEM_OVERLAY_WINDOWS权限,防止悬浮窗覆盖。该漏洞由hard_<strong>__</strong>发现。</li>
    </ul>
    <h3>Media Framework</h3>
    <h4>CVE-2021-0482</h4>
    <h4>CVE-2021-0484</h4>
    <h3>System</h3>
    <h4>CVE-2021-0473</h4>
    <ul>
    <li>NFC在处理T3T Tag的时候存在内存泄漏、越界写入和Double Free。该漏洞由Google Project Zero的Ned Williamson发现。</li>
    </ul>
    <h4>CVE-2021-0474</h4>
    <ul>
    <li>蓝牙在处理超长AVCT commands时出现溢出
    <pre><code class="language-diff">
    if (cr == AVCT_CMD && (p_pkt->layer_specific & AVCT_DATA_CTRL &&</code></pre></li>
    <li>AVRC_PACKET_LEN < sizeof(p_pkt->len))) {</li>
    <li>/<em> Ignore the invalid AV/C command frame </em>/</li>
    <li>p_drop_msg = "dropped – too long AV/C cmd frame size";</li>
    <li>p_pkt->len > AVRC_PACKET_LEN)) {</li>
    <li>android_errorWriteLog(0x534e4554, "177611958");</li>
    <li>AVRC_TRACE_WARNING("%s: Command length %d too long: must be at most %d",</li>
    <li><strong>func</strong>, p_pkt->len, AVRC_PACKET_LEN);
    osi_free(p_pkt);
    return;
    }
    <pre><code></code></pre></li>
    </ul>
    <h4>CVE-2021-0475</h4>
    <ul>
    <li>蓝牙在L2CAP连接Socket关闭后返回,感觉是一个UAF问题,该漏洞由L.O. Team的Wenwen Wang and Fei发现。
    <pre><code class="language-diff">
    << ": unable to push data to socket – closing fixed channel";
    BTA_JvL2capCloseLE(sock->handle);
    btsock_l2cap_free_l(sock);</code></pre></li>
    <li>return;
    }
    <pre><code>
    “`diff
    << ": unable to push data to socket – closing channel";
    BTA_JvL2capClose(sock->handle);
    btsock_l2cap_free_l(sock);

  • return;
    }
    }
    }

CVE-2021-0476

  • btif_av.cc中对std::map未进行加锁,该问题由GWP-ASan发现。

CVE-2021-0477

  • 在SystemUI的ScreenshotNotificationsController中,对截屏错误的PendingInten添加FLAG_IMMUTABLE标志。

CVE-2021-0481

  • 在设置多用户的用户头像时,避免使用非法的URI作为图片来源。
    
    # packages/apps/Settings/src/com/android/settings/users/EditUserPhotoController.java
         }
         final Uri pictureUri = data != null && data.getData() != null
                 ? data.getData() : mTakePictureUri;
  • // Check if the result is a content uri
  • if (!ContentResolver.SCHEME_CONTENT.equals(pictureUri.getScheme())) {
  • Log.e(TAG, "Invalid pictureUri scheme: " + pictureUri.getScheme());
  • EventLog.writeEvent(0x534e4554, "172939189", -1, pictureUri.getPath());
  • return false;
  • }

CVE-2021-0466

  • 仅在使用随机WLAN MAC地址时才使用EUI64 IPv6 link-local address generation (不太懂)。该漏洞由Google的Bram Bonné发现。

CVE-2021-0480

  • SnoozeHelper中的PendingIntent添加目标包名,使其成为显式Intent。该漏洞由Yu-Cheng Lin (林禹成) (@AndroBugs)发现。
    
    # frameworks/base/services/core/java/com/android/server/notification/SnoozeHelper.java
         return PendingIntent.getBroadcast(mContext,
                 REQUEST_CODE_REPOST,
                 new Intent(REPOST_ACTION)
  • .setPackage(PackageManagerService.PLATFORM_PACKAGE_NAME)
    .setData(new Uri.Builder().scheme(REPOST_SCHEME).appendPath(key).build())
    .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
    .putExtra(EXTRA_KEY, key)

2021-05-05 security patch level vulnerability details

2021-04-01 security patch level vulnerability details

Framework

CVE-2021-0400

  • 在使用紧急呼叫服务时,不信任模拟位置的返回。在Android里面允许用户在开发者选项中“选择模拟位置信息应用”,授予一个第三方应用模拟位置的权限,这样系统就会从这个来源获取位置坐标信息。该问题由Google的Soonil Nagarkar发现。

CVE-2021-0426

  • statsd遥测进程中的LogEvent模块,在parsePrimaryFieldFirstUidAnnotation函数中存在一个堆缓冲区溢出导致的越界写。该问题由360 Alpha Lab的Xiaobo Xiang和Guang Gong发现。
  • Android 9包含statsd遥测功能,statsd可收集应用使用情况、电池和进程统计信息以及崩溃数据。这些数据会经过分析并用于改进产品、硬件和服务。
  • 关于statsd的更多信息详见:https://source.android.google.cn/devices/architecture/modular-system/statsd

CVE-2021-0427

  • statsd遥测进程中的LogEvent模块,在parseExclusiveStateAnnotation函数中存在一个堆缓冲区溢出导致的越界写。该问题由360 Alpha Lab的Xiaobo Xiang和Guang Gong发现。
  • 0426和0427这两个漏洞新增了一些测试用例,可以有助于理解这两个问题,位于:
    // frameworks/base/cmds/statsd/tests/LogEvent_test.cpp
    TEST(LogEventTest, TestExclusiveStateAnnotationAfterTooManyFields)
    TEST(LogEventTest, TestUidAnnotationAfterTooManyFields)
    TEST(LogEventTest, TestAttributionChainEndIndexAfterTooManyFields)
    TEST(LogEventTest, TestEmptyAttributionChainWithPrimaryFieldFirstUidAnnotation)

CVE-2021-0432

  • statsd遥测进程中的StatsPullerManager模块,在ForceClearCache和ClearCacheIfNecessary函数中操作了共享资源kAllPullAtomInfo但未使用锁,可能在Puller注册或取消注册过程中存在条件竞争问题。该问题由GWP-ASan发现。

CVE-2021-0438

  • WindowManagerService中有一个hidden的flag名为NO_INPUT_CHANNEL,允许应用程序创建一个没有输入通道的窗口。在Android R以前,这会导致窗口被错误地配置一个FLAG_OBSCURED标志,导致窗口覆盖攻击,具体效果待实测。该问题由Google的Rob Carr发现。

CVE-2021-0439

  • PowerManagerService中的setPowerBoostWithHandle函数和setPowerModeWithHandle函数,由于缺失边界检查导致越界写问题。

    static void setPowerBoostWithHandle(sp<IPowerAidl> handle, Boost boost, int32_t durationMs) {
    // Android framework only sends boost upto DISPLAY_UPDATE_IMMINENT.
    // Need to increase the array size if more boost supported.
    static std::array<std::atomic<HalSupport>,
                      static_cast<int32_t>(Boost::DISPLAY_UPDATE_IMMINENT /* 1 */) + 1>
            boostSupportedArray = {HalSupport::UNKNOWN};
    
    // Quick return if boost is not supported by HAL
    // *** 传入一个负数可绕过大于1的校验,导致后续写boostSupportedArray数组溢出 ***
    if (boost > Boost::DISPLAY_UPDATE_IMMINENT /* 1 */ || 
        boostSupportedArray[static_cast<int32_t>(boost)] == HalSupport::OFF) {
            ALOGV("Skipped setPowerBoost %s because HAL doesn't support it", toString(boost).c_str());
            return;
    }
    
    if (boostSupportedArray[static_cast<int32_t>(boost)] == HalSupport::UNKNOWN) {
        bool isSupported = false;
        handle->isBoostSupported(boost, &isSupported);
        // *** OOB Write ***
        boostSupportedArray[static_cast<int32_t>(boost)] = isSupported ? HalSupport::ON : HalSupport::OFF;
        if (!isSupported) {
            ALOGV("Skipped setPowerBoost %s because HAL doesn't support it",
                  toString(boost).c_str());
            return;
        }
    }
    
    auto ret = handle->setBoost(boost, durationMs);
    processPowerHalReturn(ret.isOk(), "setPowerBoost");
    }
  • Boost的定义
    enum class Boost : int32_t {
    INTERACTION = 0,
    DISPLAY_UPDATE_IMMINENT = 1,
    ML_ACC = 2,
    AUDIO_LAUNCH = 3,
    CAMERA_LAUNCH = 4,
    CAMERA_SHOT = 5,
    };
  • setPowerModeWithHandle的问题是一样的

    static bool setPowerModeWithHandle(sp<IPowerAidl> handle, Mode mode, bool enabled) {
    // Android framework only sends mode upto DISPLAY_INACTIVE.
    // Need to increase the array if more mode supported.
    static std::array<std::atomic<HalSupport>, static_cast<int32_t>(Mode::DISPLAY_INACTIVE) + 1>
            modeSupportedArray = {HalSupport::UNKNOWN};
    
    // Quick return if mode is not supported by HAL
    // *** 传入一个负数可绕过大于9的校验,导致后续写modeSupportedArray数组溢出 ***
    if (mode > Mode::DISPLAY_INACTIVE ||
        modeSupportedArray[static_cast<int32_t>(mode)] == HalSupport::OFF) {
            ALOGV("Skipped setPowerMode %s because HAL doesn't support it", toString(mode).c_str());
            return false;
    }
    
    if (modeSupportedArray[static_cast<int32_t>(mode)] == HalSupport::UNKNOWN) {
        bool isSupported = false;
        handle->isModeSupported(mode, &isSupported);
        // *** OOB Write ***
        modeSupportedArray[static_cast<int32_t>(mode)] = isSupported ? HalSupport::ON : HalSupport::OFF;
        if (!isSupported) {
            ALOGV("Skipped setPowerMode %s because HAL doesn't support it", toString(mode).c_str());
            return false;
        }
    }
    
    auto ret = handle->setMode(mode, enabled);
    processPowerHalReturn(ret.isOk(), "setPowerMode");
    return ret.isOk();
    }
  • Mode的定义
    enum class Mode : int32_t {
    DOUBLE_TAP_TO_WAKE = 0,
    LOW_POWER = 1,
    SUSTAINED_PERFORMANCE = 2,
    FIXED_PERFORMANCE = 3,
    VR = 4,
    LAUNCH = 5,
    EXPENSIVE_RENDERING = 6,
    INTERACTIVE = 7,
    DEVICE_IDLE = 8,
    DISPLAY_INACTIVE = 9,
    AUDIO_STREAMING_LOW_LATENCY = 10,
    CAMERA_STREAMING_SECURE = 11,
    CAMERA_STREAMING_LOW = 12,
    CAMERA_STREAMING_MID = 13,
    CAMERA_STREAMING_HIGH = 14,
    };

CVE-2021-0442

  • 在InputApplicationHandle中,仅更新Native层的InputApplicationHandle一次,以避免条件竞争问题。该问题由小米的Mingming Wang发现。

CVE-2021-0443

  • 在多用户切换时终止截图进程,以避免信息泄露。该问题由Elliott Brooks发现。

CVE-2021-0444

  • 在QuickContact的onActivityResult中,将不再返回Intent的data。该问题由Oversecured Inc.的Sergey Toshin发现。

Media Framework

CVE-2021-0437

  • DrmPlugin中的mPlayPolicy由于条件竞争问题可被Double Free。该问题由Chong Wang发现。

CVE-2021-0436

  • CryptoPlugin中存在一个整数溢出问题,会导致越界读造成信息泄露。该问题由Chong Wang发现。

CVE-2021-0471

  • CryptoPlugin中存在一个整数溢出问题,会导致越界读造成信息泄露。该问题由Chong Wang发现。

System

CVE-2021-0430

  • NFC在处理MIFARE Classic卡的TLV时存在一个越界写入,可造成远程代码执行。该问题由Google Project Zero的Ned Williamson发现。

CVE-2021-0429

  • 在SensorService的HAL接口中存在一个UAF漏洞。该问题由GWP-ASan发现。

CVE-2021-0433

  • 为CompanionDeviceManager配置HIDE_NON_SYSTEM_OVERLAY_WINDOWS权限,防止悬浮窗覆盖。

CVE-2021-0446

  • 为vCard联系人导入流程配置HIDE_NON_SYSTEM_OVERLAY_WINDOWS权限,防止悬浮窗覆盖。

CVE-2021-0431

  • 在蓝牙AVRC模块中,使用calloc而不是malloc进行内存分配,以保证初始化时会以0填充缓冲区,防止信息泄露。该问题由L.O. Team的Cusas发现。

CVE-2021-0435

  • 在蓝牙AVRC模块中,使用calloc而不是malloc进行内存分配,以保证初始化时会以0填充缓冲区,防止信息泄露。该问题由L.O. Team的Cusas发现。

2021-04-05 security patch level vulnerability details

2021-03-01 security patch level vulnerability details

Android runtime

CVE-2021-0395

  • init在重启过程中存在一个潜在的UAF漏洞,由于init在遍历需停止的服务列表时使用原始的服务对象指针,遍历到已停止的服务时可能存在UAF漏洞。

Framework

CVE-2021-0391

  • 对多用户选择窗口添加SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS标志,防止悬浮窗劫持攻击。

    CVE-2021-0398

  • 在ActiveServices的bindServiceLocked方法中,调用shouldAllowWhileInUsePermissionInFgsLocked()方法时传入了Binder.getCallingPid()Binder.getCallingUid()的返回值作为pid和uid。然而在调用这些方法之前,先调用了Binder.clearCallingIdentity(),这会导致获取到的pid和uid不正确。
    
    // frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
    int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, final IServiceConnection connection, int flags,
            String instanceName, String callingPackage, final int userId)
            throws TransactionTooLargeException {
    //...
  • final int callingPid = Binder.getCallingPid();
  • final int callingUid = Binder.getCallingUid();
    //…
    final long origId = Binder.clearCallingIdentity();
    //…
    if (!s.mAllowWhileInUsePermissionInFgs) {
    s.mAllowWhileInUsePermissionInFgs =
    shouldAllowWhileInUsePermissionInFgsLocked(callingPackage,
  • Binder.getCallingPid(), Binder.getCallingUid(),
  • callingPid, callingUid,
    service, s, false);
    }
    //…
    }

System

CVE-2021-0397

  • 只会发起SDP扫描一次,如果已经有进行中的扫描,则直接返回。
    
    // system/bt/bta/ag/bta_ag_sdp.cc
  • if (p_scb->p_disc_db != nullptr) {
  • android_errorWriteLog(0x534e4554, "174052148");
  • APPL_TRACE_ERROR("Discovery already in progress… returning.");
  • return;
  • }
  • 
    #### CVE-2017-14491
  • 在dnsmasq 2.78之前的版本中基于堆的缓冲区溢出允许远程攻击者通过精心设计的DNS响应导致拒绝服务(崩溃)或执行任意代码。这是一个历史漏洞。
  • 详细分析:https://www.anquanke.com/post/id/87085

CVE-2021-0393

CVE-2021-0396

CVE-2021-0390

  • 对WifiConfigManager中的部分Wi-Fi操作相关接口,要求必须是前台才允许调用。

CVE-2021-0392

  • wificond中存在一个UAF漏洞,该漏洞是从上游同步的。

    
    // system/connectivity/wificond/main.cpp
    android::wificond::NetlinkUtils netlink_utils(&netlink_manager);
    android::wificond::ScanUtils scan_utils(&netlink_manager);
  • unique_ptr<android::wificond::Server> server(new android::wificond::Server(

  • android::sp<android::wificond::Server> server(new android::wificond::Server(
    unique_ptr<InterfaceTool>(new InterfaceTool),
    &netlink_utils,
    &scan_utils));

  • RegisterServiceOrCrash(server.get());

  • RegisterServiceOrCrash(server);

    WifiKeystoreHalConnector keystore_connector;
    keystore_connector.start();

CVE-2021-0394

  • 在ART的代码中,对JNI::NewStringUTF()增加校验,并且增加了SafetyNet日志记录。

2021-03-05 security patch level vulnerability details

2021-02-01 security patch level vulnerability details

Android runtime

CVE-2021-0341

  • 在external/okhttp中拒绝非ASCII字符的主机名和SANs,主要涉及okhttp证书校验中主机名校验(HostnameVerifier)的部分。

Framework

CVE-2021-0302

CVE-2021-0305

  • 为特殊应用权限(应用和通知-高级-特殊应用权限)中的权限开关添加了遮挡时过滤点击保护android:filterTouchesWhenObscured=true

CVE-2021-0314

  • 对确认卸载应用窗口添加SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS标志,防止悬浮窗劫持攻击。

CVE-2021-0327

  • 在AMS的getContentProviderImpl方法里,最后有一段代码可能抛出异常,中断这个方法的执行。所以将其放入try-finally里面,并且确保在finally的时候可以正确的执行restoreCallingIdentity,清除Binder调用者的CallingUid,保证后续的Binder.getCallingUid可以取到正常的值。

CVE-2021-0330

  • 在storaged进程中少了一个锁(mutex lock),这个漏洞似乎无法利用,应该是源代码审计看到的。

CVE-2021-0334

  • 从ResolverActivity中去掉了updateIntentVerificationStatusAsUser接口。
  • 该接口和“使用已安装的应用打开链接”功能有关,旨在授予App对其所声明的域的完全验证权限,也就是说,对于目标域的Web链接,将总是跳转到该App。但这允许App接管无主的链接,如果用户在“使用应用打开”的对话框中选择了该App并且点击了“始终”按钮,后续该链接都会跳转到该App,不会提示用户。
  • Google认为该API的所有用法可能都是非预期的,应该将该API删除。

CVE-2021-0337

  • 在FileSystemProvider中,当文件被删除、重命名或者移动之后,去除该文件所有的URI权限。
  • 该Provider是提供给存储访问框架使用的,旨在让应用没有存储权限的情况下,也可以访问由用户指定的单个文件,用户选择文件之后,应用可以通过URI来访问该文件,该访问能力即由FileSystemProvider提供,如果用户选择的文件被删除、重命名或者移动,但URI权限没有去除,会造成应用意外访问到其他文件。

CVE-2021-0339

  • 限制App跳转动画的最大时间,限制过渡动画的最长时间为3秒(原先为10秒)。

CVE-2021-0340

  • MediaProvider的修复,使IsoInerface能处理64位和文件末尾的box长度,这样可避免视频文件的位置数据解析错误。

CVE-2021-0338

  • 在SettingsProvider中修复固定字体大小比例检查器,限制范围为0.85-1.3之间,原先的检查只要求大于0即可,该值设置的过大或者过于逼近0会导致系统无法显示而造成拒绝服务。

Media Framework

CVE-2021-0325

  • 在libavc中增加校验,图片中的first_mb_in_slice不能>=mbs
    u2_first_mb_in_slice = ih264d_uev(pu4_bitstrm_ofst, pu4_bitstrm_buf);
    if(u2_first_mb_in_slice >= (ps_dec->u2_frm_ht_in_mbs * ps_dec->u2_frm_wd_in_mbs))) {
    //...
    }

    CVE-2021-0332

  • SurfaceFlinger里面把一段代码换了个位置,提交信息也没有具体解释原因。

CVE-2021-0335

  • libstagefright的MediaCodec中的信息泄露问题。

System

CVE-2021-0326

  • 在wpa_supplicant_8的p2p.c中,当拷贝wps_sec_dev_type_list时没有校验其长度,导致wps_sec_dev_type_list超长时出现问题。
    if (dev->info.wps_sec_dev_type_list_len > WPS_SEC_DEV_TYPE_MAX_LEN) {
    android_errorWriteLog(0x534e4554, "172937525");
    dev->info.wps_sec_dev_type_list_len = WPS_SEC_DEV_TYPE_MAX_LEN;
    }
    os_memcpy(dev->info.wps_sec_dev_type_list, cli->sec_dev_types, dev->info.wps_sec_dev_type_list_len)

CVE-2021-0328

  • GATT服务端会在发送GATT批量扫描结果广播之前,对发起扫描的GATT客户端添加和GATT普通扫描相同的权限检查。

CVE-2021-0329

  • 在GATT的AdvertiseManager中,传递不存在的GATT Advertiser ID会导致越界访问。

CVE-2021-0331

  • 对通知使用权的Activity添加SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS标志,防止悬浮窗劫持攻击。

CVE-2021-0333

  • 对蓝牙权限授予(例如蓝牙授予通讯录、通话记录等的权限)的Activity添加SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS标志,防止悬浮窗劫持攻击。

CVE-2021-0336

  • 限定BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY这一Intent的接收者必须为com.android.bluetooth,这个Intent用于传递蓝牙权限的授予状态。

2021-02-05 security patch level vulnerability details

Kernel components

Qualcomm components