HIGH clickjackinglaravel

Clickjacking in Laravel

How Clickjacking Manifests in Laravel

Clickjacking in Laravel applications typically occurs when developers fail to implement proper frame-busting mechanisms or rely on outdated security headers. Laravel's default configurations don't automatically protect against clickjacking, making this a common vulnerability in Laravel applications.

The most prevalent attack pattern involves embedding a Laravel application within an iframe on a malicious site. Attackers create seemingly innocuous pages that load the target Laravel application in a hidden iframe, then overlay deceptive UI elements that trick users into clicking buttons or links they can't see. For example, an attacker might create a game where users think they're clicking on a button to earn points, but they're actually interacting with a Laravel admin panel's 'Delete User' button.

Laravel applications are particularly vulnerable when they handle sensitive operations like:

  • Admin panel functions (user management, content moderation)
  • Financial transactions (payment processing, fund transfers)
  • Account modifications (password changes, email updates)
  • System configuration changes

Common Laravel-specific scenarios include:

// Vulnerable: No frame protection
Route::post('/admin/delete-user', [AdminController::class, 'deleteUser']);
Route::post('/transfer-funds', [PaymentController::class, 'transfer']);
Route::post('/update-profile', [ProfileController::class, 'update']);

Even when using Laravel's CSRF protection, clickjacking can bypass these defenses because the malicious site can still submit the hidden form. The attack succeeds because users believe they're interacting with the attacker's page, not your Laravel application.

Laravel-Specific Detection

Detecting clickjacking in Laravel applications requires examining both the application code and HTTP response headers. Start by checking your Laravel application's HTTP responses for the X-Frame-Options header and Content-Security-Policy frame-ancestors directive.

// Check headers using curl
curl -I https://your-laravel-app.com
// Look for:
// X-Frame-Options: DENY or SAMEORIGIN
// Content-Security-Policy: frame-ancestors 'none' or 'self'

In Laravel, you can inspect middleware to see if frame protection is implemented. Open app/Http/Middleware and look for any clickjacking protection middleware. Laravel doesn't include this by default, so you'll need to create it or use a package.

middleBrick's Laravel-specific scanning identifies clickjacking vulnerabilities by:

  • Checking for missing X-Frame-Options headers across all endpoints
  • Verifying Content-Security-Policy frame-ancestors directives
  • Testing if sensitive endpoints can be loaded in iframes
  • Analyzing route definitions for operations that shouldn't be frame-accessible
  • Checking for inline JavaScript that might interfere with frame-busting

The scanner runs in under 15 seconds and provides specific findings like:

Clickjacking Vulnerability Detected
Severity: High
Endpoint: POST /admin/delete-user
Issue: Missing X-Frame-Options header
Recommendation: Add frame protection middleware

For Laravel applications using packages like Laravel Fortify or Jetstream, ensure these packages' authentication routes aren't vulnerable to clickjacking, as they often handle sensitive operations like password resets and account modifications.

Laravel-Specific Remediation

Remediating clickjacking in Laravel applications involves multiple layers of protection. The most effective approach combines HTTP headers with Laravel middleware.

First, create a clickjacking protection middleware:

// app/Http/Middleware/FrameGuard.php
headers->set('X-Frame-Options', $guard === 'sameorigin' ? 'SAMEORIGIN' : 'DENY');
        
        // Set Content-Security-Policy header
        $csp = $guard === 'sameorigin' 
            ? "frame-ancestors 'self'"
            : "frame-ancestors 'none'";
        
        $response->headers->set('Content-Security-Policy', $csp);
        
        return $response;
    }
}

Register the middleware in app/Http/Kernel.php:

// Add to $middleware array for global protection
protected $middleware = [
    // ... existing middleware
    \App\Http\Middleware\FrameGuard::class,
];

For selective protection, add it to $routeMiddleware and apply it to specific routes:

// app/Http/Kernel.php
protected $routeMiddleware = [
    // ... existing middleware
    'frame-guard' => \App\Http\Middleware\FrameGuard::class,
];

Apply to sensitive routes:

// routes/web.php
Route::post('/admin/delete-user', [AdminController::class, 'deleteUser'])
    ->middleware('frame-guard:deny');

Route::post('/transfer-funds', [PaymentController::class, 'transfer'])
    ->middleware('frame-guard:deny');

Route::post('/update-profile', [ProfileController::class, 'update'])
    ->middleware('frame-guard:deny');

For Laravel applications that need to allow framing from specific domains (rare but possible for embedded dashboards), use:

Route::get('/dashboard', [DashboardController::class, 'show'])
    ->middleware('frame-guard:sameorigin');

middleBrick's CLI tool can verify your remediation:

npx middlebrick scan https://your-laravel-app.com/admin/delete-user
// Returns JSON with frame protection status
// Helps ensure your middleware is properly configured

After implementing these changes, use middleBrick's continuous monitoring to ensure your clickjacking protections remain effective as your Laravel application evolves.

Frequently Asked Questions

Does Laravel's default installation protect against clickjacking?
No, Laravel's default installation does not include any clickjacking protection. You must manually add middleware or configure headers to prevent your application from being framed by malicious sites.
Can clickjacking still work if I have CSRF protection enabled in Laravel?
Yes, clickjacking can bypass CSRF protection. While CSRF tokens prevent cross-site request forgery, clickjacking attacks trick users into willingly (but unknowingly) clicking buttons in your application. The malicious site can still submit the form with the correct CSRF token.