IoT小设备HTTP漏洞挖掘研究:BOA篇

BOA是IoT小设备上常见的HTTPD之一。本文将从源码分析、漏洞挖掘、真实漏洞分析三个部分总结BOA的相关特性。其中,源码分析部分涉及到Linux网络编程,漏洞挖掘部分主要关注于如何快速恢复请求结构体、了解数据包处理逻辑以及CGI如何传递数据,真实漏洞分析部分则是分析了三个典型的BOA认证前漏洞,其中两个能够导致认证前任意代码执行,一个认证前信息泄漏。 一、BOA简介 BOA是一个单任务的HTTPD,简单说,BOA不像常见的HTTPD,为每一个连接使用fork创建子进程进行处理,也不会提前创建一个进程池、线程池用于同时处理多个连接。它在内部采用了多路复用和请求链表来处理所有来自客户端的连接,并且仅仅针对CGI程序、自动目录生成和自动文件压缩采用fork子进程的形式进行处理。简而言之,BOA是一个轻量级的HTTP服务器,主要设计用于嵌入式系统,以高效的性能和小巧的代码体积著称,通常被应用于资源受限的设备,例如路由器、智能家居或者其他的嵌入式环境。 BOA具有如下的一些特点: 单线程架构:BOA采用了单线程、事件驱动的架构来处理多个HTTP请求。传统的WEB服务器会为每一个请求使用fork创建子进程进行处理,每次请求都会造成进程创建的开销。BOA的架构避免了这种操作,从而节省了系统资源。但是,只能说BOA适合嵌入式这种请求速度慢、并发少的情景。 资源占用低:BOA的代码体积非常小,内存和CPU的使用效率高,适用于资源受限的嵌入式设备。 配置简单:BOA的配置文件简单明了,容易调整和优化,可以快速进行部署。 快速响应:单线程事件驱动模型使得在轻负载情况下响应迅速,适用于处理少量并发连接。 BOA的源码和官方文档都可以在Boa Webserver处找到。 二、BOA源码分析(TL;DR) 本章节从源码分析BOA,主要从常规分析HTTPD源码的角度,例如信号量处理、socket从创建到复用、CGI数据传递等,帮助更好理解BOA的运行特性。该部分篇幅过长,对Linux网络编程已经较为熟悉的师傅可以跳过到2.4节BOA的请求结构体说明部分和2.5节状态机处理数据包示意图部分。 2.1 信号量处理 HTTPD服务器会处理一些常见的信号量,以免HTTPD发生异常终止。在BOA中也是如此,main函数中调用函数init_signals,收到指定的信号时,执行预先设定的处理函数。 信号量的处理一般是如下流程: 创建信号量处理相关的结构体变量。 初始化清空信号量集合。 将需要关注的信号量以及对应信号量的处理函数加入到信号量集合中。 当HTTPD接收到相应的信号量时,执行预先设定的处理函数。 BOA源码中,对信号量的处理也是满足如上的流程。 /* * Name: init_signals * Description: Sets up signal handlers for all our friends. */ void init_signals(void) // 初始化信号处理函数,收到指定信号的时候,执行预定义的处理函数 { struct sigaction sa; // 不使用任何特殊标志 sa.sa_flags = 0; // 初始化信号屏蔽集sa_mask // 将如下的几个信号量,添加到sa_mask中 sigemptyset(&sa.sa_mask); sigaddset(&sa.sa_mask, SIGSEGV); // 段错误 sigaddset(&sa.sa_mask, SIGBUS); // 总线错误 sigaddset(&sa.sa_mask, SIGTERM); // 终止信号 sigaddset(&sa.sa_mask, SIGHUP); // 挂起信号 sigaddset(&sa....

2025年02月26日 · 6 分钟 · OneShell

IoT 设备中的认证绕过漏洞分析

一、前言 在IOT设备中,认证漏洞出现频率较高,能够造成的很大危害。通过认证的绕过,攻击者可以访问到很多敏感接口,甚至可以结合其他漏洞直接获取设备 shell。本文将通过一些设备分析认证过程以及认证绕过。 二、分析 小设备认证可分为两个部分,一是登录逻辑,设备通常会要求用户输入用户名和密码来进行身份验证;二是对路由的鉴权,其作用是限制用户对不同功能和资源的访问权限。 (一)登录 对于IOT设备中的Web界面,通常在未认证前仅能访问登录界面。为了找到后端登陆逻辑,我们可以借助工具如Burp Suite来进行流量抓包分析。 以某设备A为例,用Burp Suite抓包发现,登陆时请求了/cgi/login路由 在/usr/bin/httpd的ida文件中搜索/cgi/login,可以快速定位到注册CGI的函数。其中http_alias_addEntryByArg的功能是为cgi注册处理函数并设置访问所需要的权限。因此登录的逻辑http_rpm_login中。 有的设备会有专门的cgibin来处理cgi。例如某设备B在cgibin的main函数中使用strcmp比较请求的cgi,如果是authentication_logout.cgi就会进入登录逻辑。 还有一些设备的路由则是在配置文件中定义,下图是一个nginx+lua的路由器的配置文件,其中定义了在在访问/authenticate时,在content_by_lua阶段加载web模块处理登陆请求。 (二)鉴权 一般来讲,http对路由都会有访问限制,一般在配置文件或者httpd初始化的时候会定义访问规则。 以某设备A为例,httpd在初始化时调用http_alias_addEntry_ByArg注册CGI处理函数。http_alias_addEntry_ByArg的最后一个参数,表示访问这个路由需要的权限。g_http_author_admin、g_http_author_default、g_http_author_all分别表示访问该CGI需要超级用户权限、普通用户权限、无需权限。 httpd中每个请求都会通过http_author_hasAuthor鉴权,参数a1是一个全局变量,记录会话相关信息,其中的user_id表示该会话登录的用户,默认为0,在登陆成功后会赋值;a2是包含访问的路由,对应的处理函数和访问所需权限信息的结构体。该函数通过user_id判断a2->author对应bit是否为1进而确定当前用户是否有权限访问。 在某设备C中则是为路由鉴权定义了一个mime_handlers结构体数组, mime_handler定义如下,patten是匹配的模式,handler就是路由对应的处理函数。第四个参数auth表示访问这个路由是否需要鉴权。 struct mime_handler { char *patten; // **.cgi **.html char *mime_type; void *handler; int auth; }; 每次httpd接收到请求时会做如下处理:遍历mime_handlers,获取对应的patten字段,调用match_one匹配,匹配成功则获取对应的handler。最后在调用handler前根据auth字段判断是否需要鉴权。 这里有一个点,匹配所用到的patten有些是只匹配文件扩展名,例如对于**.cgi,*表明可以匹配0个或多个字符,不管.cgi前有多少个字符都会匹配进去,有可能后续会造成溢出。 在某设备D中,httpd使用strstr来匹配请求的是否是不需要认证的路由,当匹配到白名单路由时设置do_not_need_auth为1,未匹配到白名单则需要认证。 在某设备E中,在配置文件nginx.conf中定义,access_by_lua阶段加载sessioncontrol模块,重新加载用户信息,获取会话管理器mgr,检查请求并处理认证。 三、绕过 下面通过一些真实漏洞分析认证绕过。 登录功能对于用户名/密码处理不恰当 最简单的绕过方式是首先登陆时有默认密码,有的是硬编码在程序中,或者调试可以发现。 案例一:CVE-2020-8864 D-LINK DIR-882设备,在登陆时密码比较的逻辑中,28行获取我们输入的密码,第47行会调用strlen获得我们输入的密码的长度,之后使用strncmp进行比较,如果我们输入空密码,strncmp的第三个参数为0,返回值一定是0,表示比较成功,即可绕过认证。 漏洞修补:比较前判断用户输入密码是否为空 会话管理存在问题,控制 Cookie 值绕过会话检查。 案例二:CVE-2021-32030 ASUS RT-AX56U设备,需要鉴权的接口都会从请求获取cookie参数,之后传入auth函数。auth函数中,从nvram获取ifttt_token。 在默认情况IFTTT没有开启,ifttt_token为空,通过请求中传入空的cookie可绕过认证。 漏洞修补:比较cookie前判断cookie是否为空 案例三:CVE-2021-35973 Netgear wac104设备,在访问需要认证的cgi时会对session进行认证,在第42、49行首先从POST请求中获取id和sp字段的值,之后第53行snprintf将/tmp/SessionFile和sp_from_post拼接在一起作为get_id_from_session_file的参数。 get_id_from_session_file中,首先返回值赋值为0,打开session_file, 从sesseion_file读取id,如果文件不存在则直接接返回初始化为0的id。session_file用户可控的,通过构造id=0&sp=AAA这种,把sessionfile设置成一定不存在的文件路径,那么返回值就一定是0,可绕过id_from_post == id_from_session_file的检查。 漏洞修补:判断session文件是否存在 对用户访问的资源路径处理不恰当,访问到敏感接口。 案例四:CVE-2021-35973 Netgear wac104设备,httpd中data段存放着无需认证的页面 在判断是否需要路由认证时使用strstr来匹配,如果匹配到了就设置do_not_need_auth为1,表示请求的页面不需要认证。 绕过方式是使用/AAA%00currentsetting.htm请求,AAA是需要认证的页面,因为匹配使用的是strstr,可以成功匹配。在成功之后整个url会解码,%00截断,实际访问/AAA页面,从而无需认证也能访问需要认证的页面。 漏洞修补:url解码前检测%00 案例五:CVE-2021-20090 同样有一个白名单,...

2023年11月22日 · 2 分钟 · noir