Modern web mimarilerinin karmaşıklaşması ve bulut altyapılarının yaygınlaşmasıyla birlikte, uygulama güvenliğikurumsal ekosistemlerin sürdürülebilirliği için kritik bir husus haline gelmiştir. Açık Web Uygulaması Güvenliği Projesi tarafından yayınlanan OWASP Top 10, dünya genelinde yazılım geliştiriciler ve siber güvenlik uzmanları için standart bir risk değerlendirme rehberi kabul edilmektedir (OWASP Foundation, 2021).

Güncellenen son OWASP Top 10 listesinde, mimari tasarım hataları ve erişim kontrol mekanizmalarındaki yetersizlikler ön plana çıkmıştır. Broken Access Control (Kırık Erişim Kontrolü) listenin 1. sırasına yükselirken, Server-Side Request Forgery (SSRF) artan bulut entegrasyonlarının bir sonucu olarak listeye müstakil bir başlık olarak giriş yapmıştır.

Bu makalede, güncel OWASP Top 10 listesindeki en kritik zafiyetler; teknik altyapıları, gerçek hayat senaryoları ve kod seviyesindeki koruma yöntemleri ile ele alınmaktadır.

1. Broken Access Control (Kırık Erişim Kontrolü - A01:2021)

Zafiyet Analizi ve Risk Boyutu

Kırık Erişim Kontrolü, kullanıcıların yetki sınırlarının sunucu tarafında tam olarak doğrulanmaması durumunda ortaya çıkar. Kullanıcıların yalnızca kendilerine tanımlanan haklar çerçevesinde işlem yapabilmesi gerekirken, bu kontrolün yetersizliği yetkisiz veri okuma, değiştirme veya silme işlemlerine yol açar (Stuttard & Pinto, 2011).

Bu kategoride en sık rastlanan türev IDOR (Insecure Direct Object References) zafiyetidir.

Gerçek Hayat Senaryosu

Bir e-ticaret platformunda kullanıcı kendi geçmiş siparişlerini incelemektedir. Web uygulaması sipariş detayını şu API adresi üzerinden çağırmaktadır: https://api.ornek-ticaret.com/v1/orders?order_id=85412

Saldırgan, oturum açmış durumdayken order_id parametresini 85411 olarak değiştirir. Sunucu, isteği gönderen kullanıcının 85411 ID'li siparişin sahibi olup olmadığını doğrulamıyorsa; başka bir müşterinin adı, adresi ve satın aldığı ürün detayları sızdırılmış olur.

Kod Seviyesinde Çözüm

Güvensiz Kod Örneği (Python / Flask):

Python

@app.route('/api/v1/orders/<int:order_id>', methods=['GET'])
@login_required
def get_order_details(order_id):
    # HATA: İstekte bulunan kullanıcının sipariş sahibi olup olmadığı kontrol edilmiyor!
    order = db.session.query(Order).filter_by(id=order_id).first()
    if not order:
        return jsonify({"error": "Sipariş bulunamadı"}), 404
    return jsonify(order.to_dict())

Güvenli Kod Örneği (Python / Flask):

Python

@app.route('/api/v1/orders/<int:order_id>', methods=['GET'])
@login_required
def get_order_details(order_id):
    # GÜVENLİ: Sorguya mevcut kullanıcının id'si (current_user.id) şart olarak ekleniyor.
    order = db.session.query(Order).filter_by(id=order_id, user_id=current_user.id).first()
    if not order:
        return jsonify({"error": "Sipariş bulunamadı veya bu veriye erişim yetkiniz yok"}), 403
    return jsonify(order.to_dict())

2. Injection (Enjeksiyon Zafiyetleri - A03:2021)

Zafiyet Analizi

Enjeksiyon zafiyetleri, güvenilmeyen girdi verilerinin bir komut dizisi veya sorgu yorumlayıcısına (SQL, NoSQL, OS Command, LDAP) filtrelenmeden doğrudan iletilmesiyle tetiklenir (Howard & LeBlanc, 2003). Saldırgan tarafından gönderilen veri, komut olarak algılanır ve veri tabanının tamamen ele geçirilmesine zemin hazırlar.

Gerçek Hayat Senaryosu

Bir bankacılık portalında kullanıcı giriş formu bulunmaktadır. Kullanıcı adı alanına yazılan girdi, SQL sorgusunda birleştirilerek çalıştırılmaktadır. Saldırgan kullanıcı adı alanına şu ifadeyi girer: admin' --

Arka planda çalışan sorgu: SELECT * FROM users WHERE username = 'admin' --' AND password = '...' haline gelir. Çift tire (--) karakteri sorgunun geri kalanını yorum satırı yaptığı için şifre kontrolü baypas edilir ve yönetici hesabına şifresiz erişim sağlanır.

Kod Seviyesinde Çözüm

Güvensiz Kod Örneği (Node.js / Express):

JavaScript

// HATA: String birleştirme (concatenation) ile SQL injection zafiyeti oluşturuluyor.
app.post('/api/login', (req, res) => {
    const { username, password } = req.body;
    const query = `SELECT * FROM users WHERE username = 'username' AND password = '{password}'`;
    
    db.query(query, (err, results) => {
        if (results.length > 0) {
            res.send({ status: "Giriş Başarılı" });
        } else {
            res.status(401).send({ error: "Yetkisiz Giriş" });
        }
    });
});

Güvenli Kod Örneği (Node.js / Express):

JavaScript

// GÜVENLİ: Parametreli sorgu (Prepared Statements) kullanılarak veri ile komut ayrıştırılıyor.
app.post('/api/login', (req, res) => {
    const { username, password } = req.body;
    const query = 'SELECT * FROM users WHERE username = ? AND password = ?';
    
    db.query(query, [username, password], (err, results) => {
        if (results.length > 0) {
            res.send({ status: "Giriş Başarılı" });
        } else {
            res.status(401).send({ error: "Yetkisiz Giriş" });
        }
    });
});

3. Server-Side Request Forgery (SSRF - A10:2021)

Zafiyet Analizi

Server-Side Request Forgery (SSRF), web uygulamasının kullanıcı tarafından sağlanan bir dış kaynak URL'ini doğrulamadan sunucu tarafında çağırması sonucu meydana gelir. Sunucu, dış ağa açık olsa da iç ağdaki (internal network) güvenli sistemlerle doğrudan iletişim kurabilir. Saldırgan, sunucuyu bir vekil (proxy) gibi kullanarak iç ağdaki gizli servisleri taranabilir veya bulut altyapı metadatasını sızdırabilir (OWASP Foundation, 2021).

Gerçek Hayat Senaryosu

Bir SaaS uygulaması, kullanıcıların profil resmi olarak bir URL adresi vermesine ve sunucunun bu resmi indirip işlemesine olanak tanımaktadır.

Saldırgan URL alanına AWS (Amazon Web Services) metadata IP adresini girer:http://169.254.169.254/latest/meta-data/iam/security-credentials/admin-role

Sunucu, iç ağındaki bu özel IP adresine istek atar ve döndürülen JSON yanıtında bulunan AWS IAM erişim anahtarlarını (Access Keys) saldırgana çıktı olarak teslim eder.

Kod Seviyesinde Çözüm

Güvensiz Kod Örneği (Python / Requests):

Python

import requests
from flask import request, Flask

app = Flask(__name__)

@app.route('/fetch-avatar', methods=['GET'])
def fetch_avatar():
    image_url = request.args.get('url')
    # HATA: Kullanıcıdan alınan URL denetlenmeden doğrudan sunucudan çağrılıyor!
    response = requests.get(image_url)
    return response.content

Güvenli Kod Örneği (Python / Requests):

Python

import requests
import ipaddress
from urllib.parse import urlparse

def is_internal_ip(url):
    try:
        hostname = urlparse(url).hostname
        ip = ipaddress.ip_address(hostname)
        # Özel (private), loopback veya link-local IP adreslerini engellereturn ip.is_private or ip.is_loopback or ip.is_link_localexcept ValueError:
        # IP adresi yerine alan adı girildiyse DNS çözümlemesi yapılarak denetlenmelidir.return False

@app.route('/fetch-avatar', methods=['GET'])
def fetch_avatar():
    image_url = request.args.get('url')
    
    # 1. Protokol Kontrolü (Sadece HTTP/HTTPS izin ver)
    parsed = urlparse(image_url)
    if parsed.scheme not in ['http', 'https']:
        return {"error": "Geçersiz protokol"}, 400
        
    # 2. İç Ağ IP Denetimi (SSRF Önleme)if is_internal_ip(image_url):return {"error": "İç ağ adreslerine erişim engellendi"}, 403
        
    response = requests.get(image_url, timeout=5)
    return response.content

4. Cryptographic Failures (Kriptografik Başarısızlıklar - A02:2021)

Eski adıyla Sensitive Data Exposure olarak bilinen bu zafiyet; kişisel verilerin (KVK/GDPR), kredi kartı bilgilerinin veya parolaların aktarım anında (in-transit) veya depolama anında (at-rest) yetersiz şifrelenmesi ya da düz metin (plaintext) olarak tutulması durumunda ortaya çıkar.

  • Depolama Güvenliği: Parolalar asla MD5 veya SHA1 gibi hızlı ve çakışmaya açık algoritmalarla saklanmamalıdır. Bunun yerine bcrypt, Argon2 veya PBKDF2 gibi tuzlama (salting) mekanizmasına sahip yavaş anahtar türetme fonksiyonları tercih edilmelidir (NIST, 2020).
  • Aktarım Güvenliği: Tüm web trafiğinde TLS 1.3 zorunlu kılınmalı, eski SSL/TLS sürümleri devre dışı bırakılmalı ve HSTS (HTTP Strict Transport Security) başlığı etkinleştirilmelidir.

Güvenli Yazılım Geliştirme Yaşam Döngüsü (SSDLC) Entegrasyonu

Zafiyetleri henüz canlı ortama geçmeden tespit etmek, reaktif yama yönetiminden çok daha düşük maliyetlidir. SSDLC (Secure Software Development Life Cycle) yaklaşımı kapsamında şu önlemler alınmalıdır:

  1. Statik Kod Analizi (SAST): Derleme aşamasında kaynak kod içerisindeki bilinen güvenlik açıklarını ve güvensiz kütüphaneleri otomatik olarak tarayın.
  2. Dinamik Kod Analizi (DAST): Uygulama canlıya alınmadan önce çalışan sistem üzerinde otomatize penetrasyon testleri gerçekleştirin.
  3. En Küçük Yetki Prensibi (Principle of Least Privilege): Veri tabanı kullanıcılarına ve API servislerine yalnızca ihtiyaç duydukları minimum erişim haklarını tanımlayın.

Sonuç

Web uygulamalarının güvenliği, tek seferlik bir denetim değil, sürekli takip gerektiren dinamik bir süreçtir. OWASP Top 10 standartları, yazılım mimarlarının ve geliştiricilerin sistemlerindeki en riskli noktaları belirlemeleri için somut bir yol haritası sunar. Broken Access Control, Injection ve SSRF gibi zafiyetlerin önüne geçebilmek için girdi doğrulaması, parametreli sorgu kullanımı ve katmanlı yetkilendirme mimarileri yazılım süreçlerinin ayrılmaz bir parçası haline getirilmelidir.

Kaynakça

  • Howard, M., & LeBlanc, D. (2003). Writing Secure Code (2nd ed.). Microsoft Press.
  • NIST. (2020). Digital Identity Guidelines: Authentication and Lifecycle Management (NIST Special Publication 800-63B). National Institute of Standards and Technology.
  • OWASP Foundation. (2021). OWASP Top 10:2021 - The Ten Most Critical Web Application Security Risks. OWASP Project.
  • Stuttard, D., & Pinto, M. (2011). The Web Application Hacker's Handbook: Finding and Exploiting Security Flaws(2nd ed.). John Wiley & Sons.

Yorumlar 0