Как кодировать встроенный javascript в представлении Razor в ASP.NET MVC 3?

Как правильно кодировать JavaScript в следующем контексте:

<html>
...
<script type="text/javascript">
var settings = @Html.PleaseEncode(settings.ToJson());
// ...
</script>
</html>

Значения в моих объектах JSON устанавливаются администратором приложения, поэтому я предполагаю, что они должны быть правильно закодированы - как для HTML, так и для JavaScript.

Я использую System.Web.Script.Serialization.JavaScriptSerializer для выполнения кодировка JSON. Похоже, что JavaScriptSerializer выполняет некоторое кодирование, когда выводит текст <None> как \u003cNone\u003c, но я не уверен, насколько это безопасно. Прямо сейчас я использую @Html.Raw, так как он работает при безопасном вводе. Он генерирует следующее:

var settings = {"UnselectedReason":"None Selected", /*...*/};

Если я использую @Html.Encode, я получаю:

var settings = {&amp;quot;UnselectedReason&amp;quot;:&amp;quot;None Selected&amp;quot;, /*...*/};

Я пробовал с AntiXSS и без него, но в любом случае не вижу разницы.


person Kaleb Pederson    schedule 28.11.2011    source источник


Ответы (5)


В AntiXSS есть JavaScriptEncode, но он предназначен для отдельных элементов, а не для всего набора настроек.

Поэтому, если вы передадите {"UnselectedReason":"None Selected", /.../}, он съест кавычки и другие вещи, что, вероятно, не то, что вам нужно. Вместо этого я бы сделал в вашем ToJson настройки с помощью построителя строк, что-то вроде

StringBuilder sb = new StringBuilder();
sb.Append("{");
foreach(KeyValuePair kv in mySettings)
{
    sb.Append("\"");
    sb.Append(Microsoft.Security.Application.Encoder.JavaScriptEncode(kv.Key, true);
    sb.Append(":");
    sb.Append(Microsoft.Security.Application.Encoder.JavaScriptEncode(kv.Value, true);
    sb.Append("\",");
}

string outputString = sb.ToString().TrimEnd(",") + "}";

return new HtmlString(outputString);

Примечание. Код не приходит мне в голову и даже не введен в VS. Он иллюстрирует принцип и может не компилироваться!

person blowdart    schedule 28.11.2011
comment
Привет, незнакомец @blowdart :) Какие векторы атак вы могли бы здесь увидеть, если модель (при условии, что здесь просто модель) написана в формате Json, что потребует отдельного кодирования? - person Adam Tuliper - MSFT; 28.11.2011
comment
Это зависит от того, откуда берутся данные модели :) Если это настройки в файле конфигурации, которые устанавливает администратор, то все должно быть в порядке. Если это настройки, которые устанавливает пользователь, например, цвет или порядок сортировки, вы можете столкнуться с риском внедрения XSS или DOM... - person blowdart; 28.11.2011
comment
хорошо, мы на одной странице, это то, что я имел в виду ниже в «действительном источнике». - person Adam Tuliper - MSFT; 29.11.2011

Если вы хотите использовать JS, зачем вы пытаетесь его кодировать? Если у вас есть json, он уже должен быть закодирован. Поскольку это JS, вам также не нужно требовать кодирования html.

Я не думаю, что вам нужно кодировать здесь, если вы не можете объяснить, почему, и я просто что-то упускаю?

С любым действительным javascript вы можете столкнуться с риском внедрения, но, поскольку вы знаете, что это происходит из какого-то действительного источника (например, модели), который кодируется, путь для получения JSON относительно безопасен.

person Adam Tuliper - MSFT    schedule 28.11.2011
comment
Я не уверен, что мне нужно или не нужно его кодировать, но я хочу быть уверен, что обработал его надлежащим образом. - person Kaleb Pederson; 28.11.2011
comment
Размышляя об этом подробнее, я думаю, что меня больше всего беспокоило то, что JSON может быть закодирован таким образом, чтобы его можно было включить в файл javascript, но не в тег скрипта. - person Kaleb Pederson; 29.11.2011

Это должно быть безопасно для прямого вывода...

<script>//<![CDATA[<!--

var settings = @Html.Raw(settings.ToJson());

//-->]]></script

Хотя, если вы действительно обеспокоены... это предполагает наличие современного браузера или json2.js.

<script>

var settings = JSON.parse("@Html.Raw(Server.UrlEncode(settings.ToJson()))");

</script
person Tracker1    schedule 28.11.2011
comment
Я считаю, что присвоение значения из этого возвращенного содержимого внутреннему html (т.е. $(#whatver).html(...)) было бы вектором для атаки. - person Adam Tuliper - MSFT; 09.01.2012
comment
@ Адам, не уверен, о чем ты говоришь ... вся цель заключалась в том, чтобы передать объекты / контент на стороне сервера на сторону клиента. Если вы запускаете непроверенный пользовательский ввод для вывода, это отдельная проблема. - person Tracker1; 24.01.2012
comment
это было помечено (и упомянуто) для кодировки antixss, также было упомянуто «безопасное» - следовательно, есть предположение, что кодировка здесь предназначена для предотвращения проблем. «непроверенный» пользовательский ввод — это такой общий термин, поскольку существует огромное количество векторов xss, которые обошли некоторые из лучших «проверенных» входных фильтров. Я хочу, чтобы люди были в безопасности в решениях, которые они внедряют, и я не считаю, что это отдельная проблема, когда люди копируют/вставляют из SO весь день :) Если решение потенциально оставляет кого-то открытым для XSS - это абсолютно относится к этому вопрос. - person Adam Tuliper - MSFT; 24.01.2012
comment
Предполагая, что settings.ToJson() дает действительный JSON, а JSON.parse является действительным синтаксическим анализатором, риска XSS нет. То, что вы делаете с закодированным значением, - это другая история. Кроме того, нигде в моем посте не предлагалось просто проталкивать любой вывод в .html(output)... вся цель заключалась в том, чтобы доставить объектную модель в JS с сервера на клиент. - person Tracker1; 25.01.2012
comment
правда правда, этот пост предназначен для дополнительной информации для людей, которые приходят сюда, а не для аргументации вашей точки зрения. Я хочу, чтобы люди знали, что только потому, что они получают данные, «кажущиеся безопасными», не означает, что они безопасны. Это безопасно в одной строке кода выше, но будьте осторожны, что вы будете делать с ним после этого. Опять же, не аргументируя свой код, просто предоставляя предупреждение. - person Adam Tuliper - MSFT; 26.01.2012

Это будет безопасно. Это не уничтожит вашу разметку.

person Daniel A. White    schedule 28.11.2011

Если вы уверены в том, что хотите сделать:

@Html.Raw(yourStringWithTheJSONcode)
person Adilson de Almeida Jr    schedule 28.11.2011