Daha Fazla
Seç

Dijital

Yazılım

Çözümleri

https://adbeardigital.com

WordPress Güvenlik Sertleştirme 2025: CSP, SRI, WAF ve Katmanlı Savunma Rehberi

Neden “şimdi”? Saldırı yüzeyleri büyüdü: eklenti tedarik zinciri, bot ağları, zayıf parola/2FA eksikliği, istek seli (rate limit), XML-RPC kötüye kullanımı, REST uçlarının yanlış konfigürasyonu… Ölçü birimi tek: ihlal sonrası değil,…

WordPress Güvenlik Sertleştirme 2025: CSP, SRI, WAF ve Katmanlı Savunma Rehberi

Neden “şimdi”?

Saldırı yüzeyleri büyüdü: eklenti tedarik zinciri, bot ağları, zayıf parola/2FA eksikliği, istek seli (rate limit), XML-RPC kötüye kullanımı, REST uçlarının yanlış konfigürasyonu… Ölçü birimi tek: ihlal sonrası değil, ihlal öncesi hazırlık. Bu rehber; WordPress (WP) projelerini CSP, SRI, güvenlik başlıkları, WAF ve en az ayrıcalık ilkeleriyle güçlendirmenin pratik yol haritasıdır.

1) Mimari & Güncelleme Disiplini

  • Çekirdek/eklenti/tema güncellemelerini minör sürümler için otomatik, majörler için kademeli/staging.
  • PHP 8.2+ / 8.3 kullan; EOL olmayan sürüm şart.
  • Eklenti/tema diyet: Kullanılmayanı kaldır; benzer işi yapan birden fazla eklentiyi tutma.
  • Tedarik zinciri: Yayıncı itibarı, commit aktivitesi, changelog düzenliliği, güvenlik duyuruları.

2) Kimlik & Erişim: Parola değil, Passkey/2FA

  • Passkeys (WebAuthn) ve/veya 2FA zorunlu: Özellikle administrator için.
  • Uygulama Parolaları (Application Passwords) yalnızca gerektiğinde ve kısıtlı süreyle.
  • En az ayrıcalık: Editör, Shop Manager vs. rolleri gerçekten ihtiyacı kadar yetkili.
  • IP/Ülke bazlı WAF kuralları: wp-login.php ve xmlrpc.php için hız limiti / ülke zorluğu.

3) wp-config.php Sertleştirme

// HTTPS
define('FORCE_SSL_ADMIN', true);

// Dosya düzenlemeyi kapat (Panel > Görünüm > Tema düzenleyici vb.)
define('DISALLOW_FILE_EDIT', true);

// (İsteğe bağlı) Panelden eklenti/tema yükleme/güncellemeyi kapat
// define('DISALLOW_FILE_MODS', true);

// Çekirdek minör otomatik güncellemeler açık kalsın
define('WP_AUTO_UPDATE_CORE', 'minor');

// Ortam etiketi (günlükleme/diagnostics için)
define('WP_ENVIRONMENT_TYPE', 'production');

// Güçlü AUTH KEYS & SALTS (her projede benzersiz!)
/*
define('AUTH_KEY','...'); // hepsi benzersiz olacak
...
*/

// Oturum/cookie ömrü ve güvenlik ayarlarını ihtiyaca göre sıkılaştır

Not: SALTS anahtarlarını mutlaka yenile; depoya koyma. wp-config.php mümkünse 600 izinleriyle korunmalı.

4) Sunucu Katmanı: Güvenlik Başlıkları (Headers) + HSTS + CSP

Önerilen başlıklar

  • Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
  • X-Content-Type-Options: nosniff
  • X-Frame-Options: SAMEORIGIN (veya CSP frame-ancestors)
  • Referrer-Policy: strict-origin-when-cross-origin
  • Permissions-Policy: camera=(), microphone=(), geolocation=()
  • Cross-Origin-Opener-Policy: same-origin
  • Cross-Origin-Resource-Policy: same-origin

CSP (Content-Security-Policy)

CSP, XSS’i etkin şekilde bastırır. Önce “Report-Only” yayınla, raporları topla, sonra enforce et.

Başlangıç şablonu (sert, ama gerçek hayata uyarlayın):

Content-Security-Policy:
  default-src 'self';
  script-src 'self' https://www.googletagmanager.com https://www.google-analytics.com 'unsafe-inline' 'unsafe-eval';
  style-src  'self' 'unsafe-inline' https:;
  img-src    'self' data: https:;
  font-src   'self' data: https:;
  connect-src 'self' https:;
  frame-src  https:;
  frame-ancestors 'self';
  base-uri 'self';

Gerçek kaynaklarınıza göre daraltın (CDN, ödeme iframe’leri, haritalar…). Önce Report-Only ile sahada test!

5) SRI (Subresource Integrity)

CDN’den çektiğiniz JS/CSS için SRI hash’leri kullanın.

// functions.php
wp_enqueue_script('alpine-cdn', 'https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js', [], null, true);

add_filter('script_loader_tag', function($tag, $handle, $src){
  if ($handle === 'alpine-cdn') {
    $integrity = 'sha384-XXXXXXXX'; // gerçek hash
    return sprintf('<script src="%s" integrity="%s" crossorigin="anonymous" defer></script>',
                   esc_url($src), esc_attr($integrity));
  }
  return $tag;
}, 10, 3);

Hash’i yayına çıkmadan üretip sabitleyin; dosya sürümü değişirse hash’i de güncelleyin.

6) Uygulama Katmanı: REST, XML-RPC, Nonce, Sanitization

XML-RPC’yi kapat veya sınırla:

# .htaccess
<Files "xmlrpc.php">
  Require all denied
</Files>

REST API’yi sınırlamak (kamuya kapatıp oturum açmışlara izin vermek) – Gutenberg/headless ihtiyacınıza göre uyarlayın:

add_filter('rest_authentication_errors', function($result){
  if (!empty($result)) return $result;
  if (is_user_logged_in()) return $result;
  return new WP_Error('rest_forbidden', 'REST API sadece oturumla kullanılabilir.', ['status' => 401]);
});

Kullanıcı enumerasyonunu engelle:

add_action('template_redirect', function(){
  if (is_author()) { wp_redirect(home_url(), 301); exit; }
});

Nonce + veri hijyeni: Form/endpoint’lerde nonce doğrula, girdileri sanitize_* ile temizle, çıktılayanı esc_* ile kaçıştır; SQL sorgularında $wpdb->prepare() kullan.

7) Dosya Sistemi & İzinler

  • Sahiplik/izinler: Klasörler 755, dosyalar 644, wp-config.php 600.
  • Uploads’ta PHP çalışmasın:
# wp-content/uploads/.htaccess
<FilesMatch "\.php$">
  Require all denied
</FilesMatch>
  • .git, .env, yedek .zip gibi hassas dosyaları public dizinde tutma.

8) WAF/CDN Katmanı (Cloudflare vb.)

  • wp-login.php ve xmlrpc.php için Rate Limiting.
  • Bot/Challenge kuralları (ülke/ASN/kaynak hesaplamalı).
  • Cache By-Pass: /wp-admin/, preview=true, ?s= aramaları.
  • Turnstile / hCaptcha gibi kullanıcı dostu korumalar.

9) İzleme, Loglama, Olay Müdahalesi

  • Giriş, yetki değişimi, eklenti/tema değişiklikleri için denetim günlükleri.
  • 404/5xx ani sıçramalarını uyarı eşiği ile yakala.
  • 3-2-1 yedek: 3 kopya, 2 farklı ortam, 1’i off-site; geri yükleme provası yap.

10) Hızlı Sorun Giderme (403/500/Bozulma Senaryoları)

  • 403: WAF/ModSecurity/izinler; wflogs, güvenlik eklentisi kilitleri; .htaccess son değişiklikleri.
  • Beyaz sayfa: WP_DEBUG_LOG ile hata kaydı; sorunlu eklentiyi plugins klasör adını değiştirerek izole et.
  • Admin-Ajax 0 döndürme: nonce/permission check; CORS, cache veya minify çakışması.

Sunucuya Göre Örnek Konfigürasyonlar

Apache (.htaccess) – Örnek paket

# Temel korumalar
<FilesMatch "^(wp-config\.php|\.htaccess)$">
  Require all denied
</FilesMatch>

# XML-RPC kapat
<Files "xmlrpc.php">
  Require all denied
</Files>

# Uploads'ta PHP yok
<Directory "/path/to/wp-content/uploads">
  <FilesMatch "\.php$">
    Require all denied
  </FilesMatch>
</Directory>

# Güvenlik başlıkları (CSP'yi önce Report-Only yayına alın)
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()"
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
# Header always set Content-Security-Policy-Report-Only "default-src 'self'; img-src 'self' data: https:; style-src 'self' 'unsafe-inline' https:; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://www.googletagmanager.com https://www.google-analytics.com; font-src 'self' data: https:; connect-src 'self' https:; frame-ancestors 'self'; frame-src https:; base-uri 'self'"

Nginx – Örnek paket

# XML-RPC kapat
location = /xmlrpc.php { return 403; }

# Uploads'ta PHP engeli
location ~* ^/wp-content/uploads/.*\.php$ { deny all; }

# Güvenlik başlıkları
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# add_header Content-Security-Policy-Report-Only "default-src 'self'; ..." always;

IIS (Windows Server) – web.config (özet)

<configuration>
  <system.webServer>
    <httpProtocol>
      <customHeaders>
        <add name="X-Content-Type-Options" value="nosniff" />
        <add name="X-Frame-Options" value="SAMEORIGIN" />
        <add name="Referrer-Policy" value="strict-origin-when-cross-origin" />
        <add name="Permissions-Policy" value="camera=(), microphone=(), geolocation=()" />
        <add name="Strict-Transport-Security" value="max-age=31536000; includeSubDomains; preload" />
        <!-- CSP'yi önce Report-Only deneyip sonra Content-Security-Policy'ye alın -->
        <!-- <add name="Content-Security-Policy-Report-Only" value="default-src 'self'; ..." /> -->
      </customHeaders>
    </httpProtocol>

    <!-- xmlrpc.php engeli -->
    <security>
      <requestFiltering>
        <fileExtensions>
          <add fileExtension=".php" allowed="true" />
        </fileExtensions>
        <hiddenSegments>
          <add segment="xmlrpc.php" />
        </hiddenSegments>
      </requestFiltering>
    </security>

    <!-- uploads'ta php çalıştırmayı engellemek için ayrı site/config kuralı önerilir -->
  </system.webServer>
</configuration>

functions.php ile başlık eklemek (sunucu yerine uygulamada)

add_action('send_headers', function () {
  header('X-Content-Type-Options: nosniff');
  header('X-Frame-Options: SAMEORIGIN');
  header('Referrer-Policy: strict-origin-when-cross-origin');
  header('Permissions-Policy: camera=(), microphone=(), geolocation=()');
  header('Strict-Transport-Security: max-age=31536000; includeSubDomains; preload');
  // CSP'yi burada yönetmek zor; sunucuda vermek daha sağlıklı.
});