Apache HTTP Server mod_lua�?榛撼迩绯鑫蟛钇饰觯–VE-2021-44790)
宣布时间 2022-01-20误差概述
2021年12月20日,Apache 团队宣布了Apache HTTP Server 2.4.52版本,修复了Apache HTTP Server中的一个缓冲区溢出误差(CVE-2021-44790),该误差保存于mod_lua剖析器中,当服务器剖析恶意请求时触发缓冲区溢出,可导致拒绝服务或执行恣意代码。
影响规模
影响版本:Apache HTTP Server <= 2.4.51
相关先容
Mod_lua�?�
Mod_lua�?槭茿pache上的一个扩展�?�,适用于2.3以上版本。该�?樵市硎褂胠ua剧本扩展服务器,还包括许多其他�?榭捎玫墓匙雍�。例如将请求 Map 到文件,天生动态响应,会见控制,身份验证和授权等。若是开启该�?�,可能会造成一些清静隐患。
在/etc/httpd/httpd.cnf设置文件中作废下面这行注释,即可开启该�?榈墓π�。

当收到.lua文件请求时,mod_lua�?榕灿胠ua-script的handle函数举行处置惩罚。下图为handle函数实例。

apr内存池
为了镌汰系统内存分派的时间,提高程序运行效率,Apache的开发者建设了一套基于池看法的内存管理计划。这套要领移到apr中成为通用的内存管理计划,也就是apr内存池。
apr的内存池结构着实是一种树状的条理结构,parent指向目今内存池的父内存池,child指向目今内存池的子内存池,sibling则指向目今内存池的兄弟内存池。用户使用的内存空间,则是active管理的一个节点链表。用户要申请内存空间的时间就会在active管理的内存节点中寻找。
结构体如下所示:

用户申请内存历程:
(1)首先取最靠近不小于8字节倍数巨细的空间(8字节对齐),然后凭证申请巨细判断active节点可用空间是否足够。若内存足够,移动first_avail指针,返回其地址;若空间缺乏,则继续举行2之后的办法。
(2)判断下一个内存节点的剩余空间是否足够,若足够则使用之,并将之脱离目今链表;若缺乏,则通太过配子分派新的内存节点。
(3)将第2步中获得的节点插入active节点之前,并成为新的active节点。
(4)盘算旧的active节点的剩余空间巨细,并且与其链表后的所有节点的剩余空间巨细较量,并插入链表中准确的位置。

补丁剖析
该误差在Apache HTTP Server 2.4.52中举行了修复,在内存申请之前,增添了对长度的正当性校验。当end-crlf小于即是8,程序会直接退出,阻止整数溢出。

误差剖析
凭证误差通告,可知误差保存于mod_lua�?橹�,lua剧本挪用了r:parsebody()函数爆发了缓冲区溢出。团结patch信息,直接定位到req_parsebody函数。
本文使用Apache HTTP Server 2.4.49版本举行剖析,代码中红色方框标识出来的部分即误差代码位置,图片中对要害部分举行了响应的注释。

下面团结post数据包来剖析程序处置惩罚逻辑。结构如下post数据包:

首先,start变量指向post数据包最先的位置,也就是对应上面第一个标识符--VILC2R2IHFHLZZ的位置,crlf指向两个空行(\r\n\r\n)最先的位置,end指向下一个标识符VILC2R2IHFHLZZ最先的位置,那么在crlf和end之间的数据就有下面这些内容,总长度为8(特殊字符长度)+len(数据参数长度)个字节。
‘\r\n\r\ntest\r\n--’
凭证上面参数内容,我们就可以明确下面这行代码的意义了。vlen即是总长度减去多余的8个特殊字符,就可以盘算出参数的长度。
vlen=end-crlf-8;
然后,程序挪用apr_pcalloc分派内存。
![]()
程序没有对vlen值的正当性举行检查,若是上面参数中的特殊字符缺失,盘算的vlen值就可能变为负数,造成整数溢出。当申请空间的时间,会泛起清静问题。
动态调试
凭证差别畸形包的结构,思量以下两种情形,团结动态调试举行剖析。
申请超大的空间
假设缺失'/r/n--'这4个特殊字符,且数据部分为2字节,vlen=(2+4-8)=-2。挪用apr_pcalloc(r->pool, vlen+1)申请内存时,vlen+1=0xffffffffffffffff。
使用gdb附加历程,举行动态调试。在误差函数处设置断点,然后发送特殊的post请求。

apr内存池无法提供这么大的内存,这时apr的分派子就会向系统申请内存空间,可是申请的重大内存空间是系统无法提供的,以是系统会直接将历程kill掉(0x75是历程号),造成拒绝服务。

溢出超长的字节
假设缺失'/r/n--'这4个特殊字符,且数据部分为3字节,vlen=(3+4-8)=-1,挪用apr_pcalloc(r->pool, vlen+1)申请内存时,长度vlen+1=0,凭证apr内存池内存分派机制,apr内存池会分派最小的内存块8字节,最后使用函数memcpy的时间:
memcpy(buffer, crlf + 4, vlen)
vlen又为FFFFFFFF.......(-1),就会爆发缓冲区溢出。
动态调试时可以看到挪用apr_palloc时,长度参数是0,现实上会分派8字节的空间。


参考链接:
[1]https://mp.weixin.qq.com/s/XLzXHZYvpPIqNrDz3OHaMA
[2]https://nakedsecurity.sophos.com/2021/12/21/apaches-other-product-critical-bugs-in-httpd-web-server-patch-now/
[3]https://httpd.apache.org/security/vulnerabilities_24.html
[4]https://ubuntu.com/security/CVE-2021-44790
[5]https://github.com/apache/httpd/commit/07b9768cef6a224d256358c404c6ed5622d8acce


京公网安备11010802024551号