cve-2013-2094是于2013年4月前后发现的linux kernel本地漏洞,该漏洞影响3.8.9之前开启了PERF_EVENT的linux系统。利用该漏洞,通过perf_event_open系统调用,本地用户可以获得系统的最高权限。

发生漏洞的是linux kernel中的perf event子系统,perf event是linux系统中提供性能分析接口的子系统,于2.6.31之后引入linux,之前被称为 Performance Counters for Linux (PCL)。通过syscall函数,用户可以调用perf event子系统提供的功能。由于perf event中的漏洞,用户可以通过精心构造的调用在任何内存地址写入数据,从而获得系统的最高权限。

引起cve-2013-2094漏洞的是位于kernel/events/core.c文件中的perf_swevent_init函数。当使用syscall打开perf_event的file descriptor时,该函数被调用。

在受影响的版本中,core.c关键部分内容如下:

static int perf_swevent_init(struct perf_event *event)
{
int event_id = event->attr.config; //dangerous! /*
* ....omit some code...
*/ if (event_id >= PERF_COUNT_SW_MAX)
return -ENOENT; /*
* .........omit........
*/ }

由于将event_id定义为了有符号型整数,而后面又只检查了event_id的上界,所以当值为负时,即可越过检查,继续执行后面的代码

if (!event->parent) {
int err; err = swevent_hlist_get(event);
if (err)
return err; atomic_inc(&perf_swevent_enabled[event_id]);
event->destroy = sw_perf_event_destroy;
}

其中,static_key_slow_inc函数将某地址内容做inc。

当使用负数值的event_id调用时,perf_swevent_enabled[event_id]将指向内核空间,如,在Cent OS 64bit系统中,当event_id = -1调用时,perf_swevent_enabled[event_id]的地址为:

0xfffffffffffffffe * 4 + 0xffffffff81f360c0 == 0xFFFFFFFF81F360B8

该地址指向内核空间。

而当file descriptor关闭时,由于event_id定义为u64型,所以关闭时做dec时,地址指向的是用户空间。

所以当我们用负数值调用perf_event_open时,将可以在perf_swevent_enabled地址后面任意地址写入数据。

x64下的利用思路

x64架构下,该漏洞比较容易利用,需要的信息更少,exploit执行更快。方法简单来说是修改IDT中 int 4 的中断向量。x64的linux中,Offset hight bits和Offset middle bits是分别保存的,而将 int 4 的高位 0xffffffff 加1之后,中断向量将指向用户空间。而将shellcode放置在用户空间的这段内存上,即可获得系统最高权限。

具体来说,

  1. 使用-1和-2调用,得到数组的偏移值。

    使用-1和-2调用,在file descriptor被关闭后,将使 0x38000000 附近的内存中某两个值减1,通过搜索可以确定perf_swevent_enabled的编译值,并保存起来方便利用。

  2. 将shellcode放入适当的用户空间内存中

    使用 sidt 指令可以获得IDT的地址,然后使用 mmap 将 shellcode 放入适当的地址。使 IDT 中的中断向量高位+1之后落在shellcode上。

  3. 修改shellcode

    将 shellcode 中的 MARKER 修改为实际的 uid 和 gid 的保存地址。这样当shellcode运行时,即可找到 task_struct 和 thread_info 的地址,从而直接修改 real_cred 值,使当前进程获得 root 权限。

  4. 修改 IDT

    从 1 中得到的信息,和IDT 地址做计算,用计算好的负数值调用 perf_event_open ,可以使 int 4 的中断向量的高位 +1,从而指向shellcode。

  5. int 0x4

    触发shellcode

  6. 在shellcode中提权,并弹shell

    修改 real_cred 获得root权限,并修复被修改的 IDT 和其他部分内存,

    最后execl("/bin/bash", "-sh", NULL);

    得到root权限的shell

移植到android系统

Android采用了linux内核,且更新较linux在PC上的发行版慢。即使linux内核在2013年4月13日修复了该漏洞,原生Android系统和大量基于Android系统的第三方ROM仍然存在该漏洞。

在ARM linux下,该漏洞仍然存在,仍然可以通过负数的event_id将任意内存地址+1。

但由于手机使用的ARM架构和x64架构下,linux内核代码有所不同,该漏洞的利用方式也有所不同。

但是在ARM linux下,IDT的结构如下

struct _idt_entry {
unsigned short base_lo;
unsigned short sel;
unsigned char unused;
unsigned char flags;
unsigned short base_hi;
} __attribute__((packed));

注意到base_hi是short型,而perf_swevent_enabled是int型的数组,所以无法将地址修改base_hi到用户空间地址。

所以在ARM下我们没有修改IDT,而是在linux内核中寻找合适的函数指针。反复调用perf_event_open,将函数指针的值加到用户能控制的地址,然后调用函数。ptmx_fops结构中的fsync函数指针被初始化为0,且不需要特殊的权限即可调用。

利用的基本思路是:

/* file_operations 结构fsync函数的偏移为56 */
int target = pmtx_ops + 56;
int payload = -((perf_table - target)/4) struct perf_event_attr event_attr;
event_attr.config = payload;
... /* 反复调用将fsync的值修改为合适的值 */
syscall(__NR_perf_event_open, &event_attr, 0, -1, -1, 0);
... /* 调用 */
int ptmx = open("/dev/ptmx", O_RDWR);
fsync(ptmx);

但是,linux系统中单个进程能够打开的file descriptor数量是有限制的,所以需要fork出足够多的进程,反复修改。

受影响的ROM

目前,测试了三款国内比较流行的手机,共4个ROM,该漏洞的情况如下:

|| Nexus 4 官方Rom 4.2.1|| 成功 || || Nexus 4 Cyanogenmod 10.1.2|| 内核已修补 || || Lenove 860i 官方ROM || 内核不支持perf_event || || Huawei U9508 官方ROM || 内核不支持perf_event ||

CVE-2013-2094 exploit for Android

【转】cve-2013-2094 perf_event_open 漏洞分析的更多相关文章

  1. 漏洞分析:CVE 2021-3156

    漏洞分析:CVE 2021-3156 漏洞简述 漏洞名称:sudo堆溢出本地提权 漏洞编号:CVE-2021-3156 漏洞类型:堆溢出 漏洞影响:本地提权 利用难度:较高 基础权限:需要普通用户权限 ...

  2. Java反序列化漏洞分析

    相关学习资料 http://www.freebuf.com/vuls/90840.html https://security.tencent.com/index.php/blog/msg/97 htt ...

  3. FFmpeg任意文件读取漏洞分析

    这次的漏洞实际上与之前曝出的一个 CVE 非常之类似,可以说是旧瓶装新酒,老树开新花. 之前漏洞的一篇分析文章: SSRF 和本地文件泄露(CVE-2016-1897/8)http://static. ...

  4. CVE-2016-10190 FFmpeg Http协议 heap buffer overflow漏洞分析及利用

    作者:栈长@蚂蚁金服巴斯光年安全实验室 -------- 1. 背景 FFmpeg是一个著名的处理音视频的开源项目,非常多的播放器.转码器以及视频网站都用到了FFmpeg作为内核或者是处理流媒体的工具 ...

  5. nginx漏洞分析与升级修复

    一 .此次漏洞分析 1 nginx HTTP/2漏洞 [nginx-announce] nginx安全公告(CVE-2018-16843,CVE-2018-16844)在nginx HTTP / 2实 ...

  6. Elasticsearch 核心插件Kibana 本地文件包含漏洞分析(CVE-2018-17246)

    不久前Elasticsearch发布了最新安全公告, Elasticsearch Kibana 6.4.3之前版本和5.6.13之前版本中的Console插件存在严重的本地文件包含漏洞可导致拒绝服务攻 ...

  7. ThinkCMF X2.2.2多处SQL注入漏洞分析

       1.     漏洞描述 ThinkCMF是一款基于ThinkPHP+MySQL开发的中文内容管理框架,其中X系列基于ThinkPHP 3.2.3开发,最后更新到2.2.2版本.最近刚好在渗透测试 ...

  8. 看个AV也中招之cve-2010-2553漏洞分析

    试想:某一天,你的基友给你了一个视频文件,号称是陈老师拍的苍老师的老师题材的最新电影.avi,你满心欢喜,在确定文件格式确实为avi格式后,愉快的脱下裤子准备欣赏,打开后却发现什么也没有,而随后你的基 ...

  9. CVE-2010-3971 CSS内存破坏漏洞分析

    看了仙果版主的议题演讲,其中提到cve-2010-3971是一个浏览器漏洞利用中的里程碑.于是找来POC,尝试分析一下. 1.漏洞重现 XP SP3+ie6.0环境 poc如下: poc.htm &l ...

随机推荐

  1. [OS] 进程互斥

    对互斥的正确软件实现算法(面包店算法)是非常耗时的,现代的计算机系统都会提供简单的硬件指令,使用这些指令能够有效地解决临界区问题. 硬件提供一个TestAndSet指令,来实现原子指令的功能: boo ...

  2. 利用FluidMoveBehavior制作出手机通讯录平滑的效果

    最近学习Blend,原来Blend制作动画等效果非常棒.下面演示一下FluidMoveBehavior应用,利用Blend中行为中的FluidMoveBehavior制作出手机通讯录平滑的效果 1.在 ...

  3. 小程序出现 “2 not found” 解决方案

    今天新建小程序的时候出现 ,控制台出现“2 not found” 报错. 解决方法: 在控制台输入  openVendor()  , 然后会弹出开发工具的文件夹,删除掉下图这两个程序,重启开发工具就可 ...

  4. RT-thread国产实时操作系统概述

    RT-Thread实时操作系统是一个分层的操作系统,它包括了: • 组件层components,这些是基于RT-Thread核心基础上的外围组件,把一些功能模块划分成独立的一个个组件模块,做到组件与组 ...

  5. BZOJ 1005 明明的烦恼(prufer序列+高精度)

    有一种东西叫树的prufer序列,一个树的与一个prufer序列是一一对应的关系. 设有m个度数确定的点,这些点的度为dee[i],那么每个点在prufer序列中出现了dee[i]-1次. 由排列组合 ...

  6. Navcat中Oracle连接的坑-Instant Client

    报错信息: 官方下载Instant Client下载: http://www.oracle.com/technetwork/cn/topics/intel-macsoft-102027-zhs.htm ...

  7. SGU - 282

    SGU - 282 题解 题意: 本质不同的集合:不存在两个方案重新编号之后对应的边集相同(对于所有x,y,,(x,y)边颜色都相同). (1≤ N≤ 53, 1≤ M≤ 1000) 对P取模 本质不 ...

  8. 创建JavaScript的哈希表Hashtable

    Hashtable是最常用的数据结构之一,但在JavaScript里没有各种数据结构对象.但是我们可以利用动态语言的一些特性来实现一些常用的数据结构和操作,这样可以使一些复杂的代码逻辑更清晰,也更符合 ...

  9. Samba共享传输大文件(ex:1G)失败的问题

    1:问题描述 1.1 基本信息 遇见这样一个bug,路由器有USB share的功能,可将U盘内的文件通过samba和LAN端PC机中文件进行共享,测试发现小文件可正常共享,一旦文件大了(比如1G左右 ...

  10. stout代码分析之七:Result类

    Result类似于Option和Try类的组合,内部有三种状态 enum State { SOME, NONE, ERROR }; SOME表示Result对象有值 NONE表示Result对象值为空 ...