07/09/2018, 17:46

Rails's Security Checklist

Trong việc xây dựng ứng dụng bằng Rails, Security đóng một vai trò hết sức quan trọng nhưng các lập trình viên vẫn chưa chú trọng những vấn đề liên quan đến nó một cách nghiêm túc. Trong bài viết này mình sẽ giới thiệu những khía cạnh khác nhau để nâng cao tính an toàn cho ứng dụng của bạn. ...

Trong việc xây dựng ứng dụng bằng Rails, Security đóng một vai trò hết sức quan trọng nhưng các lập trình viên vẫn chưa chú trọng những vấn đề liên quan đến nó một cách nghiêm túc. Trong bài viết này mình sẽ giới thiệu những khía cạnh khác nhau để nâng cao tính an toàn cho ứng dụng của bạn.

Controller

  • Sử dụng các secure default callbacks cho ApplicationController (hoặc các abstract controller khác)
    • Sử dụng authentication callbacks (Devise's authenticate_user!)
    • Sử dụng authorization callbacks (Pundit's verify_authorized)
    • Sử dụng authorization-related callbacks (Pundit's verify_policy_scoped)
    • Sử dụng CSRF
  • Khi disable các secure, hãy chỉ disable trên các action cụ thể. Tránh việc disable trên các abstract controller, làm ảnh hưởng đến các concrete controller (controller kế thừa).

Routes

  • Sử dụng authentication và authorization trong file routes.rb, mặc dù trong controller callbacks đã có rồi, nhưng vẫn nên sử dụng trong routes.rb.

defense-in-depth

  • Đảm bảo rằng tất cả các URL đều được bao bởi authentication và authorization.
  • Đảm bảo rằng không có một uncoverd URL nào trong production.

Views

  • Không được sử dụng HTML comment trong các file template. Vì khi sử dụng HTML comments, phía client sẽ đọc được đoạn code được comment đó.
# bad - HTML comments will be visible to users who "View Source":
 
 

# ok - ERB comments are removed by the server, and so not viewable to clients:
<%# This will _not_ be sent to clients %>
<%#= link_to "Admin Site", "https://admin.example.org/login" %>

URL Secrets Tokens

  • Hãy cẩn thân với header Referer khi app của bạn có chức năng sử dụng các token.
    https://robots.thoughtbot.com/is-your-site-leaking-password-reset-links

IDs

  • Tránh việc sử dụng ID có tính quy luật (98, 99, 100, ...), nó có thể làm lộ một số thông tin về ứng dụng của bạn. Ví dụ: đối thủ cạnh trang với bạn đăng kí một account, sau khi đăng kí thành công bạn redirect người đó đến /users/12000, 1 tháng sau họ lại đăng kí 1 account khác, lần này thì redirect đến /users/13000. Họ sẽ biết rằng, 1 tháng bạn có 1000 lượt đăng kí, và ứng dụng của bạn có khoảng 13000 users.
  • Nếu bạn thực sự muốn đứa ID vào URL thì nên sử dụng các dạng ID khó đoán hơn UUIDs hoặc hashids
  • Config để Rails model mặc định generate UUIDs làm khóa chính:
  # config/application.rb
  config.generators do |g|
    g.orm :active_record, primary_type: :uuid
  end

Random Token Generation

  • Sử dụng Secure Random

Logging

  • Tránh việc log lại các request parameters. Setup filter_parameters config để loại bỏ request parameters khỏi logging.
# config/initializers/filter_parameter_logging.rb

Rails.application.config.filter_parameters += [:password]
if Rails.env.production?
  MATCH_ALL_PARAMS_PATTERN = /.+/
  Rails.application.config.filter_parameters += [MATCH_ALL_PARAMS_PATTERN]
end
  • Ngoài ra bạn cũng cần kiểm tra logging của các log files của 3rb services mà ứng dụng của bạn sử dụng.
  • Logging càng ít càng tốt.
  • Tránh việc lưu lại lâu các logging của bạn cũng như 3rd services.

Input Sanitization

  • Filter và validate những gì user gửi lên.
  • Tránh việc đọc các filesystem khi user gửi query bằng paths. Nếu ứng dụng của bạn bắt buộc phải có thì nên có một safelist để liệt kê các file có thể đọc.
  • Với các query string hoặc các POST params mà ứng dụng của bạn thực hiện việc redirect đến URL khác, thì các URL này phải nằm trong safelist hoặc các URL thuộc ứng dụng của bạn. Không nên theo kiểu, muốn redirect đi đâu thì redirect.
  • Cân nhắc việc sử dụng strong_parameters để reject các parameters không cần thiết.
  • Cân nhắc sử dụng sanitizing cho toàn bộ ActiveRecord attribute, https://github.com/flavorjones/loofah-activerecord

Markdown Rendering

  • Sử dụng markdown rendering sử dụng safelist, tránh việc render tùy tiện toàn bộ HTML, đặc biệt là khi user có thể input markdown.
  • Nếu sử dụng RedCarpet, nên sử dụng RedCarpet::Render::Safe hơn là RedCarpet::Render::HTML:
# bad
renderer = RedCarpet::Render::HTMl.new
# good
renderer = RedCarpet::Render::Safe.new

Upload and File Processing

  • Tránh việc upload file lên server chứa ứng dụng của bạn
  • Sử dụng 3rd service cho việc scan viruses/malware, không chạy trên server của ứng dụng
  • Cần có một safelist các file được phép upload
  • Tránh việc chạy imagemagick hoặc các tác vụ xử lý ảnh trên chính ứng dụng của bạn.

Email

  • Kiểm soát số email được gửi đến một user (nhiều ứng dụng cho phép việc gửi email reset password nhiều lần trên một user duy nhất)
  • Tránh việc gửi email có kèm theo data do chính user nhập vào (ví dụ: thay vì nhập tên vào thì attacker nhập vào một URL gây hại, và ứng dụng của bạn sẽ vô tình gửi URL đó đến chính users của bạn)

Detecting Abuse and Fraud

  • Thông báo cho user khi password của họ thay đổi Devise
  • Thông báo cho user những thay đổi về account của họ (ví dụ: thay đổi password, thay đổi credit card, một giao dịch phát sinh, user thêm email hay các thông tin liên lạc khác, nhập sai password, setting 2FA thay đổi, login từ một IP lạ hoắc).
  • Không gửi email chứa password mà không được mã hóa.
  • Cân nhắc về việc gửi các thông tin báo cáo về account của user hằng tháng định kì.
  • Cân nhắc việc sử dụng counter để đếm các tác vụ có thể gây nguy hại đến account của user. Ví dụ: Tránh việc attacker sử dụng brute-force để dò ra password bằng cách limit số lần đăng nhập trong 1s.

Logins, Registration

  • Sử dụng multi-factor authentication
  • Khuyến khích user sử dụng 2FA bằng cách settings default hoặc đưa ra các ưu đãi nếu user sử dụng 2FA.
  • Limit IP-address, device đặc biệt là account của admin
  • Yêu cầu user sử dụng chức năng confirm account của họ (Devise confirmable module)
  • Lock account nếu vượt quá số lần đăng nhập không thành công (Devise's lockable module)
  • Sử dụng timeout cho login (Devise's timeoutable module)

Passwords

  • Khuyến khích việc sử dụng một thuật toán password hashing mạnh, luôn luôn tìm hiểu xem thuật toán password hashing nào được recommend.
  • Luôn luôn kiểm tra lại việc lưu trữ password
  • Không cho phép user sử dụng 1 password 2 lần.
  • Sử dụng password đủ mạnh và dài
  • Tránh việc sử dụng các password quen thuộc như: abc12345,...
  • Cân nhắc việc sử dụng thêm 1 layer trong ứng dụng cho việc encrypt password.

Database

  • Hãy cẩn thận với các đoạn SQL được viết bằng tay, code của bạn có thể có lỗ hổng SQL Injection, hãy chắc chắn rằng code SQL của bạn được convert bằng ActiveRecord (ví dụ: sanitize_sql_array)
  • Sử dụng Web application firewall để có thể tìm ra các lỗ hổng SQL Injection trong ứng dụng của bạn.
  • Luôn update Web application firewall
  • Cố gắng phân quyền cho database càng đơn giản càng tốt.
  • Cố gắng lưu càng ít thông tin của user càng tốt.
  • Khuyến khích lưu data đã được mã hóa.
  • Không lưu API keys, tokens, secret question/answers hoặc các thông tin secret khác dưới dạng plan text. Hãy sử dụng hash hoặc encryption.
  • Encrypt và backup data thường xuyên, hoặc có thể nghĩ đến việc lưu trữ data offline.

Gems

  • Giảm thiểu tối đa các gems ở production trong Gemfile. Để các gems không liên quan đến production ở trong group test hoặc development.
  • Chạy bundle audit thường xuyên.
  • Update Bundler Audit thường xuyên.
  • Review bundle outdated thường xuyên.

Detecting Vulnerabilities

  • Thường xuyên theo dõi các thông báo về Rails Security thông qua Rails Security mailing list
  • Chạy Brakeman và kiểm tra thường xuyên.
  • Update Brakeman thường xuyên.
  • Sử dụng các Security scanning service (Detectify)
  • Làm việc thường xuyên với các Security researcher thường xuyên.

Software Updates

  • Giữ version của Rails và Ruby luôn up-to-date

Test Coverage for Security Concerns

  • Tạo Test coverage cho các đoạn code liên quan đến Security:
    • Account sẽ bị khóa sau X lần đăng nhập thất bại.
    • Gửi notification khi password của account thay đổi.
    • URL tampering (attacker thay đổi user_id trên URL để tìm ra lỗ hổng)
    • Trong ứng dụng của bạn, attacker có thể không nhìn thấy nút Delete những vẫn có thể sử dụng HTTP Request để xóa data.

Cross Site Scripting

  • Thường xuyên check code của bạn bằng html_safe hoặc raw.

Developer Hardware

  • Tránh việc team member lưu data hoặc các thông tin secret khác ở máy.
  • Sử dụng hard disk encryption

Public, non-production Environments (Staging, Demo, etc.)

  • Không sử dụng data thật như ở production.
  • Không sử dụng lại secrets đã được sử dụng ở môi trường production.
  • Giới hạn truy cập vào môi trường staging, (IP Address, HTTP Basic credentials).

Regular expressions

  • Sử dụng A và z thay cho ^ hay $ http://guides.rubyonrails.org/security.html#regular-expressions

Handling Secrets

  • Đổi secrets khi có người rời team ^ _ ^
  • Không commit secrets lên git.
  • Nếu đã lỡ commit thì đổi ngay lập tức (haha)

Cookies

  • Secure các cookies flag trong ứng dụng của bạn.
  • Chặn các truy cập đến cookies càng nhiều càng tốt.

Headers

  • Sercure Headers gem
  • Content Security Policy

TLS/SSL

  • Đưa toàn bộ app của bạn về TLS/SSL, bao gồm links, assets, images, 3rd URLS. Không sử dụng vừa https lại vừa http.
  • Sử dụng SSL labs để check app.
  • HSTS

Traffic

  • Limit số lượng request
  • Cân nhắc việc sử dụng CloudFlare để tránh DDOS

...

Source: https://github.com/namtx/rails-security-checklist

0