c# - 在 ASP.NET MVC 中动态呈现 View 的安全隐患

标签 c# asp.net .net asp.net-mvc model-view-controller

我正在构建的 ASP.NET MVC 网站有一个要求,即管理员需要能够在文件系统中手动创建一个 cshtml 文件(当然在 Views 文件夹下),然后能够访问该文件通过 Controller 操作进行翻页。 (即创建名为 Test.cshtml 的文件,然后通过 /Content/Test 访问)

我通过以下方法完成了此操作:

首先,自定义路由配置:

routes.MapRoute(
            name: "StandardContent", // my controller
            url: "Content/{pageName}",
            defaults: new {controller = "Content", action = "Render", pageName = UrlParameter.Optional}
        );

然后controller action以 View 名作为参数,检查请求的 View 名是否存在,然后渲染 View :

public ActionResult Render(string pageName)
{
    if (pageName.IsNullOrEmpty())
    {
        return RedirectToAction("Index", "Home");
    }

    // if no view exists with this name, go 404
    if (!this.ViewExists(pageName)) // my extension method for view checking
    {
        return RedirectToAction("NotFound", "Error");
    }

    return View(pageName);
}

这工作得很好,我很满意,除了它的安全隐患。在这里,我基本上采用用户在 url 中写入的任何原始输入,并检查该输入是否存在 View 。用户是否可能写入一些恶意参数,从而允许他们访问通常应限制访问的文件(例如连接字符串文件)?如果是这样,我应该如何预防?


如果有帮助,这里是扩展方法 this.ViewExists(pageName) 的代码。

public static bool ViewExists(this Controller controller, string viewName)
{
    var result = ViewEngines.Engines.FindView(controller.ControllerContext, viewName, null);
    return result.View != null;
}

最佳答案

我在我的应用程序中有相同的功能,只是添加了一个正则表达式检查以睡得更好。
您可以简单地将它添加到您的 ViewExists 方法中:

public static bool ViewExists(this Controller controller, string viewName)
{
    // check for viewName null or empty here?

    if (!Regex.IsMatch(viewName, "^[A-Za-z0-9_]+$"))
        throw new HttpException(404, "Not found");

    var result = ViewEngines.Engines.FindView(controller.ControllerContext, viewName, null);
    return result.View != null;
}

确保在您的 View 文件名中只使用允许的符号(在我的例子中是字母、数字和下划线 (_))。


至于我,我将这个方法封装到 Controller 基类中:

public class BaseController : Controller 
{
    public ActionResult DynamicView(string viewName)
    {
        if (string.IsNullOrWhiteSpace(pageName))
            return RedirectToAction("Index", "Home");

        if (!Regex.IsMatch(viewName, "^[A-Za-z0-9_]+$"))
            return RedirectToAction("NotFound", "Error");

        var result = ViewEngines.Engines.FindView(ControllerContext, viewName, null);
        if (result.View == null)
            return RedirectToAction("NotFound", "Error");

        return View(viewName);
    }
}

然后,如果您从这个 BaseController 继承了所有 Controller ,您就可以在任何需要的时候使用这个单行代码:

public ActionResult Render(string pageName)
{
    return DynamicView(pageName); // short, simple and reusable
}

BaseController 是个很方便的东西,可以封装很多有用的 MVC 逻辑。

关于c# - 在 ASP.NET MVC 中动态呈现 View 的安全隐患,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43314539/

相关文章:

.net - 为什么 System.String 对象不缓存其哈希码?

c# - 通过索引检索 DataView 中的行

c# - 来自多线程应用程序的数据库表插入锁

asp.net - Windows Azure : How to 301 non-www url to www for a domain

C# - 以字节 block 的形式从 Google Drive 下载

c# - 如何将 Azure Function HttpRequest 正文转换为对象

c# - 播放 VS2005 中的程序是否会导致程序的工作方式与 .exe 文件不同?

c# - 有没有办法强制将 Azure CDN 文件作为浏览器附件下载?

生产环境中的 Asp.net 核心和 Angular : Spa is not being served

asp.net - 如何显示多个嵌套/动态表