While scanning an ASP.net MVC application using Checkmarx, I regularly see heap inspection vulnerabilities. So I started to wonder if I could use a custom model binder or the built-in ByteArrayModelBinder
to keep passwords and other sensitive strings out of the heap, for controlled disposal. I came up with the following solution which posts and displays the sensitive data via a byte array, but I am wondering if this data is still making its way into the heap through a string somewhere. (Note: The display action is just for debugging.)
ViewModel
public class ByteArrayViewModel
{
public byte[] SensitiveData { get; set; }
}
Input View
@model MvcHandlingSensativeStrings.Models.ByteArrayViewModel
@{
ViewBag.Title = "byte[] Post";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>@ViewBag.Title</h2>
@using (Html.BeginForm("Post", "ByteArray", FormMethod.Post))
{
@Html.TextBoxFor(m=>m.SensitiveData);
<button type="submit">Send</button>
}
Controller
public class ByteArrayController : Controller
{
public ActionResult Index()
{
return View(new ByteArrayViewModel());
}
[HttpPost]
public ActionResult Post(ByteArrayViewModel viewModel)
{
try
{
// Handle sensitive data here
return View("Display", viewModel);
}
catch
{
return View("Index");
}
finally
{
// Clear sensitive data from memory
//Array.Clear(viewModel.SensitiveData, 0, viewModel.SensitiveData.Leng
}
}
public ActionResult Display(ByteArrayViewModel viewModel)
{
return View(viewModel);
}
}
Display View
@model MvcHandlingSensativeStrings.Models.ByteArrayViewModel
@{
ViewBag.Title = "byte[] Display";
Layout = "~/Views/Shared/_Layout.cshtml";
string s = Convert.ToBase64String(Model.SensitiveData);
}
<h2>@ViewBag.Title</h2>
<p>@s</p>
<p>@Model.SensitiveData.GetType().ToString()</p>
Display Output
* Update *
This shows that before ByteArrayModelBinder
or any other model binder executes, form parameters are stored in an array of strings and are thus susceptible to heap inspection.
* Update 2 *
If you peek at Microsoft's implementation of NetworkCredential, you will noticed that even though the Password property is a string, SecureString is used underneath for storage.