Потеря данных при передаче необработанного HTML из представления в контроллер в запросе POST - безопасность XSS и потеря информации
Преамбула
Мой вариант использования включает интерфейсный редактор WYSIWYG. Получение пользовательского ввода в формате HTML5/CSS из внешнего вида CSHTML. Получение ввода в действие Backend Controller через POST-запрос. И, наконец, занимаемся с ним причудливой базой данных.
Звучит довольно просто. Используя этот чудовищный редактор, он очень простой и настраиваемый.
Посмотреть
Редактор WYSIWYG textarea
вложенный в form
для отправки необработанных данных HTML редактора с помощью POST
<form class="form" asp-controller="CreationController" asp-action="CreateSnowflakeBlogpost" method="post">
<button type="submit" class="btn btn-link">Submit Snowflake Blogpost</button>
<textarea name="snowflakeHtmlContent" id="joditEditor"> </textarea>
</form>
Контроллер
Действие контроллера при получении параметра POST.
[HttpPost]
public async Task<IActionResult> CreateSnowflakeBlogpost(string snowflakeHtmlContent)
{
// store HTML content in DB and do fancy operations
// redirect to something else
return RedirectToAction("PreviewSnowflakeBlogpost");
}
Проблема
Теги HTML5/CSS теряются при передаче данных POST. После проверки они успешно отправляются из просмотра. Однако параметр Action содержит неверные данные.
Похоже, здесь происходит дезинфекция, удаляя параметры POST из HTML-тегов, которые мы намеренно хотим сохранить.
Похоже, для этого есть возможные решения.
[Request.Unvalidated]
аннотация. Не рекомендуется.[AllowHtml]
аннотация. Устарело. Смотрите здесь и здесь.@Html.Raw(theString)
здесь, но это для передачи небезопасных данных из контроллера в представление. Наш вариант использования противоположен.- В этом вопросе собраны предыдущие пункты. Все не работает.
Вопрос
Как передать необработанные данные HTML/CSS из представления в действие? удовлетворяющие следующим условиям:
Без потери данных разметки.
Предотвратить получение небезопасных данных, представляющих риск XSS. Согласно руководству.
1 ответ
Решение
В итоге я использовал Custom Model Binding, который обошел эту чрезмерно нетерпеливую очистку / потерю данных. В результате сохранились нужные мне HTML-теги.
Однако это создает риск XSS. Чтобы противодействовать передаче небезопасных данных, я использовал HtmlSanitizer, чтобы опустить небезопасные теги HTML/CSS.
Действие
Добавлено [ModelBinder(typeof(AllowSanitizedHtmlBinder))]
аннотация к параметру
[HttpPost]
public async Task<IActionResult> CreateSnowflakeBlogpost([ModelBinder(typeof(AllowSanitizedHtmlBinder))] string snowflakeHtmlContent)
{
// store HTML content in DB and do fancy operations
// redirect to something else
return RedirectToAction("PreviewSnowflakeBlogpost");
}
Подшивка пользовательской модели
Этот связыватель настраиваемой модели похож на реле и предотвращает потерю данных в нашем параметре POST. HtmlSanitizer
здесь использовался перед привязкой значения для предотвращения XSS.
// Custom Model Binding
using Microsoft.AspNetCore.Mvc.ModelBinding;
// HTML Sanitizer
using Ganss.XSS;
public class AllowSanitizedHtmlBinder: IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
{
throw new ArgumentNullException(nameof(bindingContext));
}
var modelName = bindingContext.ModelName;
// Try to fetch the value of the argument by name
var valueProviderResult =
bindingContext.ValueProvider.GetValue(modelName);
if (valueProviderResult == ValueProviderResult.None)
{
return Task.CompletedTask;
}
bindingContext.ModelState.SetModelValue(modelName,
valueProviderResult);
var value = valueProviderResult.FirstValue;
// Check if the argument value is null or empty
if (string.IsNullOrEmpty(value))
{
return Task.CompletedTask;
}
// Sanitize HTML from harmful XSS markup
var sanitizer = new HtmlSanitizer();
var sanitizedValue = sanitizer.Sanitize(value);
bindingContext.Result = ModelBindingResult.Success(sanitizedValue);
return Task.CompletedTask;
}
}
[HELP] Отсутствующий элемент - понимание первопричины
С моим рабочим решением выше я до сих пор не понимаю, почему разметка HTML дезинфицируется и удаляется по умолчанию. Хотя все утверждают, что это не поддерживается, и такая ответственность зависит от приложения.
Вам больше не нужен [AllowHtml], потому что никто не отрицает HTML в ASP.NET Core 2.0.
Не нужен [AllowHtml] или RequestValidationEnabled, потому что в этой системе нет проверки запроса.
Любая помощь в демистификации первопричины будет ОЧЕНЬ признательна.
Источники
Мое решение было основано на:
- Это ответ. Хотя
request.Unvalidated
больше не поддерживается. - Пользовательская привязка модели.
- HtmlSanitizer.
- Этот ответ помог мне указать правильное направление.