SSL/TLS yapılandırma hataları, güvenlik açıklarının en sık karşılaşılan ve aynı zamanda en kolay gözden kaçan türlerinden biri. Bir sunucuyu yıllarca çalıştırabilirsin, her şey “çalışıyor” görünür, ama arka planda BEAST, POODLE veya Heartbleed gibi açıklara kapı aralayan eski protokoller ve zayıf cipher suite’ler sessizce bekliyordur. Bu yazıda, SSL/TLS yapılandırmalarını derinlemesine analiz etmek için kullanılan iki güçlü aracı, sslyze ve testssl.sh‘yi ele alacağız. Sadece kurulum ve temel kullanım değil, gerçek senaryolarda nasıl işe yaradıklarını da göreceğiz.
SSL/TLS Güvenliği Neden Bu Kadar Önemli?
Yönettiğin bir web sunucusunda HTTPS çalışıyor diye her şeyin yolunda olduğunu düşünmek çok yaygın bir hata. Sertifika var, kilit ikonu görünüyor, tamam değil mi? Hayır, değil.
Birkaç gerçek hayat senaryosu düşün:
- Üç yıl önce kurduğun Nginx sunucusu hala TLS 1.0 destekliyor
- PCI-DSS denetimine giriyorsun ve auditor SSLv3 desteklendiğini buluyor
- HSTS header yok, downgrade attack’a açıksın
- RC4 cipher’ları hala aktif çünkü eski bir Java client ile uyumluluk için “geçici olarak” açık bırakılmış
Bu tür sorunları bulmak için iki farklı yaklaşım sunan araçlara ihtiyacın var: hem programatik olarak kullanabileceğin Python tabanlı sslyze, hem de bash ortamında dependency gerektirmeden çalışan testssl.sh.
sslyze Nedir ve Nasıl Kurulur?
sslyze, Python ile yazılmış, SSL/TLS sunucu analizi için geliştirilmiş açık kaynaklı bir araç. Nabp Labs tarafından geliştiriliyor ve özellikle otomasyona entegre etmek istediğinde çok işe yarıyor. JSON çıktısı alabilmesi, CI/CD pipeline’larına kolayca dahil edilmesini sağlıyor.
Kurulum
# pip ile kurulum (Python 3.7+ gerekli)
pip3 install sslyze
# Veya pipx ile izole ortamda
pipx install sslyze
# Kurulumu doğrula
sslyze --version
Kali Linux veya Parrot OS kullanıyorsan muhtemelen zaten kurulu gelir, ama versiyonu kontrol etmeni öneririm çünkü paket repo’daki versiyon güncel olmayabilir.
# Kali için güncel versiyon
pip3 install --upgrade sslyze
Temel Kullanım
# Temel tarama - tüm plugin'leri çalıştırır
sslyze hedefsite.com
# Belirli port ile tarama
sslyze hedefsite.com:8443
# JSON formatında çıktı al
sslyze --json_out sonuc.json hedefsite.com
# Birden fazla hedef tara
sslyze hedef1.com hedef2.com hedef3.com
# Sadece sertifika bilgisini kontrol et
sslyze --certinfo hedefsite.com
Önemli sslyze Parametreleri
–certinfo: Sertifika zinciri, geçerlilik tarihi, OCSP durumu gibi detayları getirir
–sslv2: SSLv2 protokolünün desteklenip desteklenmediğini test eder
–sslv3: SSLv3 desteğini (POODLE açığı) kontrol eder
–tlsv1: TLS 1.0 desteğini kontrol eder
–tlsv1_1: TLS 1.1 desteğini kontrol eder
–tlsv1_2: TLS 1.2 desteğini kontrol eder
–tlsv1_3: TLS 1.3 desteğini kontrol eder
–heartbleed: Heartbleed (CVE-2014-0160) açığını test eder
–robot: ROBOT saldırısına karşı açık olup olmadığını kontrol eder
–reneg: Güvensiz renegotiation desteğini test eder
–resum: Session resumption davranışını analiz eder
–http_headers: HSTS ve güvenlik header’larını kontrol eder
–early_data: TLS 1.3 early data (0-RTT) desteğini test eder
–elliptic_curves: Desteklenen elliptic curve’leri listeler
–json_out: Çıktıyı JSON formatında dosyaya yazar
Gerçek Senaryo: Toplu Sunucu Taraması
Diyelim ki şirketinde 20-30 tane subdomain var ve hepsinin SSL yapılandırmasını kontrol etmen gerekiyor. Bunu manuel yapmak yerine bir script ile otomatize edebilirsin:
#!/bin/bash
# ssl_audit.sh - Toplu SSL denetimi
TARGETS_FILE="hedefler.txt"
SONUC_DIR="ssl_audit_$(date +%Y%m%d)"
mkdir -p $SONUC_DIR
while IFS= read -r hedef; do
echo "[*] Taraniyor: $hedef"
sslyze --certinfo --heartbleed --robot
--sslv2 --sslv3 --tlsv1 --tlsv1_1
--http_headers
--json_out "${SONUC_DIR}/${hedef////_}.json"
"$hedef" 2>/dev/null
# Kritik sorunları hemen ekrana bas
if grep -q '"is_vulnerable_to_heartbleed": true' "${SONUC_DIR}/${hedef////_}.json" 2>/dev/null; then
echo "[KRITIK] $hedef - Heartbleed acigi tespit edildi!"
fi
sleep 1 # Rate limiting
done < "$TARGETS_FILE"
echo "[+] Tarama tamamlandi. Sonuclar: $SONUC_DIR"
Bu script’i cron’a bağlayarak haftalık çalıştırabilirsin. Eğer kritik bir değişiklik varsa, output’u grep’leyip mail at.
sslyze JSON Çıktısını Parse Etme
# Python ile JSON analizi
python3 << 'EOF'
import json
import sys
with open('sonuc.json') as f:
data = json.load(f)
for server_scan in data['server_scan_results']:
hostname = server_scan['server_location']['hostname']
# Scan hatasi var mi kontrol et
if server_scan['scan_status'] == 'ERROR':
print(f"HATA: {hostname} taranamadi")
continue
scan_result = server_scan['scan_result']
# SSL 3.0 kontrolu
ssl3 = scan_result.get('ssl_3_0_cipher_suites', {})
if ssl3.get('status') == 'COMPLETED':
accepted = ssl3['result'].get('accepted_cipher_suites', [])
if accepted:
print(f"UYARI [{hostname}]: SSLv3 destekleniyor! ({len(accepted)} cipher)")
# Heartbleed kontrolu
hb = scan_result.get('heartbleed', {})
if hb.get('status') == 'COMPLETED':
if hb['result'].get('is_vulnerable_to_heartbleed'):
print(f"KRITIK [{hostname}]: Heartbleed acigi mevcut!")
print(f"OK: {hostname} analizi tamamlandi")
EOF
testssl.sh Nedir ve Nasıl Kullanılır?
testssl.sh, herhangi bir Python veya özel kütüphane bağımlılığı olmadan çalışan, bash tabanlı bir SSL/TLS test aracı. Sadece OpenSSL (veya bazı durumlarda dahili olarak derlenmiş bir binary) kullanarak son derece kapsamlı testler yapabiliyor. Özellikle hedef sistemde sadece bash ve openssl varsa ya da tam anlamıyla portable bir çözüm istiyorsan tercih edilmeli.
Kurulum
# GitHub'dan indirme
git clone --depth 1 https://github.com/drwetter/testssl.sh.git
cd testssl.sh
# Direkt çalıştır
./testssl.sh --version
# Sisteme kur (opsiyonel)
sudo cp testssl.sh /usr/local/bin/
sudo chmod +x /usr/local/bin/testssl.sh
Kali’de apt ile de kurabilirsin:
sudo apt install testssl.sh
Ama yine söylüyorum, GitHub versiyonu her zaman daha güncel. SSL/TLS dünyası hızlı değişiyor ve araçların da güncel olması kritik.
testssl.sh Temel Kullanım
# Tam tarama (tüm testleri çalıştır)
testssl.sh hedefsite.com
# HTTPS için port belirt (default 443)
testssl.sh hedefsite.com:443
# STARTTLS ile SMTP taraması
testssl.sh --starttls smtp mail.sirket.com:25
# STARTTLS ile IMAP
testssl.sh --starttls imap mail.sirket.com:143
# Sadece protokol testleri
testssl.sh --protocols hedefsite.com
# Sadece cipher testleri
testssl.sh --ciphers hedefsite.com
# Sadece açık testleri
testssl.sh --vulnerabilities hedefsite.com
Önemli testssl.sh Parametreleri
–protocols: Desteklenen SSL/TLS protokol versiyonlarını listeler
–ciphers: Tüm desteklenen cipher suite’leri test eder
–cipher-per-proto: Her protokol için ayrı ayrı cipher listesi çıkarır
–server-defaults: Sunucunun varsayılan ayarlarını gösterir
–server-preference: Sunucunun cipher tercihi sırasını analiz eder
–vulnerabilities: Bilinen açıkları (BEAST, BREACH, ROBOT, vb.) kontrol eder
–heartbleed: Sadece Heartbleed testini çalıştırır
–ccs: CCS Injection (CVE-2014-0224) açığını test eder
–ticketbleed: Ticketbleed açığını test eder
–robot: ROBOT açığını test eder
–beast: BEAST açığını test eder
–lucky13: LUCKY13 açığını test eder
–poodle: POODLE açığını test eder
–freak: FREAK açığını test eder
–logjam: Logjam açığını test eder
–drown: DROWN açığını test eder
–headers: HTTP güvenlik header’larını (HSTS, HPKP, vb.) kontrol eder
–starttls: STARTTLS protokolü ile bağlanır (smtp, imap, ftp gibi servisler için)
–html: Sonuçları HTML rapor olarak kaydeder
–jsonfile: JSON formatında çıktı dosyası belirtir
–csvfile: CSV formatında çıktı dosyası belirtir
–logfile: Log dosyası belirtir
–severity: Minimum severity seviyesi (LOW, MEDIUM, HIGH, CRITICAL)
–quiet: Başlık bilgilerini gizler, sadece bulgular gösterilir
Gerçek Senaryo: PCI-DSS Uyumluluk Kontrolü
PCI-DSS uyumluluğu için TLS 1.0 ve 1.1’i devre dışı bırakman, zayıf cipher’ları kaldırman gerekiyor. testssl.sh bunu çok güzel raporluyor:
#!/bin/bash
# pci_ssl_check.sh
TARGET=$1
RAPOR_DIR="pci_raporlar"
TARIH=$(date +%Y%m%d_%H%M%S)
if [ -z "$TARGET" ]; then
echo "Kullanim: $0 <hedef:port>"
exit 1
fi
mkdir -p $RAPOR_DIR
echo "[*] PCI-DSS SSL kontrolu basliyor: $TARGET"
testssl.sh
--protocols
--cipher-per-proto
--vulnerabilities
--headers
--severity MEDIUM
--jsonfile "${RAPOR_DIR}/pci_${TARGET//[:/.]/}_${TARIH}.json"
--htmlfile "${RAPOR_DIR}/pci_${TARGET//[:/.]/}_${TARIH}.html"
--logfile "${RAPOR_DIR}/pci_${TARGET//[:/.]/}_${TARIH}.log"
"$TARGET"
echo "[+] Rapor olusturuldu: ${RAPOR_DIR}/"
# TLS 1.0/1.1 uyari kontrolu
if grep -q '"TLSv1"' "${RAPOR_DIR}/pci_${TARGET//[:/.]/}_${TARIH}.json" 2>/dev/null; then
echo "[UYARI] TLS 1.0 aktif - PCI-DSS uyumsuzlugu!"
fi
STARTTLS Servisleri Test Etme
Sysadminlerin çoğu sadece HTTPS’i test ediyor ama SMTP, IMAP, POP3 gibi servislerdeki SSL yapılandırmaları da en az web sunucu kadar önemli. Özellikle mail sunucuları çoğu zaman unutuluyor:
# Mail sunucusu tam SSL denetimi
testssl.sh --starttls smtp mail.sirket.com:25
testssl.sh --starttls smtp mail.sirket.com:587
testssl.sh --starttls imap mail.sirket.com:143
testssl.sh --starttls pop3 mail.sirket.com:110
# Direkt SSL portlari
testssl.sh mail.sirket.com:993 # IMAPS
testssl.sh mail.sirket.com:995 # POP3S
testssl.sh mail.sirket.com:465 # SMTPS
Geçen ay bir müşteride incelemek için fırsat bulduğumda, web sunucularının tamamen temiz olduğunu ama SMTP sunucusunun hala TLS 1.0 ile SSLv3 desteklediğini gördüm. Klasik “web’e baktık, mail’i unuttuk” durumu.
İki Aracı Karşılaştırmak ve Ne Zaman Hangisini Kullanmak
Her iki araç da güçlü ama farklı senaryolar için daha uygun olabiliyor.
sslyze’ı tercih et eğer:
- Sonuçları programatik olarak işleyeceksen (JSON parse, API entegrasyonu)
- CI/CD pipeline’ına SSL taraması ekleyeceksen
- Büyük ölçekli otomasyon yazıyorsan
- Python ekosistemiyle çalışıyorsan
testssl.sh’yi tercih et eğer:
- İnsan tarafından okunabilir, renkli bir terminal çıktısı istiyorsan
- Bağımlılık olmadan çalışması gerekiyorsa
- STARTTLS servislerini test edeceksen
- HTML veya CSV rapor almak istiyorsan
- Hızlı ve pratik bir denetim yapacaksan
Gerçekte ben ikisini birlikte kullanıyorum. testssl.sh ile hızlı görsel kontrol yapıp, sslyze ile otomasyon yazıyorum.
Bulguları Yorumlamak ve Aksiyon Almak
Araçları çalıştırdın, çıktıyı aldın. Peki ne yapacaksın?
Kritik Bulgular ve Çözümleri
SSLv2/SSLv3 Aktif
Nginx için:
# /etc/nginx/nginx.conf veya site konfigürasyonu
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
# HSTS ekle
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
Apache için:
# /etc/apache2/sites-available/sirket.conf
SSLProtocol -all +TLSv1.2 +TLSv1.3
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
SSLHonorCipherOrder off
SSLSessionTickets off
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
Değişiklik sonrası hemen test et:
# Duzeltme sonrasi dogrulama
testssl.sh --protocols hedefsite.com
sslyze --sslv2 --sslv3 --tlsv1 hedefsite.com
Otomatik Günlük Kontrol Script’i
#!/bin/bash
# daily_ssl_check.sh - Cron ile gunluk calistir
# Cron: 0 6 * * * /opt/scripts/daily_ssl_check.sh
HEDEFLER=("api.sirket.com:443" "www.sirket.com:443" "mail.sirket.com:993")
MAIL_TO="[email protected]"
LOG="/var/log/ssl_check_$(date +%Y%m%d).log"
SORUN=0
for hedef in "${HEDEFLER[@]}"; do
SONUC=$(sslyze --certinfo --sslv2 --sslv3 --tlsv1
--heartbleed --json_out /tmp/ssl_tmp.json
"$hedef" 2>&1)
# Sertifika bitis tarihini kontrol et
EXPIRY=$(python3 -c "
import json, datetime
with open('/tmp/ssl_tmp.json') as f:
d = json.load(f)
try:
cert = d['server_scan_results'][0]['scan_result']['certificate_info']['result']['certificate_deployments'][0]['received_certificate_chain'][0]
expiry = cert['not_valid_after']
exp_date = datetime.datetime.strptime(expiry, '%Y-%m-%dT%H:%M:%S')
days_left = (exp_date - datetime.datetime.now()).days
print(days_left)
except:
print('ERROR')
" 2>/dev/null)
if [[ "$EXPIRY" =~ ^[0-9]+$ ]] && [ "$EXPIRY" -lt 30 ]; then
echo "[UYARI] $hedef - Sertifika $EXPIRY gun icinde sona eriyor!" | tee -a $LOG
SORUN=1
fi
echo "[$hedef] Kontrol tamamlandi" >> $LOG
done
if [ $SORUN -eq 1 ]; then
mail -s "SSL Uyari - $(date +%Y-%m-%d)" $MAIL_TO < $LOG
fi
rm -f /tmp/ssl_tmp.json
Yaygın Tuzaklar ve Dikkat Edilmesi Gerekenler
Zaman Aşımı Sorunları: Bazı yük dengeleyiciler veya WAF’lar art arda gelen SSL bağlantı denemelerini blokluyor. testssl.sh’ye --connect-timeout ve --openssl-timeout parametrelerini vermek mantıklı.
İç Ağ vs. Dış Ağ Farkı: İç ağdan test ettiğinde farklı sonuçlar alabilirsin. Bir load balancer varsa, dış trafiği başka bir şekilde handle ediyor olabilir. Mümkünse hem iç hem dış ağdan test et.
Test Edilecek Portları Unutmak: 443 dışında 8443, 8080 (bazen HTTPS), 9443 gibi portları da kontrol et. Özellikle uygulama sunucuları (Tomcat, WebSphere) kendi portlarında çalışıyor.
Wildcard Sertifikaları Kötüye Kullanımı: Tarama sırasında aynı sertifikayı kullanan ama farklı yapılandırmalara sahip birden fazla subdomain görebilirsin. Her birini ayrı ayrı test etmek gerek.
False Positive’ler: Özellikle eski OpenSSL versiyonları bazı testlerde yanlış sonuç verebiliyor. sslyze veya testssl.sh şüpheli bir bulgu gösterdiğinde, bunu ikinci bir araçla doğrula.
Sonuç
SSL/TLS güvenliği “bir kere kur, unut” meselesi değil. Yeni açıklar keşfediliyor, protokol versiyonları deprecated oluyor, cipher suite’ler zayıf bululuyor. Dolayısıyla bu taramaları düzenli olarak yapmak gerekiyor.
sslyze ve testssl.sh, birbirini tamamlayan iki araç olarak workflow’una girdiğinde çok güçlü bir denetim mekanizması elde ediyorsun. testssl.sh’nin renkli, insan gözüne hitap eden çıktısını hızlı kontroller için kullanırken, sslyze’ın JSON çıktısını otomasyon ve trend analizi için kullanmak en verimli yaklaşım.
Önerdiğim minimum senaryo şu: Her ay tam tarama, her gün sertifika son kullanma tarihi kontrolü, her deployment sonrası protokol ve cipher kontrolü. Bu üçünü otomatize ettiğinde, SSL kaynaklı güvenlik olaylarını neredeyse sıfıra indirebilirsin. Ve emin ol, bir gün auditor geldiğinde ya da bir açık duyurusu çıktığında, “biz zaten tarıyoruz” diyebilmek paha biçilemez bir rahatlık.