XSS-атаки и erb: как Rails спасает, а когда — нет

XSS (Cross-Site Scripting) — одна из самых распространённых уязвимостей веб-приложений, позволяющая злоумышленникам внедрять вредоносный код в страницы. Rails предоставляет встроенные механизмы защиты, но даже они иногда дают сбой. Разберёмся, как ERB и Rails борются с XSS, и где разработчики сами открывают двери для атак.


🔒 Как Rails защищает от XSS по умолчанию

Автоматическое экранирование в ERB

Rails использует ERB (Embedded Ruby) для шаблонов, и по умолчанию все строки экранируются:

<%= @user_input %> <!-- Безопасно: < превратится в &lt; -->

Это работает благодаря методу html_escape, который вызывается автоматически для всех строк, не помеченных как “безопасные”.

raw и html_safe: когда осторожность отключается

Но если явно указать, что строка “безопасна”, экранирование отключается:

<%= raw @user_input %> <!-- Опасно! -->
<%= @user_input.html_safe %> <!-- Тоже опасно! -->

Пример уязвимости:

# Контроллер
def show
  @comment = params[:comment]
end
<!-- Вьюха -->
<div class="comment">
  <%= raw @comment %> <!-- XSS-атака возможна! -->
</div>

💥 Где чаще всего ошибаются

1. JSON в JavaScript

<script>
  var data = <%= raw @user_data.to_json %>; <!-- Уязвимость! -->
</script>

Решение: Используйте json_escape или to_json.html_safe с осторожностью.

2. Динамические CSS/JavaScript

<style>
  .profile { background: url(<%= @user_background %>); }
</style>

Атака: @user_background = 'red;}</style><script>alert(1)</script><style>'.

3. Ошибки в хелперах

def custom_link(text, url)
  "<a href='#{url}'>#{text}</a>".html_safe
end

Проблема: Не экранируются text и url.


🛡️ Как защититься: лучшие практики

1. Всегда экранируйте по умолчанию

<%= @user_input %> <!-- Так правильно -->

2. Используйте sanitize для HTML

<%= sanitize @user_html, tags: %w[a b i], attributes: %w[href] %>

3. Content Security Policy (CSP)

Добавьте в config/initializers/content_security_policy.rb:

Rails.application.config.content_security_policy do |policy|
  policy.default_src :self
  policy.script_src :self, :https
end

4. Проверяйте данные перед вставкой в JavaScript

<script>
  var data = <%= @user_data.to_json.html_escape %>;
</script>

🧪 Тестируем защиту

Тест на уязвимость в RSpec

describe "CommentsController" do
  it "экранирует HTML в комментариях" do
    post :create, params: { comment: '<script>alert(1)</script>' }
    expect(response.body).not_to include('<script>')
  end
end

Используйте Brakeman

Добавьте в Gemfile:

gem 'brakeman', require: false

И запустите:

brakeman -q -w2

🎤 Что сказать на собеседовании

— Как Rails защищает от XSS?

— ERB автоматически экранирует все строки, но разработчик может отключить защиту через raw или html_safe. Важно избегать вставки непроверенных данных в JavaScript/CSS и использовать CSP.


🧾 Вывод

Rails даёт отличные инструменты для защиты от XSS, но они требуют осознанного использования. Автоматическое экранирование — не волшебная палочка, а html_safe — не “удобная фича”, а потенциальная дыра. Проверяйте данные, используйте CSP и помните: безопасность — это процесс, а не разовая настройка.

🗓 Дата публикации: 18.09.2024, но это не точно...

Ruby on Rails Безопасность XSS ERB PostgreSQL Веб-разработка