Rails's Security Checklist
Bài đăng này đã không được cập nhật trong 7 năm
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
choApplicationController
(hoặc các abstract controller khác)- Sử dụng
authentication callbacks
(Devise'sauthenticate_user!
) - Sử dụng
authorization callbacks
(Pundit'sverify_authorized
) - Sử dụng
authorization-related callbacks
(Pundit'sverify_policy_scoped
) - Sử dụng
CSRF
- Sử dụng
- Khi disable các
secure
, hãy chỉ disable trên cácaction
cụ thể. Tránh việc disable trên cácabstract controller
, làm ảnh hưởng đến cácconcrete controller
(controller kế thừa).
Routes
- Sử dụng
authentication
vàauthorization
trong fileroutes.rb
, mặc dù trongcontroller callbacks
đã có rồi, nhưng vẫn nên sử dụng trongroutes.rb
.
defense-in-depth
- Đảm bảo rằng tất cả các
URL
đều được bao bởiauthentication
vàauthorization
. - Đảm bảo rằng không có một
uncoverd URL
nào trongproduction
.
Views
- Không được sử dụng
HTML
comment trong các filetemplate
. Vì khi sử dụngHTML
comments, phía client sẽ đọc được đoạn code được comment đó.
# bad - HTML comments will be visible to users who "View Source":
<!-- This will be sent to clients -->
<!-- <%= link_to "Admin Site", "https://admin.example.org/login" %> -->
# 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ộtaccount
, 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ảng13000
users. - Nếu bạn thực sự muốn đứa
ID
vàoURL
thì nên sử dụng các dạng ID khó đoán hơnUUIDs
hoặchashids
- Config để
Rails model
mặc định generateUUIDs
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
. Setupfilter_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ằngpaths
. Nếu ứng dụng của bạn bắt buộc phải có thì nên có mộtsafelist
để liệt kê các file có thể đọc. - Với các
query string
hoặc cácPOST
params mà ứng dụng của bạn thực hiện việcredirect
đếnURL
khác, thì cácURL
này phải nằm trongsafelist
hoặc cácURL
thuộc ứng dụng của bạn. Không nên theo kiểu, muốnredirect
đi đâu thìredirect
. - Cân nhắc việc sử dụng
strong_parameters
đểreject
cácparameters
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ụngsafelist
, tránh việc render tùy tiện toàn bộHTML
, đặc biệt là khi user có thể inputmarkdown
. - Nếu sử dụng
RedCarpet
, nên sử dụngRedCarpet::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 scanviruses/malware
, không chạy trênserver
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.
- 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ộtuser
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ộtURL
gây hại, và ứng dụng của bạn sẽ vô tình gửiURL
đó đến chínhusers
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 đổipassword
, thay đổicredit card
, một giao dịch phát sinh,user
thêmemail
hay các thông tin liên lạc khác, nhập saipassword
,setting 2FA
thay đổi,login
từ mộtIP
lạ hoắc). - Không gửi
email
chứapassword
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ủauser
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 đếnaccount
củauser
. Ví dụ: Tránh việcattacker
sử dụngbrute-force
để dò rapassword
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ụng2FA
bằng cách settings default hoặc đưa ra các ưu đãi nếuuser
sử dụng2FA
. - Limit
IP-address
,device
đặc biệt là account củaadmin
- Yêu cầu
user
sử dụng chức năngconfirm
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ánpassword hashing
nào đượcrecommend
. - Luôn luôn kiểm tra lại việc lưu trữ
password
- Không cho phép
user
sử dụng 1password
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ệcencrypt 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ổngSQL Injection
, hãy chắc chắn rằng codeSQL
của bạn được convert bằngActiveRecord
(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 tinsecret
khác dưới dạngplan text
. Hãy sử dụnghash
hoặcencryption
. 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
trongGemfile
. Để cácgems
không liên quan đếnproduction
ở trong grouptest
hoặcdevelopment
. - 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ônup-to-date
Test Coverage for Security Concerns
- Tạo
Test coverage
cho các đoạncode
liên quan đếnSecurity
:Account
sẽ bị khóa sauX
lần đăng nhập thất bại.- Gửi
notification
khipassword
củaaccount
thay đổi. URL tampering
(attacker
thay đổiuser_id
trênURL
để tìm ra lỗ hổng)- Trong ứng dụng của bạn,
attacker
có thể không nhìn thấy nútDelete
những vẫn có thể sử dụngHTTP Request
để xóa data.
Cross Site Scripting
- Thường xuyên check code của bạn bằng
html_safe
hoặcraw
.
Developer Hardware
- Tránh việc team member lưu
data
hoặc các thông tinsecret
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ườngproduction
. - 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êngit
. - 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
gemContent Security Policy
TLS/SSL
- Đưa toàn bộ
app
của bạn vềTLS/SSL
, bao gồmlinks
,assets
,images
,3rd URLS
. Không sử dụng vừahttps
lại vừahttp
. - Sử dụng
SSL labs
để checkapp
. - HSTS
Traffic
- Limit số lượng
request
- Cân nhắc việc sử dụng
CloudFlare
để tránhDDOS
...
All rights reserved