Clickjacking in Strapi with Basic Auth
Clickjacking in Strapi with Basic Auth — how this specific combination creates or exposes the vulnerability
Clickjacking is a client-side attack where an attacker tricks a user into clicking or submitting actions on a hidden or disguised UI element. When Strapi is configured with Basic Authentication and its admin panel or custom API endpoints are embedded inside an iframe on a malicious site, the combination can expose interactive interfaces to clickjacking. Basic Auth typically relies on browser-managed credential prompts or request headers; however, if Strapi’s admin UI is accessible within an embedded frame, the attacker can overlay invisible or misleading controls on top of the authenticated session.
In this scenario, the victim is already authenticated to Strapi (via browser-stored Basic Auth credentials or a session established after initial authentication). The attacker crafts a page that loads the Strapi admin panel inside an iframe and styles it to appear as a benign element, such as a button or video play control. When the user interacts with the visible element, they inadvertently perform privileged actions inside the iframe, such as creating content types, modifying permissions, or invoking custom API routes that rely on the same Basic Auth context.
Because Strapi’s unauthenticated attack surface can be probed by a scanner like middleBrick—which runs 12 parallel security checks including Authentication and BFLA/Privilege Escalation—the presence of exposed admin interfaces accessible without additional UI boundaries becomes a detectable finding. Even though Basic Auth protects the endpoint with a credential challenge, it does not prevent the UI from being framed; thus the risk is not in credential theft via interception but in unauthorized action execution through user interaction within a malicious frame.
Basic Auth-Specific Remediation in Strapi — concrete code fixes
To mitigate clickjacking when using Basic Auth in Strapi, you should prevent the admin panel and sensitive API responses from being embedded in iframes. Strapi does not provide built-in anti-clickjacking headers for the admin panel out of the box, so you must configure your web server or reverse proxy to set appropriate HTTP headers. Below are examples for common setups, followed by Strapi configuration snippets that demonstrate how to enforce secure embedding policies.
Web server or reverse proxy configuration examples
- Nginx: Add the
X-Frame-OptionsandContent-Security-Policyheaders to your server block serving Strapi.
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://127.0.0.1:1337;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
# Anti-clickjacking headers
add_header X-Frame-Options "DENY" always;
add_header Content-Security-Policy "frame-ancestors 'none';" always;
}
}
Header directives in your virtual host configuration.<VirtualHost *:80>
ProxyPass / http://127.0.0.1:1337/
ProxyPassReverse / http://1337/
Header always set X-Frame-Options "DENY"
Header always set Content-Security-Policy "frame-ancestors 'none'"
</VirtualHost>
Strapi admin URL control
Restrict access to the Strapi admin panel by configuring allowed hosts. In ./config/admin.js, set host and ensure the admin is not unintentionally exposed to public embedding contexts.
/** @type { import('@strapi/strapi').AdminConfig } */
module.exports = {
host: '127.0.0.1',
port: 8080,
admin: {
path: '/admin',
host: '127.0.0.1',
port: 8081,
},
};
Basic Auth examples for Strapi proxy authentication
While Strapi itself does not enforce Basic Auth by default for the admin panel, you can enforce it at the proxy layer. Below are example configurations that combine Basic Auth with anti-clickjacking headers to ensure that authenticated sessions cannot be framed by untrusted origins.
Nginx with Basic Auth and CSP framing rules
server {
listen 80;
server_name api.example.com;
auth_basic "Restricted Access";
auth_basic_user_file /etc/nginx/htpasswd;
location / {
proxy_pass http://127.0.0.1:1337;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
add_header X-Frame-Options "DENY" always;
add_header Content-Security-Policy "frame-ancestors 'none';" always;
}
}
Apache with Basic Auth and frame protections
<VirtualHost *:80>
ProxyPass / http://127.0.0.1:1337/
ProxyPassReverse / http://1337/
AuthType Basic
AuthName "Restricted Area"
AuthUserFile /etc/apache2/.htpasswd
Require valid-user
Header always set X-Frame-Options "DENY"
Header always set Content-Security-Policy "frame-ancestors 'none'"
</VirtualHost>
Validation and testing
After applying these configurations, use an HTTP client or browser developer tools to confirm that X-Frame-Options and Content-Security-Policy headers are present and correct. You can also run an automated scan with middleBrick to verify that the authentication setup is exposed appropriately and that no unintended framing rules remain.