What is clickjacking?

Clickjacking (UI redressing) is an attack where a malicious site embeds your application inside a hidden or transparent <iframe> and tricks users into clicking buttons or links without realizing it.

Example scenario:

To prevent this, we must restrict how (or if) our pages can be embedded in iframes.

Defense Mechanisms in ASP.NET Core

ASP.NET Core supports two main methods for clickjacking protection:

  1. X-Frame-Options header (older but widely supported).

  2. Content Security Policy (CSP) with frame-ancestors directive (modern replacement).

It’s best to use CSP frame-ancestors, but including both ensures compatibility with legacy browsers.

1. Using X-Frame-Options

The X-Frame-Options header tells the browser whether a page can be displayed in a <frame>, <iframe>, or <object>.

Options

Example in ASP.NET Core middleware (Program.cs)

app.Use(async (context, next) =>
{
    context.Response.Headers.Add("X-Frame-Options", "SAMEORIGIN");
    await next();
});

2. Using CSP frame-ancestors

CSP provides a more flexible and modern way to control embedding.

Example policy

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

This means:

ASP.NET Core middleware

app.Use(async (context, next) =>
{
    context.Response.Headers.Add("Content-Security-Policy",
        "default-src 'self'; frame-ancestors 'self' https://trustedpartner.com");
    await next();
});

3. Using NWebsec (Recommended)

Instead of writing headers manually, use NWebsec middleware, which integrates well with ASP.NET Core.

Install

dotnet add package NWebsec.AspNetCore.Middleware

Configure in Program.cs

app.UseXfo(options => options.SameOrigin()); // X-Frame-Options: SAMEORIGIN

app.UseCsp(options => options
    .FrameAncestors(s => s.Self().CustomSources("https://trustedpartner.com"))
);

This ensures both X-Frame-Options and CSP frame-ancestors are active.

4. When to Allow Framing

In some cases, you may intentionally allow embedding, such as:

In such cases:

Example for allowing only your own site:

app.UseCsp(options => options.FrameAncestors(s => s.Self()));

5. Testing Clickjacking Protection

You can test protections by trying to embed your site in an <iframe>:

<iframe src="https://yoursite.com" width="600" height="400"></iframe>

If protections are correctly set, the page will not render inside the frame. Instead, you’ll see a blank page or a browser error in the developer console.

Best Practices

Conclusion

Clickjacking attacks exploit iframes to trick users into unintended actions. ASP.NET Core apps can defend against this by setting X-Frame-Options and CSP frame-ancestors headers. Using libraries like NWebsec makes implementation easier and more robust. By combining these protections, you ensure your Razor Pages or MVC applications cannot be maliciously embedded and abused.