У меня есть приложение, которое состоит из API REST на стороне сервера, написанного на PHP, и некоторого Javascript на стороне клиента, который использует этот API и использует JSON, который он создает для отображения страницы. Итак, довольно типичная настройка.
Данные, предоставленные REST API, являются "ненадежными" в том смысле, что он извлекает предоставленный пользователем контент из базы данных. Так, например, он может получить что-то вроде:
{
"message": "<script>alert("Gotcha!")</script>"
}
Очевидно, что если бы мой клиентский код отображал это непосредственно на странице DOM, я создал уязвимость XSS. Таким образом, этот контент должен быть сначала экранирован HTML.
Вопрос в том, когда выводить ненадежный контент, должен ли я избегать содержимого на стороне сервера или на стороне клиента? I.e., должен ли мой API вернуть исходный контент, а затем сделать его ответственным за код Javascript для того, чтобы избежать специальных символов, или мой API вернет "безопасный" контент:
{
"message": "<script>alert('Gotcha!');<\/script>"
}
который уже был экранирован?
С одной стороны, похоже, что клиенту не нужно беспокоиться о небезопасных данных с моего сервера. С другой стороны, можно утверждать, что выход всегда должен быть экранирован в последнюю минуту, когда мы точно знаем, как данные должны потребляться.
Какой подход правильный?
Примечание. Существует множество вопросов по обработке ввода и да, я знаю, что клиентский код всегда можно манипулировать. Этот вопрос касается вывода данных с моего сервера, которые не могут быть надежными.
Обновление. Я посмотрел, что делают другие люди, и кажется, что некоторые API REST имеют тенденцию отправлять "небезопасные" JSON. API Gitter фактически отправляет оба, что интересно:
[
{
"id":"560ab5d0081f3a9c044d709e",
"text":"testing the API: <script>alert('hey')</script>",
"html":"testing the API: <script>alert('hey')</script>",
"sent":"2015-09-29T16:01:19.999Z",
"fromUser":{
...
},"unread":false,
"readBy":0,
"urls":[],
"mentions":[],
"issues":[],
"meta":[],
"v":1
}
]
Обратите внимание, что они отправляют исходное содержимое в ключ text
, а затем версию с экранированным HTML в html
. Неплохая идея, ИМО.
Я принял ответ, но я не думаю, что это проблема с вырезом. Я хотел бы поддержать дальнейшее обсуждение этой темы.