Clickjacking with Api Keys
How Clickjacking Manifests in Api Keys
Clickjacking attacks against API keys exploit the same-origin policy weaknesses to trick users into unintentionally exposing their credentials. In API contexts, this typically manifests when developers embed API keys in client-side applications or expose key management interfaces through web applications that can be framed.
The most common attack pattern involves creating a malicious website that loads a legitimate API key management page inside an invisible iframe. The attacker then overlays transparent elements on top of the iframe, tricking users into clicking buttons that reveal, copy, or regenerate API keys without their knowledge. This is particularly dangerous when API keys are displayed in plain text or when key regeneration buttons are accessible without additional authentication.
Consider this vulnerable implementation:
<!-- Vulnerable API key display page -->
<div class="api-key-display">
<h2>Your API Key</h2>
<p id="key-display">sk-1234567890abcdef</p>
<button onclick="copyKey()">Copy Key</button>
</div>An attacker could create a page that loads this interface in an iframe and overlays a button that, when clicked, triggers the copyKey() function, stealing the API key. The user believes they're clicking a legitimate button on the attacker's site, but they're actually interacting with the hidden API key management interface.
Another variant involves API documentation sites that display example API keys or code snippets containing keys. Attackers can frame these documentation pages and use CSS to highlight and copy key examples, which users might then paste into their own applications without realizing the keys were stolen.
API key regeneration interfaces are especially vulnerable. If a key management page allows regenerating keys through simple button clicks, an attacker can frame the page and programmatically trigger regeneration, potentially locking out legitimate users while capturing the new keys.
Api Keys-Specific Detection
Detecting clickjacking vulnerabilities in API key contexts requires both automated scanning and manual verification. middleBrick's black-box scanning approach tests for these vulnerabilities without requiring credentials or access to source code.
middleBrick performs several specific checks for API key clickjacking:
- X-Frame-Options header verification - ensuring the API key management interface isn't frameable
- Content-Security-Policy frame-ancestors directive analysis - checking for proper framing restrictions
- Interactive element testing - attempting to trigger key-related actions through framed interfaces
- API documentation analysis - scanning for exposed keys in documentation endpoints
- Key regeneration endpoint testing - verifying that key regeneration requires additional authentication
Here's an example of what middleBrick detects:
middlebrick scan https://api.example.com/key-management
=== Clickjacking Detection ===
[X] X-Frame-Options header missing
[X] Content-Security-Policy missing frame-ancestors restriction
[X] API key display page is frameable
[X] Key regeneration endpoint accessible without additional auth
[X] API documentation exposes example keys in plain text
Risk Score: D (Vulnerability allows key theft through framing)For manual verification, developers should test their API key interfaces using the following techniques:
// Test if page can be framed
const iframe = document.createElement('iframe');
iframe.src = 'https://your-api.com/key-management';
document.body.appendChild(iframe);
// Check if interactive elements work
// Try to trigger copyKey() or regenerateKey() functions
// Verify if API keys are visible in the framed contentmiddleBrick also scans OpenAPI specifications for endpoints that might expose API keys and checks if those endpoints have proper clickjacking protections. This includes analyzing the spec's security definitions and ensuring that key management operations aren't exposed through unsecured web interfaces.
Api Keys-Specific Remediation
Securing API keys against clickjacking requires implementing multiple defense layers. The most effective approach combines HTTP header protections with architectural changes to how API keys are managed and displayed.
Implement proper framing protection using HTTP headers:
// For modern browsers (recommended)
Content-Security-Policy: frame-ancestors 'none'
// For older browser support (fallback)
X-Frame-Options: DENY
// For specific trusted origins (if framing is required)
X-Frame-Options: ALLOW-FROM https://trusted.example.comModify API key management interfaces to prevent key exposure:
// Instead of displaying keys in plain text
function displayApiKey() {
const maskedKey = key.replace(/./g, '*');
document.getElementById('key-display').textContent = maskedKey;
// Show only last 4 characters on hover with confirmation
const showButton = document.createElement('button');
showButton.textContent = 'Show Last 4';
showButton.onclick = () => {
if (confirm('This will temporarily reveal part of your API key')) {
document.getElementById('key-display').textContent =
maskedKey.slice(0, -4) + key.slice(-4);
}
};
}Implement additional authentication for key operations:
// Require re-authentication for sensitive operations
async function regenerateKey() {
const currentAuth = await getCurrentUserAuth();
if (!currentAuth || !currentAuth.hasRecentAuth) {
throw new Error('Re-authentication required for key regeneration');
}
// Additional confirmation step
if (!confirm('Regenerating your API key will invalidate existing integrations. Continue?')) {
return;
}
// Proceed with regeneration only after confirmation
return api.regenerateKey(currentAuth.token);
}Secure API documentation by using placeholder keys:
// Instead of real example keys
const exampleKey = 'sk-0000000000000000000'; // All zeros
// Or use environment-specific keys
const exampleKey = process.env.EXAMPLE_API_KEY || 'sk-test-1234567890';For applications that must display API keys (like developer dashboards), implement time-based visibility:
class SecureKeyDisplay {
constructor() {
this.visibleUntil = 0;
this.maskKey();
}
showKey() {
if (Date.now() < this.visibleUntil) return;
// Show key for 10 seconds
this.visibleUntil = Date.now() + 10000;
this.unmaskKey();
// Auto-mask after timeout
setTimeout(() => this.maskKey(), 10000);
}
maskKey() {
const key = this.getKey();
const masked = key.replace(/./g, '*');
this.updateDisplay(masked);
}
}middleBrick's Pro plan includes continuous monitoring that can alert you when clickjacking protections are removed or when API key management interfaces become accessible through framing. This helps maintain security as your API evolves.