本文仅供学习和研究,由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,海青实验室及文章作者不承担任何责任。
安全狗海青实验室拥有此文章的修改和解释权,如欲转载或传播,必须保证此文的完整性,包括版权声明在内的全部内容,未经海青实验室同意,不得任意修改或者增减此文章内容,不得以任何方式将其用于商业目的。
攻击者可以快速的从文件上传功能点获得一个网站服务器的权限,所以一直是红蓝对抗中的“兵家必争之地”。而随着对抗不断升级,开发人员的安全意识的不断提高,多多少少也学会了使用黑名单或者白名单等一些手段进行防御,但刁钻的攻击者,依然发现了疏忽之处。本文以两个实例,简单介绍文件解压功能导致的getshell问题。
首先,准备一个zip文件里,里面包含了一个PHP文件。然后,在导入模块中将zip文件上传。
在尝试的时候发现,导入模块失败了,但是查看文件夹内容,可以发现文件已经成功被写入了。
从代码层面来看看整个流程是怎样的?
当我们点击导入模块时,浏览器会发送两条请求。先看第一条POST请求。根据PHPOK CMS路由分发的规则,可以定位到upload控制器中的zip方法。
而在43行处,引入了libs\upload.php文件并且调用zipfile()函数。
在第135行处,设定了文件后缀类型为zip,由于137行处的if条件不成立,流程进入140行,调用_save()方法。继续跟进_save()方法。
_save()方法在276行处使用file_ext()方法对传入的name参数也就是文件名进行后缀判断,而如果判断通过,则会在之后将压缩文件保存下来。跟进一下file_ext()方法。
在该方法中,设置了一个白名单,文件名只能是jpg,gif,png,zip中的其中一种。为什么包含zip呢?不管是程序执行到第186或者189行处,在前面就已经给这两个变量设置值为zip了,所以在白名单中自然包含了zip。 目前到此为止,整个上传流程没有什么问题,并且使用了白名单来限制后缀,所以只能上传zip压缩文件。接着再来看第二处请求
admin.php?c=module&f=import&zipfile=_cache%2Fa9414ae41044fc5a.zip&_=1570603538199
同样根据路由规则,可以定位到module控制器下的import方法
程序会接受到zipfile参数,是刚刚压缩包保存在缓存文件夹里的文件名。在第705行处判断了是不是存在这个压缩包,如果存在则在708行处进行解压。其中引入了libs/phpzip.php中的unzip函数进行解压。跟进unzip函数,程序实例化了ZipArchive类进行解压,而目标路径$to则是缓存文件夹。
到此不难看出问题,程序将压缩包中的文件解压出来之后,并未进一步的进行判断,以至于里面包含的 PHP文件可以绕过上传文件的限制,使得原本建立的安全防御土崩瓦解。
由于这套CMS做了相关防御配置,压缩包里像上文中直接加入JSP文件是无法执行的,会报403错误。因而想到使用目录穿越的方式,跳出JspxCM的根目录,并根据war包会自动解压的特点,从而getshell。
首先,建立一个恶意的war包,并且打成压缩包,如图所示。
然后点击“上传文件”按钮,上传test5.zip,如图所示。
紧接的使用解压功能,将上传的压缩包解压出来。点击“ZIP解压按钮”,如图所示。
此时,在服务器端查看webapps目录的变化,可以发现safedog.html和vul.war文件被解压到了网站根目录“webapps/ROOT”之外,如图所示。
访问上传的webshell,效果如下。
http://192.168.114.132:8080/vul/webshell.jsp?pwd=023&cmd=calc
在后台登录之后,找到ZIP解压功能,通过BurpSuite进行抓包可以发现“解压文件”的接口调用情况,如图所示。
该接口对应了jspxcms-9.5.1-release-src/src/main/java/com/jspxcms/core/web/back/WebFileUploadsController.java的unzip方法,如图所示。
对unzip方法进行跟进,发现它的具体实现在/jspxcms-9.5.1-release-src/src/main/java/com/jspxcms/core/web/back/WebFileControllerAbstractor.java中。可以发现,在对zip文件进行解压的时候,调用了AntZipUtil类的unzip方法,如图所示。
对AntZipUtil类的unzip方法进行跟进,可发现该方法未对ZIP压缩包里的文件名进行参数校验,就进行文件的写入。这样的代码写法会引发“目录穿越漏洞”,如图所示。
从上述两则实例来看,压缩包里包含着webshell颇有些特洛伊木马的味道。当程序对上传后缀限制的相当严格,例如上文提到的PHPOK CMS,已经使用白名单的机制只能上传四种后缀的文件,却依然因为对压缩文件的处理不当,导致整个防御机制的失效。在ZZZCMS中的实例,猜测开发者的本意是zip文件夹内的内容应该别可控的,但在目录穿越的加持下,超出了开发者的预期从而防御机制土崩瓦解。
那么如何防御呢?建议开发者在实现文件解压功能时考虑以下要点:
1)限制文件的扩展名(如采用白名单的方式);
2)限制文件的名称(以较为严谨的黑名单约束文件名);
3)限制文件的大小(以免遭受压缩包**的DDoS攻击)。
因此,在开发的各个环节,都要将安全意识贯彻其中。千里之堤毁于蚁穴,也正是这种细微之处的小问题,才使得攻击者有机可乘。