Content Security Policy (CSP) là một tiêu chuẩn bảo mật web bổ sung. Nó hoạt động như một danh sách trắng (whitelist) các nguồn tài nguyên (script, CSS, hình ảnh, v.v.) mà trình duyệt được phép tải và thực thi trên trang web. Bằng cách định cấu hình CSP qua tiêu đề phản hồi HTTP Content-Security-Policy, bạn có thể hạn chế các tài nguyên từ các nguồn không tin cậy. Từ đó giúp giảm thiểu các cuộc tấn công. Mời bạn đọc cùng tìm hiểu ngay trong bài viết dưới đây của GDATA nhé!
Tại sao cần bảo mật ứng dụng web?

CSP là gì? – Kiến thức bảo mật ứng dụng web
CSP (Content Security Policy) là một HTTP Response Header (hoặc <meta http-equiv>). Đặt chính sách nguồn tài nguyên cho trình duyệt: script, style, img, font, frame, connect, worker. Mục tiêu chính của CSP là chặn XSS và giảm rủi ro supply-chain bằng cách kiểm soát nguồn tài nguyên mà trình duyệt được phép tải và thực thi. Ví dụ như:
- Chặn XSS (đặc biệt DOM XSS/inline script) bằng cách cấm “inline” và chỉ cho phép nguồn tin cậy.
- Giảm rủi ro supply chain từ bên thứ ba. Chỉ cho phép domain cụ thể, dùng nonce/hash và SRI.
- Tối ưu hiệu năng gián tiếp. Loại bỏ script rác/không cần thiết, giảm request, kiểm soát third-party.
Kiến trúc CSP: 3 lớp phòng thủ bảo mật ứng dụng web
1. Lớp trình duyệt (CSP + Trusted Types + COOP/COEP/CORP)
– CSP cứng: script-src 'self' 'strict-dynamic' 'nonce-…' + base-uri 'none' + object-src 'none' + frame-ancestors thay cho X-Frame-Options.
– Trusted Types để chống DOM XSS (Chrome-based), ép code chỉ chèn HTML/Script qua policy đã đăng ký.
2. Lớp ứng dụng
– Tạo nonce mỗi request, gán cho tất cả <script> hợp lệ (kể cả JSON-LD, module, dynamic import).
– Linter/CI: chặn inline event handler (onclick…), nội suy nguy hiểm, eval, new Function.
3. Lớp biên
– CDN/WAF/Reverse proxy tự động tiêm header, thêm report-to/report-uri, tự động xoay nonce, ghi log vi phạm.
Các kỹ thuật bảo mật ứng dụng web cần biết
1. default-src 'none' + whitelist per-directive
– Mục đích: bắt buộc bạn phải tư duy “zero-trust” cho mọi loại tài nguyên – không còn mặc định lỏng lẻo.
– Cách làm: Đặt header CSP với default-src 'none' rồi khai báo cụ thể script-src, style-src, img-src, connect-src, v.v.
– Ví dụ:Content-Security-Policy: default-src 'none'; script-src 'self'; style-src 'self'; img-src 'self' data:;
Lưu ý: default-src 'none' buộc phải liệt kê mọi nguồn cần thiết. Để đảm bảo loại được rất nhiều rủi ro “vô tình” từ third-party.
2. script-src 'self' 'strict-dynamic' 'nonce-<RND>'
– Mục đích: cho phép chỉ những script được cấp nonce hoặc hash thực thi; strict-dynamic cho phép script được nonce tải thêm script động mà không cần liệt kê domain. Giải quyết vấn đề phải whitelist nhiều domain.
– Cách làm:
- Ứng dụng sinh nonce crypto-secure mỗi request (trên server) – Có ít nhất 128 bit, base64.
- Tiêm nonce vào template HTML:
<script nonce="...">và vào header CSP:script-src 'strict-dynamic' 'nonce-....' 'unsafe-inline'?(không dùngunsafe-inline). - Bật
report-uri/report-toban đầu để ghi nhận.
Lưu ý: SPAs/CSR: nonce chỉ hữu ích cho HTML nạp ban đầu. Nếu runtime tạo script dynamic, tốt nhất cho loader script (có nonce) chịu trách nhiệm nạp module khác.
3. Nonce generation & binding – Bảo mật ứng dụng web
– Mục đích: tránh rò rỉ nonce và phát hiện replay/leak.
– Cách làm tham khảo:
- Server tạo nonce = HMAC(server_secret, random || timestamp); gửi nonce trong HTML và header
X-CSP-Nonce. Khi nhận report vi phạm thì có thể verify nonce hợp lệ bằng HMAC. - Nonce timeout: nonce hợp lệ trong 30s–2min. Giúp phát hiện replay từ attacker cố gắng reuse nonce cũ.
Lưu ý: không lưu nonce trong cookie có thể bị leak; embed trực tiếp vào HTML.
4. style-src + CSS handling
– Mục đích: tránh unsafe-inline cho CSS (loại bỏ vector chèn style độc hại) nhưng vẫn xử lý các thư viện CSS-in-JS.
– Cách làm:
- Tách CSS sang file tĩnh
style.css(nạp từ'self'). - Nếu dùng CSS-in-JS (styled-components, emotion): Hãy bật nonce feature của engine (ví dụ
StyleSheetManager nonce={nonce}) để style tags hợp lệ. - Với một số inline critical CSS nhỏ thì dùng hash (
'sha256-...') thay vìunsafe-inline.
Lưu ý: Sử dụng nonce cho style nếu bạn không thể tách hoàn toàn CSS.
5. Subresource Integrity (SRI) kết hợp CSP – Bảo mật ứng dụng web
– Mục đích: đảm bảo file tải từ CDN không bị thay đổi (integrity verification).
– Cách làm: kèm integrity="sha384-..." crossorigin="anonymous" vào <script>/<link>. Ngoài ra, CSP vẫn cần cho phép domain CDN (hoặc dùng strict-dynamic + nonce).
– Ví dụ:
Lưu ý: nếu CDN thay version (checksum thay đổi), SRI vỡ → phải deploy phối hợp.
6. report-uri / report-to – Giám sát vi phạm
– Mục đích: thu thập thông tin vi phạm CSP mà không chặn — rất hữu ích khi rollout.
– Cách làm:
- Bật
Content-Security-Policy-Report-Onlyvớireport-urihoặcreport-topointing đến endpoint/csp-report. - Viết processor (Node/Express) để chuẩn hoá, dedupe, enrich (resolve blocked-uri to domain), và gửi sang ELK/Splunk/Cloud SIEM.
- Mẫu server (Express):
Lưu ý: filter out noise từ browser extensions (chrome-extension://) và services (adblock) trước khi báo động.
7. strict-dynamic / domain whitelisting – Chọn cái nào khi bảo mật ứng dụng web?
– Mục đích: Chọn chiến lược quản lý third-party.
- strict-dynamic + nonce được dùng khi bạn kiểm soát loader script (cho SPA/modern apps). Và nó có ưu điểm là không cần whitelist hàng loạt domain.
- Domain whitelist + SRI sẽ được dùng khi third-party là static libs (CDN) và bạn không muốn loader dynamic.
Lưu ý: strict-dynamic bỏ qua host list for scripts; vẫn cần connect-src để cho phép network endpoints.
8. Trusted Types (TT)
– Mục đích: chặn DOM XSS từ innerHTML, outerHTML, insertAdjacentHTML bằng cách bắt buộc chỉ nội dung đã được “sanitized” qua policy được đăng ký.
– Cách làm:
- Bật
require-trusted-types-for 'script'trong CSP. - Trong code, register policies:
Lưu ý: TT có hiệu quả mạnh với SPA; cần cập nhật legacy libs.
9. frame-ancestors & sandbox cho iframe
– Mục đích: ngăn clickjacking hoặc ngăn trang khác nhúng website bạn (phishing). Đồng thời giới hạn quyền iframe 3rd-party.
– Cách làm:
frame-ancestors 'self'(thay X-Frame-Options).- Khi embed 3rd-party (payment), dùng
<iframe sandbox="allow-scripts allow-forms">+CSP frame-src pay.example.com.
Lưu ý: Sandbox thiết lập đúng attributes (allow-popups?) chặt chẽ để tránh quyền vượt mức.
10. worker-src + Service Worker scope giúp bảo mật ứng dụng web
– Mục đích: giới hạn nơi worker có thể load script, tránh kẻ xấu đăng worker độc hại.
– Cách làm: set worker-src 'self' blob: nếu dùng blob URLs; nếu host worker file trên CDN phải cho phép domain đó. Service worker scope phải match domain chính.
Lưu ý: Service Worker chịu CSP của HTML khi đăng ký; giữ file worker nhỏ & ký SRI nếu serve tĩnh.
11. JSON-LD / Structured Data & CSP
– Mục đích: cho phép rich snippets cho SEO mà không mở cửa cho XSS.
– Cách làm: dùng <script type="application/ld+json" nonce="..."> — nonce works for non-executable JSON-LD as well.
Lưu ý: Tránh dangerouslySetInnerHTML khi inject JSON-LD từ nguồn không tin cậy.
12. Report pipeline → SIEM integration
– Mục đích: biến CSP reports thành tín hiệu bảo mật hữu dụng (alert, correlation).
– Cách làm:
- Normalise report fields:
effective-directive,blocked-uri,source-file,status-code,user-agent,ip. - Dedupe (same
blocked-uri/source-filewithin window). - Enrich: reverse DNS, ASN, GeoIP nếu blocked-uri external.
- Correlate với WAF/IDS logs: nếu cùng IP có WAF block + CSP report → HIGH.
Cách triển khai bảo mật ứng dụng web – rollout an toàn
– Inventory tự động: dùng headless Chrome crawler (Puppeteer) để thu thập mọi script, style, img, connect endpoints trên site (desktop + mobile).
– Generate initial CSP (Report-Only): từ inventory tạo CSP (script-src list / connect-src list / img-src list). Deploy header Content-Security-Policy-Report-Only với report-to.
– Collect & Analyse 7-14 ngày: parse reports, tạo bảng top blocked URIs. Lọc noise (extensions).
– Refine CSP: convert stable resources to nonces or SRI; replace some third-party with proxied versions (see below).
– Gradual enforce: Enforce 10% traffic → 50% → 100%. Monitor errors and rollback plan.
– Hardening: enable require-trusted-types-for 'script', enable frame-ancestors 'none' if feasible, move to default-src 'none' if not already.
Những câu hỏi thường gặp khi bảo mật ứng dụng web
Q: SPA có thể dùng nonce không?
→ Yes, nonce bảo vệ initial HTML. For client-side dynamic scripts, use a nonce-bearing bootstrap script that loads app modules.
Q: Có nên dùng unsafe-inlinevì nó tiện lợi?
→ Không. unsafe-inline phá hỏng mục tiêu CSP. Dùng hash hoặc nonce.
Q: Report-Only cần bao lâu?
→ Ít nhất 7–14 ngày thu thập traffic; phức tạp sites cần 30 ngày.
Q: Làm sao để quản lý third-party (analytics)?
→ Proxy hoặc host minimal shim trên your domain; hạn chế connect-src domain dùng cho analytics.
Kết luận
Bài viết trên của GDATA đã giúp bạn hiểu rõ hơn về bảo mật ứng dụng web với CSP. Hi vọng bài viết đã mang đến cho bạn những thông tin hữu ích. Nếu bạn gặp bất kỳ khó khăn nào trong việc bảo mật ứng dụng web thì hãy liên hệ ngay với GDATA nhé!
Thông tin liên hệ:
Hotline: 0904 299 668
Tổng đài: 1800 4814 – Phím 2
Email: lienhe@gdata.com.vn
Website: gdata.com.vn
Facebook:https://www.facebook.com/gdata.com.vn
CÔNG TY CP DỮ LIỆU TOÀN CẦU
Địa chỉ: Tầng 03 Tòa Lạc Hồng/ 27 Lê Văn Lương, Thanh Xuân, Hà Nội
GDATA – Thuê VPS toàn diện cho doanh nghiệp!
>> Xem thêm về giá VPS
