Android Security Bulletin Analysis (December 2021)

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);
 void* osi_calloc(size_t size) {
+  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);
  • 影响版本:9, 10, 11, 12
  • 致谢信息:Vijay Prakash and Ruian Duan, Palo Alto Networks Inc

CVE-2021-0956

  • NFC组件中的越界写
   if (mTechListTail < (MAX_NUM_TECHNOLOGY - 1)) {
     mNumTechList = mTechListTail;
+  } else {
+    LOG(ERROR) << StringPrintf("%s: exceed max=%d", fn, MAX_NUM_TECHNOLOGY);
+    android_errorWriteLog(0x534e4554, "189942532");
+    goto TheEnd;
   }
  • 影响版本:11, 12
  • 致谢信息:Nguyễn Hoàng Thạch (d4rkn3ss) of STAR Labs

CVE-2021-0953

  • QuickSearchBox组件中的SearchWidgetProvider存在不安全的PendingIntent。由于OEM的定制,这个漏洞可能不影响部分OEM的系统。
     private void setOnClickActivityIntent(Context context, RemoteViews views, int viewId,
             Intent intent) {
+        intent.setPackage(context.getPackageName());
         PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
         views.setOnClickPendingIntent(viewId, pendingIntent);
     }
  • 影响版本:9, 10, 11, 12
  • 致谢信息:无

CVE-2021-0954

  • com.android.internal.app.ResolverActivity的点击劫持问题,添加SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS标志。
  • 影响版本:10, 11
  • 致谢信息:无

CVE-2021-0963

  • com.android.keychain.KeyChainActivity的点击劫持问题,添加SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS标志并使用setFilterTouchesWhenObscured(true)。
  • 影响版本:9, 10, 11, 12
  • 致谢信息:Tianyi Hu (胡天易) of Bytedance Wuheng Lab

CVE-2021-0965

  • 防止恶意应用调用com.android.settings.bluetooth.BluetoothPairingDialog来伪造蓝牙配对窗口,添加android.permission.BLUETOOTH_PRIVILEGED权限来保护。
  • 影响版本:9, 10, 11, 12
  • 致谢信息:Yu-Cheng Lin (林禹成) (@AndroBugs)

CVE-2021-0952

  • 通讯录应用选联系人头像并编辑的AttachPhotoActivity,限制只调用系统应用来进行联系人头像编辑防止第三方应用在没有权限的情况下从Intent中读取到通讯录。由于OEM的定制,这个漏洞可能不影响部分OEM的系统。
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;
}
  • 影响版本:9, 10, 11, 12
  • 致谢信息:Sithija Abhishek Kotuwewatta

CVE-2021-0966

  • 在编译AIDL文件的时候,如果enum没有默认值,则用0进行填充。
  • 影响版本:11, 12
  • 致谢信息:Jann Horn of Google Project Zero

CVE-2021-0958

  • KeyStore 2.0中km_compat的问题,TBD。https://android.googlesource.com/platform/system/security/+/b7f303146fecc166260aced8de677dfc7322f7a3
  • 影响版本:11, 12
  • 致谢信息:无

CVE-2021-0969

  • AP名称为空会导致NPE
public String getTitle() {
-    if (isPasspoint()) {
+    if (isPasspoint() && !TextUtils.isEmpty(mConfig.providerFriendlyName)) {
         return mConfig.providerFriendlyName;
-    } else if (isPasspointConfig()) {
+    } else if (isPasspointConfig() && !TextUtils.isEmpty(mProviderFriendlyName)) {
         return mProviderFriendlyName;
-    } else if (isOsuProvider()) {
+    } else if (isOsuProvider() && !TextUtils.isEmpty(mOsuProvider.getFriendlyName())) {
         return mOsuProvider.getFriendlyName();
-    } else {
+    } else if (!TextUtils.isEmpty(getSsidStr())) {
         return getSsidStr();
+    } else {
+        return "";
     }
}
  • 影响版本:10, 11
  • 致谢信息:无

2021-12-05 security patch level vulnerability details

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注