使用破壳平台自动化漏洞挖掘实践
一、前言 本文主要是讲述用静态分析平台——破壳平台进行批量漏洞快速挖掘和扫描的思路分享。 破壳平台在近日提交了TP-Link,TENDA,D-Link,Linksys,Edimax,Netgear等系列设备六十余个漏洞点,并已经获得30个CVE的批复。 CVE-2024-57357,CVE-2025-22900,CVE-2025-22903,CVE-2025-22904,CVE-2025-22905,CVE-2025-22906,CVE-2025-22907,CVE-2025-22911,CVE-2025-22912,CVE-2025-22913,CVE-2025-22916,CVE-2025-25456,CVE-2025-25458,CVE-2025-25453,CVE-2025-25455,CVE-2025-25454,CVE-2025-25457,CVE-2024-57536,CVE-2024-57537,CVE-2024-57538,CVE-2024-57539,CVE-2024-57540,CVE-2024-57541,CVE-2024-57542,CVE-2024-57543,CVE-2024-57544,CVE-2024-57545,CVE-2024-42520,CVE-2025-25579 后面我们会从三个方面来讲一下查询的策略: 边界二进制寻找 漏洞模式分析及规则编写 平台使用 二、边界二进制寻找 所谓边界二进制就是用户可以访问到的二进制,一般我们进行漏挖也是主要针对这些程序进行针对性,无需对固件中所有的程序都进行分析。 而对于静态分析来说,上传的文件越多那么分析速度和查询速度就会相应的越慢。因此需要有一个初步的文件过滤的步骤来帮助我们初步筛选一些边界二进制。根据平时的漏洞挖掘经验对于常见的路由器,摄像头,nvr等设备,其http服务及相关cgi是漏洞出现的重灾区。 上传平台后平台会自动对压缩包,固件进行解压。同时平台可以设置正则表达式进行过滤: \b(?:\w*httpd\w*|\w*.cgi|\w*onvif\w*|\w*boa\w*|\w*webs\w*|\w*goahead\w*)\b 个人平时在漏洞挖掘时也习惯使用下面的方式来大致确定一些具有网络服务的边界二进制: cd usr grep -r "bind" . | grep Binary 主要是因为值得分析的二进制一般会位于usr目录下,根目录下的bin和sbin一般是linux系统自己的系统服务。且边界二进制必然会监听端口,因此存在bind字符串的很大概率是边界二进制。 三、漏洞模式分析及规则编写 在物联网漏洞挖掘中,命令注入和缓冲区溢出是最为常见的高危漏洞类型。在我初期的自动化工作中也先以这两种漏洞模式进行查询。下面介绍这两种漏洞类型中我所使用的常见漏洞模式。 2.1 命令注入漏洞模式 大部分命令注入漏洞都会经过字符串拼接函数。 edimax CVE-2025-22905 下图是平台漏洞个查询结果,可以看到这个漏洞就是从websGetVar中获取到了对应字段,然后经过了字符串拼接后传递给了system函数,造成了命令注入漏洞。 tplink-8630 CVE-2024-57357 这个漏洞其实从调用流程上来说比较复杂,首先他会使用aes解密用户传入的数据为json,然后从json中拿取一个字符串,然后根据这个字符串去一个虚标中调用对应的函数,然后再经过一个虚表调用后再经过一个假鉴权最终达到命令注入,但是核心漏洞点就是字符串拼接后执行了system 在sub_424ab0函数中会将v20这个变量直接传递给system函数作为参数。 查询规则 针对于大部分命令注入漏洞都会经过字符串拼接函数这个漏洞模式,,使用正则进行字符串匹配或者单纯直接寻找sprintf和system函数作为危险函数点总体来说误报还是比较多的,而且不支持跨函数的情况。 因此个人采用的是使用snprintf,sprintf函数的参数作为source点,常见的命令执行函数作为sink点,然后使用平台进行污点分析,相对来说误报较少,能查到的很大概率是会存在漏洞的。 MATCH (n:identifier)<-[:ast*2]-(code:code_line) WHERE n.callee in ["snprintf","sprintf"] and n.index in [2,3,4,5,6] and code.name contains "%s" WITH collect(id(n)) as sourceSet MATCH (m:identifier{index:0}) WHERE m.callee in ['system', '_system', '_popen', 'popen', 'wpopen', '_wpopen', 'spawn', '_wexecl', '_wspawnv', 'eval', '_wsystem', 'spawnve', '_wspawnlp', '_spawnl', 'execle', '_wspawnve', '_texeclp', '_wexeclp', '_spawnlpe', '_execvp', '_exec', 'COMM_SystemEx', '_wspawnl', '_wspawnvp', 'execlp', 'system_en', '_wspawnvpe', '_wexecv', 'WinExec', '_wspawnle', '_texecvp', 'CreateProcessW', 'twsystem_nowait', '_texecle', '_execv', '__system', '_spawn', 'spawnvp', '_tspawnl', 'doSystemCmd', 'callSystemCmd', '_tspawnlpe', 'CreateProcess', '_spawnve', '_tspawnv', 'spawnlp', 'spawnlpe', 'g_spawn_command_line_async', '_wexecle', 'spawnl', '_spawnvp', '_tspawnlp', '_tspawnle', '_execl', '_wexec', '_wexeclpe', '_tspawnve', 'spawnv', '_tspawn', 'twsystem', '_spawnle', '_execle', 'execvp', '___system', '_wspawn', '_texecl', '_tspawnvp', '_eval', '_texecv', '_spawnlp', '_spawnvpe', 'spawnle', '_execlp', 'execl', '_execlpe', 'CreateProcessA', '_spawnv', '_tspawnvpe', '_texec', '_wexecvp', 'bstar_system', 'prctl_runCommandInShellBlocking', 'execv', 'spawnvpe', '_wspawnlpe', '_texeclpe', 'execlpe', 'jhl_system', 'ATP_UTIL_ExecCmdNoHang', 'j_ATP_UTIL_ExecCmdNoHang', 'bs_SetCmd', 'ExeShell','doSystemCmd','lxmldbc_system'] WITH sourceSet,collect(id(m)) as sinkSet CALL VQL....