tl; dr;
Можно ли изменить поведение привязки angular {{ }}
, чтобы оно не дезинфицировало / не экранировало значения?
Полный вопрос
У нас есть довольно большое приложение angular 5, поддерживаемое json REST API. REST API взаимодействует с гораздо более крупной системой и базой данных, которые были созданы в течение многих лет. Другие установленные приложения читают и записывают данные, и ключевым моментом является то, что данные, введенные пользователем из всех приложений, должны храниться в базе данных дословно, поскольку другим приложениям (устаревшим, не веб-приложениям) необходимо читать и записывать данные.
Это означает, что (хотя и нежелательно) REST API поддерживает POST и PUT с такими телами:
{
"reportName" : "<a href=\"http://somewhere.bad\">My report</a>",
"reportType" : "VEHICLE"
}
(это необходимо, потому что данные должны быть дословно записаны в базу данных, чтобы другие устаревшие не веб-приложения могли читать данные, введенные пользователем)
В настоящее время приложение angular является единственным клиентом REST API, но есть планы по раскрытию API, чтобы другой клиентский код, в том числе сторонние, мог его использовать.
В настоящее время REST API возвращает данные в том виде, в каком они были введены и сохранены:
{
"reportName" : "<a href=\"http://somewhere.bad\">My report</a>",
"reportType" : "VEHICLE"
}
Удобно, что приложение angular 5 очищает или экранирует (?) Значения перед рендерингом (привязкой?). Шаблон angular связывает значения следующим образом:
<div>{{report.reportName}}</div>
поэтому вывод на экран:
<a href = "http://somewhere.bad">My report</a>
что является желаемым поведением. (Простите за несомненно неправильное использование терминологии angular - я скорее бэкенд-разработчик!)
К сожалению, у нас был внешний тест на проникновение REST API, и они, что неудивительно, подняли проблемы типа XSS, с их рекомендацией, что REST API избегает содержимого на выходе. Их аргумент состоит в том, что безопасность не должна зависеть от клиента. В то время как angular очищает / ускользает из коробки, другой клиентский код может этого не делать. Имея это в виду, я сделал изменение на стороне сервера, чтобы строковые значения json экранировались в теле ответа:
{
"reportName" : "<a href="http://somewhere.bad">My report</a>",
"reportType" : "VEHICLE"
}
Но теперь, конечно, angular очищает / избегает амперсандов, поэтому на экране он отображается как:
<a href="http://somewhere.bad">My report</a>
т.е. привязка фактически выполнила:
<div>&lt;a href=&quot;http://somewhere.bad&quot;&gt;My report&lt;/a&gt;</div>
Я думаю, что нам нужно, чтобы angular доверял данным в ответе и отображал их дословно. т.е. если бы он интерполировал, а не привязал (опять же, простите мою терминологию!), он бы эффективно сделал это:
<div><a href="http://somewhere.bad">My report</a></div>
что приведет к отображению на экране
<a href = "http://somewhere.bad">My report</a>
И это было бы нормально, потому что это текущее поведение. Он не был бы добавлен в DOM как интерактивный или исполняемый фрагмент разметки - это просто текст.
Есть ли глобальный способ сказать angular 5, что значениям доверяют? Проблема, которую мы имеем, конечно же, заключается в том, что, поскольку мы уже разработали приложение разумного размера, в шаблонах, вероятно, есть тысячи привязок стилей {{ }}
, поэтому вместо того, чтобы идти дальше и менять этот синтаксис на что-то другое (я видел, как люди делали такие вещи, как <div innerHTML = "{{report.reportName}}"/>
или использование каналов типа <div>{{report.reportName | safeHtml}}</div>
) Я ищу более глобальный подход.
Любые идеи?
Я предпочитаю начальный подход. Отсутствие побега на клиенте может вызвать собственные уязвимости. Теперь безопасность клиента зависит от сервера. Если клиент использует несколько API-интерфейсов или переходит от одного к другому, они могут смешивать, следует ли экранировать данные или нет.
Сервер не может надежно экранировать контент, потому что правильное экранирование зависит от контекста. То, что безопасно для контекста HTML, небезопасно для контекста JS или CSS. Любой клиент, у которого могут возникнуть проблемы с XSS из-за этого API, вероятно, имеет свои собственные уязвимости, не имеющие к нему никакого отношения.
Вам придется использовать канал, вы не можете изменить поведение всей интерполяции (
{{...}}
) сразу. Если вы это сделаете, вам придется изменить сам фреймворк.