议题简介
本议题《五颜六色的漏洞 - 从RGB到提权》是由CyberArk 实验室的Tal Lossos和Eran Shimony带来的。主要提出了对Linux内核第三方驱动 - 雷蛇系列产品的RGB驱动进行漏洞挖掘并完成本地提权漏洞利用的过程。主要从目标选取、漏洞挖掘方法、内核驱动交互模式、漏洞细节与漏洞利用等方面阐述一次完整的漏洞挖掘经历。
议题分析
开源与闭源
闭源需要逆向分析(废话),但闭源存在问题的概率更高,赏金可能更高。
开源提供代码(废话),挖洞更容易,可以使用很多静态分析工具。
挖掘方法:
逆向工程、代码审计、静态分析工具
fuzz:AFL、LibFuzzer、kAFL、syzkaller… 需要定制自己的测试套,需要花时间
dumb Fuzzer:只需知道内核中一个函数的参数是什么,然后只针对参数进行变异
目标选取
linux内核模块:linux内核是工作在用户层和硬件层之间的层级。提供给用户使用代码访问硬件的方式。linux内核模块是 Linux 内核的一部分功能,它们在系统运行时可被动态加载和卸载。内核模块使得内核具有了模块化的特性,可以按需求添加或者移除功能,而无需重新编译整个内核。这种设计极大地提升了 Linux 系统的灵活性和扩展性。
在内核模块中,第三方的内核模块更容易被发现漏洞,因为很少被别人挖。并且他们出现漏洞也会造成跟原生内核漏洞一样的后果,提权或者DOS。所以目标选择了OpenRazer,雷蛇硬件驱动:
雷蛇是一家大型游戏硬件公司,专注提供电竞外设,如鼠标键盘或者水杯(游戏外设???),当然现在游戏外设非常花里胡笑,自带各种RGB并且一定程度上实现灯光逻辑可编程,这就需要一些内核模块来控制设备,并提供用户控制和输入逻辑的接口。而雷蛇的驱动也提供了linux的版本。
然后我们需要知道如何在用户层和内核驱动通信,主要有以下几种方法:
- read/write:通过在内核模块中实现file_operations,用户层就可以向访问文件一样使用read/write系统调用访问驱动,实际调用的是驱动中实现的read和write回调函数。linux中万物皆文件。
- OTCTL:如果实现的功能很多很复杂,有很多情况,可以使用同样是file_operations中的IOCTL回调函数实现,IOCTL中可以使用switch处理多种传入的cmd操作码,处理多种情况。
- 伪文件系统:如sys文件系统,proc文件系统等。将每个功能变成上述伪文件系统中的一个文件,然后我们通过读写该文件的形式访问这些功能。使用sysfs_create_file内核函数在sys文件系统下创建一个访问文件。
- mmap:内存映射,使用file_operations中的mmap回调函数可以提供一个用户可以将内核页映射到用户空间的方法,然后用户和内核模块共同访问这段内存区域来进行交互。
- netlink:netlink是一种linux内部的通信协议,主要是用户层到内核模块或者内核模块中间通信使用。不同于TCP/IP网络协议,netlink的socket的对端是内核模块,自己端是进程,可以实现广播、单播、多播、异步等所有的报文式交互方式。
看看漏洞
查看雷蛇驱动的一些指令:
lsmod | grep razer
lsusb - 0x1532 #0x1532是厂商id
ls /sys/bus/hid/devices/XXX:VENDOR_ID:PRODUCT_ID.XXXX
echo -n "1" > /sys/bus.../matrix_effect_wave #水杯灯光自动变换接口...
寻找的目标漏洞:空指针解引用、缓冲区溢出、整数上下溢等
漏洞案例
传入参数start_col和stop_col都是我们可控,计算获得的row_length最大是768,然后会作为长度用于下面的memcpy,但memcpy 的目的缓冲区repor.arguments总长度只有80,造成溢出。
类似的漏洞在鼠标、键盘、水杯都有。
漏洞利用
我们现在有一个缓冲区溢出的漏洞原语,尝试完成利用。
采用modprobe_path的利用方法,在linux内核中,我们执行一个文件的时候,linux内核会判断这个文件的类型, 然后使用正确的方式执行它,一般是通过文件头去判断。如果我们执行了一个linux内核不认识的文件格式,那么linux内核就会调用modeprobe_path指向的文件去执行这个文件。
重要的是,这里是由内核启动modeprobe_path,这使得它拥有root的权限,默认情况下modeprobe_path指向/sbin/modprobe这个文件。但我们可以通过一些内核漏洞篡改modeprobe_path指向的文件路径,modeprobe_path本质是一个存储在内核bss段的文件路径字符串,可以被篡改。如果我们将其指向恶意文件,就可以让内核以root权限执行我们的恶意文件。
防御
glibc提供了一个默认的安全功能fortify,他使得可以在编译阶段进行安全检查来预防和发信啊常见的编程错误。在最新6.1模式已经堆memcpy开启缓冲区溢出缓解:
在目标漏洞内核模块中,开启fortify后编译成这个样子,多加了一句判断和报错:
总结
这个议题给我们讲述了一个完整的第三方内核模块漏洞挖掘的过程,漏洞比较简单易懂,他们的目标选取比较好,第三方外设驱动的内核模块,逻辑比较简单好分析,并且暴露给用户面的接口也很多。值得学习。