IoT 拒绝服务:内存、连接、电池与恢复能力如何被耗尽
IoT 设备不需要被植入恶意程序,也可能失去作用。攻击者让传感器持续唤醒、让网关保存大量未完成连接,或者让设备不断重启,就可能阻断原本的测量、告警与控制功能。
实操:在真实固件上同时记录资源与正常业务
先启动QEMU 中的 OpenWrt 官方固件,让串口控制台保持可用。以下测试只对自己的固件副本发送有限请求,用来建立测量方法;若没有实际耗尽或业务失败,就不报告拒绝服务漏洞。真实传感器的电池与射频结果不能由虚拟机替代。
在施加负载前取得基线
固件控制台执行:
free
top -b -n 1
netstat -ant
cat /proc/meminfo
logread -f
在电脑读取管理页,记录应用级响应时间:
curl --max-time 3 -sS -o /dev/null \
-w 'http=%{http_code} total=%{time_total}\n' http://127.0.0.1:8080/
一次请求只能提供单点,先重复正常操作并确认波动范围。另用真实管理登录、状态查询或设备本地功能作为业务基线,不能只测试静态首页。
使用有限并发,观察谁先出现异常
Ubuntu 的 apache2-utils 提供 ab。在电脑执行:
ab -n 40 -c 4 -s 3 -e latency.csv -g request-times.tsv http://127.0.0.1:8080/
这是最多 40 次请求、并发 4、套接字等待超时 3 秒的首轮测量,不预设会触发缺陷。另一终端重做正常业务,控制台观察进程、剩余内存、连接与日志。记录完成数、失败类型、延迟和哪个功能受到影响。ab 参数文档
latency.csv 保存响应耗时的百分位,request-times.tsv 保存逐请求测量值;它们都不是设备内存或功耗曲线。将两份文件与同一时间段的设备日志、资源记录和正常业务请求对应。Failed requests 中的长度变化需要检查实际响应,动态页面大小不同不等于服务中断;重定向和错误页也应单独核对。
发现异常后先停止负载,观察连接和资源是否自行释放,以及业务何时恢复。只在确认恢复并约定资源预算后,再改变连接数、保持时间或认证阶段中的一项;不要把一轮网页基准测试当作电池耗尽或握手状态耗尽的证据。
把异常定位到实际资源
内存持续下降时结合目标进程与分配路径定位;连接达到上限时检查进程文件描述符、服务并发限制和超时;Broker 队列积压时检查真实持久会话与离线消息配置。依据固件实际具备的工具读取,不假定精简系统安装了完整 procps 或 ss。
对电池设备,需要功耗仪与设备唤醒日志,在相同供电、无线与业务条件下对照正常和异常请求。对射频干扰,需要单独的隔离射频条件;HTTP 测量不能覆盖这一层。
修复后重测恢复能力
调整实际服务的并发、队列、状态超时或资源预留后,重跑原负载与正常业务,比较失败、回收和恢复。QEMU 退出会丢弃 -snapshot 模式的修改,需要先导出配置与日志;复位后症状消失不等于输入或持久队列已被处理。
成立前提与能力变化
资源耗尽需要攻击者能反复触发分配、运算、唤醒或重试,并且设备缺少足够的准入、配额或回收能力。链路是“小成本输入 → 持续资源占用 → 合法业务受阻 → 检查移除输入后能否恢复”。仅记录流量增加,不能证明服务中断;物理信道干扰也不能直接归因于应用解析漏洞。
先确定哪种资源支撑业务
资源可能是处理器时间、堆内存、连接槽位、消息队列、Flash 写入寿命、电池或无线信道。RFC 7228 为受限设备与网络提供术语,强调内存、计算和能源等约束;它并不为具体产品提供统一安全容量。RFC 7228
分析时需要把资源与业务结果连接起来。连接数耗尽可能只影响新连接,也可能阻断已经运行的关键服务;Flash 被日志持续写满,可能进一步导致配置保存和更新失败;无线信道被干扰,则未必能由应用程序修补。
还应区分实现错误和容量耗尽。一个畸形包触发崩溃,根因可能是解析漏洞;许多合法请求占满内存,根因可能是资源分配策略。它们可能产生相同“设备离线”现象,但修复不同。
在确认来源之前支付了多少成本
TLS、DTLS、设备配对和注册流程可能涉及证书解析、密码运算与状态分配。攻击者如果能用很小请求反复触发昂贵工作,就建立了有利于自己的资源交换。
DTLS 1.3 的 RFC 9147 第 5.1 节描述了无状态 Cookie 与地址可达性检查,用于减轻伪造来源握手和放大等风险。规范也明确指出,这并不抵御来自有效地址的所有拒绝服务攻击。因此,Cookie 应与配额、握手预算和资源回收共同评估。RFC 9147
产品设计可把便宜检查放在昂贵处理之前,并给未认证状态设置短生命周期和明确上限。已经认证的主体也需要独立配额,避免一台合法但失陷的设备占满整个网关。
状态表可能比带宽更早耗尽
RAID 2022 的 Zigbee 重入网研究构造了 Capacity Exploitation:模拟设备通过重入网交互消耗父设备容量,使合法设备无法加入。作者在所测产品中观察到不同恢复时间,部分影响不能靠简单重置立即消除。这里的关键是资源被分配给不该获得它的交互,而不是攻击者拥有巨大网络带宽。原始论文,4.1 与 6 节
这类结果提示验证者检查邻居表、子设备表、连接表和未完成事务。只观察 CPU 与入口流量,可能看不到有限表项已经被消耗。
回收策略也需要避免相互影响:攻击者制造新身份时,系统不能无限挤掉合法设备;过于激进的超时,又可能误伤正常休眠节点。配额应结合身份、状态与实际业务模式设计。
电池耗尽依赖唤醒与重试行为
一个休眠设备的能耗不只由成功业务决定。重复唤醒、失败握手、反复重连、日志写入和无效消息处理,都可能增加活动时间。评估时可使用一个概念模型:
总能耗 = 正常业务能耗 + 额外唤醒能耗 + 无效处理能耗 + 重试与恢复能耗
这个模型用于定位测量项,不是续航预测。真实结果需要电流轨迹、工作周期、网络条件和电池模型,不能凭请求次数给出“几分钟耗尽”的结论。
退避、批处理和唤醒预算可以减少无效工作,但需保留关键告警的时效。设备面对持续异常时,还应避免在高耗能状态无限重试。
资源预算要有分配上限和退出条件
可以给每项状态分配记录三个参数:单项占用、并发上限、最长存活时间。对握手,还要增加失败或重试的速率预算;对休眠节点,则要记录一次交互允许延长的活动时间。
| 资源 | 需要观察的入口 | 需要定义的退出行为 |
|---|---|---|
| 未认证握手状态 | 新连接与重复握手 | 超时回收、总量上限与来源约束 |
| 子设备或邻居表 | 加入、重入网与身份变化 | 授权后分配、过期和合法设备保护 |
| 消息与重组队列 | 离线消息、分片和重复请求 | 累计大小、片数、有效期与丢弃规则 |
| 电池活动时间 | 唤醒、重连和失败重试 | 活动预算、退避与关键业务保留 |
准入、配额和回收需要一起设计。只限制每个身份的数量,可能被大量伪造身份绕过;只按来源地址限速,又可能误伤共享网关后的合法设备。未认证请求需要系统总预算,可信身份建立后再使用更细的主体预算。
恢复验收也要明确触发条件是否已经清除。重启会重建内存,但不会自动清除持久化队列、错误配置和邻居状态;设备重新联网后再次读到同一内容,可能立即恢复异常循环。
恢复机制也会被反复触发
看门狗可以帮助设备离开死锁,但如果重启后立刻再次处理同一恶意消息,设备会陷入重启循环。日志若在循环中持续写入,可能扩大存储与寿命问题。
一种可评估设计是隔离异常消息或状态,限制自动重试,并为关键本地功能保留最低资源。安全降级的具体动作需要产品定义:摄像头可以暂缓云同步,但门禁或控制器的失效行为涉及物理安全,不能统一规定“全部关闭”或“全部放行”。
射频干扰还需要不同处置。身份认证和消息签名不能阻止攻击者占用信道,应结合频段、冗余链路、本地控制和异常检测评估残余风险。
用资源预算解释为什么低流量也能阻断服务
本文 OpenWrt 24.10.5 镜像的 /etc/config/uhttpd 同时设置了 max_requests 3 与 max_connections 100。这两个实际配置分别约束请求处理和连接,不能把连接数直接当作同时执行的业务请求数。在运行固件中核对:
uci get uhttpd.main.max_requests
uci get uhttpd.main.max_connections
检查服务达到各自上限时是排队、拒绝还是继续分配状态,以及超时后是否回收。再结合实际单项状态占用与内存预算计算能承载的并发,关键业务所需的内存、队列和执行时间应独立保留。
如果只按单个用户限额,攻击者可能通过大量未认证标识绕过;如果超时很长,低速创建也能逐步占满表项;如果回收依赖已经被阻塞的业务线程,上限与超时虽然存在,也可能没有生效。
因此测试需要同时运行正常读取、告警或控制任务,记录资源占用曲线与业务完成情况。停止异常请求后,还要观察状态是否按时回收。峰值流量、CPU 或设备重启次数都不能单独替代这些结果。
验证需要正常业务同时运行
在隔离环境中,分别测试未认证握手、合法高频消息、未完成事务、离线重连和异常消息恢复。先记录正常负载基线,再观察合法动作延迟、丢失、内存、表项、平均功耗及恢复时间。
测试结束后移除异常输入,确认资源是否回收、设备是否恢复、是否丢失配置,以及是否仍存在队列或存储中的触发条件。仅证明设备最终重启,不能说明它已经恢复业务。
跨平台的进程崩溃与资源耗尽机制见拒绝服务;本篇进一步区分电池、无线状态表和设备恢复条件。