How to save HTML to database and retrieve it properly
asp.net-mvc, asp.net-mvc-4, razor, xss
Solution
The rule of thumb is the following:
- Store in your database the RAW HTML without any encodings or sanitizings. A SQL server doesn't care if you store some string containing XSS code.
- When displaying this output to your page make sure that it is sanitized.
So:
[HttpPost, ActionName("Create")]
[ValidateAntiForgeryToken]
public ActionResult Create(Post model)
{
// store model.Data directly in your database without any cleaning or sanitizing
}
and then when displaying:
@Html.Raw(HtmlUtility.SanitizeHtml(Model.Data))
Notice how I used the Html.Raw helper here to ensure that you don't get double HTML encoded output. The `HtmlUtility.SanitizeHtml` function should already take care of sanitizing the value and return a safe string that you could display in your view and it will not be further encoded. If on the other hand you used `@HtmlUtility.SanitizeHtml(Model.Data)`, then the `@` razor function would HTML encode the result of the `SanitizeHtml` function which might not be what you are looking for.
Problem
Learning security these days :) I need to allow users to enter text in a form and allow them some HTML tags: bold, italic, list etc. and to prevent them to add some dangerous JavaScript code. So I have used this whitelist implementation to sanitize HTML. But I am still confused about how to save and display it in the right way. So here what I did: Model: ``` public class Post { [AllowHtml] public string Data { get; set; } } ``` Controller: ``` [HttpPost, ActionName("Create")] [ValidateAntiForgeryToken] public ActionResult Create(Post model) { // Decode model.Data as it is Encoded after post string decodedString = HttpUtility.HtmlDecode(model.Data); // Clean HTML string sanitizedHtmlText = HtmlUtility.SanitizeHtml(decodedString); string encoded = HttpUtility.HtmlEncode(sanitizedHtmlText); ``` View: ``` @using (Html.BeginForm("Create", "Home", FormMethod.Post)) { @Html.AntiForgeryToken() @Html.TextAreaFor(a=>a.Data) <input type="submit" value="submit" /> } ``` So when I post a form I see: ``` <p>Simple <em><strong>whitelist</strong> </em>test:</p> <ul> <li>t1</li> <li>t2</li> </ul> <p>Image:</p> <p><img src="http://metro-portal.hr/img/repository/2010/06/medium/hijena_shutter.jpg" /></p> ``` Becaouse of `<p><` I think that I need to decode it first: ``` <p>Simple <em><strong>whitelist</strong> </em>test:</p> <ul> <li>t1</li> <li>t2</li> </ul> <p>Image:</p> <p><img src="http://metro-portal.hr/img/repository/2010/06/medium/hijena_shutter.jpg" /></p> ``` Then I sanitize it against whitelist and I get sanitized HTML: ``` <p>Simple <em><strong>whitelist</strong> </em>test:</p> <ul> <li>t1</li> <li>t2</li> </ul> <p>Image:</p> <p> ``` 1) Should I save it like this in database? 2) Or I need to Encode this result and then save it to database (encoded bellow)? ``` <p>Simple <em><strong>whitelist</strong> </em>test:</p> <ul> <li>t1</li> <li>t2</li> </ul> <p>Image:</p> <p> ``` Here I am confused if I put it on the view like this: ``` @Model.Data ``` I get this on the view: ``` <p>Simple <em><strong>whitelist</strong> </em>test:</p> <ul> <li>t1</li> <li>t2</li> </ul> <p>Image:</p> <p> ``` or ``` <p>Simple <em><strong>whitelist</strong> </em>test:</p> <ul> <li>t1</li> <li>t2</li> </ul> <p>Image:</p> <p> ``` So what to do to display this HTML properly (bold, list etc.)?