奇安信天工实验室技术博客

👋 奇安信天工实验室,聚焦真实世界漏洞分析。漏洞研究成果曾发表于DEFCON、BlackHat、GeekCon、HITB、ACM CCS、Usenix、EuroS&P、RAID等国际重量级会议。

  • 团队研发的破壳平台,提供基于查询、面向团队协作的漏洞辅助分析能力。

探索协程世界:原理、现实与漏洞模式(下)

在本文的上篇关于协程相关理论的介绍后,相信读者已经对协程有了大致的认识,所以接下来将会介绍在过去发生过的与协程相关的安全问题。因为协程在不同语言的实现差异,会导致其呈现的形式也会有所差异。本篇将选取几个比较有特征的案例介绍。 一、anyio - Race Condition 这个问题并没有获得CVE编号,是用户进行测试的时候发现的。anyio是一个 Python 异步网络并发库,可以在trio或者asyncio上运行。其完美的兼容了asyncio和trio,可以很方便的让代码进行重构。 然而这个库存在一个奇怪的问题,当尝试使用多线程访问这个库的时候,有概率触发一个库未初始化的问题。经过开发者定位,错误的代码位置如下: def get_async_backend(asynclib_name: str | None = None) -> AsyncBackend: if asynclib_name is None: asynclib_name = sniffio.current_async_library() modulename = "anyio._backends._" + asynclib_name try: module = sys.modules[modulename] except KeyError: module = import_module(modulename) return getattr(module, "backend_class") 这段代码的逻辑本质上为取出anyio中视线的另一个module对象并返回。实际上,在普通程序中他也被这样使用: async def sleep(delay: float) -> None: """ Pause the current task for the specified duration. :param delay: the duration, in seconds """ return await get_async_backend().sleep(delay) 可以看到,其取出来的库是提供支持协程异步函数的库。然而,这种写法其实存在一定的迷惑性。例如: async def func(d): await asy()....

2025年02月19日 · 10 分钟 · l1nk

探索协程世界:原理、实现与漏洞模式(上)

一、前言 在操作系统中,每当谈及异步,通常都是使用多线程/多进程来实现多任务的执行。然而在现代开发过程中,往往会听到一个新的概念:协程。这是一种更轻量化的并发处理模型,协程被广泛集成到诸如 Go、JavaScript、Rust 和 Python 等主流语言中,成为异步编程的核心工具。为了更好地理解协程,从而探究协程中可能存在的相关的安全问题,文章将简要介绍协程的起源与基本概念,然后通过分析协程模型的特点揭示潜在的安全风险,最后结合真实的漏洞案例,展示协程可能引发的安全隐患,并讨论如何更有效地规避这些问题。 由于内容较多,文章将分为上下两篇。在本文上篇中,会介绍协程的定义,包括常见的协程的用途以及协程在代码中的形式,接下来会给大家一个直观的感受,推断协程是如何诞生的。 二、什么是协程 关于协程的定义,这里直接摘自AI: 协程与传统函数调用的主要区别在于控制权的转移和状态的保存,这使得协程可以在中途挂起并在稍后恢复。 总结来看,协程具有如下的特征: 它不是一个由操作系统提供的特性,它是基于语言层面模拟的一个效果; 调度需要显示的声明起转换过程。 这里需要注意的是,协程于线程并非是同一个层级的概念,协程是一个用户态模拟的概念,而线程属于操作系统的原生概念。 通常,协程挂起的时候,会保存当前的上下文,包括栈堆以及寄存器等等。 由于协程非一个存在于操作系统的概念,所以对于操作系统而言,它并非真实存在,这就导致传统的调试器无法直接看到它,也就不存在直接观察它的办法。为了能对其有一个比较感性的认知,我们可以尝试先从编程语言中感受它的存在形式。在不同于语言中,协程的呈现形式也不同。比如在python中,协程的函数一般长成这样: import asyncio async def my_coroutine(): print("Start coroutine") await asyncio.sleep(1) print("End coroutine") async def main(): print("Start main") await my_coroutine() print("End main") ## Run the main function asyncio.run(main()) 其输出如下: Start main Start coroutine End coroutine End main 可以看到有几个关键点: 程序以异步的形式运行; 存在async/await关键字,被声明的函数才具有协程异步的能力; 需要使用asyncio.run将其包裹。 在协程使用更加广泛的go语言中,协程的代码如下所示: package main import ( "fmt" "time" ) func asyncTask(done chan string) { time.Sleep(2 * time....

2025年02月12日 · 6 分钟 · l1nk

Java XStream 反序列化:Gadget 挖掘思路分享

0x01 前言 Java语言中最常见的一类漏洞就是反序列化漏洞,在各种数据格式到Java对象的转化过程中,常常存在这类漏洞。常见的数据类型例如jdk提供的原生序列化数据、json、yaml、xml等等。针对这类漏洞存在一种特别的漏洞挖掘方式—Gadget挖掘,这种漏洞挖掘不需要去寻找特定的外部入口漏洞入口,入口往往是公开的,应用通过对传入的数据内容进行过滤和检查。XStream是一款针对XML和Java对象转换而开发的工具库,由于其本身的一些特点,成为了这类漏洞挖掘里一个很典型的例子,因此本文针对XStream进行Gadget挖掘分析。本文更多的是分享Gadget挖掘时的思路,进而可以在其他类型的序列化中进行类似的思考和尝试。 0x02 XStream简介 XStream是一个常用的Java对象和XML相互转换的Java库。 从java对象到XML: 从XML到Java对象: XStream在1.4.18版本以前是存在许多CVE的,核心原因在于的它使用类的黑名单进行防御,因此层出不穷的绕过,在1.4.18版本以后默认为白名单,用户需要自行根据需要使用的类进行配置,到这个版本XStream才没有继续爆出高危的反序列化漏洞。 值得一提的是,XStream中有CVE编号的利用链都是不依赖任何第三方库,纯利用JDK中的类进行利用,由此可见XStream对于反序列化的宽泛程度。 0x03 历史漏洞 简单介绍一下XStream反序列的特点。反序列化漏洞的本质是,基于可以利用的Java类:序列化数据流→Source→Gadget→Sink。 对于原生的Java反序列化来说,可以利用的Java类是任意实现了Serializable的类,入口是ObjectInputStream的readObject方法。 对于XStream来说,可以利用的Java是任意类,入口是XStream的fromXML方法。 以一个经典的CVE-2013-7285来说,poc如下,执行的sink是ProcessBuilder.start() XStream中有一系列的Converter,用于对不同的标签进行转化。 这里sorted-set标签对应的是TreeSetConverter,它的代码逻辑中会调用TreeMap的put方法,而TreeMap的put方法会调用方法的compare方法对传入Map的对象进行判断对象应该存放的位置 public V put(K key, V value) { ... // split comparator and comparable paths Comparator<? super K> cpr = comparator; if (cpr != null) { do { parent = t; cmp = cpr.compare(key, t.key); if (cmp < 0) t = t.left; else if (cmp > 0) t = t.right; else return t.setValue(value); } while (t !...

2025年01月22日 · 4 分钟 · yyhy

Android保护机制及利用技巧总结

一、前言 本文总结了在Android上利用漏洞时遇到的一些新的保护机制以及在真机上的内核漏洞利用和调试技巧。虽然Android底层为Linux内核,但是相比较下Android内核更加难利用,主要体现在真机不能实时调试,可能开启了BTI保护、PAC保护和CFI保护,同时在近年新出的一些手机,如Pixel 10开启了内存标记访问保护Memory Tagging Extension(MTE)。本文还将介绍MTE保护在用户态时的一个特殊的绕过方法,通过探讨这些新的保护机制及其应对策略,我们希望能够帮助读者更好地理解当前Android安全环境,并为未来的漏洞研究提供新的思路和技术手段。 二、真机内核利用适配 对于一个真机内核,在编写漏洞利用程序期间可以编译一个版本一样的Linux内核用qemu模拟运行,便于掌握数据的处理过程。还可以使用Android模拟器,目前高版本的Android模拟器无法在x86/x64架构下模拟AARCH64的镜像,可以在AARCH64架构下的主机,如树莓派等下面运行模拟器。在模拟的内核中利用成功后,就是如何将其移植到真机上的问题。虽然真机不能实时调试,但是可以通过查看/sys/fs/pstore/目录下的日志文件以及dmesg来获取内核最后崩溃时的寄存器值。根据寄存器信息来定位漏洞利用程序中需要适配的位置。 root@apalis-imx8:~$ cat /sys/fs/pstore/dmesg-ramoops-0 Panic#1 Part1 <6>[ 0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd034] <5>[ 0.000000] Linux version 5.4.77-5.1.0-devel+git.a2f08dfd79ae (eichest@eichest-laptop) (gcc version 10.2.0 (Ubuntu 10.2.0-8ubuntu1)) #19 SMP PREEMPT Tue Apr 6 17:18:18 CEST 2021 <6>[ 0.000000] Machine model: Toradex Apalis iMX8QM V1.1 on Apalis Evaluation Board ... <6>[ 64.111102] sysrq: Trigger a crash <0>[ 64.114539] Kernel panic - not syncing: sysrq triggered crash <4>[ 64....

2025年01月15日 · 3 分钟 · ha1vk

CVE-2024-38054 Windows ksthunk.sys驱动提权漏洞分析

0x00 前言 最近,windows的Kernel Streaming框架出现了许多漏洞,本文通过分析CVE-2024-38054来了解一下Kernel Streaming这个攻击面。 CVE-2024-38054由 Angelboy提交给微软,在今年7月份修补的一个堆溢出漏洞。该漏洞在ksthunk.sys。驱动的作用是将WOW64(Windows 32-bit on Windows 64-bit)程序对使用Kernel Streaming框架的设备发起irp请求转化为64位的irp请求。以便后续处理无需区分wow64程序和正常64位程序。 目前由Fr0st1706编写的CVE-2024-38054的poc已经在GitHub公开。 0x01 Kernel Streaming框架简介 Kernel Streaming框架主要为windows中的音频、视频等设备提供支持。Kernel Streaming框架提供三种多媒体类驱动模型: port类, stream类和 AVStream类。 port 类是指用于 PCI 和基于 DMA 的音频设备。 stream类是指视频类设备。 AVStream 是 Microsoft 提供的多媒体类驱动程序,支持纯视频流和集成音频/视频流。 kernel steam架构如下所示: 由于音视频类的驱动大多是pnp类型的驱动,在windows中的设备不是类似\Devcie\NamedPipe的形式。而是类似下面形式: \\?\root#system#0000#{cf1dda2c-9743-11d0-a3ee-00a0c9223196}\{cfd669f1-9bc2-11d0-8299-0000f822fe8a}&{cf1dda2c-9743-11d0-a3ee-00a0c9223196} 如果想枚举pnp设备的路径的话,比较方便的方式是使用windows自带的工具: pnputil /enum-interfaces 也可以使用WDK提供的工具KsStudio来查看使用Kernel Streaming框架的驱动,我目前在win10下面测试正常,win11 ksmon.sys加载不上去。以wdk 10.0.26100.0为例,该程序的位置在:C:\Program Files (x86)\Windows Kits\10\Tools\10.0.26100.0\x64 中。该工具显示信息比较详细,对于某一项还是会有缺失。 另外一个缺点是筛选的种类有限,例如mskssrv.sys的类别是KSSTRING_Server 类别是{3C0D501A-140B-11D1-B40F-00A0C9223196}就没有在列表中。 在Kernel Streaming框架中有两个比较重要的内核对象种类:KS Filters 和 KS Pins ks filters是由微型端口驱动提供的filter factory创建的,用户态程序可以发起irp请求基于filter实例创建ks pin,然后使用ks pin实现向filter提交nodes 或者读取经过filter的数据。 0x02 pnp设备注册逻辑 以mskssrv.sys为例,可以在C:\Windows\INF\ks.inf中DeviceRegistration节中找到注册逻辑 可以看到在DeviceRegistration节中对HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce 写入 rundll32.exe streamci,StreamingDeviceSetup {96E080C7-143C-11D1-B40F-00A0C9223196},{3C0D501A-140B-11D1-B40F-00A0C9223196},{3C0D501A-140B-11D1-B40F-00A0C9223196} 这个表示只会执行一次,执行streamci....

2025年01月08日 · 3 分钟 · pwnht

WSGI中的请求走私问题研究

一、WSGI介绍 WSGI是一种规范,描述了web server如何与web application通信的规范。 WSGI规范是为python生态定义的,符合WSGI接口的server如下所示: def application(environ, start_response): start_response('200 OK', [('Content-Type', 'text/html')]) return '<h1>Hello, web!</h1>' environ:一个包含所有HTTP请求信息的dict对象; start_response:一个发送HTTP响应的函数。 WSGI server负责完成http请求解析到environ的映射过程,这样python的Web框架可以专注于业务逻辑,直接使用解析好的http请求对象。 二、请求走私 2.1 keep-alive 与 pipeline 为了缓解源站的压力,一般会在用户和后端服务器(源站)之间加设前置服务器,用以缓存、简单校验、负载均衡等,而前置服务器与后端服务器往往是在可靠的网络域中,ip 也是相对固定的,所以可以重用 TCP 连接来减少频繁 TCP 握手带来的开销。这里就用到了 HTTP1.1 中的 Keep-Alive 和 Pipeline 特性: 所谓 Keep-Alive,就是在 HTTP 请求中增加一个特殊的请求头 Connection: Keep-Alive,告诉服务器,接收完这次 HTTP 请求后,不要关闭 TCP 链接,后面对相同目标服务器的 HTTP 请求,重用这一个 TCP 链接,这样只需要进行一次 TCP 握手的过程,可以减少服务器的开销,节约资源,还能加快访问速度。这个特性在 HTTP1.1 中是默认开启的。 有了 Keep-Alive 之后,后续就有了 Pipeline,在这里呢,客户端可以像流水线一样发送自己的 HTTP 请求,而不需要等待服务器的响应,服务器那边接收到请求后,需要遵循先入先出机制,将请求和响应严格对应起来,再将响应发送给客户端。现如今,浏览器默认是不启用 Pipeline 的,但是一般的服务器都提供了对 Pipleline 的支持。 http消息处理过程中出现两次http解析就可能出现走私,常见的情景里,容易出现在Content-Length 和 Transfer-Encoding 的处理差异中。而WSGI中进行了一次http请求解析,并且经常置于nginx等中间件后使用,所以也容易出现请求走私问题。 三、WSGI server中的走私问题 3....

2024年12月25日 · 5 分钟 · m4yfly

硬件辅助虚拟化及Fuzzing工作研究

一、前言 在IaaS的云平台架构中,VMM(Virtual Machine Manager,也称为Hypervisor)将宿主机物理资源分配给多个客户机使用,租户拥有对客户机的控制权。VMM在不同的客户机之间实现隔离,保证租户之间互不影响。但恶意的租户可能会利用VMM的安全漏洞,逃逸到宿主机上,并进一步危害宿主机上的其他客户机,因此,在攻击者之前发现并修复VMM中的漏洞,是保证云安全的重要工作之一。 下面将依次介绍,虚拟化的背景知识、现有对VMM进行模糊测试的工作、以及VMM相关CVE的case study。 二、硬件辅助虚拟化(以Intel VT为例) 2.1 VT-x (Virtualizition Technology for X86):CPU虚拟化 处理器引入了两种操作模式: VMX Root Operation:VMM(虚拟机监控器)运行的模式,简称根模式。 VMX Non-Root Operation:Guest(客户机)运行的模式,简称非根模式。 每种模式都对应着不同的ring0-ring3特权级别。当处理器从非根模式切换到根模式时,称为VM-Exit;而当处理器从根模式切换到非根模式(例如,VMM调度某个客户机运行)时,称为VM-Entry。 此外,Intel VT-x引入了VMCS(Virtual Machine Control Structure),该结构用于保存虚拟CPU的状态信息。例如,在模式切换时,VMCS会保存处理器状态,如RIP(指令指针)的值,以及两种模式下控制寄存器的值等。VMM可以通过修改VMCS中的内容,来影响CPU的行为。 VT-x还新增了一些指令,用于虚拟化控制: VMLAUNCH/VMRESUME:用于触发VM-Entry。 VMREAD/VMWRITE:用于读取或写入VMCS。 VMXON/VMXOFF:用于进入或退出VMX模式(是否可以执行VMXON取决于处理器的支持)。 VMX的lifecycle如下图所示,首先,软件通过执行VMXON指令进入根模式。在此模式下,VMM可以通过VM Entry(使用VMLAUNCH和VMRESUME指令)加载客户机运行,处理器切换到非根模式。当遇到客户机无法处理的情况,会通过VM Exit将控制权转交给VMM,处理器切换回根模式。VMM可以根据VM Exit的原因采取相应的操作,处理后再通过VM Entry重新加载客户机运行。最后,VMM可以通过执行VMXOFF指令退出VMX操作模式,结束VMX的lifecycle。 VCPU VCPU描述符类似进程描述符,本质是一个结构体,除了VMCS以外,这个结构体还包含VCPU标识信息(例如属于哪个客户机)、VCPU状态信息(例如睡眠还是运行)等,主要供VMM调度时使用。VMM创建客户机时,首先要为其创建VCPU,客户机的运行就是VMM调度不同的VCPU运行。 VCPU的创建 创建VCPU描述符实际上是分配相应大小的内存并进行初始化,具体的初始化内容包括: 分配VCPU标识:标识该VCPU所属的客户机。 初始化虚拟寄存器组:主要就是指初始化VMCS的相关域。 初始化VCPU的状态信息。 初始化额外部件:包括未被VMCS覆盖的寄存器和虚拟LAPIC等部件的配置。 初始化其他信息:根据VMM实现的不同,对VCPU的私有数据进行初始化。 其中,VMCS初始化包括以下几个部分: 客户机状态域:根据物理CPU初始化的状态来设置。例如,物理CPU加电后跳转到BIOS,GUEST RIP字段会设置为虚拟机BIOS的起始地址。 宿主机状态域:参考VMM运行时CPU的状态,用于描述VM-Exit时,CPU切换回根模式时的寄存器值。例如,HOST RIP通常设置为VMM中VM-Exit处理函数的入口地址。 VM-Execution控制域:设置哪些特权指令会触发VM-Exit。 VM-Exit控制域:通常由VMM设置,控制一些字段,如Acknowledge interrupt on exit,有助于快速响应外部中断。 VCPU的运行 当VMM调度VCPU到物理CPU上运行时,需要进行上下文切换,既包括硬件自动切换(VMCS部分),也包括VMM软件切换(非VMCS部分,如浮点寄存器)。具体步骤如下: VMM保存自己的上下文:VMM保存VMCS中未包含的寄存器内容。 加载VCPU上下文:VMM将VCPU中由软件切换的上下文加载到物理CPU。 执行VMLAUNCH/VMRESUME:VMM通过执行VMLAUNCH/VMRESUME指令触发VM-Entry,CPU自动将VCPU中的VMCS部分加载到物理CPU,并切换到非根模式。 \ VCPU的退出 与进程类似,VCPU作为调度单位不会一直运行,它会因为执行特权指令、物理中断等原因发生退出,这种退出称为VM-Exit。发生VM-Exit时,VMM的处理流程如下: VM-Exit发生时,CPU自动进行部分上下文切换。 CPU切换到根模式,并执行VM-Exit的处理函数。 \ 当发生VM-Exit时,相关的处理函数由VMM实现。该处理函数负责根据触发VM-Exit的原因采取相应的处理。虽然VM-Exit的原因可能各不相同,但这些原因的代码可以在Intel的开发者手册中找到。下图截取了手册中的部分exit reasons。 \ VCPU的再运行 当VMM处理完VM-Exit后,会重新调度VCPU继续运行。如果VCPU继续在同一物理CPU上执行,可以通过VMRESUME指令实现VM-Entry。若VCPU被调度到另一物理CPU上运行,由于VMCS与物理CPU是一对一绑定的,VMM需要将VMCS重新绑定到新的物理CPU,然后通过VMLAUNCH指令触发VM-Entry。...

2024年12月18日 · 4 分钟 · tiangong

vCenter漏洞分析:CVE-2024-37079 & CVE-2024-37080

一、前言 CVE-2024-37079 和 CVE-2024-37080 是两个存在于DCERPC组件中的漏洞,攻击者可以通过构造恶意请求,在远程触发 vCenter Server 上的任意代码执行。这些漏洞位于 DCE/RPC 协议中,具有 vCenter Server 网络访问权限的远程攻击者可以通过发送特制的网络数据包,在 DCERPC 协议实施过程中触发堆溢出漏洞,从而实现远程代码执行。。目前两个漏洞已报送厂商并于6月份修复完成。本文将详细讲解两个漏洞的成因。这两个漏洞已于2024年6月报送厂商并修复完成。本文将详细分析这两个漏洞的成因。 二、DCE/RPC协议介绍 DCE/RPC协议(Distributed Computing Environment / Remote Procedure Call)源于20世纪80年代,由Open Software Foundation(OSF)开发,作为开放分布式计算架构的一部分。其最初设计目的是为跨网络的异构计算机系统提供一种统一的远程过程调用(RPC)机制,从而简化不同系统之间的通信。随着网络技术的发展,DCERPC逐渐被广泛应用,特别是在Unix、Windows NT等系统中。微软在采用DCERPC协议的基础上进行了扩展,用于Windows系统中的重要服务和应用程序,尤其在Windows NT中用于SMB(Server Message Block)协议。由于微软的广泛采用,DCE/RPC成为了企业网络和操作系统中不可或缺的通信协议。 DCE/RPC协议为了实现远程过程调用,使用接口定义语言(IDL)定义接口。在IDL代码中定义了UUID,版本,接口,方法,参数,返回值以及使用到的复杂数据类型等信息。服务端和客户端通过共享这些信息完成远程过程调用的通信,其中UUID作为接口标识用于客户端向服务端发送绑定请求,建立上下文。 DCE/RPC远程过程调用通信的流程(如图一)通常如下: 客户端初始化请求:客户端向服务器发起绑定请求(Bind),选择所需的远程接口,提供接口UUID和版本号,并协商通信协议和数据传输语法(如NDR)。 服务器响应绑定:服务器接收到客户端的绑定请求后,确认是否支持请求的接口UUID、版本号和传输语法。如果支持,返回绑定确认(Bind Ack),否则返回绑定失败(Bind Nack)。 客户端发送调用请求:在成功绑定后,客户端构造远程过程调用的请求(Request)消息,包含所调用的方法及其参数,并将这些参数进行编组(序列化)。 服务器处理请求:服务器接收到请求消息后,解组请求中的参数,调用相应的本地方法进行处理。处理完成后,服务器将结果重新编组并发送响应(Response)消息。 客户端接收响应:客户端接收到响应消息后,解组数据并获取调用结果。如果调用过程中发生错误,服务器会返回故障消息(Fault),客户端需进行相应处理。 上下文修改请求:如果客户端需要更改通信中的上下文(如修改接口、更新权限或改变数据传输语法),客户端可以发送Alter Context Request,请求修改现有的上下文参数。 上下文修改响应:服务器接收到Alter Context Request后,检查请求的上下文修改是否有效。如果上下文修改成功,服务器返回Alter Context Response,确认新的上下文已生效。如果修改失败,服务器返回错误信息,客户端可以重新发送修改请求或终止会话。 客户端解除绑定:在完成所有调用后,客户端可以选择发送解除绑定请求(Unbind),通知服务器结束通信。 三、漏洞分析 2.1 CVE-2024-37079 CVE-2024-37079出现在bind认证数据包的响应处理过程中。负责处理认证的函数rpc__cn_assoc_process_auth_tlr 的函数声明如下,其中参数header_size 为((pres_cont_list->n_context_elem - 1) * 0x18) + 0x1c + 0x20 INTERNAL void rpc__cn_assoc_process_auth_tlr ( rpc_cn_assoc_p_t assoc, rpc_cn_packet_p_t req_header, unsigned32 req_header_size, rpc_cn_packet_p_t resp_header, unsigned32 *header_size, unsigned32 *auth_len, rpc_cn_sec_context_p_t *sec_context, boolean old_client, unsigned32 *st ) pres_cont_list->n_context_elem 的值来源于与数据包的Num Ctx Items字段...

2024年12月11日 · 4 分钟 · zhz

系统文件管理行为漏洞导致本地提权

一、前言 近期,符号链接在本地提权利用中的比重逐渐增加。无论是macOS、Windows、Linux操作系统,还是其第三方安装的应用程序,都可能使用符号链接。越是底层的函数调用,开发者越需要关注相关漏洞模式及函数参数传递的安全性。 一个漏洞的产生通常是由于在使用API函数时未充分考虑潜在的漏洞模式。如果在执行过程中存在恶意行为对这些函数进行修改,防护措施不严格会导致执行流程走向错误的分支,最终被攻击者利用。下面将以open和rename两个基础函数为例,介绍多个相关漏洞。 二、函数介绍 2.1 OPEN函数 open函数是C语言中的一个基础函数,主要用于打开文件并返回一个文件描述符。其他函数可以通过这个文件描述符对文件或目录进行读写操作。其函数原型如下: #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode); open函数存在三个参数: mode: 可以在调用时省略第三个参数mode,在创建新文件的时候,会通过此参数修改新文件的文件属性; pathname: 用于一个指向文件或者文件夹的路径,可以为绝对路径也可以为相对路径; flag: 作为open函数最重要的一环,参数flag能赋予的值有各种,不同的flag字段代表着不同的功能。 2.2 RENAME函数 rename函数作为C语言中的一个基础函数,主要用于处理文件或目录的移动和重命名。该函数不会修改文件或目录的属性。其函数原型如下: #include <stdio.h> int rename(const char *oldpath, const char *newpath); rename函数只有两个参数,一个是指向旧文件的字符串指针,另一个是指向想要修改后的新文件字符串指针。无论是哪一个参数,它都不会去检测访问路径是否是符号链接,即目录是通过符号链接访问的依旧会执行。反之,若是指向的最终文件/目录是符号链接,rename不会对其访问,只有在访问过程中的目录路径属于符号链接时才会进入。 三、行为检测与漏洞分析 通常,对于系统调用号的检测,在Linux上有成熟的方法。在macOS上,也有专门用于监控文件行为的系统命令fs_usage。fs_usage可以实时监听系统用户态上对文件的各种操作行为,包括文件状态获取、读写操作以及页面交换等。通过使用fs_usage,开发者和安全研究人员能够详细地跟踪和分析文件相关的系统活动,从而更好地理解和诊断文件操作中的问题。 如上图所示,可以配合grep命令获取对应进程的相关行为。通过该命令,可以简化对文件流处理的追踪,直接从所执行的系统行为或系统调用中定位到具体的代码。 对于编程语言而言,它们提供了许多封装好的API函数。在Objective-C和Swift中,也有相当多的函数底层实现可以进行分析。这些封装好的API函数不仅简化了开发过程,还为开发者提供了强大的功能。通过对这些底层实现的分析,可以更好地理解其工作原理,并在必要时进行优化或调试。 此处编写一个使用moveItemAtPath:toPath:函数的示例代码,并为rename函数设置断点。通过这种方式,可以发现最终实现也会调用rename函数。 3.1 CVE-2020-9900 文件写入自定义目录 在macOS系统中,后台存在一个以root权限启动的进程,即CrashReporter。该进程负责收集系统各种崩溃报告和日志,并将其存放于/Library/Logs/DiagnosticReports和~/Library/Logs/DiagnosticReports目录中。这两个目录的所属用户是_analyticsusers,而默认用户通常属于admin用户组,因此默认用户拥有读写上述两个目录的权限。 如上图所示,系统会根据报告生成的时间和进程名等字段,将崩溃报告存放于指定目录中。在这些目录中,存在一个名为Retired的子目录。报告的存放时间是有期限的,当报告超过这个期限时,另一个以root权限启动的进程SubmitDiagInfo会将旧报告移动到Retired目录中。由于SubmitDiagInfo同样是以root权限运行的进程,在没有沙箱等安全规则干扰的情况下,它在访问相关root权限的目录或文件时不会因为权限不足而受到限制。 fmyy@Macbook_M1 DiagnosticReports % ps -ef |grep SubmitDiagInfo 0 1043 1 0 一10上午 ?? 0:03....

2024年12月04日 · 3 分钟 · fmyy

CVE-2018-9568漏洞分析和利用

一、前言 CVE-2018-9568是一个Linux内核中的类型混淆漏洞,Zer0Con2019有研究人员分享了利用该漏洞root Android的思路,并给漏洞命名为WrongZone。这是一个影响范围较广的漏洞,本文记录了学习分析该漏洞及在 x86_64 Linux 完成利用的过程。 二、漏洞分析 2.1 补丁 该漏洞的补丁链接:commit 9d538fa60bad4f7b23193c89e843797a1cf71ef3 diff --git a/net/core/sock.c b/net/core/sock.c index 9b7b6bbb2a23e7..7d55c05f449d30 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1654,6 +1654,8 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority) sock_copy(newsk, sk); + newsk->sk_prot_creator = sk->sk_prot; + /* SANITY */ if (likely(newsk->sk_net_refcnt)) get_net(sock_net(newsk)); 补丁代码很简单,只有一行赋值代码,因此sk_prot和sk_prot_creator是该漏洞的关键。 sk_prot与sk_prot_creator 它们都是struct sock结构体的成员: struct sock { /**/ struct sock_common __sk_common; /**/ #define sk_prot __sk_common.skc_prot /**/ struct proto *sk_prot_creator; }; struct sock_common { /**/ struct proto *skc_prot; /**/ }; sk_prot_creator和sk_prot(即skc_prot)在源码中的定义如下:...

2024年11月27日 · 4 分钟 · clingcling