FCKEditor ASP Version 2.6.8任意文件上传漏洞分析

2012-12-23 14:45:19 31 12311


一.  漏洞概要
漏洞描述:
FCKeditor是一款开放源码的HTML文本编辑器。
FCKEditor 2.6.8及其他版本在'FileUpload()'函数的实现上存在安全漏洞,攻击者可利用此漏洞上传任意文件到受影响计算机。
受影响版本:
FCKEditor 2.6.8
二.  原理分析
总共存在两处漏洞,第一处在对上传文件扩展名的正则表达式匹配上,第二处在FileUpload()函数中SanitizeFileName()只对sFileName文件名做清洗而未对sExtension做清洗,导致上传同名文件的时候扩展名中的%00截断未被替换为“_”而直接保存文件。

0x01 正则表达式不完全匹配

首先看如下代码:

这里ConfigAllowedExtensions中存的是文件扩展名的白名单,要看它是如何被调用的还用跟一下NetRube_Upload这个类的代码。分析其代码发现,oUploader.Allowed这个属性实际上是被传递给IsAllowed()这个函数,而最终传给了RegExp对象的Pattern属性,然后调用Test()方法匹配白名单。


这里我们看一下白名单ConfigAllowedExtensions中的内容,

事实上Test()方法只会在sExt中搜索白名单中的这些扩展名,如果搜索到就返回成功,这里是做的不完全匹配,换句话说如果扩展名为aatxt,一样能够返回成功。所以这个白名单基本可以无视。

0x02 SanitizeFileName()未清洗sExtension

首先分析FileUpload()函数的代码,在/fckeditor/editor/filemanager/connectors/asp/commands.asp中,如下所示:
Sub FileUpload( resourceType, currentFolder, sCommand )
        Dim oUploader
        Set oUploader = New NetRube_Upload
        oUploader.MaxSize        = 0
        oUploader.Allowed        = ConfigAllowedExtensions.Item( resourceType )
        oUploader.Denied        = ConfigDeniedExtensions.Item( resourceType )
        oUploader.HtmlExtensions = ConfigHtmlExtensions
        oUploader.GetData

        Dim sErrorNumber
        sErrorNumber = "0"

        Dim sFileName, sOriginalFileName, sExtension
        sFileName = ""

        If oUploader.ErrNum > 0 Then
                sErrorNumber = "202"
        Else
                ' Map the virtual path to the local server path.
                Dim sServerDir
                sServerDir = ServerMapFolder( resourceType, currentFolder, sCommand )

                Dim oFSO
                Set oFSO = Server.CreateObject( "Scripting.FileSystemObject" )
                if not (oFSO.FolderExists( sServerDir ) ) then
                        sErrorNumber = "102"
                else
                        ' Get the uploaded file name.
                        sFileName        = oUploader.File( "NewFile" ).Name
                        sExtension        = oUploader.File( "NewFile" ).Ext
                        sFileName = SanitizeFileName( sFileName )
                        sOriginalFileName = sFileName

                        Dim iCounter
                        iCounter = 0

                        Do While ( True )
                                Dim sFilePath
                                sFilePath = CombineLocalPaths(sServerDir, sFileName)

                                If ( oFSO.FileExists( sFilePath ) ) Then
                                        iCounter = iCounter + 1
                                        sFileName = RemoveExtension( sOriginalFileName ) & "(" & iCounter & ")." & sExtension
                                        sErrorNumber = "201"
                                Else
                                        oUploader.SaveAs "NewFile", sFilePath
                                        If oUploader.ErrNum > 0 Then sErrorNumber = "202"
                                        Exit Do
                                End If
                        Loop
                end if
        End If

        Set oUploader        = Nothing

        dim sFileUrl
        sFileUrl = CombinePaths( GetResourceTypePath( resourceType, sCommand ) , currentFolder )
        sFileUrl = CombinePaths( sFileUrl, sFileName )

        If ( sErrorNumber = "0" or sErrorNumber = "201" ) then
                SendUploadResults sErrorNumber, sFileUrl, sFileName, ""
        Else
                SendUploadResults sErrorNumber, "", "", ""
        End If
End Sub
这里sFileName        = oUploader.File( "NewFile" ).Name为获取上传文件的文件名(包含扩展名),sExtension        = oUploader.File( "NewFile" ).Ext为获取上传文件的扩展名。
主要看这个while循环,当第一次上传的时候,因为sFilePath文件不存在,所以会执行else语句保存文件。这里文件名是经过SanitizeFileName( sFileName )处理过的。而第二次上传同名文件的时候,执行这个If ( oFSO.FileExists( sFilePath ) ),如下所示:
sFileName = RemoveExtension( sOriginalFileName ) & "(" & iCounter & ")." & sExtension
这里可以看到这里的sFileName直接用sExtension拼接而成,而sExtension之前未用SanitizeFileName()做清洗,所以导致在扩展名中插入%00截断不被替换。SanitizeFileName()代码如下:
function SanitizeFileName( sNewFileName )
        Dim oRegex
        Set oRegex = New RegExp
        oRegex.Global                = True

        if ( ConfigForceSingleExtension = True ) then
                oRegex.Pattern = "\.(?![^.]*$)"
                sNewFileName = oRegex.Replace( sNewFileName, "_" )
        end if

' remove \ / | : ? *  " < > and control characters
        oRegex.Pattern = "(\\|\/|\||:|\;|\?|\*|""|\<|\>|[\u0000-\u001F]|\u007F)"
        SanitizeFileName = oRegex.Replace( sNewFileName, "_" )

        Set oRegex = Nothing
end function
三.  技术验证
这里上传一个webshell然后抓包修改扩展名为func.aspx%00txt,如图所示:

第一次上传文件名被修改为func.aspx_txt,如图所示

第二次上传同名文件,成功getshell,如图所示:


四.  总结
4.1  漏洞小结
问题最终还是出在对变量的过滤问题上,虽然fckeditor已经多次死在扩展名过滤上,但这次还是没有摆脱被上传的宿命。
4.2  防护方案
01 修改/fckeditor/editor/filemanager/connectors/asp/config.asp中的
ConfigAllowedExtensions.Add        "File", "7z|aiff|asf|avi|bmp|csv|doc|fla|flv|gif|gz|gzip|jpeg|jpg|mid|mov|mp3|mp4|mpc|mpeg|mpg|ods|odt|pdf|png|ppt|pxd|qt|ram|rar|rm|rmi|rmvb|rtf|sdc|sitd|swf|sxc|sxw|tar|tgz|tif|tiff|txt|vsd|wav|wma|wmv|xls|xml|zip"

ConfigAllowedExtensions.Add        "File", "^(7z|aiff|asf|avi|bmp|csv|doc|fla|flv|gif|gz|gzip|jpeg|jpg|mid|mov|mp3|mp4|mpc|mpeg|mpg|ods|odt|pdf|png|ppt|pxd|qt|ram|rar|rm|rmi|rmvb|rtf|sdc|sitd|swf|sxc|sxw|tar|tgz|tif|tiff|txt|vsd|wav|wma|wmv|xls|xml|zip)$"

02 在/fckeditor/editor/filemanager/connectors/asp/commands.asp的第167行添加sExtension = SanitizeFileName( sExtension )

关于作者

winxwin8篇文章38篇回复

评论31次

要评论?请先  登录  或  注册