Công cụ kiểm tra iframe

Công cụ kiểm tra iframe trực tuyến miễn phí: nhập URL trang web bất kỳ để phân tích tiêu đề X-Frame-Options và Content-Security-Policy frame-ancestors, xác định xem trang có thể nhúng vào iframe hay không, và xác nhận qua bản xem trước trực tiếp. Lịch sử được lưu tạm trong phiên duyệt web hiện tại.

Kiểm tra nhúng iFrame

:

Chạy từng dòng qua cùng quy trình kiểm tra tiêu đề và thêm vào lịch sử phiên bên dưới. Giới hạn 20 URL mỗi lượt, được kiểm tra theo nhóm nhỏ để giảm thiểu tác động lên trang đích.

Đã kiểm tra: /
URL Kết quả HTTP

Xem trước trực tiếp

Quét tiêu đề là bước kiểm tra nhanh ban đầu, nhưng không thể phát hiện JavaScript chống nhúng (frame-busting): nếu tiêu đề báo "Có thể nhúng" mà bản xem trước vẫn trống, thoát khỏi iframe hoặc hiện trang lỗi, thì trang web không thể nhúng an toàn. Bản xem trước trực tiếp là cơ sở chính xác nhất.

Lịch sử (phiên này)

Chỉ được lưu trong tab này (sessionStorage); sẽ bị xóa khi đóng tab. Không có dữ liệu nào được gửi đến máy chủ.

Chưa có kiểm tra nào trong phiên này.

Cách thức hoạt động

  1. Nhập URL đích và nhấp Kiểm tra. Máy chủ sẽ truy xuất trang dưới dạng yêu cầu iframe thực tế (có Sec-Fetch-Dest: iframe) và đọc các tiêu đề phản hồi.
  2. Kết quả được xác định dựa trên X-Frame-Options (DENY / SAMEORIGIN chặn nhúng) và Content-Security-Policy frame-ancestors (chỉ * hoặc ký tự đại diện lược đồ mới cho phép các nguồn cha bên thứ ba tùy ý).
  3. Cùng URL đó sẽ được tải vào iframe xem trước trực tiếp để bạn xác nhận hành vi thực tế của trình duyệt, bao gồm cả các cơ chế JavaScript chống nhúng mà tiêu đề không thể tiết lộ.

Yếu tố quyết định việc trang web có thể được nhúng hay không

Khả năng hiển thị một trang web bên trong `<iframe>` trên một trang khác được quyết định bởi trình duyệt, dựa trên các tiêu đề phản hồi do chính trang đó trả về. Trình kiểm tra này mô phỏng cùng quy trình kiểm tra phía máy chủ và cung cấp kết quả phân tích ngay lập tức cho bạn.

`X-Frame-Options` là tiêu đề kinh điển: `DENY` cấm mọi trang web nhúng lại; `SAMEORIGIN` chỉ cho phép các trang cùng nguồn gốc thực hiện việc này; `ALLOW-FROM` đã bị gỡ bỏ khỏi các trình duyệt hiện đại. Khi thiếu tiêu đề này, các trình duyệt cũ sẽ không tự động chặn việc nhúng khung.

`Content-Security-Policy` với directive `frame-ancestors` là giải pháp hiện đại thay thế. Nó quy định rõ các nguồn gốc được phép nhúng trang — ví dụ: `frame-ancestors 'self' https://example.com`. Giá trị `*` (hoặc lược đồ đơn như `https:`) sẽ cho phép mọi nguồn HTTPS nhúng vào; các giá trị hạn chế hơn sẽ chặn các yêu cầu nhúng từ bên thứ ba.

Tuy nhiên, header không quyết định tất cả: script phía client có thể chạy mã phá vỡ iframe (`top !== self` để ép thoát khỏi khung), và các trang đăng nhập hay API giới hạn khu vực địa lý có thể phản hồi khác khi nhận yêu cầu từ máy chủ trung tâm dữ liệu. Chính vì vậy, mỗi kết quả kiểm tra luôn đi kèm bản xem trước trực tiếp để đảm bảo tính chính xác.

Hướng dẫn nhanh: Cấu hình tiêu đề phản hồi

Nếu bạn quản lý trang web này, hãy kiểm soát trực tiếp việc nhúng khung bằng cách thiết lập trong tiêu đề phản hồi.

Chặn nhúng từ mọi trang

X-Frame-Options: DENY Content-Security-Policy: frame-ancestors 'none'

Trình duyệt sẽ từ chối hiển thị trang web trong mọi iframe — giải pháp bảo vệ chống clickjacking nghiêm ngặt nhất.

Chỉ cho phép nhúng từ cùng nguồn gốc

X-Frame-Options: SAMEORIGIN Content-Security-Policy: frame-ancestors 'self'

Chỉ những trang có cùng lược đồ, tên miền và cổng mới được phép nhúng vào khung; các trang web bên thứ ba sẽ bị chặn.

Chỉ cho phép nhúng từ các nguồn gốc cụ thể

Content-Security-Policy: frame-ancestors 'self' https://trusted.example.com

Hãy liệt kê các nguồn gốc tin cậy trong giá trị `frame-ancestors`; các nguồn gốc không nằm trong danh sách sẽ bị chặn.

Cho phép nhúng từ mọi trang web

Không cấu hình X-Frame-Options Content-Security-Policy: frame-ancestors *

Mọi trang web đều có thể nhúng nội dung của bạn vào iframe. Vui lòng cân nhắc kỹ lưỡng về đánh đổi rủi ro bảo mật.

Lưu ý: Tiêu đề X-Frame-Options hiện đã lỗi thời và được thay thế bằng `frame-ancestors` trong CSP. Khi cả hai cùng tồn tại, `frame-ancestors` sẽ được ưu tiên thực thi — khuyến nghị sử dụng `frame-ancestors`.

Máy chủ phát hiện yêu cầu đến từ iframe như thế nào?

Kể từ khoảng năm 2020, các trình duyệt dựa trên Chromium và Firefox tự động gắn thêm một nhóm tiêu đề Fetch Metadata cho mọi yêu cầu điều hướng và tải tài nguyên phụ. Tiêu đề hữu ích nhất cho việc kiểm tra ngữ cảnh nhúng là `Sec-Fetch-Dest` — nó cho máy chủ biết loại ngữ cảnh nào đang yêu cầu tài nguyên, mà hoàn toàn không cần trang gọi phải hỗ trợ.

  • `Sec-Fetch-Dest: document` — yêu cầu điều hướng cấp cao nhất (trình duyệt đang chuyển hướng trang chính), không nằm trong bất kỳ iframe/frame nào.
  • `Sec-Fetch-Dest: iframe` — yêu cầu được tải bên trong thành phần `<iframe>`.
  • `Sec-Fetch-Dest: frame` — tải bên trong thành phần `<frame>` (nhóm khung) thế hệ cũ.
  • `Sec-Fetch-Dest: embed/object` — tải bên trong thành phần `<embed>` hoặc `<object>`.

Trình kiểm tra này sẽ tự gửi yêu cầu thăm dò kèm tiêu đề Sec-Fetch-Dest: iframe, mô phỏng chính xác hành vi gửi đi của trình duyệt thật khi nhúng trang — nhờ đó, kết quả đánh giá phản ánh đúng cách máy chủ đích xử lý yêu cầu iframe thực tế, thay vì chỉ là các lệnh fetch chung chung.

Sec-Fetch-Dest là tín hiệu hữu ích nhưng không đóng vai trò là ranh giới bảo mật: nó chỉ được gửi bởi trình duyệt hiện đại, trong khi các ứng dụng khách ngoài trình duyệt — như curl, bot, một số webview hay trình duyệt đời cũ — có thể bỏ qua hoàn toàn hoặc gửi giá trị tùy ý. Máy chủ có thể dùng nó để ghi log hoặc áp dụng rate-limit, nhưng tuyệt đối không nên dựa duy nhất vào đây để quyết định tính an toàn của việc dựng iframe; quyết định đó vẫn thuộc về X-Frame-Options và CSP frame-ancestors, vốn do trình duyệt cưỡng chế thực thi độc lập với các tiêu đề yêu cầu.

Về phía client, trang web vẫn có thể tự phát hiện mình đang chạy trong iframe mà không cần phụ thuộc vào header, chẳng hạn bằng cách so sánh window.top !== window.self (hoặc truy xuất window.frameElement đối với các iframe đồng nguồn), sau đó kích hoạt phản ứng — như hiển thị cảnh báo hoặc ép chuyển hướng lên cửa sổ gốc. Đây chính là kỹ thuật bứt khung (frame-busting) đã đề cập ở trên và nó hoạt động hiệu quả bất kể tiêu đề yêu cầu ra sao.

Ví dụ cấu hình máy chủ: Chặn nhúng iframe

Các đoạn mã bên dưới minh họa cách cấu hình máy chủ hoặc framework tương ứng để chặn hoàn toàn việc nhúng iframe (thêm `X-Frame-Options: DENY` và `Content-Security-Policy: frame-ancestors 'none'`) — đây là chế độ bảo vệ nghiêm ngặt nhất trong hướng dẫn nhanh phía trên.

server {
    location / {
        add_header X-Frame-Options "DENY" always;
        add_header Content-Security-Policy "frame-ancestors 'none'" always;
    }
}
<IfModule mod_headers.c>
    Header always set X-Frame-Options "DENY"
    Header always set Content-Security-Policy "frame-ancestors 'none'"
</IfModule>
app.use((req, res, next) => {
  res.setHeader('X-Frame-Options', 'DENY');
  res.setHeader('Content-Security-Policy', "frame-ancestors 'none'");
  next();
});
// next.config.js
module.exports = {
  async headers() {
    return [
      {
        source: '/:path*',
        headers: [
          { key: 'X-Frame-Options', value: 'DENY' },
          { key: 'Content-Security-Policy', value: "frame-ancestors 'none'" },
        ],
      },
    ];
  },
};
class SetFrameOptions
{
    public function handle(Request $request, Closure $next): Response
    {
        $response = $next($request);
        $response->headers->set('X-Frame-Options', 'DENY');
        $response->headers->set('Content-Security-Policy', "frame-ancestors 'none'");

        return $response;
    }
}
export default {
  async fetch(request) {
    const response = await fetch(request);
    const headers = new Headers(response.headers);
    headers.set('X-Frame-Options', 'DENY');
    headers.set('Content-Security-Policy', "frame-ancestors 'none'");
    return new Response(response.body, { status: response.status, headers });
  },
};

Bạn chỉ cần cho phép trang web của mình hoặc một danh sách nguồn gốc hạn chế được nhúng vào, thay vì chặn hoàn toàn? Chỉ cần thay `DENY` bằng `SAMEORIGIN`, `'none'` bằng `'self'` hoặc danh sách nguồn gốc cụ thể — các cấu hình khác vẫn giữ nguyên.

Lưu ý quan trọng về các nền tảng

Ngoài các quy tắc chung về header, một số nền tảng lớn lại có những đặc thù riêng — rất đáng để tìm hiểu trước khi chỉ dựa vào tiêu đề HTTP để mặc định cho rằng tài nguyên bị "chặn" hay "có thể nhúng".

Nền tảng / Trường hợp Cách xử lý Lý do
Trang xem video YouTube (youtube.com/watch) Bị chặn Thay thế bằng URL trình embed chính thức của youtube.com/embed/{id} — trang xem thông thường luôn trả về chính sách dựng iframe rất nghiêm ngặt.
Trang địa điểm trên Google Maps Bị chặn Chỉ URL iframe của Google Maps Embed API (google.com/maps/embed) mới thực sự được thiết kế để nhúng.
Trang đăng nhập OAuth của Google / Microsoft Bị chặn Chủ động bị chặn từ năm 2015 nhằm ngăn lừa đảo đánh cắp thông tin đăng nhập (credential phishing) xảy ra trong iframe; quy trình đăng nhập bắt buộc phải chạy trên cửa sổ gốc hoặc popup.
Trang thanh toán / Checkout (Stripe Checkout, PayPal, hầu hết cổng ngân hàng) Bị chặn Việc đặt form thanh toán trong iframe là kênh tấn công clickjacking kinh điển, nên các nhà xử lý thanh toán đều từ chối ngay lập tức.
Trang kho lưu trữ / tệp tin trên GitHub Bị chặn Toàn site đều cấu hình frame-ancestors 'none'; nên dùng REST/GraphQL API hoặc chụp màn hình thay vì nhúng iframe.
Trang dạng "Publish to web" của Notion / Google Docs Có thể nhúng Được thiết kế sẵn để nhúng, sản phẩm cung cấp sẵn mã nhúng (embed code) tích hợp.
Bài viết Wikipedia Có thể nhúng Mặc định không có X-Frame-Options/CSP nghiêm ngặt, nhưng hãy kiểm tra kỹ giấy phép và điều kiện ghi nhận trước khi triển khai nhúng số lượng lớn.

Các trường hợp sử dụng phổ biến

  • Xác định xem widget, bảng điều khiển (dashboard) hoặc tài liệu bên thứ ba có thể nhúng vào sản phẩm của bạn hay không trước khi bắt đầu viết mã tích hợp.
  • Xác minh rằng site của bạn đang gửi chính sách X-Frame-Options hoặc CSP frame-ancestors đúng như mong muốn.
  • Gỡ lỗi cơ chế bảo vệ chống clickjacking: tìm hiểu lý do tại sao một trang hiển thị about:blank hoặc thông báo từ chối khi được đặt trong iframe.
  • Kiểm tra hàng loạt các URL ứng viên trong quá trình tổng hợp nội dung hoặc tích hợp cổng thông tin, đồng thời dùng lịch sử phiên để truy vết và xem lại kết quả.
  • Chuẩn bị cho đợt rà soát bảo mật hoặc kiểm thử xâm nhập bằng cách ghi nhận chính sách nhúng khung (framing policy) của các thành phần bên thứ ba.

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

Tại sao trang được hệ thống báo là "Có thể nhúng" nhưng vẫn hiển thị trống trong bản xem trước?
Header phản hồi cho phép nhúng, nhưng trang thực tế có thể chứa mã JavaScript chặn khung (frame-busting), yêu cầu đăng nhập hoặc cookie, hoặc trả về nội dung khác tùy thuộc vào người dùng. Hãy luôn tin tưởng kết quả trong bản xem trước.
Tôi có thể bỏ qua X-Frame-Options hay CSP không?
Không. Các header này do trình duyệt cưỡng chế thực thi nhằm đảm bảo bảo mật (chống clickjacking); các giải pháp thay thế phía client không đáng tin cậy. Để nhúng nội dung từ bên thứ ba, hãy yêu cầu chủ sở hữu trang web đưa origin của bạn vào danh sách cho phép trong tham số frame-ancestors, hoặc sử dụng giải pháp nhúng/API chính thức mà họ cung cấp.
Sự khác biệt giữa DENY và SAMEORIGIN là gì?
DENY sẽ chặn hoàn toàn việc nhúng trang đó trong bất kỳ iframe nào, kể cả từ trang cùng miền; SAMEORIGIN chỉ cho phép nhúng bởi các trang cùng lược đồ, tên miền và cổng.
Công cụ kiểm tra có lưu trữ các URL của tôi không?
Lịch sử chỉ được lưu cục bộ trên tab trình duyệt của bạn thông qua sessionStorage và sẽ tự động xóa khi bạn đóng tab đó. Máy chủ kiểm tra chỉ thực hiện truy xuất URL bạn nhập để đọc header phản hồi.
Tại sao cùng một URL lại trả về kết quả khác nhau ở các thời điểm khác nhau?
Một số trang web có thể trả về header khác nhau tùy theo đường dẫn, sau khi chuyển hướng, theo User-Agent, hoặc dựa trên thử nghiệm A/B và quy tắc WAF. Bạn vui lòng chạy lại kiểm tra để cập nhật kết quả mới nhất.