资讯详情

资讯详情

Linux触摸板驱动UAF漏洞:“幽灵点击”前因后果与排查实战

有段时间我调一台一体机的触摸板现象很邪门机器放在桌上没人碰光标偶尔自己跳一下甚至出现一次“无人参与的点击”刚好选中了桌面上的一个文件。我一开始以为是硬件接触不良拆机、换排线、加屏蔽折腾一轮都没用。最后把事件流打出来一看物理触点那里干干净净问题出在驱动自己生成的逻辑事件上。后来翻内核CVE列表发现这类问题比想象中常见——CVE-2023-52840就是其中典型触摸板驱动里存在一处内存生命周期缺陷可以在设备重连或休眠唤醒时触发悬垂指针让系统在没有任何真实触碰的情况下上报点击。安全圈把这个现象叫“幽灵点击”听起来带点玄学本质却是一个非常经典的use-after-free漏洞。这类漏洞值得聊不只是因为影响面覆盖大量笔记本和一体机设备更因为它动摇了系统里“输入事件可信”的假设。触摸板在主流操作系统里被当作高可信输入设备锁屏解锁、权限确认、支付弹窗都依赖对物理按压的信任。驱动一旦在无人触碰时伪造出点击信号就等于给攻击者开了一扇GUI层面注入的窗户。这篇文章我不打算只贴一个公告链接而是按照我实际排查的思路把整条链路拆开漏洞怎么定性、驱动代码里哪一步写错了、攻击者要付出多大代价才能利用、我们用什么手段复现和追证据最后是补丁和缓解方案。适合内核驱动开发、设备安全测试和做系统运维的朋友参考。1. 定性一个输入设备CVE为什么值得上心1.1 CVE编号背后的标准流程CVE编号不是随便分配的它由编号机构在厂商或研究员提交详细报告后审核发布。拿到一个CVE意味着漏洞已经被社区确认不再是“可能存在问题”而是“确实存在、且需要排期修复”的官方认证。CVE-2023-52840从编号年份看是2023年报出的问题类型属于Linux内核触摸板驱动模块的释放后使用也就是我们常说的UAF。从评分上看这类输入设备漏洞的CVSS基础分通常不会高得吓人一般落在中危到中高危区间。原因也直白触发它往往需要本地物理接触或特定设备事件配合不像网络漏洞那样能隔着网线直接打。但我在实际评估中一直有个观点——CVSS对输入设备的低估是结构性的因为它衡量的是“直接可利用性”而不是“信任被破坏后的连锁反应”。一个能伪造点击的驱动缺陷在真实攻击链条里往往不是终点而是绕过前端安全校验的“钥匙”。1.2 操作系统把触摸板当可信输入设备我们平时不会意识到一个底层假设操作系统安全机制默认“触摸板/触摸屏上报的事件是可信的”。锁屏界面的密码输入、权限弹窗的“是/否”按钮、指纹验证后的确认步骤本质上都是把“存在一次物理输入”当作“用户本人同意”的证据。这个假设在正常硬件下是成立的。物理设备只有人用手触碰时才会产生电信号信号变成内核事件再变成用户态的一次点击中间链路相对干净。但UAF打破的正是这里驱动在无人触碰时凭空生成一个点击事件而且这个事件走的是完全正常的input子系统通道桌面环境根本无法区分它和真实手指点击的差别。这就像门禁系统的门把手在没人触碰时自己转了一下——门禁读卡器再安全门把手自己动了整个信任链就出了问题。我在评估这类漏洞时最常提醒团队的一句话是不要问“攻击者能不能直接拿到root”而要问“如果锁屏界面上的某个按钮被自动点击会发生什么”。这样一想幽灵点击的价值立刻清晰起来。1.3 幽灵点击和普通触控误触是两种病很多朋友看到“幽灵点击”第一反应是“我电脑触摸板也有乱跳问题”这里必须把两类现象严格分开。特征普通物理误触驱动UAF幽灵点击触发来源电容信号噪声、手掌误贴、电磁干扰驱动逻辑层凭空生成物理层证据evtest能看到触点坐标漂移、压力值异常evtest显示无物理信号但BTN_TOUCH被置位复现稳定性与环境、手势相关不稳定与热插拔/休眠时序相关可脚本化复现危害误操作影响体验可被利用绕过输入可信假设我遇到过不少设备被说“触摸板闹鬼”最后查明是电源适配器接地不好造成电容噪声。那种情况evtest里坐标数值会贴着某个角落轻微跳动和UAF产生的完整点击事件有明显区别。下一节我们进代码里看看真正的UAF长什么样。2. 漏洞根因一块被提前释放的触摸状态内存2.1 一条点击从物理到应用要过几道门一条触摸板点击事件从手指到应用至少要经过五个环节触摸控制器采集物理信号固件把它组装成HID报告内核HID驱动解析报告input子系统分发事件最后由桌面环境的libinput之类组件转成GUI操作。中间每个环节都有结构体在传递状态最关键的叫“设备私有数据”通常由一个结构体指针挂在驱动和input设备之间。这个结构体保存当前触点数量、slot状态、坐标缓存、工作队列等运行时信息。驱动正常工作时每次触摸事件都会读写这块内存并在合适的时机调用input_report_key和input_sync上报。问题恰恰出在“合适时机”这四个字上。很多触摸板驱动为了提高吞吐会把事件上报放到异步工作队列里而不是在中断上下文里立即执行。这就引入了一个时间差事件处理函数可能还排在队列里设备却已经被拔出或进入低功耗模式。时间差意味着“什么先发生”不再是确定性的一旦设备先销毁了状态结构体队列里的处理函数再跑起来就会踩进一块已经释放的内存。2.2 缺陷模式释放后的悬垂引用下面是这类驱动中非常典型的UAF模式我以通用代码示意不是某个厂商的原样代码但结构几乎一致struct touch_dev { int slot_count; int *slot_state; // 触点状态数组 struct input_dev *input; struct work_struct report_work; }; static void touch_report_worker(struct work_struct *work) { struct touch_dev *ts container_of(work, struct touch_dev, report_work); // 访问已被释放的 slot_state就是这一行踩进了悬垂内存 input_report_key(ts-input, BTN_TOUCH, ts-slot_state[0] ? 1 : 0); input_report_abs(ts-input, ABS_MT_POSITION_X, ts-slot_state[1]); input_report_abs(ts-input, ABS_MT_POSITION_Y, ts-slot_state[2]); input_sync(ts-input); } static void touch_dev_release(struct touch_dev *ts) { // 注意这里只 cancel 了当前正在执行的 work但队列里后续的 work 还在 cancel_work_sync(ts-report_work); kfree(ts-slot_state); kfree(ts); }问题核心在kfree(ts)之后touch_report_worker仍然可能执行。驱动的某个断开路径或电源管理回调在释放设备状态时只取消了当下正在执行的一个工作项但异步机制下的竞态让使用了同样函数的工作项仍可能被调度执行。于是ts-slot_state变成悬垂指针读出来的值完全取决于这块内存被释放后有没有被其他数据覆盖。说得直白点快递员一直在往一个已经挂牌“暂停营业”的中转站投递包裹系统照常签收。用户看到的就是一个凭空出现、完全没有物理来源的点击事件。2.3 触发窗口重连与休眠唤醒的竞态UAF不是每次设备断开都会发生它需要卡中一个很窄的竞态窗口。最常见的触发条件是两个第一个是热插拔。触摸板如果是USB接口方案用户或系统拔插设备时驱动会走disconnect流程释放私有数据。如果正好有事件报告work已经入队但还没执行释放后work一跑就是UAF。第二个是休眠唤醒。现代笔记本的触摸板在系统进入待机状态时会经历一个完整的电源管理回调序列驱动如果在这个序列里做了“部分释放”而唤醒过程中又有残留的触摸报告在处理同样会撞上。竞态窗口可能只有几个毫秒到几十毫秒所以用户看到的不是“每次插拔必现”而是“偶尔乱点一下”。我见过不少故障单工程师把这种偶发现象当成玄学问题处理最后靠加日志才定位到。说白了这类驱动漏洞比网络漏洞更难养眼因为它不触发则以一触发就是逻辑层凭空多了个动作而这个动作可能正好落在危险的GUI按钮上。3. 攻击者视角一个幽灵点击如何变成一次越权操作3.1 利用路径先要克服的物理门槛说清楚一点CVE-2023-52840这类漏洞不是那种攻击者能在公网上一键利用的远程漏洞。要触发UAF要么让目标设备经历一次触摸板热插拔要么诱导系统进入特定电源状态。听起来门槛不高但实际操作中还要满足几个前提。目标设备必须使用受影响驱动系统里不能已经打了补丁触发时序还得稳定复现。对于共享工位、机房一体机、公共查询终端这类无人值守设备攻击者确实有物理接触机会可以反复插拔触摸板设备来撞概率。对于个人笔记本攻击者更多是借助“诱导”而非“物理接触”——比如通过恶意软件模拟一次USB设备重连或者调用系统电源管理接口强制休眠唤醒。我不建议把“需要物理接触”当作高枕无忧的借口。真实攻击场景里公共设备和半可信环境是最容易中招的地方而这类环境的运维往往又对内核补丁不够敏感。3.2 从“漂移点击”到“定点确认”的距离UAF产生的事件坐标和状态是读悬垂内存的残留数据一开始是“随机鬼画符”。攻击者真正想要的是让点击落在屏幕上的特定按钮——比如支付确认、权限提升确认、锁屏界面的回车键。这中间的距离叫“堆布局控制”。常规思路是堆风水在释放触摸状态结构体之前攻击者大量分配同类型、同大小的内存对象让系统把刚释放的内存重新分配给攻击者可控的数据。这样后续slot_state[0]、slot_state[1]这些字段读出来的就不再是随机残留而是攻击者精心构造的“坐标点”和“触点状态”。严格说要做到把一次UAF变成精准点击已经属于内核漏洞利用的进阶水平比单纯触发一次崩溃要难得多。但即使不做完整堆布局控制幽灵点击仍有实际风险。哪怕是随机坐标的乱点只要攻击者反复触发点击落在高风险区域的概率仍然存在尤其在一些按钮很大的界面里。安全评估时我们把这种场景叫“概率型利用”不一定完美但足够给业务造成实质影响。3.3 风险权重最高的场景锁屏与支付确认我把这类漏洞的风险权重排序为三个场景从上到下依次递减锁屏界面如果驱动在锁定状态下生成一次键盘Enter或触摸点击攻击者可能直接跳过锁屏认证进入桌面。这是影响最严重的一类。权限确认弹窗攻击者借幽灵点击“替”用户点了提权确认后续配合社工可以完成隐性的权限提升。支付/核身机制一些支付软件在安全环境里把“用户点击确认”作为风控因子之一幽灵点击会污染这个因子。一句话安全体系越是把“物理输入”当成信任根这类驱动漏洞的价值就越高。对个人用户来说发现设备乱跳一定要当回事别只当成驱动不完善。4. 复现与追踪像排查疑难杂症一样定位幽灵点击4.1 复现环境搭建硬件和内核配置怎么选要复现这类问题虚拟机基本不行因为触摸事件过不了虚拟化这层必须用物理机。选一台使用受影响触摸板驱动的设备系统内核换成漏洞版本范围内的版本最好再重新编译一个开启KASAN的内核来跑。KASAN是内核的内存越界检测工具它能在每次访问释放内存的地方立刻停下来并打印完整栈回溯。编译调试内核时几个关键开关# 内核 .config 中确保这些选项开启 CONFIG_KASANy CONFIG_KASAN_GENERICy CONFIG_DEBUG_INFOy CONFIG_FRAME_POINTERy内核编译可以稍慢但调试体验好很多不用靠猜。同时准备一个稳定的触发脚本循环做热插拔和休眠唤醒#!/bin/bash # 循环触发休眠唤醒观察输入事件 for i in $(seq 1 100); do echo round $i rtcwake -m mem -s 2 sleep 1 done4.2 用系统自带工具抓事件铁证先确认事件节点。触摸板在Linux下通常是一个input event节点可以通过/proc/bus/input/devices找到对应设备cat /proc/bus/input/devices然后开一个终端跑evtest选择触摸板对应的event设备。紧接着执行复现脚本观察输出。正常情况下没人触摸时屏幕应该一动不动如果UAF被触发你会看到类似Event: time 1690000000.123456, type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 982 Event: time 1690000000.123456, type 3 (EV_ABS), code 54 (ABS_MT_POSITION_Y), value 532 Event: time 1690000000.123456, type 1 (EV_KEY), code 330 (BTN_TOUCH), value 1 Event: time 1690000000.123456, type 4 (EV_SYN), code 0 (SYN_REPORT), value 0看到BTN_TOUCH value 1而此刻你根本没有碰触摸板这就是“幽灵点击”的铁证。用另一台干净系统做同样的循环测试如果事件消失基本坐实是驱动UAF导致。4.3 KASAN让内存错误现形拿到input事件证据后再回来看内核日志。KASAN环境下UAF触发瞬间的dmesg里会打印类似这样的报告BUG: KASAN: use-after-free in touch_report_worker0x3c/0x90 Read of size 4 at addr ffff88802345abc0 by task kworker/u8:2/1234 ... Call Trace: touch_report_worker process_one_work worker_thread kthread栈回溯会把我们从touch_report_worker到工作队列调度器的调用关系完整拉出来一眼就能看出是哪条路径访问了已释放内存。配合addr2line工具还能把函数地址转换成源文件行号直接定位代码bug位置。我一般把KASAN报告截图存档再补一段完整输入事件日志这样无论是报给上游内核社区还是写内部漏洞报告都具备完整的证据链。4.4 一份实用的鉴别表别把所有“乱跳”都当成CVE做设备维护和驱动调试的朋友拿到“触摸板乱跳”工单后建议先按这张表对症排查别一上来就认定是CVE现象优先怀疑验证手段光标轻微漂移随环境变化电容噪声、接地干扰换电源、脱离金属桌面后复测手掌贴边时误触防误触算法失效libinput配置调整 palm rejection无人触碰出现完整点击事件驱动UAF或固件bugevtest KASAN 固件更新对比插拔/休眠后偶发乱点驱动生命周期问题循环热插拔/休眠脚本复现点击事件重复多次固件去抖逻辑问题查看固件版本和事件时间戳经验是先看事件时间戳和eytest输出能不能对应上物理动作如果对不上再往驱动生命周期层面深挖。5. 修复与缓解把补丁补在生命周期上5.1 上游修复的正确写法UAF修复的核心不是“在worker函数开头加个if”而是把设备状态的生命周期和异步事件的生命周期彻底绑死。比较标准的手法是给touch_dev加引用计数并在提交异步工作时自动持有引用static void touch_report_worker(struct work_struct *work) { struct touch_dev *ts container_of(work, struct touch_dev, report_work); // 正常使用 ts 和 ts-slot_state if (ts-slot_state[0]) { input_report_key(ts-input, BTN_TOUCH, 1); } input_sync(ts-input); // 工作完成释放引用 kref_put(ts-refcnt, touch_dev_free); } static int touch_dev_submit_report(struct touch_dev *ts) { kref_get(ts-refcnt); if (!queue_work(ts-wq, ts-report_work)) { kref_put(ts-refcnt, touch_dev_free); return -EBUSY; } return 0; }配合释放函数做完整清理static void touch_dev_free(struct kref *ref) { struct touch_dev *ts container_of(ref, struct touch_dev, refcnt); kfree(ts-slot_state); kfree(ts); }这样设计的核心逻辑是异步任务在运行期间一定持有设备对象的引用设备不会在任务执行过程中被释放任务结束后再通过引用计数触发真正的释放。与此同时驱动移除路径要保证调用cancel_work_sync把还没执行完的任务先排空。只说一句“修复是释放后置空”是不完整的真正的要点是“让对象死掉之前所有对它的引用都已消失”。5.2 运维侧可以立刻做的临时缓解对还没拿到补丁、又不能在第一时间升级内核的环境可以做几件临时处置优先方案升级到厂商修复后的内核版本或者打上发行版安全团队发布的热补丁。热补丁一般只替换内核函数不需要重启系统适合生产设备。临时缓解在受影响的设备上禁用内置触摸板改用外接USB鼠标/键盘。做法可以根据驱动模块名写入模块黑名单。这要以管理员权限操作并且提前确认外接输入设备可用否则机器会失去输入手段。物理加固公共设备如果无法接受关闭触摸板就在BIOS层面禁用触摸板或者用硬件开关隔离。这类设备通常以键鼠为主禁用触摸板对日常使用影响不大。脚本监控在关键终端上部署一个输入事件监控脚本检测到无人触碰且无进程操作时出现BTN_TOUCH事件就告警至少能第一时间发现被利用。需要强调的是临时缓解只是争取时间的方案最终还是要走内核升级或补丁回归。只靠禁用设备不是长久之计因为触摸板是这些设备的基础交互方式。5.3 补丁回归验证清单我每次验证输入设备驱动修复都会按下面的清单逐项做回归而不是只看漏洞用例是否消失检查项验证方法基础触控功能单指移动、双指滚动、点击、拖拽逐一确认休眠唤醒稳定性循环休眠唤醒100轮全程monitor input事件热插拔稳定性对可插拔设备做100轮插拔确认无UAF报告锁屏输入可信锁屏后循环触发复现脚本确认无幽灵事件内存检测用KASAN内核跑复现用例确认无任何use-after-free报告第4项是我特别加上的因为锁屏是这类漏洞最敏感的攻防场景。如果修复后锁屏状态下不再出现幽灵点击才算真正意义上的安全回归完成。我自己排查这类问题时最深的感受是触摸板这种每天被摸上千次的设备很少有人在驱动代码上多看一眼。它不像网络协议栈那样到处都是攻击面所以生命周期管理的松懈往往藏得很深。如果你手头也有“没人碰却乱点”的设备我的建议是先别急着换硬件把event节点的时间戳抓出来对一下确认是物理信号还是驱动逻辑生成的。再一个值得养成的习惯把“休眠唤醒热插拔”写进驱动和固件的例行回归测试里这类UAF几乎都藏在电源和连接管理回调的夹缝中。如果这篇文章能让你下次看到“幽灵点击”不再先怀疑硬件而是想到“这会不会是一个驱动生命周期问题”那我的目的就达到了。设备输入可信这件事比大多数人想象的重要得多。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →