When i developed my first asp.net web application, and users receives an exception, i thought that IIS will have a full details about the exception, which was not the case. And i was told that to store any exception info i can use a library name Elmah, which worked for us. But recently i was checking an exception raised by a user after his sign-in to our asp.net mvc, and i found that Elmah stored the username and password inside the xml file as follow:-
-<item name="__RequestVerificationToken">
<value string="X***************************81"/>
</item>
-<item name="UserName">
<value string="******"/>
</item>
-<item name="Password">
<value string="******"/>
</item>
-<item name="domains">
<value string="******"/>
</item>
-<item name="RememberMe">
<value string="true"/>
<value string="false"/>
</item>
</form>
in our case the asp.net mvc-4 provide a login view,to enter username/password which is connected to our active directory using ldap connection string , here is the code for the login (not sure if it can help):-
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
[ValidateInput(false)]
public ActionResult Login(LoginModel model, string returnUrl)
{
MembershipProvider domainProvider;
domainProvider = Membership.Providers["DomainADMembershipProvider"];
if (ModelState.IsValid)
{
// Validate the user with the membership system.
if (domainProvider.ValidateUser(model.UserName, model.Password))
{
FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
}
else
{
ModelState.AddModelError("", "The user name or password provided is incorrect.");
List<String> domains2 = new List<String>();
domains2.Add("*****");
ViewBag.Domains = domains2;
return View(model);
}
return RedirectToLocal(returnUrl);
}
List<String> domains = new List<String>();
domains.Add("***");
ViewBag.Domains = domains;
return View(model);
}
and here is the Elmah components inside our web.config
:-
<sectionGroup name="elmah">
<section name="security" requirePermission="false" type="Elmah.SecuritySectionHandler, Elmah" />
<section name="errorLog" requirePermission="false" type="Elmah.ErrorLogSectionHandler, Elmah" />
<section name="errorMail" requirePermission="false" type="Elmah.ErrorMailSectionHandler, Elmah" />
<section name="errorFilter" requirePermission="false" type="Elmah.ErrorFilterSectionHandler, Elmah" />
</sectionGroup>
<appSettings>
<add key="elmah.mvc.disableHandler" value="false" />
<add key="elmah.mvc.disableHandleErrorFilter" value="false" />
<add key="elmah.mvc.requiresAuthentication" value="false" />
<add key="elmah.mvc.IgnoreDefaultRoute" value="false" />
<add key="elmah.mvc.allowedRoles" value="*" />
<add key="elmah.mvc.allowedUsers" value="*" />
<add key="elmah.mvc.route" value="elmah" />
<add key="elmah.mvc.UserAuthCaseSensitive" value="true" />
</appSettings>
<httpModules>
<add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" />
<add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" />
<add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah" />
</httpModules>
<modules>
<add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" preCondition="managedHandler" />
<add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" preCondition="managedHandler" />
<add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah" preCondition="managedHandler" />
</modules>
<elmah>
<errorLog type="Elmah.XmlFileErrorLog, Elmah" logPath="C:\elmaherrorlogs\" />
</elmah>
now to be honest Elmah had helped us a lot when users face un-handled exceptions, but if there is not a way to prevent it from exposing users' password then i think i will need to disable it.
can anyone advice if we can prevent Elmah from exposing the users' passwords inside the exception xml file? Thanks
Finally found the code we used in one of our MVC4 projects. Place this in your Global.asax.cs
file:
// remove Password field from logging
// http://blog.elmah.io/removing-sensitive-form-data-before-logging-to-elmah/
public void ErrorLog_Filtering(object sender, ExceptionFilterEventArgs e) {
var httpContext = e.Context as HttpContext;
if (httpContext != null && httpContext.Request.Form.AllKeys.Any(k => k == "Password")) {
var error = new Error(e.Exception, httpContext);
error.Form.Set("Password", "******");
ErrorLog.GetDefault(httpContext).Log(error);
e.Dismiss();
}
}
It appears that the referenced blog at elmah.io has changed, but that code may be useful as well.