找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

1733

积分

0

好友

229

主题
发表于 昨天 21:37 | 查看: 3| 回复: 0

在针对一款基于 .NET Framework 开发的企业级 Web 应用进行安全评估时,代码审计是发现深层次安全漏洞的有效手段。本次审计实践将复盘三个典型漏洞的发现与验证过程,涵盖文件上传、SQL注入与身份认证绕过。

前期工作准备

开始审计前,首先需要获取并分析目标应用的源码。通常,我们可以通过反编译工具(如ILSpy)对发布的DLL程序集进行逆向,还原出可读的C#源码。反编译后,由于ILSpy的全局搜索功能有限,建议同时使用代码编辑器(如Visual Studio Code)打开项目文件夹,以便高效地搜索关键词和跟踪代码逻辑。

漏洞一:未校验路径的文件上传

在网站根目录下,通过文件名FileUpload.ashx很容易定位到一个文件上传功能点。通过反编译工具ILSpy查看其源码,发现FileUpload.ashx.cs文件定义了一个FileUpload类,它继承自UploadHandler

反编译后的FileUpload.ashx关键代码如下:

using System;
using System.Linq;
using System.Web;
using JZSoft.Core.Tools.Upload;
using JZSoft.Service.Common;
using Newtonsoft.Json;

public class FileUpload : UploadHandler
{
    public override string GetResult(string localFileName, string uploadFilePath)
    {
        if (err.Length > 0)
        {
            return JsonConvert.SerializeObject(new
            {
                msg = new
                {
                    localName = localFileName
                }
            });
        }
    }
}

可以看到,该类主要负责上传成功后的结果(如缩略图路径)序列化为JSON返回。真正的上传逻辑在其父类UploadHandler中。继续跟进UploadHandler类,发现它创建了一个FileUploader实例来处理核心上传流程。

UploadHandler抽象类的关键逻辑如下:

using System.Web;
using JZSoft.Core.Tools.Upload;

public abstract class UploadHandler : IHttpHandler
{
    protected FileUploader _fileUploader = new FileUploader();
    protected virtual string[] ImageExt => _fileUploader.ImageExt;
    protected UpfileResult Result { get { return set; } }
    public bool IsReusable => false;

    public abstract string GetResult(string localFileName, string uploadFilePath, string err);
    public abstract void OnUploaded(HttpContext context, string filePath);

    public void ProcessRequest(HttpContext context)
    {
        UpfileResult res = (Result = _fileUploader.Upload(context));
        if (res.Success)
        {
            OnUploaded(context, res.FilePath);
            context.Response.Write(GetResult(Result.LocalPath, Result.FilePath, Result.Error));
            context.Response.End();
        }
    }
}

因此,审计的重点转向FileUploader类。在该类中,发现了对上传文件扩展名的白名单校验,允许上传的类型包括常见的文档、图片和压缩包,安全性看似有一定保障。

public virtual string[] AllowExt => new string[15]
{
    "txt", "rar", "zip", "gif", "jpg", "jpeg", "bmp", "png", "swf", "xls", "xlsx", "doc", "docx", "pdf", "apk"
};
public virtual string[] ImageExt => new string[5] { "gif", "jpg", "jpeg", "bmp", "png" };

然而,在保存文件的SaveFile方法中,存在一个关键缺陷:上传的子目录(subfolder)参数直接取自用户请求,未做任何校验,这导致了目录遍历攻击的可能。

private string SaveFile(HttpContext context, string subFolder, string ext, string filePath, byte[] file)
{
    string folder = (string.IsNullOrEmpty(context.Request["subfolder"])? "default" : context.Request["subfolder"]);
    filePath = Path.Combine(UploadConfig.UploadPath, folder, subFolder);
    // ... 后续文件保存逻辑
}

尽管有白名单限制,但由于上传路径可控,攻击者可以将文件上传到非预期目录,结合其他漏洞(如文件解析漏洞)可能扩大危害。通过构造一个包含subfolder参数的multipart/form-data请求,可以验证此上传点确实存在且未授权。

请求与响应示例:

  • 请求报文:/FileUpload.ashx发起POST请求,包含一个文件字段file(值为1.png)和一个可控的subfolder参数。
  • 响应报文: 服务器返回状态码200,并包含一个JSON对象,其中url字段显示了文件在服务器上的存储路径,路径中包含了用户可控的subfolder值,证实了路径可控的问题。

这本质上是一个未授权+路径可控的文件上传漏洞。在安全/渗透/逆向实践中,此类漏洞常被作为入口点。

漏洞二:拼接导致的SQL注入

为了寻找SQL注入点,使用代码编辑器的全局搜索功能查找select * from等常见SQL语句模式。结果中,TaskReportConfigController类引起了注意,其代码中存在大量明显的字符串拼接。

部分存在风险的代码逻辑如下:

if (!string.IsNullOrEmpty(YeWuHaoMa))
{
    text2 = text2 + " and TBG_GamTaskInfoBM.TaskNumber Like '%" + YeWuHaoMa + "%'";
}
if (!string.IsNullOrEmpty(KuWeiName))
{
    text2 = text2 + " and TB_StoreBM.StoreName Like'%" + KuWeiName + "%' ";
}
// ... 更多类似拼接
List<TB_TaskReportConfig> list = (from p in managerEFRepository.GetModel((TB_TaskReportConfig p) => p.IsDisable == 0)
    orderby p.XuHao
    select p).ToList();
for (int i = 0; i < list.Count; i++)
{
    // ... 复杂的SQL语句动态构建过程
    string text4 = "select text.Trim() from (select text2)"; // 注意,text2是用户输入拼接的字符串
    DataTable datatable = new ManagerReportQuery(TB_TaskReportConfig).GetDataTable(text4, null);
    ajaxResult.ResultTable = datatable.Rows.Count;
}

可以看到,用户传入的参数(如YeWuHaoMaKuWeiName)被直接拼接到SQL查询条件字符串text2中,最终这个未经任何过滤的text2又被拼接到完整的SQL语句text4中,并交由GetDataTable方法执行,存在典型的SQL注入风险。

根据ASP.NET MVC的默认路由规则(/{Controller}/{Action}/{参数}),可推导出对应的访问路径。ControllerTaskReportConfig(去掉Controller后缀),Action为存在注入的方法名GetDataListZongHe

然而,在构造请求测试时,访问被拒绝。回溯代码发现,TaskReportConfigController继承自BaseController,而BaseController类上标注了[CheckUserStateAuthorize]特性,这意味着所有继承该类的控制器方法都会先进行用户身份校验。

[CheckUserStateAuthorize]
public class BaseController : Controller
{
    protected string errorPage = "Save";
    private TBS_YongHu _currentUser;
    protected TBS_YongHu CurrentUser
    {
        get
        {
            // ... 从当前用户身份信息中获取用户实体的逻辑
            return _currentUser;
        }
    }
}

因此,要利用这个SQL注入漏洞,首先需要获得一个有效的登录身份。这也体现了在C#/.Net应用审计中,权限校验机制对漏洞利用条件的影响。

漏洞三:默认密码导致的弱口令与突破

面对需要登录才能触发的SQL注入点,我们转向身份认证系统。虽然网站存在用户名枚举和登录验证码延时等缺陷,但由于密码加密和错误次数限制,直接爆破收效甚微。

通过代码搜索“密码”、“重置”等关键词,在权限管理相关的配置或代码中,发现了用户忘记密码后的初始化密码值。

相关配置代码片段显示:

...
value="将重置初始化" icon="glyphicon glyphicon-trash" url="/sysManage/ext">
...
value="将重置初始化" icon="glyphicon glyphicon-pencil" url="/sysManage/ext">

这提示我们,系统存在一个默认的、固定的密码重置值。攻击者只需要遍历有效的用户名,并尝试使用这个默认的初始化密码,即可绕过复杂的加密和风控机制,实现“弱口令”攻击。

在通过此方法成功获取一个有效账户的登录权限后,我们便满足了BaseController的权限校验要求,之前发现的SQL注入漏洞得以成功复现和验证。

这个案例清晰地展示了一次完整的软件测试与安全审计路径:从文件上传功能切入,发现SQL注入风险,再通过代码审计找到认证系统的薄弱点(默认密码),最终将多个漏洞串联形成完整的攻击链。

参考资料

[1] .NET代码审计初识, 微信公众号:mp.weixin.qq.com/s/2fVLVUVrWm8TsoeEqeAjiQ

版权声明:本文由 云栈社区 整理发布,版权归原作者所有。




上一篇:扒开 1.4 万 Star 的 WiFi-DensePose 源码:教科书般的 Rust 架构,与 AI 写的“空壳”
下一篇:OpenHarmony应用开发:用cached_query实现顶级数据缓存
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-3-2 04:40 , Processed in 0.384149 second(s), 42 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表