一文看懂.NET应用程序安全!
介绍
此页面旨在为开发人员提供.NET安全提示。
.NET Framework
.NET Framework是Microsoft用于企业开发的主要平台。它是ASP.NET,Windows桌面应用程序,Windows Communication Foundation服务,SharePoint,Visual Studio Tools for Office和其他技术的支持API。
译者注:本文中提供的许多操作指引在.NET Core中也同样适用。
更新框架
Microsoft通过Windows Update服务使.NET Framework保持最新。开发人员通常不需要对框架运行单独的更新。可以在Windows Update[1]或Windows计算机上的Windows Update程序中访问Windows Update[2]。
使用[NuGet](https://nuget.codeplex.com/wikipage?title=Getting Started&referringTitle=Home)可以使各个框架保持最新。当Visual Studio提示您进行更新时,请将其构建到您的生命周期中。
请记住,第三方库必须单独更新,并且并非所有人都使用NuGet。例如,ELMAH需要单独的更新工作。
安全公告
通过选择以下存储库中的“监视”按钮来接收安全通知:
•.NET Core安全公告[3]•ASP.NET Core和Entity Framework核心安全公告[4]
.NET Framework
.NET Framework是一组API,它们支持高级类型的系统,数据,图形,网络,文件处理以及在Microsoft生态系统中编写企业应用程序所需的大多数其余内容。它是一个几乎无处不在的库,在程序集级别上被强命名和版本化。
资料存取
•使用参数化的SQL[5]命令进行所有数据访问,无一例外。•不要将SqlCommand[6]与由串联的SQL String[7]组成的字符串参数一起使用。•来自用户的白名单允许值。使用枚举,TryParse或查找值来确保来自用户的数据符合预期。•枚举仍然容易受到意外值的影响,因为.NET仅验证是否成功转换为基础数据类型,默认情况下为整数。Enum.IsDefined[8]可以在定义的常量列表中验证输入值是否有效。•在您选择的数据库中设置数据库用户时,请应用最小特权原则。数据库用户应该只能访问对用例有意义的项目。•在使用实体框架[9]是一种非常有效的SQL注入[10]防范机制。请记住,在Entity Framework中建立自己的关联查询与普通SQL查询一样容易受到SQL的影响。•使用SQL Server时,首选集成身份验证而[11]不是SQL身份验证[12]。•对敏感数据(SQL Server 2016和SQL Azure)尽可能使用“始终加密”[13],
加密
•永远不要写自己的加密。•使用Windows数据保护API(DPAPI)[14]对敏感数据进行安全的本地存储。•使用强大的哈希算法。•在.NET(框架和内核)中,满足常规哈希要求的最强哈希算法是System.Security.Cryptography.SHA512[15]。•在.NET框架中,最强的密码哈希算法是PBKDF2,它实现为System.Security.Cryptography.Rfc2898DeriveBytes[16]。•在.NET Core中,最强的密码哈希算法是PBKDF2,它实现为Microsoft.AspNetCore.Cryptography.KeyDerivation.Pbkdf2[17],它比Rfc2898DeriveBytes
。•当使用散列函数散列非唯一输入(例如密码)时,请在散列之前使用添加到原始值的盐值。•确保您的应用程序或协议可以轻松支持将来更改密码算法。•使用Nuget[18]可以使所有软件包保持最新状态。观看开发设置上的更新,并计划相应的应用程序更新。
一般
•锁定配置文件。•删除所有未使用的配置方面。•加密web.config
using的敏感部分aspnet_regiis -pe
(命令行帮助[19])。•对于“单击一次”应用程序,应将.Net Framework升级为使用版本4.6.2
以确保TLS 1.1/1.2
支持。
ASP NET Web表单指南
ASP.NET Web窗体是用于.NET框架的基于浏览器的原始应用程序开发API,并且仍然是用于Web应用程序开发的最常见的企业平台。
•始终使用HTTPS[20]。•对cookie和表单元素启用requireSSL[21],并在web.config中对cookie启用HttpOnly[22]。•实现customErrors[23]。•确保跟踪[24]已关闭。•虽然viewstate并不总是适合于Web开发,但使用它可以缓解CSRF。为了使ViewState免受CSRF攻击,您需要设置ViewStateUserKey[25]:
protected override OnInit(EventArgs e) {
base.OnInit(e);
ViewStateUserKey = Session.SessionID;
}
如果您不使用Viewstate,请使用双重提交cookie查找ASP.NET Web窗体默认模板的默认母版,以获取手动反CSRF令牌。
private const string AntiXsrfTokenKey = "__AntiXsrfToken";
private const string AntiXsrfUserNameKey = "__AntiXsrfUserName";
private string _antiXsrfTokenValue;
protected void Page_Init(object sender, EventArgs e)
{
// The code below helps to protect against XSRF attacks
var requestCookie = Request.Cookies[AntiXsrfTokenKey];
Guid requestCookieGuidValue;
if (requestCookie != null && Guid.TryParse(requestCookie.Value, out requestCookieGuidValue))
{
// Use the Anti-XSRF token from the cookie
_antiXsrfTokenValue = requestCookie.Value;
Page.ViewStateUserKey = _antiXsrfTokenValue;
}
else
{
// Generate a new Anti-XSRF token and save to the cookie
_antiXsrfTokenValue = Guid.NewGuid().ToString("N");
Page.ViewStateUserKey = _antiXsrfTokenValue;
var responseCookie = new HttpCookie(AntiXsrfTokenKey)
{
HttpOnly = true,
Value = _antiXsrfTokenValue
};
if (FormsAuthentication.RequireSSL && Request.IsSecureConnection)
{
responseCookie.Secure = true;
}
Response.Cookies.Set(responseCookie);
}
Page.PreLoad += master_Page_PreLoad;
}
protected void master_Page_PreLoad(object sender, EventArgs e)
{
if (!IsPostBack)
{
// Set Anti-XSRF token
ViewState[AntiXsrfTokenKey] = Page.ViewStateUserKey;
ViewState[AntiXsrfUserNameKey] = Context.User.Identity.Name ?? String.Empty;
}
else
{
// Validate the Anti-XSRF token
if ((string)ViewState[AntiXsrfTokenKey] != _antiXsrfTokenValue ||
(string)ViewState[AntiXsrfUserNameKey] != (Context.User.Identity.Name ?? String.Empty))
{
throw new InvalidOperationException("Validation of Anti-XSRF token failed.");
}
}
}
•考虑IIS中的HSTS[26]。有关步骤,请参见此处[27]。•建议您使用此web.config
设置来处理HSTS等。
xml version="1.0" encoding="UTF-8"?>
enableVersionHeader="false"/>
removeServerHeader="true" />
cacheControlMode="UseMaxAge"
cacheControlMaxAge="1.00:00:00"
setEtag="true" />
value="default-src 'none'; style-src 'self'; img-src 'self'; font-src 'self'" />
name="X-Content-Type-Options" value="NOSNIFF" />
name="X-Frame-Options" value="DENY" />
name="X-Permitted-Cross-Domain-Policies" value="master-only"/>
name="X-XSS-Protection" value="0"/>
name="X-Powered-By"/>
name="Redirect to https">
url="(.*)"/>
input="{HTTPS}" pattern="Off"/>
input="{REQUEST_METHOD}" pattern="^get$|^head$" />
type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent"/>
name="Add HSTS Header" enabled="true">
serverVariable="RESPONSE_Strict_Transport_Security" pattern=".*" />
input="{HTTPS}" pattern="on" ignoreCase="true" />
type="Rewrite" value="max-age=15768000" />
•删除版本头。
enableVersionHeader="false" />
•同时删除服务器标头。
HttpContext.Current.Response.Headers.Remove("Server");
HTTP验证和编码
•不要在或页面设置中禁用validateRequest[28]web.config
。此值在ASP.NET中启用了有限的XSS保护,应保留完整的位置,因为它提供了跨站点脚本的部分防护。除了内置保护之外,建议进行完整的请求验证。•.NET Framework的4.5版本包括AntiXssEncoder[29]库,该库具有用于防止XSS的全面输入编码库。用它。•随时接受用户输入,将允许值列入白名单。•使用Uri.IsWellFormedUriString[30]验证URI格式。
表格认证
•尽可能使用cookie来保持持久性。Cookieless
auth将默认为UseDeviceProfile[31]。•不要信任会话或授权的持久性请求的URI。它很容易伪造。•将表单身份验证超时从默认的20分钟减少到适合您的应用程序的最短时间。如果使用了slideExpiration,[32]则此超时将在每次请求后重置,因此活动用户不会受到影响。•如果不使用HTTPS,则[33]应该禁用slideExpiration[34]。考虑使用HTTPS禁用slideExpiration[35]。•始终实施适当的访问控制。•将用户提供的用户名与进行比较User.Identity.Name
。•检查角色User.Identity.IsInRole
。•使用ASP.NET成员资格提供程序和角色提供程序[36],但查看密码存储。默认存储使用SHA-1的单次迭代对密码进行哈希处理,这很弱。ASP.NET MVC4模板使用ASP.NET身份[37]而不是ASP.NET成员身份,并且ASP.NET身份默认使用PBKDF2,这更好。查看OWASP密码存储备忘单[38]以获取更多信息。•明确授权资源请求。•利用基于角色的授权User.Identity.IsInRole
。
ASP NET MVC指南
ASP.NET MVC(模型–视图–控制器)是一种当代的Web应用程序框架,与Web Forms回发模型相比,它使用更加标准化的HTTP通信。
OWASP 2017年十大最重要的威胁列出了当今世界上最普遍和最危险的网络安全威胁,并且每三年进行一次审查。
本部分基于此。保护Web应用程序安全的方法应该是从下面的最高威胁A1开始并逐步解决,这将确保花在安全性上的任何时间都可以最有效地花费,并且首先覆盖最重要的威胁,然后覆盖较小的威胁。在进入前十名之后,通常建议评估其他威胁或获得专业完成的渗透测试。
A1注射
SQL注入
应做:使用对象关系映射器(ORM)或存储过程是解决SQL Injection漏洞的最有效方法。
要做的事情:使用必须直接使用SQL查询的参数化查询。在这里[39]可以找到更多信息。
例如在实体框架中:
var sql = @"Update [User] SET FirstName = @FirstName WHERE Id = @Id";
context.Database.ExecuteSqlCommand(
sql,
new SqlParameter("@FirstName", firstname),
new SqlParameter("@Id", id));
请勿:在代码中的任何位置连接字符串,并在数据库中执行它们(称为动态sql)。
注意:您仍然可能会意外地使用ORM或存储过程执行此操作,因此请检查所有位置。
例如
string strQry = "SELECT * FROM Users WHERE UserName='" + txtUser.Text + "' AND Password='"
+ txtPassword.Text + "'";
EXEC strQry // SQL Injection vulnerability!
要做:练习最小权限-使用具有执行该工作所需的最小权限集的帐户(即不是sa帐户)连接到数据库
操作系统注入
有关OS注入的信息可以在该备忘单[40]上找到。
应做:使用System.Diagnostics.Process.Start[41]调用底层OS函数。
例如
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.FileName = "validatedCommand";
startInfo.Arguments = "validatedArg1 validatedArg2 validatedArg3";
process.StartInfo = startInfo;
process.Start();
应做:在所有用户提供的输入上使用白名单验证。输入验证可防止格式不正确的数据进入信息系统。有关更多信息,请参见输入验证备忘单[42]。
例如,使用IPAddress.TryParse方法[43]验证用户输入
//User input
string ipAddress = "127.0.0.1";
//check to make sure an ip address was provided
if (!string.IsNullOrEmpty(ipAddress))
{
// Create an instance of IPAddress for the specified address string (in
// dotted-quad, or colon-hexadecimal notation).
if (IPAddress.TryParse(ipAddress, out var address))
{
// Display the address in standard notation.
return address.ToString();
}
else
{
//ipAddress is not of type IPAddress
...
}
...
}
LDAP注入
专有名称中几乎可以使用任何字符。但是,某些\
字符必须使用反斜杠转义符进行转义。可以在LDAP注入预防速查表上[44]找到一张表格,其中显示了应为Active Directory逃脱的字符。
注意:仅当空格字符是组件名称(例如通用名称)中的前导或尾随字符时,才必须转义。嵌入式空间不应逃脱。
在这里[45]可以找到更多信息。
A2身份验证失败
要做:使用ASP.net Core Identity[46]。默认情况下,ASP.net Core Identity框架配置正确,在该框架中,它使用安全的密码哈希和单独的符号。身份使用PBKDF2哈希函数输入密码,并且每位用户都会生成随机的盐。
应做:设置安全密码策略
例如ASP.net核心身份
//startup.cs
services.Configure<IdentityOptions>(options =>
{
// Password settings
options.Password.RequireDigit = true;
options.Password.RequiredLength = 8;
options.Password.RequireNonAlphanumeric = true;
options.Password.RequireUppercase = true;
options.Password.RequireLowercase = true;
options.Password.RequiredUniqueChars = 6;
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30);
options.Lockout.MaxFailedAccessAttempts = 3;
options.SignIn.RequireConfirmedEmail = true;
options.User.RequireUniqueEmail = true;
});
要做的:设置Cookie政策
例如
//startup.cs
services.ConfigureApplicationCookie(options =>
{
options.Cookie.HttpOnly = true;
options.Cookie.Expiration = TimeSpan.FromHours(1)
options.SlidingExpiration = true;
});
A3敏感数据暴露
请勿:存储加密的密码[47]。
请执行以下操作:使用强哈希值存储密码凭据。对于哈希,请参阅本节[48]。
应做:以最小的复杂度来强制密码,使其在字典攻击中幸免,即较长的密码使用完整的字符集(数字,符号和字母)来增加熵。
要做的事情:使用强大的加密例程(例如AES-512),其中需要将个人身份数据恢复为原始格式。保护加密密钥要比保护其他任何资产都重要,请查找更多有关静止存储加密密钥的信息[49]。应用以下测试:您是否愿意将数据保留在总线上的电子表格中,以供所有人阅读。假设攻击者可以直接访问您的数据库并进行相应的保护。在这里[50]可以找到更多信息。
要做:在整个站点上使用TLS 1.2。获得免费的证书LetsEncrypt.org[51]。
请勿:允许使用SSL,现在已过时了[52]。
请执行:拥有强大的TLS策略(请参阅SSL最佳做法[53]),请尽可能使用TLS 1.2。然后使用SSL Test[54]或TestSSL[55]检查配置。
请执行以下操作:确保标头未公开有关您的应用程序的信息。请参阅HttpHeaders.cs[56],Dionach StripHeaders[57],通过viaweb.config
或startup.cs[58]禁用:
有关传输层保护的更多信息,请参见此处[59]。例如Web.config
enableVersionHeader="false"/>
removeServerHeader="true" />
name="X-Content-Type-Options" value="nosniff" />
name="X-Frame-Options" value="DENY" />
name="X-Permitted-Cross-Domain-Policies" value="master-only"/>
name="X-XSS-Protection" value="0"/>
name="X-Powered-By"/>
例如Startup.cs
app.UseHsts(hsts => hsts.MaxAge(365).IncludeSubdomains());
app.UseXContentTypeOptions();
app.UseReferrerPolicy(opts => opts.NoReferrer());
app.UseXXssProtection(options => options.FilterDisabled());
app.UseXfo(options => options.Deny());
app.UseCsp(opts => opts
.BlockAllMixedContent()
.StyleSources(s => s.Self())
.StyleSources(s => s.UnsafeInline())
.FontSources(s => s.Self())
.FormActions(s => s.Self())
.FrameAncestors(s => s.Self())
.ImageSources(s => s.Self())
.ScriptSources(s => s.Self())
);
有关标题的更多信息,请参见此处[60]。
A4 XML外部实体(XXE)
请参考XXE备忘单,以获取更多详细信息,可在此处[61]找到。
当XML解析未正确处理在XML有效负载的doctype中包含外部实体声明的用户输入时,就会发生XXE攻击。
以下是.NET的三个最常见的XML处理选项[62]。
A5损坏的访问控制
弱账户管理
确保通过httpOnly发送cookie:
CookieHttpOnly = true,
通过减少会话超时并消除滑动到期来减少会话被盗的时间:
ExpireTimeSpan = TimeSpan.FromMinutes(60),
SlidingExpiration = false
有关完整的启动代码段,请参见此处[63]
确保在生产环境中通过HTTPS发送cookie。这应该在配置转换中强制执行:
requireSSL="true" xdt:Transform="SetAttributes(requireSSL)"/>
requireSSL="true" xdt:Transform="SetAttributes(requireSSL)"/>
通过限制请求来保护登录,注册和密码重置方法免受暴力攻击(请参见下面的代码),也可以考虑使用ReCaptcha。
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
[AllowXRequestsEveryXSecondsAttribute(Name = "LogOn",
Message = "You have performed this action more than {x} times in the last {n} seconds.",
Requests = 3, Seconds = 60)]
public async Task<ActionResult> LogOn(LogOnViewModel model, string returnUrl)
不要:进行自己的身份验证或会话管理,请使用.Net提供的身份验证或会话管理
请勿:告诉某人该帐户是否存在登录,注册或密码重置的信息。说类似“用户名或密码不正确”或“如果此帐户存在,则重置令牌将发送到注册的电子邮件地址”之类的内容。这样可以防止帐户枚举。
无论在内容和行为上,无论是否存在该帐户,对用户的反馈都应该相同:例如,如果在真实帐户中的响应时间延长了50%,则可以猜测和测试成员资格信息。
缺少功能级别的访问控制
应做:授权所有面向外部端点的用户。.NET框架有很多方法可以授权用户,可以在方法级别使用它们:
[Authorize(Roles = "Admin")]
[HttpGet]
public ActionResult Index(int page = 1)
或更好,在控制器级别:
[Authorize]
public class UserController
您还可以使用.net中的身份功能检查代码中的角色: System.Web.Security.Roles.IsUserInRole(userName, roleName)
你可以找到更多的信息,这里[64]的访问控制,并在这里[65]进行授权。
不安全的直接对象引用
当您拥有可由引用访问的资源(对象)(在下面的示例中是id
)时,您需要确保打算将用户放在那里
// Insecure
public ActionResult Edit(int id)
{
var user = _context.Users.FirstOrDefault(e => e.Id == id);
return View("Details", new UserViewModel(user);
}
// Secure
public ActionResult Edit(int id)
{
var user = _context.Users.FirstOrDefault(e => e.Id == id);
// Establish user has right to edit the details
if (user.Id != _userIdentity.GetUserId())
{
HandleErrorInfo error = new HandleErrorInfo(
new Exception("INFO: You do not have permission to edit these details"));
return View("Error", error);
}
return View("Edit", new UserViewModel(user);
}
有关不安全的直接对象引用的更多信息,请参见此处[66]。
A6安全配置错误
调试和堆栈跟踪
确保调试和跟踪已在生产环境中关闭。可以使用web.config转换来强制执行:
xdt:Transform="RemoveAttributes(debug)" />
enabled="false" xdt:Transform="Replace"/>
请勿:使用默认密码
做:(使用TLS时)将通过Http发出的请求重定向到https:
例如Global.asax.cs
protected void Application_BeginRequest()
{
#if !DEBUG
// SECURE: Ensure any request is returned over SSL/TLS in production
if (!Request.IsLocal && !Context.Request.IsSecureConnection) {
var redirect = Context.Request.Url.ToString()
.ToLower(CultureInfo.CurrentCulture)
.Replace("http:", "https:");
Response.Redirect(redirect);
}
#endif
}
例如Configure()中的Startup.cs
app.UseHttpsRedirection();
跨站点伪造
请勿:在不验证防伪令牌(.NET[67] / .NET Core[68])的情况下发送敏感数据。
请执行:在每个POST / PUT请求中发送防伪令牌:
使用.NET FRAMEWORK
using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm",
@class = "pull-right" }))
{
@Html.AntiForgeryToken()
class="nav nav-pills">
role="presentation"> Logged on as @User.Identity.Name
role="presentation"> href="javascript:document.getElementById('logoutForm').submit()">Log off
}
然后在方法或控制器级别进行验证:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult LogOff()
确保令牌已完全删除,以使注销无效。
///
/// SECURE: Remove any remaining cookies including Anti-CSRF cookie
///
public void RemoveAntiForgeryCookie(Controller controller)
{
string[] allCookies = controller.Request.Cookies.AllKeys;
foreach (string cookie in allCookies)
{
if (controller.Response.Cookies[cookie] != null &&
cookie == "__RequestVerificationToken")
{
controller.Response.Cookies[cookie].Expires = DateTime.Now.AddDays(-1);
}
}
}
使用.NET CORE 2.0或更高版本
从.NET Core 2.0开始,可以自动生成和验证防伪令牌[69]。
如果您使用tag-helpers[70],这是大多数Web项目模板的默认设置,则所有表单都会自动发送防伪令牌。您可以通过检查主_ViewImports.cshtml
文件是否包含以下内容来检查是否启用了标记辅助功能:
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
IHtmlHelper.BeginForm
还会自动发送防伪令牌。
除非您使用tag-helpers或IHtmlHelper.BeginForm
,否则必须在表单上使用必需的帮助器,如下所示:
@Html.AntiForgeryToken()
要自动验证除GET,HEAD,OPTIONS和TRACE之外的所有其他请求,您需要添加一个全局操作过滤器,该过滤器内部应具有AutoValidateAntiforgeryToken[71]属性,Startup.cs
如以下文章所述[72]:
services.AddMvc(options =>
{
options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
});
如果需要禁用控制器上特定方法的属性验证,可以将IgnoreAntiforgeryToken[73]属性添加到控制器方法(对于MVC控制器)或父类(对于Razor页面):
[IgnoreAntiforgeryToken]
[HttpDelete]
public IActionResult Delete()
[IgnoreAntiforgeryToken]
public class UnsafeModel : PageModel
如果您还需要验证GET,HEAD,OPTIONS或TRACE-请求上的令牌,则可以将ValidateAntiforgeryToken[74]属性添加到控制器方法(对于MVC控制器)或父类(对于Razor页面):
[HttpGet]
[ValidateAntiforgeryToken]
public IActionResult DoSomethingDangerous()
[HttpGet]
[ValidateAntiforgeryToken]
public class SafeModel : PageModel
如果您不能使用全局操作过滤器,请将AutoValidateAntiforgeryToken[75]属性添加到控制器类或剃刀页面模型中:
[AutoValidateAntiforgeryToken]
public class UserController
[AutoValidateAntiforgeryToken]
public class SafeModel : PageModel
将.NET CORE 2.0或.NET FRAMEWORK与AJAX一起使用
您将需要在AJAX请求上附加防伪令牌。
如果您在ASP.NET Core MVC视图中使用jQuery,则可以使用以下代码段实现:
@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery antiforgeryProvider
$.ajax(
{
type: "POST",
url: '@Url.Action("Action", "Controller")',
contentType: "application/x-www-form-urlencoded; charset=utf-8",
data: {
id: id,
'__RequestVerificationToken': '@antiforgeryProvider.GetAndStoreTokens(this.Context).RequestToken'
}
})
如果您使用的是.NET Framework,则可以在此处[76]找到一些代码段。
可以在此处[77]找到“跨站点请求伪造”的更多信息。
A7跨站脚本(XSS)
不要:信任用户发送给您的任何数据,更喜欢白名单(始终安全)而不是黑名单
您可以使用MVC3对所有HTML内容进行编码,无论HTML,javascript,CSS,LDAP等是否使用Microsoft AntiXSS库都可以对所有内容进行正确编码:
Install-Package AntiXSS
然后在配置中设置:
enableVersionHeader="false"
encoderType="Microsoft.Security.Application.AntiXssEncoder, AntiXssLibrary"
maxRequestLength="4096" />
请勿:使用[AllowHTML]
属性或帮助程序类,@Html.Raw
除非您真的知道要写入浏览器的内容是安全的并且已被正确转义。
请执行以下操作:启用内容安全策略[78],这将阻止您的页面访问其不应该访问的资产(例如恶意脚本):
value="default-src 'none'; style-src 'self'; img-src 'self';
font-src 'self'; script-src 'self'" />
可以在此处[79]找到有关跨站点脚本的更多信息。
A8不安全的反序列化
有关不安全反序列化的信息可以在此备忘单[80]上找到。
不要:接受来自不受信任来源的序列化对象
要做:验证用户输入恶意用户能够使用Cookie之类的对象插入恶意信息来更改用户角色。在某些情况下,黑客可以使用上一个会话中预先存在或缓存的密码哈希将其特权提升为管理员权限。
应做:防止域对象的反序列化
请执行:以有限的访问权限运行反序列化代码如果反序列化的敌对对象试图启动系统进程或访问服务器或主机OS中的资源,则将拒绝访问该对象,并且将引发权限标志,以便系统管理员被告知服务器上的任何异常活动。
可以在这里找到更多信息:反序列化备忘单[81]
A9使用具有已知漏洞的组件
要做的:用最新的补丁更新.Net框架
要做:使您的NuGet[82]软件包保持最新,许多将包含其自身的漏洞。
要做:作为构建过程的一部分,对您的应用程序运行OWASP Dependency Checker,[83]并对任何高级漏洞进行处理。
A10记录和监控不足
请执行以下操作:确保可以使用足够的用户上下文记录所有登录,访问控制失败和服务器端输入验证失败,以识别可疑或恶意帐户。
应做:建立有效的监视和警报,以便及时发现可疑活动并做出响应。
请勿:记录一般错误消息,例如:csharp Log.Error("Error was thrown");
记录引起错误的堆栈跟踪,错误消息和用户ID。
请勿:记录敏感数据,例如用户的密码。
记录中
在该备忘单[84]上可以找到要收集的日志以及有关日志的更多信息。
.NET Core带有一个LoggerFactory,位于Microsoft.Extensions.Logging中。有关ILogger的更多信息,请参见此处[85]。
如何记录来自的所有错误Startup.cs
,以便在引发错误时都会记录该错误。
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
_isDevelopment = true;
app.UseDeveloperExceptionPage();
}
//Log all errors in the application
app.UseExceptionHandler(errorApp =>
{
errorApp.Run(async context =>
{
var errorFeature = context.Features.Get<IExceptionHandlerFeature>();
var exception = errorFeature.Error;
Log.Error(String.Format("Stacktrace of error: {0}",exception.StackTrace.ToString()));
});
});
app.UseAuthentication();
app.UseMvc();
}
}
例如,注入到类构造函数中,这使得编写单元测试更加简单。建议使用依赖注入(例如MVC控制器)创建类的实例。以下示例显示了所有未成功登录尝试的日志记录。
public class AccountsController : Controller
{
private ILogger _Logger;
public AccountsController( ILogger logger)
{
_Logger = logger;
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(LoginViewModel model)
{
if (ModelState.IsValid)
{
var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false);
if (result.Succeeded)
{
//Log all successful log in attempts
Log.Information(String.Format("User: {0}, Successfully Logged in", model.Email));
//Code for successful login
}
else
{
//Log all incorrect log in attempts
Log.Information(String.Format("User: {0}, Incorrect Password", model.Email));
}
}
...
ILogger的日志记录级别按重要性从高到低的顺序列出如下:
监控方式
监视使我们能够通过关键性能指标来验证正在运行的系统的性能和运行状况。
在.NET中,添加监视功能的绝佳选择是Application Insights[86]。
可以在此处[87]找到有关日志记录和监视的更多信息。
OWASP 2013
以下是OWASP 2017中未讨论的漏洞
A10未经验证的重定向和转发
Mvc 3模板中引入了针对此问题的保护措施。这是代码:
public async Task<ActionResult> LogOn(LogOnViewModel model, string returnUrl)
{
if (ModelState.IsValid)
{
var logonResult = await _userManager.TryLogOnAsync(model.UserName, model.Password);
if (logonResult.Success)
{
await _userManager.LogOnAsync(logonResult.UserName, model.RememberMe);
return RedirectToLocal(returnUrl);
...
private ActionResult RedirectToLocal(string returnUrl)
{
if (Url.IsLocalUrl(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Landing", "Account");
}
}
其他建议:
•为防止Clickjacking和中间人攻击而捕获初始的非TLS请求,请设置X-Frame-Options
和Strict-Transport-Security
(HSTS)标头。完整细节在这里[88]•防止从未来过您网站的用户遭受中间人攻击。注册以获取HSTS预载[89]•维护Web API服务的安全测试和分析。它们隐藏在MEV站点内部,并且是攻击者将发现的站点的公共部分。所有MVC指南和许多WCF指南都适用于Web API。•未经验证的重定向和转发备忘单[90]。
更多信息:
有关上述所有内容的更多信息,以及合并到具有增强的安全性基准的示例MVC5应用程序中的代码示例,请转到Security Essentials Baseline项目。[91]
XAML指导
•在您的应用程序的Internet区域安全性约束内工作。•使用ClickOnce部署。要增强权限,请在运行时使用权限提升或在安装时使用可信应用程序部署。
Windows表单指导
•尽可能使用部分信任。部分受信任的Windows应用程序可减少应用程序的攻击面。管理您的应用必须使用的权限列表以及可能使用的权限列表,然后在运行时声明性地请求这些权限。•使用ClickOnce部署。要增强权限,请在运行时使用权限提升或在安装时使用可信应用程序部署。
WCF指导
•请记住,在RESTful服务中传递请求的唯一安全方法是通过HTTP POST
,和TLS enabled
。GETs在中可见,querystring
缺少TLS意味着可以拦截该正文。•避免使用BasicHttpBinding[92]。它没有默认的安全配置。请改用WSHttpBinding[93]。•至少使用两种安全模式进行绑定。消息安全性包括标头中的安全性规定。传输安全性意味着使用SSL。TransportWithMessageCredential[94]结合了两者。•用诸如ZAP之[95]类的模糊测试您的WCF实现。
References
[1]
Windows Update: http://windowsupdate.microsoft.com/[2]
Windows Update: http://windowsupdate.microsoft.com/[3]
.NET Core安全公告: https://github.com/dotnet/announcements/issues?q=is%3Aopen+is%3Aissue+label%3ASecurity[4]
ASP.NET Core和Entity Framework核心安全公告: https://github.com/aspnet/Announcements/issues?q=is%3Aopen+is%3Aissue+label%3ASecurity[5]
参数化的SQL: https://docs.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlcommand.prepare?view=netframework-4.7.2[6]
SqlCommand: https://docs.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlcommand[7]
串联的SQL String: https://docs.microsoft.com/en-gb/visualstudio/code-quality/ca2100-review-sql-queries-for-security-vulnerabilities?view=vs-2017[8]
Enum.IsDefined: https://docs.microsoft.com/en-us/dotnet/api/system.enum.isdefined[9]
实体框架: https://docs.microsoft.com/en-us/ef/[10]
SQL注入: https://owasp.org/www-community/attacks/SQL_Injection[11]
集成身份验证而: https://docs.microsoft.com/en-us/sql/connect/odbc/linux-mac/using-integrated-authentication?view=sql-server-2017[12]
SQL身份验证: https://docs.microsoft.com/en-us/sql/relational-databases/security/choose-an-authentication-mode?view=sql-server-2017#connecting-through-sql-server-authentication[13]
始终加密”: https://docs.microsoft.com/en-us/sql/relational-databases/security/encryption/always-encrypted-database-engine[14]
Windows数据保护API(DPAPI): https://docs.microsoft.com/en-us/dotnet/standard/security/how-to-use-data-protection[15]
System.Security.Cryptography.SHA512: https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.sha512[16]
System.Security.Cryptography.Rfc2898DeriveBytes: https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.rfc2898derivebytes[17]
Microsoft.AspNetCore.Cryptography.KeyDerivation.Pbkdf2: https://docs.microsoft.com/en-us/aspnet/core/security/data-protection/consumer-apis/password-hashing[18]
Nuget: https://docs.microsoft.com/en-us/nuget/[19]
命令行帮助: https://docs.microsoft.com/en-us/previous-versions/dotnet/netframework-2.0/k6h9cz8h(v=vs.80)[20]
HTTPS: https://support.microsoft.com/kb/324069[21]
requireSSL: https://docs.microsoft.com/en-us/dotnet/api/system.web.configuration.httpcookiessection.requiressl[22]
HttpOnly: https://docs.microsoft.com/en-us/dotnet/api/system.web.configuration.httpcookiessection.httponlycookies[23]
customErrors: https://docs.microsoft.com/en-us/dotnet/api/system.web.configuration.customerror[24]
跟踪: http://www.iis.net/configreference/system.webserver/tracing[25]
ViewStateUserKey: https://docs.microsoft.com/en-us/dotnet/api/system.web.ui.page.viewstateuserkey[26]
HSTS: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security[27]
此处: https://support.microsoft.com/en-us/help/954002/how-to-add-a-custom-http-response-header-to-a-web-site-that-is-hosted[28]
validateRequest: https://www.asp.net/whitepapers/request-validation[29]
AntiXssEncoder: https://docs.microsoft.com/en-us/dotnet/api/system.web.security.antixss.antixssencoder?view=netframework-4.7.2[30]
Uri.IsWellFormedUriString: https://docs.microsoft.com/en-us/dotnet/api/system.uri.iswellformeduristring[31]
UseDeviceProfile: https://docs.microsoft.com/en-us/dotnet/api/system.web.httpcookiemode?view=netframework-4.7.2[32]
slideExpiration,: https://docs.microsoft.com/en-us/dotnet/api/system.web.security.formsauthentication.slidingexpiration?view=netframework-4.7.2[33]
则: https://docs.microsoft.com/en-us/dotnet/api/system.web.security.formsauthentication.slidingexpiration?view=netframework-4.7.2[34]
slideExpiration: https://docs.microsoft.com/en-us/dotnet/api/system.web.security.formsauthentication.slidingexpiration?view=netframework-4.7.2[35]
slideExpiration: https://docs.microsoft.com/en-us/dotnet/api/system.web.security.formsauthentication.slidingexpiration?view=netframework-4.7.2[36]
ASP.NET成员资格提供程序和角色提供程序: https://docs.microsoft.com/en-us/dotnet/framework/wcf/samples/membership-and-role-provider[37]
ASP.NET身份: https://www.asp.net/identity/overview/getting-started/introduction-to-aspnet-identity[38]
密码存储备忘单: https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html[39]
这里: https://cheatsheetseries.owasp.org/cheatsheets/Query_Parameterization_Cheat_Sheet.html[40]
备忘单: https://cheatsheetseries.owasp.org/cheatsheets/OS_Command_Injection_Defense_Cheat_Sheet.html#net[41]
System.Diagnostics.Process.Start: https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.process.start?view=netframework-4.7.2[42]
输入验证备忘单: https://cheatsheetseries.owasp.org/cheatsheets/Input_Validation_Cheat_Sheet.html[43]
IPAddress.TryParse方法: https://docs.microsoft.com/en-us/dotnet/api/system.net.ipaddress.tryparse?view=netframework-4.8[44]
LDAP注入预防速查表上: https://cheatsheetseries.owasp.org/cheatsheets/LDAP_Injection_Prevention_Cheat_Sheet.html#introduction[45]
这里: https://cheatsheetseries.owasp.org/cheatsheets/LDAP_Injection_Prevention_Cheat_Sheet.html#introduction[46]
ASP.net Core Identity: https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity?view=aspnetcore-2.2&[47]
存储加密的密码: https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#do-not-limit-the-character-set-and-set-long-max-lengths-for-credentials[48]
本节: https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#guidance[49]
更多有关静止存储加密密钥的信息: https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#guidance[50]
这里: https://cheatsheetseries.owasp.org/cheatsheets/Transport_Layer_Protection_Cheat_Sheet.html[51]
LetsEncrypt.org: https://letsencrypt.org/[52]
允许使用SSL,现在已过时了: https://github.com/ssllabs/research/wiki/SSL-and-TLS-Deployment-Best-Practices[53]
SSL最佳做法: https://www.ssllabs.com/projects/best-practices/index.html[54]
SSL Test: https://www.ssllabs.com/ssltest/[55]
TestSSL: https://testssl.sh/[56]
HttpHeaders.cs: https://github.com/johnstaveley/SecurityEssentials/blob/master/SecurityEssentials/Core/HttpHeaders.cs[57]
Dionach StripHeaders: https://github.com/Dionach/StripHeaders/[58]
startup.cs: https://medium.com/bugbountywriteup/security-headers-1c770105940b[59]
此处: https://cheatsheetseries.owasp.org/cheatsheets/Transport_Layer_Protection_Cheat_Sheet.html[60]
此处: https://owasp.org/www-project-secure-headers/[61]
此处: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#net[62]
XML处理选项: https://docs.microsoft.com/en-us/dotnet/standard/data/xml/xml-processing-options[63]
此处: https://github.com/johnstaveley/SecurityEssentials/blob/master/SecurityEssentials/App_Start/Startup.Auth.cs[64]
这里: https://cheatsheetseries.owasp.org/cheatsheets/Access_Control_Cheat_Sheet.html#introduction[65]
在这里: https://cheatsheetseries.owasp.org/cheatsheets/Authorization_Testing_Automation_Cheat_Sheet.html[66]
此处: https://cheatsheetseries.owasp.org/cheatsheets/Insecure_Direct_Object_Reference_Prevention_Cheat_Sheet.html[67]
.NET: https://docs.microsoft.com/en-us/aspnet/web-api/overview/security/preventing-cross-site-request-forgery-csrf-attacks[68]
.NET Core: https://docs.microsoft.com/en-us/aspnet/core/security/anti-request-forgery?view=aspnetcore-3.0#aspnet-core-antiforgery-configuration[69]
自动生成和验证防伪令牌: https://docs.microsoft.com/en-us/aspnet/core/security/anti-request-forgery?view=aspnetcore-3.0#aspnet-core-antiforgery-configuration[70]
tag-helpers: https://docs.microsoft.com/en-us/aspnet/core/mvc/views/tag-helpers/intro[71]
AutoValidateAntiforgeryToken: https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.autovalidateantiforgerytokenattribute?view=aspnetcore-2.2[72]
文章所述: https://andrewlock.net/automatically-validating-anti-forgery-tokens-in-asp-net-core-with-the-autovalidateantiforgerytokenattribute/[73]
IgnoreAntiforgeryToken: https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.ignoreantiforgerytokenattribute?view=aspnetcore-2.2[74]
ValidateAntiforgeryToken: https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.validateantiforgerytokenattribute?view=aspnetcore-2.2[75]
AutoValidateAntiforgeryToken: https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.autovalidateantiforgerytokenattribute?view=aspnetcore-2.2[76]
在此处: https://docs.microsoft.com/en-us/aspnet/web-api/overview/security/preventing-cross-site-request-forgery-csrf-attacks#anti-csrf-and-ajax[77]
此处: https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html[78]
内容安全策略: https://cheatsheetseries.owasp.org/cheatsheets/Content_Security_Policy_Cheat_Sheet.html#context[79]
此处: https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html[80]
备忘单: https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html#net-csharp[81]
反序列化备忘单: https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html#net-csharp[82]
NuGet: https://docs.microsoft.com/en-us/nuget/[83]
OWASP Dependency Checker,: https://cheatsheetseries.owasp.org/cheatsheets/Vulnerable_Dependency_Management_Cheat_Sheet.html[84]
备忘单: https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html[85]
此处: https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.logging.ilogger[86]
Application Insights: https://docs.microsoft.com/en-us/azure/azure-monitor/app/asp-net-core[87]
此处: https://github.com/microsoft/code-with-engineering-playbook/tree/master/observability[88]
在这里: https://github.com/johnstaveley/SecurityEssentials/blob/master/SecurityEssentials/Core/HttpHeaders.cs[89]
HSTS预载: https://hstspreload.org/[90]
未经验证的重定向和转发备忘单: https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html[91]
Security Essentials Baseline项目。: https://github.com/johnstaveley/SecurityEssentials/[92]
BasicHttpBinding: https://docs.microsoft.com/en-us/dotnet/api/system.servicemodel.basichttpbinding?view=netframework-4.7.2[93]
WSHttpBinding: https://docs.microsoft.com/en-us/dotnet/api/system.servicemodel.wshttpbinding?view=netframework-4.7.2[94]
TransportWithMessageCredential: https://docs.microsoft.com/en-us/dotnet/framework/wcf/samples/ws-transport-with-message-credential[95]
ZAP之: https://www.zaproxy.org/