在一次众测项目中,面对大量目标站点,逐一进行手动测试效率低下。为了提高效率,我决定先使用 ehole 这类指纹识别工具进行批量扫描,筛选出可能存在独特漏洞的站点。
扫描结果不尽如人意,大量目标站点运行着老版本的PHP应用,技术栈较为陈旧。

正当感觉收获寥寥时,一个异常现象引起了我的注意:其中一个站点存在目录遍历漏洞。


这无疑是一个好的开始。既然存在目录遍历,那么站点内部很可能存在其他未受保护的文件或接口。我继续深入探索,在目录中发现了一个名为 bin 的文件夹,其中包含了一个编辑器组件的相关文件。

该编辑器提供了一个演示页面 (demo.aspx),但尝试上传非图片文件时,前端会进行拦截并提示“只允许gif,jpg,jpeg,png,bmp格式”。

前端限制通常容易绕过。我直接寻找并测试了后台的上传接口(例如 file_manager_json.ashx 或 upload_json.ashx)。通过构造一个 multipart/form-data 格式的 HTTP POST 请求,直接将一个 ASPX 格式的 Webshell 文件(例如 111.aspx)发送到上传接口。

结果令人惊喜:服务器返回了“上传文件成功!”的 JSON 响应,并提供了文件路径。这意味着后端并未对文件内容和扩展名进行有效校验,成功实现了任意文件上传。

通过访问上传的 ASPX 文件,成功获得了服务器命令行执行权限。虽然当前权限是 iis apppool\company,属于应用程序池账户,权限较低,但已经成功进入内网,为后续的横向移动奠定了基础。一次成功的 渗透测试 往往始于一个简单的突破口。
(工具推荐插播)
前段时间我开发的内存马查杀工具已完成多次迭代和 Bug 修复,最新版本已发布在 GitHub:
https://github.com/private-xss/memory-shell-detector
欢迎使用并提交 Issues 反馈问题。
既然已经拿到一个据点,不妨再深入探索一下,看看这套通用框架是否存在其他安全隐患。通过反编译站点引用的 DLL 文件进行代码审计,很快就发现了问题。在第一个审查的方法中,就看到了典型的 XML 外部实体(XXE)漏洞代码。
string text = “<xml>”;
foreach (KeyValuePair<string, string> item in arr)
{
string key = item.Key;
string value = item.Value;
if (IsNumeric(value))
{
string text2 = text;
text = text2 + “<” + key + “>” + value + “</” + key + “>”;
}
else
{
string text2 = text;
text = text2 + “<” + key + “><![CDATA[ ” + value + “]]></” + key + “>”;
}
}
return text + “</xml>”;

这段代码的功能是将一个键值对数组合并为 XML 字符串,并为非数字值添加 CDATA 块。关键在于,如果攻击者能够控制输入 arr 中的值,并使其包含外部实体声明,就可能触发 XXE。接下来需要做的就是根据 DLL 文件名和之前目录遍历发现的路径,定位到调用此方法的具体路由(接口),然后构造包含恶意 DTD 引用的 POST 数据包进行测试。

通过 Burp Suite Collaborator 或类似的外带检测平台,可以验证漏洞是否存在。

如图所示,成功收到了来自目标服务器的 DNS 查询请求,这证实了 XXE 漏洞的存在,并且可以用于读取服务器文件或发起内部网络请求。
在继续的 代码审计 过程中,我查看了数据访问层的代码,发现 SQL 查询语句大量使用了字符串拼接,这是 SQL 注入漏洞的典型特征。
public DataSet GetList(string strWhere)
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append(“select id,user_id,typeId,article_id,title,price,quantity,integral,property_value,note,is_checked,updateTime ”);
stringBuilder.Append(“ FROM C_user_cart ”);
if (strWhere.Trim() != “”)
{
stringBuilder.Append(“ where ” + strWhere); // 危险!参数 strWhere 被直接拼接
}
return DbHelperSQL_Query(stringBuilder.ToString());
}

这几乎意味着“毫无安全性”可言。正当我在思考如何绕过前台验证,利用这些后台的注入点时,一个更简单的入口出现了:管理登录页面存在弱口令。

使用常见的弱口令(如 admin/admin)尝试,竟然直接登录成功。这样一来,就不需要再费力寻找前台的注入点或绕过限制了,可以直接在后台功能点进行 SQL 注入测试。

使用 sqlmap 等自动化工具对后台的查询接口进行测试,很快便确认了存在基于时间的盲注,并且数据库为 Microsoft SQL Server,甚至具备了 sysadmin 权限。这意味着通过注入可以完全控制数据库服务器。
最后,出于好奇,我对这套框架的特征(如特定的 body 内容)进行了网络空间资产测绘。

搜索结果显示有超过 150 个独立 IP 使用了这套框架。从规模上看,这像是一个资产规模不大(可能小于五千万)的开发商产品,通常这类产品的安全投入和响应能力有限,且大概率未获得安全认证。除了登录页面,其官网也未能找到开发商的有效联系方式。
至此,针对该通用框架的一轮安全评估告一段落。整个过程揭示了从信息泄露(目录遍历)到高危漏洞(任意文件上传、XXE、SQL注入)的完整攻击链,再次说明了系统化 安全测试 与安全开发生命周期(SDLC)的重要性。