Tìm hiểu về html_safe

1. Cơ bản

Html_safe gần giống với raw nên một số người vẫn thường thắc mắc đến sự khác nhau của chúng, mình xin nói về điều này ở bên dưới. Về cơ bản, tên của nó đã cho chúng ta biết chức năng của nó, đánh dấu một String là an toàn, nó sẽ được chèn vào html, các thẻ html trong đó sẽ được thực thi điều này khiên cho hacker có thể lợi dụng nó để thực hiện tấn công XSS, dĩ nhiên bạn sẽ là người phải chịu trách nhiệm về việc đó nên hãy cẩn thận khi dùng html_safe.

Source:

# File activesupport/lib/active_support/core_ext/string/output_safety.rb, line 259
  def html_safe
    ActiveSupport::SafeBuffer.new(self)
  end

2. Cách mà html_Safe làm viêc

Việc gọi phương thức html_safe sẽ trông giống như nó trả về một đối tượng mới nhìn "giống" String, nhưng chính xác nó là ActiveSupport::SafeBuffer:

"foo".length
# => 3
"foo".class
# => String

"foo".html_safe.length
# => 3
"foo".html_safe.class
# => ActiveSupport::SafeBuffer

Sự khác nhau của String và SafeBuffer được thể hiện ở ví dụ sau:

"<foo>".html_safe + "<bar>"
# => "<foo>&lt;bar&gt;"

Html_safe và String

"<foo>".html_safe + "<bar>".html_safe
# => "<foo><bar>"

Html_safe và Html_safe

3. Cách mà Rails tự động đưa nó vào trong Views

Rails render views vào SafeBuffer. Nó bắt đầu với một SafeBuffer rỗng gắn thêm từng thành phần Views của bạn vào nó. Nó giống như là <%= biểu thức%> trong Views của bạn sẽ được đưa vào HTML. Ví dụ về một file ERB:

<p>
  <%= '<br />' %>
  <%= '<br />'.html_safe %>
</p>

Trong Rails, file ERB này sẽ được chuyển đổi như sau:

html = ''.html_safe
html << '<p>'.html_safe
html << '<br />'
html << '<br />'.html_safe
html << '</p>'.html_safe
html

Và kết quả:

<p>
  &lt;br /&gt;
  <br />
</p>

4. Sự khác nhau giữa html_safe và raw

Html_safe thực sự "Sets the Strings" như HTML Safe (nó phức tạp hơn một chút, nhưng về cơ bản là vậy). Bằng cách này, bạn có thể trả lại các chuỗi HTML an toàn từ helpers hoặc models theo ý thích

raw là tương đương với gọi to_s kèm html_safe vào nó, nhưng được khai báo trên một helper, do đó, nó chỉ có thể được sử dụng trên controller và views.

Ngoài ra raw cho phép sử dụng với chuỗi rỗng còn html_Safe thì không. Nếu bạn đang làm những việc như: <img src = '# {..}' />.html_safe.html_safe hoàn toàn ổn chuỗi sẽ không bao giờ được nil, nhưng nếu bạn đang đối phó với chuỗi có thể là nil .html_safe Sẽ "break" vì không có phương pháp .html_safe trên đối tượng nil. (Ví dụ nếu bạn đang tải một cái gì đó từ một config hoặc database) Trong trường hợp đó bằng cách sử dụng raw (...) sẽ chỉ bỏ qua chuỗi thay vì tạo ra một ngoại lệ.

Tuy vậy, thực tế cho thấy html_Safe nhanh hơn raw nên html_safe được sử dụng nhiều hơn.

5. Rủi ro gặp phải khi sử dụng html_safe

Sử dụng html_safe để render các thẻ html có trong văn bản đồng nghĩa với việc html_safe sẽ render tất cr thẻ html trong đoạn String đó. Bạn đã nhận ra vấn đề về sự rủi ro rồi chứ ? Nếu trong đoạn String đó có cả thẻ scripts thì sao ? Đó quả là một tai họa. Thật vậy, giả sự bạn sử dụng thẻ html_safe cho nội dung của một ô comment, một hacker có thể lợi dụng nó để gửi một đoạn scripts với mã độc nhằm tấn công người dùng ăn cắp dữ liệu, đây chính là hình thức tấn công XSS khá phổ biến. Ví dụ : Hacker gửi một đoạn văn bản như vậy:

<scripts> alert("Bạn đã bị tấn công")</scripts>

và bất cứ người dùng nào load đến trang web có chứ bình luận này sẽ tự động bị chạy đoạn scripts này, thật tai họa nếu nó là một đoạn mã ăn cắp thông tin, và bạn chính là người phải chịu trách nhiệm cho việc đó. Theo tôi được biết thì Rails đã phòng chống việc tấn công XSS và thậm chí đa số framework khác cũng đều như vậy. Nhưng ngoài ra bạn có thể tự mình phòng chống nó bằng cách chắc chắn những gì bạn đang làm với thẻ html_safe, bạn cũng có thể tìm hiểu về sanitize, một lệnh cũng render các thẻ html nhưng có tùy biến cao hơn html_safe. Ví dụ: thay vì dùng đoạn code như vậy:

<%= @user.comment.html_safe %>

dễ dàng bị hacker lợi dụng để tấn công bạn co thể sử dụng sanitize như sau:

<%= sanitize @user.comment %>

và khi hacker gửi một comment như bên trên thì kết quả trả về sẽ là

<scripts> alert("Bạn đã bị tấn công")</scripts>

chứ không có thông báo nào được đưa ra thực sự cả

Sanitize cũng dùng để phòng tránh cả việc hacker sử dụng các field input dạng link để gửi mã độc, ngoài ra sanitize còn có thể tùy biến loại bỏ một số thẻ html tùy người dùng, bài viết sau mình sẽ giới thiệu sâu hơn về sanitize, hãy đón đọc bài viết tiếp theo của mình vào tháng tới nhé 😉

Các bạn có thể tìm hiểu thêm về XSS trong tại đây : https://viblo.asia/p/xss-attacks-in-rails-rEBRAaKVR8Zj

nguồn: https://apidock.com/rails/String/html_safe https://stackoverflow.com/questions/4251284/raw-vs-html-safe-vs-h-to-unescape-html https://makandracards.com/makandra/2579-everything-you-know-about-html_safe-is-wrong