T
Trinh Digital
Xây dựng Hệ thống

Security Hardening: Từ 'F' lên 'A+' trên Mozilla Observatory cho website DN

Trinh Digital · · 9 phút đọc

Case study bảo mật website này ghi lại hành trình chúng tôi hardening website của một công ty luật tại TP.HCM — từ điểm F (0/100) lên A+ (125/100) trên Mozilla Observatory, và từ grade C lên A+ trên SSL Labs. Đây là case study chi tiết với từng bước thực hiện, giúp bất kỳ developer nào có thể áp dụng.

Bối cảnh

Khách hàng: Công ty luật với 15 luật sư, chuyên tư vấn doanh nghiệp và M&A.

Website: WordPress, host trên VPS DigitalOcean.

Tại sao cần hardening:

  • Đối tác nước ngoài audit website trước khi ký hợp đồng → phát hiện điểm bảo mật F
  • Khách hàng gửi thông tin nhạy cảm (hợp đồng, tài liệu pháp lý) qua website
  • Yêu cầu tuân thủ Nghị định 13/2023 về bảo vệ dữ liệu cá nhân

Yêu cầu: Đạt A+ trên Mozilla Observatory, A+ trên SSL Labs, đáp ứng OWASP Top 10.

Đánh giá ban đầu

Mozilla Observatory: Grade F (Score: 0/100)

TestKết quảĐiểm
Content Security PolicyKhông có-25
CookiesKhông Secure, không HttpOnly-20
Cross-Origin Resource SharingKhông cấu hình0
HTTP Strict Transport SecurityKhông có-20
RedirectionCó redirect HTTP→HTTPS+5
Referrer PolicyKhông có-5
Subresource IntegrityKhông có-5
X-Content-Type-OptionsKhông có-5
X-Frame-OptionsKhông có-20
X-XSS-ProtectionKhông có-10

SSL Labs: Grade C

Vấn đềChi tiết
TLS 1.0 enabledDeprecated, vulnerable
TLS 1.1 enabledDeprecated
Weak cipher suitesDES-CBC3-SHA, RC4
No HSTSKhông enforce HTTPS
No OCSP staplingSlower SSL handshake

Scan bổ sung

ToolKết quả
Sucuri SiteCheck2 outdated plugins, jQuery vulnerable
WPScan5 known vulnerabilities
NmapPort 22, 80, 443, 3306 (MySQL exposed!)
ShodanMySQL visible from internet

12 bước hardening

Bước 1: Đóng port MySQL (5 phút)

MySQL port 3306 mở ra internet = bất kỳ ai đều có thể thử kết nối.

# Bind MySQL chỉ localhost
sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
# bind-address = 127.0.0.1

# Update firewall
sudo ufw deny 3306

sudo systemctl restart mysql

Kết quả: MySQL không còn accessible từ internet.

Bước 2: SSL/TLS Hardening (15 phút)

# /etc/nginx/conf.d/ssl-hardening.conf

# Chỉ cho phép TLS 1.2 và 1.3
ssl_protocols TLSv1.2 TLSv1.3;

# Cipher suites mạnh
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers on;

# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 1.1.1.1 8.8.8.8 valid=300s;

# SSL session caching
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;

# DH parameters (2048-bit)
ssl_dhparam /etc/nginx/dhparam.pem;
# Generate DH parameters
sudo openssl dhparam -out /etc/nginx/dhparam.pem 2048

Kết quả: SSL Labs: C → A+

Bước 3: Security Headers (10 phút)

# /etc/nginx/conf.d/security-headers.conf

# Chống clickjacking
add_header X-Frame-Options "SAMEORIGIN" always;

# Chống MIME type sniffing
add_header X-Content-Type-Options "nosniff" always;

# XSS Protection
add_header X-XSS-Protection "1; mode=block" always;

# Referrer Policy
add_header Referrer-Policy "strict-origin-when-cross-origin" always;

# HSTS (1 năm + subdomains + preload)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

# Permissions Policy
add_header Permissions-Policy "camera=(), microphone=(), geolocation=(), interest-cohort=()" always;

Kết quả: +75 điểm trên Mozilla Observatory.

Bước 4: Content Security Policy (30 phút)

CSP là header phức tạp nhất — cần test kỹ:

# Phase 1: Report-Only (1 tuần)
add_header Content-Security-Policy-Report-Only "
    default-src 'self';
    script-src 'self' 'unsafe-inline' https://www.googletagmanager.com https://www.google-analytics.com https://www.gstatic.com;
    style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
    img-src 'self' data: https:;
    font-src 'self' https://fonts.gstatic.com;
    connect-src 'self' https://www.google-analytics.com;
    frame-src 'self' https://www.youtube.com https://www.google.com;
    object-src 'none';
    base-uri 'self';
    form-action 'self';
    frame-ancestors 'self';
    upgrade-insecure-requests;
" always;

# Phase 2: Enforce (sau 1 tuần không có lỗi)
# Đổi Content-Security-Policy-Report-Only → Content-Security-Policy

Kết quả: +25 điểm trên Mozilla Observatory.

Bước 5: Secure Cookies (10 phút)

// wp-config.php — trước "/* That's all, stop editing! */"

// Force secure cookies
@ini_set('session.cookie_httponly', true);
@ini_set('session.cookie_secure', true);
@ini_set('session.cookie_samesite', 'Lax');
@ini_set('session.use_only_cookies', true);

define('COOKIE_DOMAIN', '.yourdomain.com');
define('COOKIEPATH', '/');
# Nginx: Thêm flags cho tất cả cookies
proxy_cookie_path / "/; HTTPOnly; Secure; SameSite=Lax";

Kết quả: +20 điểm.

Bước 6: Update WordPress + Plugins (30 phút)

PluginPhiên bản cũPhiên bản mớiLỗ hổng đã fix
Elementor3.123.19XSS, Privilege Escalation
Contact Form 75.65.9File Upload vulnerability
Yoast SEO20.122.3Information Disclosure
WooCommerce7.58.5SQL Injection
jQuery3.4.13.7.1XSS vulnerability
# WP-CLI update tất cả
wp core update
wp plugin update --all
wp theme update --all
wp core update-db

Bước 7: WordPress Hardening (20 phút)

// wp-config.php

// Tắt file editing trong admin
define('DISALLOW_FILE_EDIT', true);

// Tắt file mods (cài plugin qua admin)
define('DISALLOW_FILE_MODS', true);

// Giới hạn post revisions
define('WP_POST_REVISIONS', 5);

// Custom database prefix (đã có từ cài)
// $table_prefix = 'wp_abc123_';

// Security keys (regenerate)
// https://api.wordpress.org/secret-key/1.1/salt/
# Nginx: WordPress-specific security
location /wp-admin/includes/ { deny all; }
location /wp-includes/theme-compat/ { deny all; }
location /wp-includes/js/tinymce/langs/ { deny all; }
location ~* /wp-config.php { deny all; }
location ~* /readme.html { deny all; }
location ~* /xmlrpc.php { deny all; }

# Chặn PHP execution trong uploads
location ~* /wp-content/uploads/.*\.php$ {
    deny all;
}

Bước 8: Rate Limiting (10 phút)

limit_req_zone $binary_remote_addr zone=login:10m rate=3r/m;
limit_req_zone $binary_remote_addr zone=contact:10m rate=5r/m;

location /wp-login.php {
    limit_req zone=login burst=2 nodelay;
    limit_req_status 429;
    # Thêm: chỉ cho phép IP văn phòng
    # allow 103.x.x.x;
    # deny all;
}

location /wp-admin/admin-ajax.php {
    limit_req zone=contact burst=10 nodelay;
}

Bước 9: 2FA cho Admin (15 phút)

Cài plugin Two Factor Authentication cho WordPress:

wp plugin install two-factor --activate

Bật 2FA bắt buộc cho tất cả admin accounts (Google Authenticator).

Bước 10: Backup & Recovery (20 phút)

Setup backup tự động theo quy tắc 3-2-1:

# Database backup hàng ngày → B2
# Files backup hàng tuần → B2
# Config backup hàng tháng → B2

Bước 11: Monitoring (15 phút)

  • UptimeRobot: Kiểm tra uptime mỗi 5 phút
  • SSL Monitor: Alert khi SSL sắp hết hạn
  • Sucuri SiteCheck: Scan malware hàng tuần

Bước 12: Firewall & WAF (15 phút)

Cloudflare Free:

  • DNS proxy → ẩn IP thật
  • DDoS protection
  • Basic WAF rules
  • Rate limiting

Kết quả

Mozilla Observatory

TestTrướcSau
Content Security PolicyFail (-25)Pass (+25)
CookiesFail (-20)Pass (+5)
HSTSFail (-20)Pass (+15)
Referrer PolicyFail (-5)Pass (+5)
X-Content-Type-OptionsFail (-5)Pass (+5)
X-Frame-OptionsFail (-20)Pass (+20)
X-XSS-ProtectionFail (-10)Pass (+5)
Subresource IntegrityN/APass (+5)
Tổng điểm0/100 (F)125/100 (A+)

SSL Labs

TestTrướcSau
Protocol SupportTLS 1.0, 1.1, 1.2TLS 1.2, 1.3 only
Key ExchangeWeak DHECDHE
Cipher StrengthWeak ciphersStrong only
HSTSNoYes (preload)
OCSP StaplingNoYes
GradeCA+

Security scan

ToolTrướcSau
Sucuri SiteCheck2 warningsClean
WPScan5 vulnerabilities0 vulnerabilities
Nmap (external)4 ports open2 ports open (80, 443)
SecurityHeaders.comFA+

Business impact

MetricTrướcSau
Đối tác security auditFailPass
Trust score (khảo sát nội bộ)5.2/108.8/10
SSL Labs badgeKhông dám hiển thịHiển thị A+ trên website
Compliance NĐ 13/2023Chưa đạtĐạt cơ bản

Chi phí

Hạng mụcChi phí
Hardening (one-time)8 triệu VND
Cloudflare Free0 VND/tháng
2FA plugin0 VND
Backup (Backblaze B2)~5.000 VND/tháng
Monitoring (UptimeRobot Free)0 VND
Tổng one-time8 triệu VND
Tổng hàng tháng~5.000 VND

Timeline: 12 bước trong 1 ngày

Thời gianBướcKết quả
9:00–9:05Đóng port MySQLPort 3306 closed
9:05–9:20SSL/TLS hardeningSSL Labs: A+
9:20–9:30Security headers+75 điểm
9:30–10:00CSP (Report-Only)Monitoring
10:00–10:10Secure cookies+20 điểm
10:10–10:40Update WP + plugins0 known vulnerabilities
10:40–11:00WordPress hardeningAdmin secured
11:00–11:10Rate limitingLogin protected
11:10–11:252FAAdmin 2FA enabled
11:25–11:45Backup setup3-2-1 backup active
11:45–12:00MonitoringUptimeRobot active
12:00–12:15Cloudflare WAFDDoS protection active
Tổng3 giờ 15 phútF → A+

FAQ — Câu hỏi thường gặp

Có cần thuê chuyên gia hay tự làm được?

12 bước trong bài viết đều có thể tự làm nếu bạn quen với Linux và Nginx. Tuy nhiên, CSP (bước 4) cần test kỹ vì có thể break website nếu cấu hình sai. Nếu không chắc chắn, thuê chuyên gia để tránh rủi ro.

A+ trên Mozilla Observatory có giữ được mãi không?

Không tự động — cần maintenance. Khi thêm third-party scripts (analytics, chat widget, ads), CSP cần update. Khi update WordPress/plugins, cần kiểm tra lại. Khuyến nghị: scan lại mỗi tháng 1 lần.

Kết luận

Từ F lên A+ trong 1 ngày — không khó, chỉ cần biết làm gì và làm đúng thứ tự. 12 bước trong case study này áp dụng được cho bất kỳ website nào: WordPress, Laravel, Node.js, hoặc static site.

Nếu bạn cần security audit hoặc dịch vụ hardening website chuyên nghiệp, hãy liên hệ Trinh Digital — chúng tôi đảm bảo A+ trên cả Mozilla Observatory và SSL Labs.

#Mozilla Observatory#security#hardening#case study
Chia sẻ: Z

Sẵn sàng chuyển đổi số cùng Trinh Digital?

Liên hệ ngay để nhận tư vấn miễn phí. Đội ngũ chuyên gia sẽ phân tích nhu cầu và đề xuất giải pháp tối ưu.

Zalo