UEditor 是一款颇为老旧的富文本编辑器,曾经普遍流行过所以在一些老的项目里面,还会存在。但是该项目到目前为止已经永久停止更新,所以当发现漏洞时,只能自己维护。最好停止使用并更换富文本编辑器组件,个人推荐modstart-lib/ueditor-plus、Notadd/Neditor。这些都是UEditor为核心的二次开发项目,方便升级。
1、漏洞原理
网上关于这个漏洞已经有了十分详细的解释、各路大神已经指明了道路,这边简单介绍一下出现的位置与原理。
1.1出现漏洞的代码位置
文件上传漏洞影响UEditor 的.Net版本,其他版本暂未影响,漏洞出现在图中的CrawlerHandler.cs中,其中controller.ashx是入口。
UEditor 在抓取远程数据源的时候,会进入【catchimage】这个分支里面。然后就进入了漏洞出现的CrawlerHandler类中。
上面是CrawlerHandler类中的漏洞位置,最重要的是if判断语句,只是对ContentType进行了简单的验证,这个黑客留下了余地。
1.2 漏洞实现原理
既然在1.1中已经了解了在图片验证时只验证了ContentType,那我就可以通过工具修改ContentType,躲避掉这个判断,然后就可以进入到接下来的流程中。
而接下来就是下载到服务器操作,从而可以上传全部类型的文件,只需要你自己拥有一台服务器即可。
这个漏洞危险程度之高甚至能获取到服务器的高级权限。具体做法是修改ContentType伪装自己是图片,然后在路径里添加?.aspx绕过获取文件名的检测,然后你就能向服务器上传aspx动态页面文件,从而获取webshell,到了这一步服务器就已经被攻破了。
2.漏洞修复
推荐的修复方式就是在CrawlerHandler类添加文件类型检查的代码,使用各类WAF软件增强服务器防护等级。
网上大部分关于如何添加文件类型检查都只是建议并没有具体实现,这里提供了一个简单的实现方式仅供参考。
static bool IsImage(HttpWebResponse response)
{
using (Stream responseStream = response.GetResponseStream())
{
if (responseStream == null || !responseStream.CanRead)
{
return false;
}
byte[] buffer = new byte[40]; // 40个字节应该足够涵盖大多数格式的文件头
int bytesRead = responseStream.Read(buffer, 0, buffer.Length);
return IsJPEG(buffer, bytesRead) || IsPNG(buffer, bytesRead) || IsGIF(buffer, bytesRead)
}
}
static bool IsJPEG(byte[] buffer, int bytesRead)
{
return bytesRead >= 3 &&
buffer[0] == 0xFF &&
buffer[1] == 0xD8 &&
buffer[2] == 0xFF;
}
static bool IsPNG(byte[] buffer, int bytesRead)
{
return bytesRead >= 8 &&
buffer[0] == 0x89 &&
buffer[1] == 0x50 &&
buffer[2] == 0x4E &&
buffer[3] == 0x47 &&
buffer[4] == 0x0D &&
buffer[5] == 0x0A &&
buffer[6] == 0x1A &&
buffer[7] == 0x0A;
}
static bool IsGIF(byte[] buffer, int bytesRead)
{
return bytesRead >= 6 &&
buffer[0] == 0x47 &&
buffer[1] == 0x49 &&
buffer[2] == 0x46 &&
buffer[3] == 0x38 &&
(buffer[4] == 0x39 || buffer[4] == 0x37) &&
buffer[5] == 0x61;
}
尽可能小的改动量下,对类型进行验证,在此代码中:
- 读取响应流的前几个字节。
- 通过检查图像格式的特定魔数来判断响应是否为图片格式。
这里列举了4中类型(jpg\jpeg、png、gif)进行判断,可扩展。
通过读取响应流的前几个字节来判断文件类型,实际上已经是一种相对较为安全和通用的方法,特别是在ContentType不可用或不可靠的情况下。这是因为文件头(或魔数)通常是标识文件类型的更直接和可靠的方式。