1. 极安网首页
  2. 网络安全技术

FreeBSD内核特权提升漏洞(CVE-2020-7460)

0x00 概述

2020年8月,FreeBSD发布更新,修复了条件竞争(TOCTOU)漏洞,该漏洞可能会被不具有特权的用户空间恶意程序利用,从而实现特权提升。一位名为m00nbsd的研究人员将该漏洞报告给ZDI,并提供了该漏洞的详细描述和漏洞验证代码详情,该漏洞的编号为ZDI-20-949/CVE-2020-7460

攻击者利用32位sendmsg()系统调用中存在的TOCTOU漏洞,可以以无特权的用户在FreeBSD上执行内核代码。该漏洞影响自2014年以来的所有FreeBSD内核,已经为该漏洞分配了CVE-2020-7460编号。在进行漏洞的详细分析之前,我们首先可以通过演示视频快速了解该漏洞的实际利用方式。

演示视频:https://youtu.be/LBFfX90Acw8

0x01 漏洞详情

我们直接跳到漏洞所在的位置,即freebsd32_copyin_control()函数。该函数由两个循环组成,如下所示:

  1. //
  2. // ----------------------- FIRST LOOP -----------------------
  3. //
  4. while (idx < buflen) {
  5.     error = copyin(buf + idx, &msglen, sizeof(msglen));
  6.     if (error)
  7.         return (error);
  8.     if (msglen < sizeof(struct cmsghdr))
  9.         return (EINVAL);
  10.     msglen = FREEBSD32_ALIGN(msglen);
  11.     if (idx + msglen > buflen)
  12.         return (EINVAL);
  13.     idx += msglen;
  14.     msglen += CMSG_ALIGN(sizeof(struct cmsghdr)) -
  15.         FREEBSD32_ALIGN(sizeof(struct cmsghdr));
  16.     len += CMSG_ALIGN(msglen);
  17. }
  18. if (len > MCLBYTES)
  19.     return (EINVAL);
  20. //
  21. // ALLOCATE KERNEL MEMORY
  22. //
  23. m = m_get(M_WAITOK, MT_CONTROL);
  24. if (len > MLEN)
  25.     MCLGET(m, M_WAITOK);
  26. m->m_len = len;
  27. //
  28. // ----------------------- SECOND LOOP -----------------------
  29. //
  30. md = mtod(m, void *);
  31. while (buflen > 0) {
  32.     error = copyin(buf, md, sizeof(struct cmsghdr));
  33.     if (error)
  34.         break;
  35.     msglen = *(u_int *)md;
  36.     msglen = FREEBSD32_ALIGN(msglen);
  37.     /* Modify the message length to account for alignment. */
  38.     *(u_int *)md = msglen + CMSG_ALIGN(sizeof(struct cmsghdr)) -
  39.         FREEBSD32_ALIGN(sizeof(struct cmsghdr));
  40.     md = (char *)md + CMSG_ALIGN(sizeof(struct cmsghdr));
  41.     buf += FREEBSD32_ALIGN(sizeof(struct cmsghdr));
  42.     buflen -= FREEBSD32_ALIGN(sizeof(struct cmsghdr));
  43.     msglen -= FREEBSD32_ALIGN(sizeof(struct cmsghdr));
  44.     if (msglen > 0) {
  45.         error = copyin(buf, md, msglen); // <<-------- OVERFLOW
  46.         if (error)
  47.             break;
  48.         md = (char *)md + CMSG_ALIGN(msglen);
  49.         buf += msglen;
  50.         buflen -= msglen;
  51.     }
  52. }

我们来看看这里发生了什么。第一个循环从用户区域获取数据。这个数据是一组连续的cmsghdr结构:

  1. struct cmsghdr {
  2.     socklen_t cmsg_len;       /* data byte count, including hdr */
  3.     int       cmsg_level;     /* originating protocol */
  4.     int       cmsg_type;      /* protocol-specific type */
  5.     /* u_char cmsg_data[]; */
  6. };

FreeBSD内核特权提升漏洞(CVE-2020-7460)-极安网

投稿文章,不代表 极安网 立场,转载请注明出处:https://secvery.com/646.html