MySQL/MariaDB Security cho Web Server tập trung vào ba câu hỏi: database service có cần reachable từ network nào, account nào được phép kết nối từ host nào, và dữ liệu/credential có được bảo vệ khi truyền và khi backup hay không. Với website thông thường, database chỉ nên expose đúng cho application hoặc administration path cần thiết; public Internet exposure phải là ngoại lệ có lý do rõ.
MySQL 8.4 xác định account theo cả user và host, hỗ trợ quyền chi tiết và yêu cầu TLS theo account. MariaDB cũng nhấn mạnh network isolation, allowlist và encrypted connections. Vì vậy hardening database không nên bắt đầu bằng “đổi port 3306”, mà bằng bind/reachability → identity/host → privilege → TLS → logging/backup → validation.
Network exposure và reachability
1. Xác định database đang listen ở đâu
sudo ss -lntup | egrep '3306|33060|mariadb|mysqld'
Đừng chỉ nhìn port. Hãy xem service bind 127.0.0.1, private IP hay wildcard như 0.0.0.0/::. Nếu application và database cùng host, loopback/Unix socket thường giảm exposure hơn public bind.
2. bind_address phải khớp kiến trúc
MySQL có bind_address cho client TCP connections. Nếu database chỉ phục vụ local application, không nên bind public interface chỉ vì mặc định cũ hoặc convenience. Nếu app ở host khác, ưu tiên private network/VPN/segmentation và host/cloud firewall.
Mọi thay đổi bind cần dependency check: replication, backup agent, monitoring, control panel và remote DBA có thể đang kết nối.
3. Firewall là lớp bổ sung, không thay bind policy
Một database bind wildcard nhưng firewall chặn Internet vẫn cần patch và vẫn reachable từ các source được allow. Hãy dùng cả Linux Firewall và database bind policy để giảm reachability.
Identity, privilege và credential transport
4. Không dùng một database account cho mọi ứng dụng
Mỗi application nên có account riêng theo purpose. MySQL account là dạng 'user'@'host', vì vậy cùng username từ host khác có thể là identity khác. Điều này cho phép giới hạn source kết nối thay vì dùng wildcard host không cần thiết.
5. Least privilege ở database
Application account chỉ nên có quyền cần cho schema/workflow. Website đọc/ghi dữ liệu không nhất thiết cần GRANT OPTION, account-management privilege hay administrative privilege. Migration/deploy account có thể tách khỏi runtime account.
Audit nên review:
SHOW GRANTS FOR 'appuser'@'host';
Không revoke production privilege chỉ dựa trên tên quyền; phải test application path trước.
6. Root/admin database account
Administrative account không nên được ứng dụng dùng thường xuyên. MariaDB guidance lâu nay khuyến nghị root local-only; với MySQL, host component của account cho phép thiết kế tương tự. Tách human DBA, automation và application identities giúp giảm blast radius và cải thiện accountability.
7. TLS cho remote database connection
Nếu database traffic đi qua network không hoàn toàn tin cậy, TLS nên được bật và xác minh. MySQL hỗ trợ REQUIRE SSL cho account và require_secure_transport ở server; client có thể dùng VERIFY_CA hoặc VERIFY_IDENTITY để kiểm certificate.
MariaDB cũng hỗ trợ TLS và có thể yêu cầu REQUIRE SSL/REQUIRE X509 cho account. Không chỉ bật encryption; client phải xác minh server identity khi threat model yêu cầu.
8. Secret database không nên nằm trong public web root
Credential có thể nằm trong environment, secret store hoặc config file tùy application. Điều quan trọng là web server không phục vụ file đó và chỉ identity cần thiết mới đọc được. Xem File Permission & Ownership để kiểm soát filesystem layer.
9. Password rotation phải tính dependency
Rotate credential không phải đổi password trước rồi sửa application sau. Workflow an toàn nên có dual credential hoặc maintenance plan khi platform hỗ trợ, cập nhật secret consumer, test connection, rồi mới revoke credential cũ.
10. Anonymous, test và stale accounts
Inventory account định kỳ để tìm user không owner, host wildcard không cần, account của app đã decommission hoặc account tạm không hết hạn. Đừng xóa tự động: replication, monitoring hoặc backup có thể dùng account nhìn tên không rõ.
Host process, data protection và validation
11. Database không nên chạy bằng OS root
mysqld/mariadbd nên chạy bằng service identity riêng theo package/distro. Nếu database process chạy root bất thường, đây là finding cần điều tra ngay vì blast radius tăng mạnh.
12. File permission của data/config/key
Data directory, config và TLS private key cần owner/mode phù hợp. Web runtime không nên đọc database data files trực tiếp. Backup dump cũng nhạy cảm tương đương dữ liệu production.
13. Backup security
Database backup cần:
- Credential riêng hoặc mechanism phù hợp.
- Storage access tối thiểu.
- Encryption khi threat model yêu cầu.
- Retention/cleanup.
- Restore test.
- Không để dump trong public web root.
Một file dump có thể chứa password reset token, PII hoặc secret application; backup success không đồng nghĩa backup an toàn.
14. Logging và audit
Database logs cần đủ để điều tra startup/error, authentication failure và administrative event theo risk. General query log không nên bật vô hạn chỉ để “có audit” vì volume lớn và có thể chứa dữ liệu nhạy cảm. Nếu cần audit chi tiết, chọn facility/plugin phù hợp edition và requirement.
15. Không public admin interface ngoài nhu cầu
MySQL 8.4 có administrative interface riêng khi cấu hình admin_address; không có mặc định nếu không chỉ định. Nếu sử dụng, nó cũng cần network/TLS/access policy riêng. Không mở thêm admin port chỉ để “dễ quản trị”.
16. Patch database theo support lifecycle
Database engine là security-critical service. Theo dõi vendor advisory và distro package source. Patch có thể cần restart/failover, nên áp dụng quy trình Linux Patch Management với snapshot, dependency check và functional validation.
17. Validation sau hardening
- Read-back listening socket/bind.
- Test application connection.
- Test remote admin/backup/monitoring path intended.
- Test source không hợp lệ bị từ chối khi có phép test.
- Read-back grants/account host.
- Verify TLS mode/certificate khi dùng remote TLS.
- Kiểm tra error log.
- Test transaction/function quan trọng của website.
Database Security Review Record
Đây là template evidence, không phải trạng thái database của SecureWebOps.
| Control | Observed | Expected | Evidence | Result |
|---|---|---|---|---|
| Listen/bind | IP/socket | Local/private intended | Socket + config | PASS/FAIL |
| App account | User@host | Owned + scoped | Account/grants | PASS/FAIL |
| TLS | Enabled/required/unknown | Per architecture | Config + client verification | PASS/FAIL |
| Backup | Storage/access | Protected + restoreable | Backup/restore evidence | PASS/FAIL |
Checklist MySQL/MariaDB Security
- Database version/source còn support.
- Listening socket khớp architecture.
- Không public 3306 ngoài nhu cầu.
- Firewall và bind policy nhất quán.
- Mỗi application có account riêng.
- Account host được giới hạn.
- Runtime account least privilege.
- Admin account tách runtime.
- TLS được yêu cầu cho remote path khi cần.
- Credential không nằm trong public web root.
- Stale/anonymous/test account được review.
- Database process không chạy OS root.
- Data/config/key permissions đúng.
- Backup có access control và restore test.
- Logging/audit đủ nhưng không thu thập secret vô ích.
- Patch lifecycle có owner.
- Functional validation sau change.
Nguồn kỹ thuật tham khảo
- MySQL 8.4 — Access Control and Account Management
- MySQL 8.4 — Encrypted Connections
- MySQL 8.4 — General Security Issues
- MariaDB — Database Security
Kết luận
MySQL/MariaDB security tốt nhất khi database không bị expose rộng hơn nhu cầu và mỗi application có identity/privilege riêng. Đổi port hoặc giấu banner không bù được wildcard bind, wildcard account host hay credential dùng chung.
Ưu tiên theo thứ tự: giảm network exposure → tách account → giảm privilege → bảo vệ transport/secret → backup/log → patch → validation. Database chỉ PASS khi application và operational dependency vẫn hoạt động sau hardening.
