İçeriğe geç
Educora
İleri18 dk7 / 12

Güvenli kod yazma

Dört temel alışkanlık: girdiyi izin listesiyle doğrulamak, en az yetki ilkesi, sırları kodun dışında tutmak ve bağımlılıklardaki zafiyetleri izlemek.

Kendini test et
Bu derste öğreneceklerin
  • Sunucu tarafında izin listesine dayalı girdi doğrulaması yazmak
  • En az yetki ilkesini veri tabanlarına ve hizmetlere uygulamak
  • Sırları koddan çıkarmak ve bir sızıntıdan sonra doğru davranmak
  • CVE, CVSS ve bağımlılık denetimi araçlarını anlamak

Zafiyetlerin çoğu egzotik hilelerden değil, sıradan programcı alışkanlıklarından doğar: girdiye güvenmek, bir hizmeti yönetici yetkisiyle çalıştırmak, bir parolayı Git deposuna yazmak, üç yıldır güncellenmemiş bir kütüphane. Bu derste kodunu her gün daha güvenli yapan dört alışkanlığı öğreneceksin.

1. Girdi doğrulama: izin listesi

Her girdi güvenilmezdir: formlar, URL parametreleri, başlıklar, çerezler, yüklenen dosyalar, hatta kendi mobil uygulamandan gelen istekler (değiştirilebilirler). Doğrulama sunucuda yapılmalıdır; tarayıcıdaki kontroller yalnızca kullanıcının rahatlığı içindir. Türü, uzunluğu, aralığı ve biçimi kontrol et; kötü karakterleri aramak yerine neyin geçerli olduğunu tanımla.

Yasak listesi: hep eksiktir
BAD = ['<script>', 'DROP TABLE', '--']

def is_safe(text):
    return not any(bad in text for bad in BAD)

is_safe('<SCRIPT>')   # True - uppercase slips through
İzin listesi: yalnızca geçerli olan geçer
import re

def is_valid_username(text):
    return re.fullmatch(r'[a-z0-9_]{3,16}', text) is not None

is_valid_username('<SCRIPT>')   # False
Saldırgan bir yasak listesini atlatmanın binlerce yolunu bulabilir; izin listesi ise yalnızca senin tanımladığın biçimi kabul eder.
Python
import re

USERNAME = re.compile(r'[a-z0-9_]{3,16}')

def validate_signup(username, age):
    errors = []
    if not USERNAME.fullmatch(username):
        errors.append('username: 3-16 of a-z 0-9 _')
    if not (type(age) is int and 10 <= age <= 120):
        errors.append('age: whole number 10-120')
    return errors or ['OK']

for username, age in [('aysel_07', 15), ('Murad!', 16), ('elvin', -3), ('x', 200)]:
    print(username.ljust(9), validate_signup(username, age))
▸ Beklenen çıktı
aysel_07  ['OK']
Murad!    ['username: 3-16 of a-z 0-9 _']
elvin     ['age: whole number 10-120']
x         ['username: 3-16 of a-z 0-9 _', 'age: whole number 10-120']
Fonksiyon tüm hataları bir kerede döndürür, böylece kullanıcı formu tek seferde düzeltebilir. fullmatch, dizenin tamamının biçime uymasını ister.

2. En az yetki ilkesi

Her kullanıcı, süreç ve hizmet yalnızca işi için gereken yetkileri ve yalnızca gerektiği süre boyunca almalıdır. Bir web uygulamasının veri tabanı hesabı yönetici olmamalı, hizmetler root ya da Administrator olarak çalışmamalı, yönetim işleri için ayrı bir hesap olmalıdır. Uygulama ele geçirilse bile hasar yarıçapı küçük kalır.

Her şeye, her yerden
GRANT ALL PRIVILEGES ON *.* TO 'shop_app'@'%';
Yalnızca gereken, yalnızca iç ağdan
GRANT SELECT, INSERT, UPDATE ON shop.orders TO 'shop_app'@'10.0.0.%';
GRANT SELECT ON shop.products TO 'shop_app'@'10.0.0.%';
Bir MySQL örneği: ele geçirilen uygulama DROP DATABASE çalıştıramaz ya da başka veri tabanlarını okuyamaz, çünkü bu yetkiler ona hiç verilmedi.

Bu ilkenin iki yakın “akrabası” vardır. Güvenli varsayılanlar: yeni bir hesap, dosya ya da API anahtarı başta hiçbir şeye izin vermez, yetkiler sonradan bilinçli olarak eklenir. Kapalı konumda kalmak (fail closed): bir kontrol hatayla biterse, örneğin yetkilendirme sunucusu yanıt vermezse, kod isteği “ne olur ne olmaz” diye geçirmek yerine erişimi reddetmelidir.

3. Sırların yönetimi

Parolalar, API anahtarları, belirteçler ve gizli anahtarlar asla kodda saklanmaz. Git geçmişi silinmiş dosyaları bile sonsuza dek hatırlar ve botlar herkese açık depolarda anahtar arar. Sırları ortam değişkenlerinde ya da bir sır yöneticisinde (HashiCorp Vault, AWS Secrets Manager, Azure Key Vault) tut, .env dosyasını .gitignore'a ekle ve commit'ten önce bir sır tarayıcısı (örneğin gitleaks) çalıştır.

Sır kodun içinde
DB_PASSWORD = 'Baku2024!'   # now in Git history forever

connect(user='shop_app', password=DB_PASSWORD)
Sır ortamdan gelir
import os

DB_PASSWORD = os.environ['DB_PASSWORD']   # set by the server or a secrets manager

connect(user='shop_app', password=DB_PASSWORD)

4. Bağımlılıklardaki zafiyetler

Modern bir uygulamanın kodunun büyük kısmı başkalarının kütüphaneleridir. Bilinen bir zafiyet bir CVE kimliği ve bir CVSS puanı (0–10) alır. npm audit, pip-audit, Dependabot ve OWASP Dependency-Check gibi araçlar bağımlılıklarını bu veri tabanlarıyla karşılaştırır. Kilit dosyaları (package-lock.json, poetry.lock) tam sürümleri sabitler, bir SBOM ise tüm bileşenleri listeler. Popüler paketlere benzer adlı sahte paketlere (typosquatting) de dikkat et.

CVSS puanıÖnem derecesiNe yapmalı
0,1–3,9Düşükbir sonraki planlı güncellemede düzelt
4,0–6,9Ortabirkaç hafta içinde düzelt
7,0–8,9Yükseköncelik ver, birkaç gün içinde düzelt
9,0–10,0Kritikhemen güncelle ya da geçici bir önlem uygula
Dereceler CVSS v3 ölçeğine göredir; son karar, o bileşenin sisteminde gerçekten erişilebilir olup olmamasına da bağlıdır.
Terminal
# JavaScript project: check dependencies against known vulnerabilities
npm audit

# Python project
pip install pip-audit
pip-audit
Bu komutları kendi projende çalıştır ve bulunan zafiyetleri CVSS puanına göre sırala.
Alıştırma

Bir sipariş formundaki “miktar” alanı için is_valid_quantity(text) fonksiyonunu yaz: yalnızca 1'den 99'a kadar bir tam sayıyı gösteren dizeler ([0-9] rakamları, 1–2 karakter) True döndürsün. Boşluk, eksi işareti, 5e3 ve ² gibi karakterler reddedilmeli ve fonksiyon asla çökmemelidir.

Alıştırma · Python
import re

def is_valid_quantity(text):
    # allow-list: 1-2 ASCII digits, value 1..99
    return False

for value in ['3', '99', '0', '100', '-1', ' 7', '5e3', '²']:
    print(repr(value), is_valid_quantity(value))
▸ Beklenen çıktı
'3' True
'99' True
'0' False
'100' False
'-1' False
' 7' False
'5e3' False
'²' False

Önemli noktalar

  • Her girdiyi sunucuda izin listesiyle doğrula: tür, uzunluk, aralık, biçim.
  • Doğrulama, parametreli sorguların ve kaçışlamanın yerini tutmaz.
  • En az yetki, ele geçirilen bir bileşenin verebileceği zararı sınırlar.
  • Sırlar kodda değil, ortamda ya da bir sır yöneticisinde tutulur; sızan sır hemen değiştirilir.
  • Bağımlılıkları denetim araçlarıyla kontrol et, CVSS puanına göre önceliklendir ve bir SBOM tut.

Kendini test et

10 soru. Her doğru cevap XP kazandırır.

1 / 10
Yasak listesiyle doğrulama neden güvenilmez sayılır?