Clickjacking (UI Redressing) , saldırganın, bir web sayfasını şeffaf veya görünmez bir katman (iframe) içinde kullanıcıya göstererek, kullanıcının farkında olmadan başka bir site üzerinde işlem yapmasını sağladığı bir saldırı tekniğidir. Kullanıcı, görünürdeki butona tıkladığını sanarken, aslında gizli katmandaki butona tıklar.
Clickjacking Nasıl Çalışır?
Clickjacking saldırısı 3 temel adımdan oluşur:
Saldırgan hedef siteyi bir iframe içine yerleştirir.
iframe'i şeffaf veya görünmez yapar (opacity: 0).
Kullanıcıyı, görünürdeki butona tıklamaya yönlendirir; aslında iframe'deki butona tıklar.
Örnek Senaryo:
Bir banka sitesinde "100 TL Gönder" butonu var. Saldırgan şu sayfayı oluşturur:
html
<!DOCTYPE html>
<html>
<head>
<style>
#target-site {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0.01; /* Neredeyse görünmez */
z-index: 2;
}
#fake-button {
position: absolute;
top: 400px;
left: 400px;
z-index: 1;
}
</style>
</head>
<body>
<button id="fake-button">🎁 Hediye Kazan!</button>
<iframe id="target-site" src="https://banka.com/transfer"></iframe>
</body>
</html>
Kullanıcı "Hediye Kazan!" butonuna tıkladığında, aslında banka sitesindeki "100 TL Gönder" butonuna tıklar.
Clickjacking Türleri:
1. Classic Clickjacking
Standart clickjacking saldırısı. Kullanıcı, görünürdeki butona tıklar, aslında gizli iframe'deki butona tıklar.
2. Cursorjacking
Saldırgan, kullanıcının imleç konumunu değiştirir.
Örnek:
javascript
document.addEventListener('mousemove', function(e) {
// İmleç konumunu gizlice değiştir
// Kullanıcı farklı bir yere tıklamış gibi göster
});
3. Likejacking
Sosyal medya beğeni butonlarının clickjacking ile manipüle edilmesi.
Örnek: Kullanıcı bir butona tıklar, aslında Facebook beğeni butonuna tıklar.
4. Filejacking
Kullanıcının dosya yükleme işlemlerinin manipüle edilmesi.
Örnek: Kullanıcı "Dosya Seç" butonuna tıklar, aslında gizli iframe'deki dosya yükleme butonuna tıklar.
5. DOM-based Clickjacking
JavaScript ile DOM manipülasyonu yaparak clickjacking.
Clickjacking Nasıl Tespit Edilir? (Test Teknikleri)
A. Manuel Keşif Teknikleri:
Sayfayı iframe içinde açmayı deneyin:
html
<iframe src="https://hedef.com" width="800" height="600"></iframe>
Sayfa iframe içinde açılıyorsa, clickjacking riski var.
Farklı iframe parametreleri deneyin:
html
<iframe src="https://hedef.com" sandbox="allow-scripts"></iframe>
<iframe src="https://hedef.com" allow="payment"></iframe>
Sayfanın X-Frame-Options header'ını kontrol edin:
bash
curl -I https://hedef.com | grep -i x-frame-options
CSP header'ını kontrol edin:
bash
curl -I https://hedef.com | grep -i content-security-policy
B. Otomatik Test Araçları:
Burp Suite: Clickjacking scanner
Nuclei: Clickjacking template'leri
OWASP ZAP: Clickjacking tarayıcısı
Clickjacking Koruma Teknikleri:
1. X-Frame-Options Header (Eski Ama Etkili)
En Basit ve En Etkili Yöntem:
http
X-Frame-Options: DENY
X-Frame-Options: SAMEORIGIN
X-Frame-Options: ALLOW-FROM https://hedef.com
Açıklamalar:
DENY: Hiçbir domainde iframe içinde gösterilmez.
SAMEORIGIN: Sadece aynı domain'de iframe içinde gösterilir.
ALLOW-FROM: Belirtilen domain'de iframe içinde gösterilir.
Web Sunucu Yapılandırması:
Apache:
apache
Header always append X-Frame-Options SAMEORIGIN
Nginx:
nginx
add_header X-Frame-Options "SAMEORIGIN" always;
IIS:
xml
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="X-Frame-Options" value="SAMEORIGIN" />
</customHeaders>
</httpProtocol>
</system.webServer>
2. Content-Security-Policy (Modern Yaklaşım)
Güncel ve Daha Esnek Yöntem:
http
Content-Security-Policy: frame-ancestors 'self'
Content-Security-Policy: frame-ancestors https://hedef.com
Content-Security-Policy: frame-ancestors 'none'
Açıklamalar:
'self': Sadece aynı domain'de iframe içinde gösterilir.
https://hedef.com: Belirtilen domain'de iframe içinde gösterilir.
'none': Hiçbir domainde iframe içinde gösterilmez.
Nginx Örneği:
nginx
add_header Content-Security-Policy "frame-ancestors 'self';" always;
Apache Örneği:
apache
Header always set Content-Security-Policy "frame-ancestors 'self';"
Not: CSP, X-Frame-Options'dan daha esnektir ve X-Frame-Options'ı geçersiz kılar (CSP daha önceliklidir).
3. JavaScript ile Koruma (Frame Busting)
Eski Yöntem (Halen Kullanılabilir):
javascript
// Sayfa iframe içindeyse, üst frame'e yönlendir
if (window.top !== window.self) {
window.top.location = window.self.location;
}
Gelişmiş Frame Busting:
javascript
// 1. İframe içinde olup olmadığını kontrol et
function isInIframe() {
try {
return window.self !== window.top;
} catch (e) {
return true; // Cross-origin erişim engellendi
}
}
// 2. Koruma
(function() {
// Önceki konumu kontrol et
var referrer = document.referrer;
if (referrer && !referrer.includes('hedef.com')) {
// Farklı bir domain'den geliyorsa risk
console.log('Clickjacking koruması aktif');
}
// 3. Frame içinde ise üst frame'i yönlendir
if (isInIframe()) {
try {
// Top frame'i yönlendir
window.top.location.href = window.location.href;
} catch (e) {
// Cross-origin erişim hatası
document.body.innerHTML = '<h1>Güvenlik Uyarısı</h1>';
}
}
})();
Modern Frame Busting (CSS):
css
/* İframe içinde olduğunda sayfayı gizle */
@supports (display: none) {
body:has(>
nly-child) {
display: none;
}
}
4. Python/Django Uygulaması
python
# middleware.py
class ClickjackingProtectionMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
# X-Frame-Options header'ını ekle
response['X-Frame-Options'] = 'SAMEORIGIN'
# CSP header'ını ekle
response['Content-Security-Policy'] = "frame-ancestors 'self';"
return response
# settings.py
MIDDLEWARE = [
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'myapp.middleware.ClickjackingProtectionMiddleware',
]
X_FRAME_OPTIONS = 'SAMEORIGIN'
5. Flask Uygulaması
python
from flask import Flask, Response
app = Flask(__name__)
@app.after_request
def add_security_headers(response):
# X-Frame-Options header'ı
response.headers['X-Frame-Options'] = 'SAMEORIGIN'
# CSP header'ı (frame-ancestors)
response.headers['Content-Security-Policy'] = "frame-ancestors 'self';"
return response
# Dekoratör ile belirli endpoint'ler için
@app.route('/sensitive')
def sensitive_page():
response = make_response(render_template('sensitive.html'))
response.headers['X-Frame-Options'] = 'DENY'
return response
6. Node.js/Express Uygulaması
javascript
const express = require('express');
const helmet = require('helmet');
const app = express();
// Helmet middleware (X-Frame-Options ve CSP ekler)
app.use(helmet());
// Veya manuel
app.use((req, res, next) => {
res.setHeader('X-Frame-Options', 'SAMEORIGIN');
res.setHeader('Content-Security-Policy', "frame-ancestors 'self';");
next();
});
// Belirli route'lar için
app.get('/sensitive', (req, res) => {
res.setHeader('X-Frame-Options', 'DENY');
res.send('Sensitive page');
});
Clickjacking Koruması Kontrol Listesi:
A. Header Yapılandırması:
X-Frame-Options header'ı var mı?
DENY veya SAMEORIGIN?
Content-Security-Policy header'ı var mı?
frame-ancestors direktifi doğru yapılandırılmış mı?
B. Web Sunucu Yapılandırması:
Nginx/Apache/IIS doğru yapılandırılmış mı?
Tüm sayfalarda header'lar dönüyor mu?
Statik dosyalar için de header'lar dönüyor mu?
C. Uygulama Seviyesi:
Frame busting JavaScript kullanılıyor mu?
Özellikle hassas sayfalar (login, transfer, profil) korunuyor mu?
D. Test:
Sayfa iframe içinde açılabiliyor mu?
Farklı domain'lerden test edildi mi?
CSP header'ı test edildi mi?
Özel Senaryolar:
1. Üçüncü Parti Widget'lar
Eğer widget'larınızı başka sitelerde göstermeniz gerekiyorsa:
http
X-Frame-Options: ALLOW-FROM https://partner-site.com
Content-Security-Policy: frame-ancestors https://partner-site.com
2. OAuth ve OpenID Connect
OAuth provider'ları için clickjacking koruması kritiktir:
http
X-Frame-Options: DENY
Content-Security-Policy: frame-ancestors 'none'
3. İçerik Yönetim Sistemleri (CMS)
WordPress:
php
// functions.php
add_action('send_headers', function() {
header('X-Frame-Options: SAMEORIGIN');
header('Content-Security-Policy: frame-ancestors \'self\';');
});
Drupal:
php
// settings.php
$config['system.logging']['error_level'] = 'hide';
$config['security.x_frame_options'] = 'SAMEORIGIN';
4. API ve Backend
API endpoint'leri genellikle iframe içinde gösterilmez, ancak yine de header'ları ekleyin:
http
X-Frame-Options: DENY
Content-Security-Policy: frame-ancestors 'none'
X-Frame-Options vs CSP (Karşılaştırma):
Özellik X-Frame-Options CSP frame-ancestors
Destek Eski tarayıcılar Modern tarayıcılar
Esneklik Sınırlı (3 seçenek) Yüksek (çoklu domain, wildcard)
Çoklu domain ALLOW-FROM (sınırlı) Birden fazla domain
Wildcard Hayır Evet
Geçersiz kılma CSP tarafından X-Frame-Options'ı geçersiz kılar
Öneri: Her iki header'ı da kullanın (hem eski hem modern tarayıcılar için).
Clickjacking Nasıl Çalışır?
Clickjacking saldırısı 3 temel adımdan oluşur:
Saldırgan hedef siteyi bir iframe içine yerleştirir.
iframe'i şeffaf veya görünmez yapar (opacity: 0).
Kullanıcıyı, görünürdeki butona tıklamaya yönlendirir; aslında iframe'deki butona tıklar.
Örnek Senaryo:
Bir banka sitesinde "100 TL Gönder" butonu var. Saldırgan şu sayfayı oluşturur:
html
<!DOCTYPE html>
<html>
<head>
<style>
#target-site {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0.01; /* Neredeyse görünmez */
z-index: 2;
}
#fake-button {
position: absolute;
top: 400px;
left: 400px;
z-index: 1;
}
</style>
</head>
<body>
<button id="fake-button">🎁 Hediye Kazan!</button>
<iframe id="target-site" src="https://banka.com/transfer"></iframe>
</body>
</html>
Kullanıcı "Hediye Kazan!" butonuna tıkladığında, aslında banka sitesindeki "100 TL Gönder" butonuna tıklar.
Clickjacking Türleri:
1. Classic Clickjacking
Standart clickjacking saldırısı. Kullanıcı, görünürdeki butona tıklar, aslında gizli iframe'deki butona tıklar.
2. Cursorjacking
Saldırgan, kullanıcının imleç konumunu değiştirir.
Örnek:
javascript
document.addEventListener('mousemove', function(e) {
// İmleç konumunu gizlice değiştir
// Kullanıcı farklı bir yere tıklamış gibi göster
});
3. Likejacking
Sosyal medya beğeni butonlarının clickjacking ile manipüle edilmesi.
Örnek: Kullanıcı bir butona tıklar, aslında Facebook beğeni butonuna tıklar.
4. Filejacking
Kullanıcının dosya yükleme işlemlerinin manipüle edilmesi.
Örnek: Kullanıcı "Dosya Seç" butonuna tıklar, aslında gizli iframe'deki dosya yükleme butonuna tıklar.
5. DOM-based Clickjacking
JavaScript ile DOM manipülasyonu yaparak clickjacking.
Clickjacking Nasıl Tespit Edilir? (Test Teknikleri)
A. Manuel Keşif Teknikleri:
Sayfayı iframe içinde açmayı deneyin:
html
<iframe src="https://hedef.com" width="800" height="600"></iframe>
Sayfa iframe içinde açılıyorsa, clickjacking riski var.
Farklı iframe parametreleri deneyin:
html
<iframe src="https://hedef.com" sandbox="allow-scripts"></iframe>
<iframe src="https://hedef.com" allow="payment"></iframe>
Sayfanın X-Frame-Options header'ını kontrol edin:
bash
curl -I https://hedef.com | grep -i x-frame-options
CSP header'ını kontrol edin:
bash
curl -I https://hedef.com | grep -i content-security-policy
B. Otomatik Test Araçları:
Burp Suite: Clickjacking scanner
Nuclei: Clickjacking template'leri
OWASP ZAP: Clickjacking tarayıcısı
Clickjacking Koruma Teknikleri:
1. X-Frame-Options Header (Eski Ama Etkili)
En Basit ve En Etkili Yöntem:
http
X-Frame-Options: DENY
X-Frame-Options: SAMEORIGIN
X-Frame-Options: ALLOW-FROM https://hedef.com
Açıklamalar:
DENY: Hiçbir domainde iframe içinde gösterilmez.
SAMEORIGIN: Sadece aynı domain'de iframe içinde gösterilir.
ALLOW-FROM: Belirtilen domain'de iframe içinde gösterilir.
Web Sunucu Yapılandırması:
Apache:
apache
Header always append X-Frame-Options SAMEORIGIN
Nginx:
nginx
add_header X-Frame-Options "SAMEORIGIN" always;
IIS:
xml
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="X-Frame-Options" value="SAMEORIGIN" />
</customHeaders>
</httpProtocol>
</system.webServer>
2. Content-Security-Policy (Modern Yaklaşım)
Güncel ve Daha Esnek Yöntem:
http
Content-Security-Policy: frame-ancestors 'self'
Content-Security-Policy: frame-ancestors https://hedef.com
Content-Security-Policy: frame-ancestors 'none'
Açıklamalar:
'self': Sadece aynı domain'de iframe içinde gösterilir.
https://hedef.com: Belirtilen domain'de iframe içinde gösterilir.
'none': Hiçbir domainde iframe içinde gösterilmez.
Nginx Örneği:
nginx
add_header Content-Security-Policy "frame-ancestors 'self';" always;
Apache Örneği:
apache
Header always set Content-Security-Policy "frame-ancestors 'self';"
Not: CSP, X-Frame-Options'dan daha esnektir ve X-Frame-Options'ı geçersiz kılar (CSP daha önceliklidir).
3. JavaScript ile Koruma (Frame Busting)
Eski Yöntem (Halen Kullanılabilir):
javascript
// Sayfa iframe içindeyse, üst frame'e yönlendir
if (window.top !== window.self) {
window.top.location = window.self.location;
}
Gelişmiş Frame Busting:
javascript
// 1. İframe içinde olup olmadığını kontrol et
function isInIframe() {
try {
return window.self !== window.top;
} catch (e) {
return true; // Cross-origin erişim engellendi
}
}
// 2. Koruma
(function() {
// Önceki konumu kontrol et
var referrer = document.referrer;
if (referrer && !referrer.includes('hedef.com')) {
// Farklı bir domain'den geliyorsa risk
console.log('Clickjacking koruması aktif');
}
// 3. Frame içinde ise üst frame'i yönlendir
if (isInIframe()) {
try {
// Top frame'i yönlendir
window.top.location.href = window.location.href;
} catch (e) {
// Cross-origin erişim hatası
document.body.innerHTML = '<h1>Güvenlik Uyarısı</h1>';
}
}
})();
Modern Frame Busting (CSS):
css
/* İframe içinde olduğunda sayfayı gizle */
@supports (display: none) {
body:has(>
display: none;
}
}
4. Python/Django Uygulaması
python
# middleware.py
class ClickjackingProtectionMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
# X-Frame-Options header'ını ekle
response['X-Frame-Options'] = 'SAMEORIGIN'
# CSP header'ını ekle
response['Content-Security-Policy'] = "frame-ancestors 'self';"
return response
# settings.py
MIDDLEWARE = [
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'myapp.middleware.ClickjackingProtectionMiddleware',
]
X_FRAME_OPTIONS = 'SAMEORIGIN'
5. Flask Uygulaması
python
from flask import Flask, Response
app = Flask(__name__)
@app.after_request
def add_security_headers(response):
# X-Frame-Options header'ı
response.headers['X-Frame-Options'] = 'SAMEORIGIN'
# CSP header'ı (frame-ancestors)
response.headers['Content-Security-Policy'] = "frame-ancestors 'self';"
return response
# Dekoratör ile belirli endpoint'ler için
@app.route('/sensitive')
def sensitive_page():
response = make_response(render_template('sensitive.html'))
response.headers['X-Frame-Options'] = 'DENY'
return response
6. Node.js/Express Uygulaması
javascript
const express = require('express');
const helmet = require('helmet');
const app = express();
// Helmet middleware (X-Frame-Options ve CSP ekler)
app.use(helmet());
// Veya manuel
app.use((req, res, next) => {
res.setHeader('X-Frame-Options', 'SAMEORIGIN');
res.setHeader('Content-Security-Policy', "frame-ancestors 'self';");
next();
});
// Belirli route'lar için
app.get('/sensitive', (req, res) => {
res.setHeader('X-Frame-Options', 'DENY');
res.send('Sensitive page');
});
Clickjacking Koruması Kontrol Listesi:
A. Header Yapılandırması:
X-Frame-Options header'ı var mı?
DENY veya SAMEORIGIN?
Content-Security-Policy header'ı var mı?
frame-ancestors direktifi doğru yapılandırılmış mı?
B. Web Sunucu Yapılandırması:
Nginx/Apache/IIS doğru yapılandırılmış mı?
Tüm sayfalarda header'lar dönüyor mu?
Statik dosyalar için de header'lar dönüyor mu?
C. Uygulama Seviyesi:
Frame busting JavaScript kullanılıyor mu?
Özellikle hassas sayfalar (login, transfer, profil) korunuyor mu?
D. Test:
Sayfa iframe içinde açılabiliyor mu?
Farklı domain'lerden test edildi mi?
CSP header'ı test edildi mi?
Özel Senaryolar:
1. Üçüncü Parti Widget'lar
Eğer widget'larınızı başka sitelerde göstermeniz gerekiyorsa:
http
X-Frame-Options: ALLOW-FROM https://partner-site.com
Content-Security-Policy: frame-ancestors https://partner-site.com
2. OAuth ve OpenID Connect
OAuth provider'ları için clickjacking koruması kritiktir:
http
X-Frame-Options: DENY
Content-Security-Policy: frame-ancestors 'none'
3. İçerik Yönetim Sistemleri (CMS)
WordPress:
php
// functions.php
add_action('send_headers', function() {
header('X-Frame-Options: SAMEORIGIN');
header('Content-Security-Policy: frame-ancestors \'self\';');
});
Drupal:
php
// settings.php
$config['system.logging']['error_level'] = 'hide';
$config['security.x_frame_options'] = 'SAMEORIGIN';
4. API ve Backend
API endpoint'leri genellikle iframe içinde gösterilmez, ancak yine de header'ları ekleyin:
http
X-Frame-Options: DENY
Content-Security-Policy: frame-ancestors 'none'
X-Frame-Options vs CSP (Karşılaştırma):
Özellik X-Frame-Options CSP frame-ancestors
Destek Eski tarayıcılar Modern tarayıcılar
Esneklik Sınırlı (3 seçenek) Yüksek (çoklu domain, wildcard)
Çoklu domain ALLOW-FROM (sınırlı) Birden fazla domain
Wildcard Hayır Evet
Geçersiz kılma CSP tarafından X-Frame-Options'ı geçersiz kılar
Öneri: Her iki header'ı da kullanın (hem eski hem modern tarayıcılar için).
🔒 Bu içeriği görmek için giriş yapın