你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
| 产品/服务 | 文章 |
|---|---|
| WCF | |
| Web API |
|
| Web 应用程序 |
WCF - 不要在配置文件中包含 serviceDebug 节点
| 标题 | 详细信息 |
|---|---|
| 组件 | WCF |
| SDL 阶段 | 构建 |
| 适用的技术 | 泛型、NET Framework 3 |
| 特性 | 不适用 |
| 参考 | MSDN、巩固王国 |
| 步骤 | Windows通信框架(WCF)服务可配置为公开调试信息。 不应在生产环境中使用调试信息。 该 <serviceDebug> 标记定义是否为 WCF 服务启用调试信息功能。 如果属性 includeExceptionDetailInFaults 设置为 true,则应用程序的异常信息将返回到客户端。 攻击者可以利用他们从调试输出中获得的其他信息来装载针对应用程序使用的框架、数据库或其他资源的攻击。 |
示例
以下配置文件包括 <serviceDebug> 标记:
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name=""MyServiceBehavior"">
<serviceDebug includeExceptionDetailInFaults=""True"" httpHelpPageEnabled=""True""/>
...
禁用服务中的调试信息。 这可以通过从应用程序的配置文件中删除 <serviceDebug> 标记来实现。
WCF - 不要在配置文件中包含 serviceMetadata 节点
| 标题 | 详细信息 |
|---|---|
| 组件 | WCF |
| SDL 阶段 | 构建 |
| 适用的技术 | 常规 |
| 特性 | 泛型、NET Framework 3 |
| 参考 | MSDN、巩固王国 |
| 步骤 | 公开有关服务的信息可以向攻击者提供有关他们如何利用该服务的宝贵见解。 该 <serviceMetadata> 标记启用元数据发布功能。 服务元数据可能包含不应公开访问的敏感信息。 至少只允许受信任的用户访问元数据,并确保不公开不必要的信息。 更好的是,完全禁用发布元数据的功能。 安全 WCF 配置将不包含 <serviceMetadata> 标记。 |
确保在 ASP.NET Web API中执行正确的异常处理
| 标题 | 详细信息 |
|---|---|
| 组件 | 网络应用程序接口 |
| SDL 阶段 | 构建 |
| 适用的技术 | MVC 5、MVC 6 |
| 特性 | 不适用 |
| 参考 | ASP.NET Web API 中的异常处理,ASP.NET Web API 中的模型验证 |
| 步骤 | 默认情况下,ASP.NET Web API中大多数未捕获的异常将转换为状态代码为 500, Internal Server Error 的 HTTP 响应 |
示例
若要控制 API 返回的状态代码, HttpResponseException 可以使用如下所示:
public Product GetProduct(int id)
{
Product item = repository.Get(id);
if (item == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
return item;
}
示例
若要进一步控制异常响应, HttpResponseMessage 可以使用类,如下所示:
public Product GetProduct(int id)
{
Product item = repository.Get(id);
if (item == null)
{
var resp = new HttpResponseMessage(HttpStatusCode.NotFound)
{
Content = new StringContent(string.Format("No product with ID = {0}", id)),
ReasonPhrase = "Product ID Not Found"
}
throw new HttpResponseException(resp);
}
return item;
}
若要捕获不是类型的 HttpResponseException未经处理的异常,可以使用异常筛选器。 异常筛选器实现 System.Web.Http.Filters.IExceptionFilter 接口。 编写异常筛选器的最简单方法是从 System.Web.Http.Filters.ExceptionFilterAttribute 类派生并重写 OnException 方法。
示例
下面是将异常转换为 NotImplementedException HTTP 状态代码 501, Not Implemented的筛选器:
namespace ProductStore.Filters
{
using System;
using System.Net;
using System.Net.Http;
using System.Web.Http.Filters;
public class NotImplExceptionFilterAttribute : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext context)
{
if (context.Exception is NotImplementedException)
{
context.Response = new HttpResponseMessage(HttpStatusCode.NotImplemented);
}
}
}
}
可通过多种方式注册 Web API 异常筛选器:
- 按操作
- 通过控制器
- 全球
示例
若要将筛选器应用于特定操作,请将筛选器添加为操作的属性:
public class ProductsController : ApiController
{
[NotImplExceptionFilter]
public Contact GetContact(int id)
{
throw new NotImplementedException("This method is not implemented");
}
}
示例
若要将筛选器应用于 controller 的所有操作,请将筛选器作为 controller 类的属性添加。
[NotImplExceptionFilter]
public class ProductsController : ApiController
{
// ...
}
示例
若要将筛选器全局应用到所有 Web API 控制器,请将筛选器的实例添加到 GlobalConfiguration.Configuration.Filters 集合。 此集合中的异常筛选器适用于任何 Web API 控制器作。
GlobalConfiguration.Configuration.Filters.Add(
new ProductStore.NotImplExceptionFilterAttribute());
示例
对于模型验证,可以将模型状态传递给 CreateErrorResponse 方法,如下所示:
public HttpResponseMessage PostProduct(Product item)
{
if (!ModelState.IsValid)
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}
// Implementation not shown...
}
请查看参考部分中的链接,了解有关 ASP.NET Web API中异常处理和模型验证的其他详细信息
不要在错误消息中公开安全详细信息
| 标题 | 详细信息 |
|---|---|
| 组件 | Web 应用程序 |
| SDL 阶段 | 构建 |
| 适用的技术 | 常规 |
| 特性 | 不适用 |
| 参考 | 不适用 |
| 步骤 | 将常规错误消息直接提供给用户,而无需包括敏感的应用程序数据。 敏感数据的示例包括:
捕获应用程序中的所有错误并提供通用错误消息,以及在 IIS 中启用自定义错误将有助于防止信息泄露。 SQL Server数据库和.NET异常处理以及其他错误处理体系结构,对于恶意用户分析应用程序尤其详细和极其有用。 请勿直接显示从 .NET Exception 类派生的类的内容,并确保具备适当的异常处理机制,这样可以避免意外的异常直接显示给用户。
|
实现默认错误处理页
| 标题 | 详细信息 |
|---|---|
| 组件 | Web 应用程序 |
| SDL 阶段 | 构建 |
| 适用的技术 | 常规 |
| 特性 | 不适用 |
| 参考 | 编辑 ASP.NET 错误页设置对话框 |
| 步骤 | 当 ASP.NET 应用程序失败并导致 HTTP/1.x 500 内部服务器错误或功能配置(如请求筛选)阻止显示页面时,将生成错误消息。 管理员可以选择应用程序是否应向客户端显示友好消息、向客户端显示详细的错误消息,还是仅向 localhost 显示详细的错误消息。
打开 |
在 IIS 中将部署方法设置为 Retail
| 标题 | 详细信息 |
|---|---|
| 组件 | Web 应用程序 |
| SDL 阶段 | 部署 |
| 适用的技术 | 常规 |
| 特性 | 不适用 |
| 参考 | deployment 元素(ASP.NET 配置架构) |
| 步骤 | 该 通常,主要面向开发人员的开关和选项(例如,对失败的请求进行跟踪和调试)是在现行开发的过程中启用的。 建议将任何生产服务器上的部署方式设置为零售模式。 打开 machine.config 文件,确保 |
异常应安全失败
| 标题 | 详细信息 |
|---|---|
| 组件 | Web 应用程序 |
| SDL 阶段 | 构建 |
| 适用的技术 | 常规 |
| 特性 | 不适用 |
| 参考 | 安全失效 |
| 步骤 | 应用程序应以安全的方式失败。 返回布尔值并用于做出某些决策的方法,应仔细设计异常处理块。 粗心编写异常块会导致许多逻辑错误,从而引发安全问题。 |
示例
public static bool ValidateDomain(string pathToValidate, Uri currentUrl)
{
try
{
if (!string.IsNullOrWhiteSpace(pathToValidate))
{
var domain = RetrieveDomain(currentUrl);
var replyPath = new Uri(pathToValidate);
var replyDomain = RetrieveDomain(replyPath);
if (string.Compare(domain, replyDomain, StringComparison.OrdinalIgnoreCase) != 0)
{
//// Adding additional check to enable CMS urls if they are not hosted on same domain.
if (!string.IsNullOrWhiteSpace(Utilities.CmsBase))
{
var cmsDomain = RetrieveDomain(new Uri(Utilities.Base.Trim()));
if (string.Compare(cmDomain, replyDomain, StringComparison.OrdinalIgnoreCase) != 0)
{
return false;
}
else
{
return true;
}
}
return false;
}
}
return true;
}
catch (UriFormatException ex)
{
LogHelper.LogException("Utilities:ValidateDomain", ex);
return true;
}
}
如果发生某些异常,上述方法将始终返回 True。 如果最终用户提供格式不正确的 URL,浏览器会遵循该 URL,但 Uri() 构造函数不遵循,这将引发异常,受害者将转到有效但格式不正确的 URL。