Rails's Security Checklist
Bài đăng này đã không được cập nhật trong 8 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 callbackschoApplicationController(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ácactioncụ 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
authenticationvàauthorizationtrong 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ởiauthenticationvàauthorization. - Đảm bảo rằng không có một
uncoverd URLnào trongproduction.
Views
- Không được sử dụng
HTMLcomment trong các filetemplate. Vì khi sử dụngHTMLcomments, 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
Refererkhi 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
IDcó 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ó1000lượt đăng kí, và ứng dụng của bạn có khoảng13000users. - Nếu bạn thực sự muốn đứa
IDvàoURLthì nên sử dụng các dạng ID khó đoán hơnUUIDshoặchashids - Config để
Rails modelmặc định generateUUIDslà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_parametersconfig để loại bỏrequest parameterskhỏ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 servicesmà ứ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
Filtervàvalidatenhững gì user gửi lên.- Tránh việc đọc các
filesystemkhi 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 stringhoặc cácPOSTparams mà ứng dụng của bạn thực hiện việcredirectđếnURLkhác, thì cácURLnày phải nằm trongsafelisthoặc cácURLthuộ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đểrejectcácparameterskhông cần thiết. - Cân nhắc sử dụng
sanitizingcho toàn bộActiveRecord attribute, https://github.com/flavorjones/loofah-activerecord
Markdown Rendering
- Sử dụng
markdown renderingsử 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::Safehơ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
serverchứa ứng dụng của bạn - Sử dụng
3rd servicecho việc scanviruses/malware, không chạy trênservercủa ứng dụng - Cần có một
safelistcác file được phép upload - Tránh việc chạy
imagemagickhoặ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ộtuserduy nhất) - Tránh việc gửi email có kèm theo data do chính
usernhập vào (ví dụ: thay vì nhập tên vào thìattackernhập vào mộtURLgây hại, và ứng dụng của bạn sẽ vô tình gửiURLđó đến chínhuserscủa bạn)
Detecting Abuse and Fraud
- Thông báo cho
userkhi password của họ thay đổi Devise - Thông báo cho
usernhững thay đổi vềaccountcủa họ (ví dụ: thay đổipassword, thay đổicredit card, một giao dịch phát sinh,userthêmemailhay các thông tin liên lạc khác, nhập saipassword,setting 2FAthay đổi,logintừ mộtIPlạ hoắc). - Không gửi
emailchứapasswordmà 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ề
accountcủauserhằ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 đếnaccountcủauser. Ví dụ: Tránh việcattackersử dụngbrute-forceđể dò rapasswordbằng cách limit số lần đăng nhập trong 1s.
Logins, Registration
- Sử dụng
multi-factor authentication - Khuyến khích
usersử dụng2FAbằng cách settings default hoặc đưa ra các ưu đãi nếuusersử dụng2FA. - Limit
IP-address,deviceđặc biệt là account củaadmin - Yêu cầu
usersử dụng chức năngconfirmaccount 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 hashingmạnh, luôn luôn tìm hiểu xem thuật toánpassword hashingnào đượcrecommend. - Luôn luôn kiểm tra lại việc lưu trữ
password - Không cho phép
usersử dụng 1password2 lần. - Sử dụng
passwordđủ mạnh và dài - Tránh việc sử dụng các
passwordquen thuộc như:abc12345,... - Cân nhắc việc sử dụng thêm 1
layertrong ứ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 codeSQLcủ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 Injectiontrong ứng dụng của bạn. - Luôn update
Web application firewall - Cố gắng phân quyền cho
databasecàng đơn giản càng tốt. - Cố gắng lưu càng ít thông tin của
usercàng tốt. - Khuyến khích lưu data đã được mã hóa.
- Không lưu
API keys,tokens,secret question/answershoặc các thông tinsecretkhác dưới dạngplan text. Hãy sử dụnghashhoặcencryption. Encryptvàbackupdata 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ởproductiontrongGemfile. Để cácgemskhông liên quan đếnproductionở trong grouptesthoặcdevelopment. - Chạy
bundle auditthường xuyên. - Update
Bundler Auditthường xuyên. - Review
bundle outdatedthường xuyên.
Detecting Vulnerabilities
- Thường xuyên theo dõi các thông báo về
Rails Securitythông qua Rails Security mailing list - Chạy
Brakemanvà kiểm tra thường xuyên. - Update
Brakemanthườ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 researcherthường xuyên.
Software Updates
- Giữ version của
RailsvàRubyluônup-to-date
Test Coverage for Security Concerns
- Tạo
Test coveragecho các đoạncodeliên quan đếnSecurity:Accountsẽ bị khóa sauXlần đăng nhập thất bại.- Gửi
notificationkhipasswordcủaaccountthay đổi. URL tampering(attackerthay đổiuser_idtrênURLđể tìm ra lỗ hổng)- Trong ứng dụng của bạn,
attackercó thể không nhìn thấy nútDeletenhữ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_safehoặcraw.
Developer Hardware
- Tránh việc team member lưu
datahoặc các thông tinsecretkhá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
\Avà\zthay cho^hay$http://guides.rubyonrails.org/security.html#regular-expressions
Handling Secrets
- Đổi
secretskhi có người rời team ^ _ ^ - Không commit
secretslêngit. - Nếu đã lỡ commit thì đổi ngay lập tức (haha)
Cookies
- Secure các
cookies flagtrong ứng dụng của bạn. - Chặn các truy cập đến
cookiescàng nhiều càng tốt.
Headers
Sercure HeadersgemContent Security Policy
TLS/SSL
- Đưa toàn bộ
appcủa bạn vềTLS/SSL, bao gồmlinks,assets,images,3rd URLS. Không sử dụng vừahttpslạ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