Экранирование HTML в Rails - PullRequest
25 голосов
/ 30 марта 2009

Каков рекомендуемый способ выхода из HTML для предотвращения уязвимостей XSS в приложениях Rails?

Следует ли разрешить пользователю помещать какой-либо текст в базу данных, но избегать его при отображении? Должны ли вы добавить фильтры before_save для экранирования ввода?

Ответы [ 5 ]

22 голосов
/ 31 марта 2009

Существует три основных подхода к этой проблеме.

  1. используйте h() в ваших взглядах. Недостатком здесь является то, что если вы забудете, вы получите pwnd.
  2. Используйте плагин, который экранирует контент при его сохранении. Мой плагин xss_terminate делает это. Тогда вам не нужно использовать h() в ваших представлениях (в основном). Есть другие, которые работают на уровне контроллера. Недостатками здесь являются: (а) если в экранирующем коде есть ошибка, вы можете получить XSS в своей базе данных; и (b) Есть угловые случаи, когда вы все еще хотите использовать h().
  3. Используйте плагин, который экранирует контент, когда он отображается. CrossSiteSniper , вероятно, самый известный из них. Это псевдоним ваших атрибутов, так что когда вы вызываете foo.name, он экранирует содержимое. Есть способ обойти это, если вам нужен контент без экранирования. Мне нравится этот плагин, но я не в восторге от того, что XSS впущу в мою базу данных ...

Тогда есть несколько гибридных подходов.

Нет причин, по которым вы не можете использовать xss_terminate и CrossSiteSniper одновременно.

Существует также реализация ERb под названием Erubis , которую можно настроить так, чтобы любой вызов, например <%= foo.name %>, был экранирован - эквивалент <%= h(foo.name) %>. К сожалению, Erubis, кажется, всегда отстает от Rails, и поэтому его использование может замедлить вас.

Если вы хотите узнать больше, я написал сообщение в блоге (на которое любезно ссылался Xavor) о с использованием xss_terminate .

14 голосов
/ 31 марта 2009

h - это псевдоним для html_escape , который является служебным методом для экранирования всех символов HTML-тега:

html_escape('<script src=http://ha.ckers.org/xss.js></script>')
# => &lt;script src=http://ha.ckers.org/xss.js&gt;&lt;/script&gt;

Если вам нужен больший контроль, используйте метод sanitize , который можно использовать как белый список тегов и атрибутов, чтобы разрешить:

sanitize(@article.body, :tags => %w(table tr td), :attributes => %w(id class style))

Я бы позволил пользователю вводить что-либо, сохранять его как есть в базе данных и экранировать при его отображении. Таким образом, вы не потеряете введенную информацию. Вы всегда можете настроить логику побега позже ...

5 голосов
/ 30 марта 2009

Используйте метод h в вашем шаблоне представления. Допустим, у вас есть объект записи со свойством комментария:

<div class="comment">
    <%= h post.comment %>
</div>
2 голосов
/ 31 марта 2009

Или с этим плагином - не нужно ч 8)

http://railspikes.com/2008/1/28/auto-escaping-html-with-rails

0 голосов
/ 15 октября 2009

Я только что выпустил плагин под названием ActsAsSanitiled , использующий гем Sanitize , который может гарантировать правильное формирование, а также возможность настройки в зависимости от того, какой тип HTML разрешен, и все это без манипулирования ввод пользователя или запоминание чего-либо на уровне шаблона.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...