Linux 中 glibc 的攻击面 —— 从CVE-2024-6387中产生的思考

CVE-2024-6387简介

OpenSSH是SSH(Secure Shell)协议的开源实现,它支持在两个主机之间提供安全的加密通信,广泛用于Linux等系统,通常用于安全远程登录、远程文件传输和其它网络服务。

2024年7月1日,OpenSSH Server中存在的一个远程代码执行漏洞(CVE-2024-6387,又被称为regreSSHion)细节被公开,该漏洞影响基于glibc的Linux系统上的OpenSSH Server (sshd)。

默认配置下的OpenSSH Server (sshd)中存在信号处理程序竞争条件漏洞,如果客户端未在LoginGraceTime内(默认情况下为120秒,旧版OpenSSH中为600秒)进行身份验证,则sshd的SIGALRM处理程序将被异步调用,但该信号处理程序会调用非异步信号安全的函数,最终造成Double-Free内存管理问题。威胁者可利用该漏洞在基于glibc的Linux系统上以root身份实现未经身份验证的远程代码执行。根据已公开技术细节中的描述,在开启ASLR的i386设备上,利用该漏洞大约需要6-8小时获取root shell,在开启ASLR的amd64设备上则可能需要约一周左右。

CVE-2024-6387的攻击方式

  • 攻击手段

    • 利用glibc中malloc()和free()函数在signal信号量中断下不同步的性质进行条件竞争
    • 使得代码只进行一部分,另一部分在没进行时就被信号截断了
    • 信号截断后openssh会进行一系列函数,从而控制程序运行
  • 它的前身CVE-2006-5051的攻击路径

    • 利用signal中断攻击chunk_free函数,使得chunk堆块处于修改完inuse状态但是没有进行unlink的过程
    • 然后会调用中断后执行的packet_close()函数,进行free,从而实现unsafe unlink的攻击
    • 攻击__free_hook指针,从而实现控制程序运行的目的
  • 它的攻击路径

    • 利用signal中断攻击malloc()函数,使得它拆分了堆块,但是另一个堆块的大小还没改变
    • 修改另一个堆块的大小,使其和下面的堆块重叠
    • 调用syslog()函数,会使用open创建,申请出一个IO_file,而这一块会恰好和上面一块有一部分重叠
    • 控制IO_file,应用House Of Apple2,控制程序流运行

很明显的是,这个漏洞是在不知道glibc基址的情况下进行的爆破攻击,并且想要产生竞争的条件苛刻,实际利用价值不高

linux中的程序攻击方式

  • 程序本身elf文件的攻击

    • 栈溢出从而控制程序流
    • 格式化字符串导致任意地址读写
  • glibc相关攻击

    • 堆漏洞攻击

      • 任意地址读写
      • 限制地址读写
    • IO块攻击

      • 虚表攻击
  • 针对内核的攻击

    • 内核栈溢出
    • 内核堆slab,slub的uaf攻击

glibc中的堆结构和bin结构

堆结构

  • linux在glibc中的堆分配策略

    • 申请一页可读写的地址作为堆地址(页对齐)
    • 创建一个叫做top chunk的空闲堆
    • 每次在malloc等函数申请堆的时候都切割top chunk
  • 堆的数据结构

    struct malloc_chunk{
      INTERNAL_SIZE_T prev_size;
      INTERNAL_SIZE_T size;
      struct malloc_chunk *fd;
      struct malloc_chunk *bk;
    
      struct malloc_chunk *fd_nextsize;
      struct malloc_chunk *bk_nextsize;
    }
  • glibc的堆回收策略

    • 在glibc中,当堆使用完成后,通常会利用free()函数回收这个堆
    • 但是有可能回收的堆会被马上用到,并且堆可能是不连续的
    • 回收策略是建立bin来实现缓存快速使用
    • 在一开始建立了4个bin:fast bin, unsorted bin, small bin, large bin,在glibc2.27之后引入了tcache bin
    • 但是这样的bin策略就会产生安全隐患
  • 各个bin的特性

    • 单链表链接的bin:fast bin(栈模式), tcache bin
    • 双链表链接的bin:unsorted bin, small bin, large bin

针对堆的攻击

  • 堆漏洞从大方向可以分为两类

    • overflow

      • 溢出,产生的原因是堆写入的长度控制不当形成的
      • 溢出很多位(8位就会产生堆重叠的大问题)
      • off by one
      • off by none
    • use after free

      • 通常情况下产生原因是free之后的指针没有清空造成的
      • 野指针利用
  • 针对bin的攻击

    • 针对fastbin

      • double free
      • fastbin consolidate(来自scanf的攻击)
    • 针对tcache bin

      • double free(后期被修复了)
      • tcache stashing unlink attack
    • 针对small bin 和 large bin

      • unsafe unlink
      • small bin attack
      • large bin attack
      • 只能任意地址写堆地址
  • 针对堆的攻击链

    • house of 系列
    • 针对hook的攻击

      • __malloc_hook
      • __realloc_hook
      • __free_hook
    • 针对栈的攻击

      • environ指向栈
    • 针对IO的攻击

      • house of orange
      • house of apple

        • 主要是攻击_wide_data的vtable
        • 造成虚表函数可控
        • 从而在程序exit或者报错退出时,在释放IO的时候调用某虚表函数
        • 而后造成程序运行控制