İçeriğe geç
academia.sh

Ders 01 / 21

İstem Enjeksiyonu

Modele giren metnin bir saldırı yüzeyi olarak sayılması: kurgu kayıt kümesinde 240 kaydın 93'ü zararlı, 147'si temiz ve zararlı olma bilgisi metinde değil yapısal bir öznitelik profilinde duruyor. Savunmasız tabanda durdurulan zararlı 0, yanlış alarm 0; kural süzgeci 74 zararlı durduruyor, 23 temiz kaydı yanlışlıkla engelliyor ve 19 zararlı kaçıyor (kesinlik 0,7629, duyarlılık 0,7957, yanlış engelleme payı 0,1565). Doğrudan ile dolaylı biçim kaynak dağılımıyla ayrılıyor: 37 doğrudan zararlıda duyarlılık 0,6486, 56 dolaylı zararlıda 0,8929. İkinci koşumda aynı süzgeç 0,6988 veriyor; kümenin çözünürlüğü duyarlılıkta 0,0108, yanlış engellemede 0,0068.

İçindekiler

Bir önceki kursun on bir dersi aracın kimin elinde olduğunu ölçtü: tanım karşı tarafa taşındı, zarfın bedeli sayıldı, güvenilmeyen bir sunucunun bildirdiği tanım tek tek denetlendi. Bütün bunlar arayüzün dışındaydı — sayılan şey mesajın kabuğuydu, içindeki metin değil. Oysa bir dil modeli için veri ile yönerge arasında yapısal bir sınır yoktur: ikisi de aynı bağlam penceresine aynı biçimde girer. Kullanıcının yazdığı cümle, erişilen bir belgenin gövdesi ve bir aracın döndürdüğü değer modelin gözünde aynı türdendir. İstem enjeksiyonu bu ayrımsızlığın adıdır: modele giren metnin, o metni taşıyan yolun yetkisinden fazlasını yaptırabilmesi.

Bu ders yüzeyi anlatmaz, sayar. Sorusu şudur: aynı kayıt kümesinde hiçbir savunma yokken kaç zararlı durdurulur, bir kural süzgeci eklendiğinde kaç zararlı durdurulur ve o süzgeç kaç temiz kaydı yanlışlıkla engeller. Kursun kuralı ilk satırdan itibaren geçerlidir: durdurduğu pay ile yanlışlıkla durdurduğu pay birlikte yazılmayan savunma ölçülmemiş sayılır.

  • SY1. Kayıt kümesi, sınıflar, öznitelikler ve savunma katmanları kurgudur; gerçek bir model uç noktası ya da gerçek bir olay kaydı kullanılmaz. Tohum 20260218.
  • SY2. Bu bir saldırı dersi değildir. Koşan kodun tamamı savunma tarafındadır: sınıflandırma, süzgeç, sayım ve ölçü. Çalışan bir yük, şablon, yönerge dizisi ya da atlatma yordamı yazılmaz.
  • SY3. Kural yapısaldır: saldırı bir metin değil, bir öznitelik profilidir. Kayıtların metni tümüyle zararsız destek talepleridir ve sınıfla hiçbir ilişkisi yoktur.
  • SY4. Sınıf adları birer etikettir, yordam tarifi değildir. Yeni bir sınıf gerektiğinde öznitelik listesine bir bayrak eklenir, metin eklenmez.
  • SY5. Girdi doğrulama ve tehdit modelleme Güvenli Yazılım Geliştirme kursunda ölçüldü; yordamları tekrarlanmaz. Burada yalnız dil modeline özgü yüzey eklenir.
  • SY6. kesinlik ve duyarlılık Makine Öğrenmesi kursundaki sınıflandırma anlamıyla kullanılır. Yanlış alarm temiz bir kaydın zararlı sayılmasıdır, yanlış negatif zararlı bir kaydın kaçmasıdır.
  • SY7. Kural süzgeci örnekleme içermez, aynı küme üzerinde her koşumda aynı sayıyı verir; ikinci koşum kümeyi ikinci tohumla yeniden üretir.
  • SY8. Duyarlılığın en küçük adımı 1/93, yanlış engelleme payının adımı 1/147’dir; bu adımlardan küçük hiçbir fark ölçülemez.

Saldırı Bir Metin Değil, Bir Öznitelik Profilidir

Bir saldırı yüzeyini öğretmenin alışılmış yolu örnek göstermektir. Bu kurs onu yapmaz ve bunu bir üslup tercihi olarak değil yapısal bir kısıt olarak uygular: kayıt kümesinde saldırı metni diye bir alan yoktur. Kaydın taşıdığı şey yedi bayraktır — yönerge kipi, rol değiştirme isteği, gizli alan adı, yan etkili araç adı, kaynak damgası uyuşmazlığı, olağandışı damga dağılımı, aşırı uzunluk. Her biri bir kaydın yapısı hakkında bir doğru-yanlış değeridir; hiçbiri çalışan bir şey değildir.

Kaydın metin alanı da vardır ve orada altı kurgu destek talebinden biri durur. O altı cümle sıradan abone sorularıdır ve sınıfla hiçbir ilişkileri yoktur: hangi cümlenin hangi kayda düştüğü ayrı bir çekilişle belirlenir. Metin sınıfı belirlemediği için ders bir saldırı metni göstermek zorunda kalmaz, ve savunmanın ölçüsü metnin içeriğine değil kaydın profiline dayanır. Gerçek bir kurulumda süzgeç metni okur; burada ölçülen şey o okumanın çıktısı gibi davranan bir profildir.

# KURGUDUR. Kayit kumesi, siniflar, oznitelikler ve savunma katmanlari ders icinde
# tanimlanir; gercek bir model uc noktasi cagrilmaz. Saldiri METNI yazilmaz.
TOHUM, M32 = 20260218, 0xFFFFFFFF


def uretec(t):
    x = ((t ^ (t >> 16)) * 2246822507) & M32
    x = ((x ^ (x >> 13)) * 3266489909) & M32
    s = [(x ^ (x >> 16)) & M32]

    def sonraki():
        s[0] = (s[0] * 1664525 + 1013904223) & M32
        return s[0] / 4294967296
    return sonraki


def ayrik(u, w):
    t = 0.0
    for i, x in enumerate(w):
        t += x
        if u < t:
            return i
    return len(w) - 1


def izno(m):
    h = 2166136261
    for c in str(m):
        h = ((h ^ ord(c)) * 16777619) & M32
    return h


# ---- KURGU kayitlar: saldiri METNI yazilmaz, saldiri bir OZELLIK PROFILIDIR
SINIF = ["temiz", "dolayli_yonerge", "gizli_alan_istegi", "yetki_asimi",
         "kaynak_taklidi", "bozulmus_girdi"]
KAYNAK = ["kullanici", "erisilen_belge", "arac_ciktisi"]
# Ozellikler yapisaldir; hicbiri calisan bir yuk degildir.
OZELLIK = ["yonerge_kipi", "rol_degistirme_istegi", "gizli_alan_adi", "yan_etkili_arac_adi",
           "kaynak_damgasi_uyusmuyor", "olagandisi_damga_dagilimi", "asiri_uzunluk"]
# Sinif basina ozellik olasiligi (kurgu). Temiz kayitlarda da dusuk paylar var:
# gercek dunyada iyi niyetli metin de bu ozellikleri tasiyabilir.
PROFIL = {
    "temiz":              [0.06, 0.02, 0.05, 0.03, 0.02, 0.04, 0.05],
    "dolayli_yonerge":    [0.88, 0.42, 0.10, 0.30, 0.35, 0.08, 0.12],
    "gizli_alan_istegi":  [0.35, 0.15, 0.86, 0.12, 0.10, 0.06, 0.08],
    "yetki_asimi":        [0.30, 0.25, 0.12, 0.84, 0.14, 0.05, 0.07],
    "kaynak_taklidi":     [0.22, 0.55, 0.08, 0.10, 0.82, 0.07, 0.06],
    "bozulmus_girdi":     [0.05, 0.03, 0.04, 0.03, 0.06, 0.80, 0.62],
}
KAYNAK_PAYI = {
    "temiz":             [0.72, 0.20, 0.08],
    "dolayli_yonerge":   [0.05, 0.70, 0.25],
    "gizli_alan_istegi": [0.55, 0.30, 0.15],
    "yetki_asimi":       [0.40, 0.35, 0.25],
    "kaynak_taklidi":    [0.10, 0.60, 0.30],
    "bozulmus_girdi":    [0.65, 0.20, 0.15],
}
# Kurgu, tumuyle zararsiz destek metinleri. Sinifla iliskisi YOKTUR;
# sinif bilgisi yalnizca ozellik profilinde durur.
METIN = ["bu ayki fatura tutari gecen aya gore yuksek geldi",
         "sayac endeksi yanlis girilmis olabilir",
         "mahallede kesinti ne zaman bitecek",
         "tarife basamagimi ogrenmek istiyorum",
         "ariza kaydim icin ekip ne zaman gelir",
         "adres degisikligi nasil yapilir"]

KAYIT = []
for i in range(240):
    r = uretec(TOHUM + 6151 * i)
    s = SINIF[ayrik(r(), [0.62, 0.10, 0.07, 0.07, 0.07, 0.07])]
    kaynak = KAYNAK[ayrik(r(), KAYNAK_PAYI[s])]
    oz = {o: (r() < p) for o, p in zip(OZELLIK, PROFIL[s])}
    KAYIT.append({"no": i + 1, "sinif": s, "kaynak": kaynak, "ozellik": oz,
                  "metin": METIN[int(r() * len(METIN))],
                  "uzunluk": 40 + int(r() * 260)})


def zararli(k):
    return k["sinif"] != "temiz"


# ---- SAVUNMA 1: kural suzgeci (yapisal, aciklanabilir)
def kural_suzgeci(k, kurallar=("yonerge_kipi", "gizli_alan_adi", "yan_etkili_arac_adi",
                               "kaynak_damgasi_uyusmuyor")):
    return any(k["ozellik"][o] for o in kurallar)


# ---- SAVUNMA 2: model temelli suzgec (puan + esik)
AGIRLIK = {"yonerge_kipi": 0.42, "rol_degistirme_istegi": 0.26, "gizli_alan_adi": 0.44,
           "yan_etkili_arac_adi": 0.40, "kaynak_damgasi_uyusmuyor": 0.38,
           "olagandisi_damga_dagilimi": 0.30, "asiri_uzunluk": 0.12}
KAYNAK_EK = {"kullanici": 0.00, "erisilen_belge": 0.18, "arac_ciktisi": 0.12}


def puan(k):
    p = sum(AGIRLIK[o] for o in OZELLIK if k["ozellik"][o]) + KAYNAK_EK[k["kaynak"]]
    r = uretec(TOHUM ^ izno(k["no"]))
    return min(max(p + (r() - 0.5) * 0.20, 0.0), 1.6)


def model_suzgeci(k, esik=0.40):
    return puan(k) >= esik


# ---- OLCU: durdurulan ve yanlislikla durdurulan birlikte yazilir
def olc(kayitlar, karar):
    dp = yp = dn = yn = 0
    for k in kayitlar:
        isaret, gercek = karar(k), zararli(k)
        if isaret and gercek:
            dp += 1
        elif isaret and not gercek:
            yp += 1
        elif not isaret and gercek:
            yn += 1
        else:
            dn += 1
    kesinlik = dp / (dp + yp) if dp + yp else 0.0
    duyarlilik = dp / (dp + yn) if dp + yn else 0.0
    return {"dp": dp, "yp": yp, "yn": yn, "dn": dn,
            "kesinlik": round(kesinlik, 4), "duyarlilik": round(duyarlilik, 4),
            "yanlis_engelleme_payi": round(yp / (yp + dn), 4) if yp + dn else 0.0}

Savunmasız Taban ve Kural Süzgeci

İkinci blok önce kümenin bileşimini basar, sonra iki kurulumu yan yana koyar. Birincisi savunmasız tabandır: hiçbir süzgeç, işaretleme ya da kapı yoktur, dolayısıyla hiçbir kayıt durdurulmaz. İkincisi dört bayrağa bakan bir kural süzgecidir.

from collections import Counter

print("kayit:", len(KAYIT), " zararli:", sum(1 for k in KAYIT if zararli(k)),
      " temiz:", sum(1 for k in KAYIT if not zararli(k)))
print("sinif:", {s: sum(1 for k in KAYIT if k["sinif"] == s) for s in SINIF})
print("kaynak:", {x: sum(1 for k in KAYIT if k["kaynak"] == x) for x in KAYNAK})
print("her metnin gorundugu sinif sayisi:",
      [len({k["sinif"] for k in KAYIT if k["metin"] == t}) for t in METIN])


def savunmasiz(k):
    """Taban: hicbir suzgec, isaretleme ya da kapi yok."""
    return False


print("\nkurulum         durdurulan  yanlis alarm  kacan  kesinlik  duyarlilik  yanlis eng")
for ad, karar in (("savunmasiz", savunmasiz), ("kural suzgeci", kural_suzgeci)):
    m = olc(KAYIT, karar)
    print(f"{ad:<15} {m['dp']:>10} {m['yp']:>13} {m['yn']:>6}"
          f" {m['kesinlik']:>9.4f} {m['duyarlilik']:>11.4f} {m['yanlis_engelleme_payi']:>11.4f}")

dogrudan = [k for k in KAYIT if zararli(k) and k["kaynak"] == "kullanici"]
dolayli = [k for k in KAYIT if zararli(k) and k["kaynak"] != "kullanici"]
print("\nbicim      zararli  kural yakaladi  duyarlilik")
for ad, g in (("dogrudan", dogrudan), ("dolayli", dolayli)):
    y = sum(1 for k in g if kural_suzgeci(k))
    print(f"{ad:<10} {len(g):>7} {y:>15} {y / len(g):>11.4f}")

print("\nsinif basina kaynak dagilimi")
for s in SINIF:
    c = Counter(k["kaynak"] for k in KAYIT if k["sinif"] == s)
    print(f"  {s:<18} " + "  ".join(f"{x}={c.get(x, 0):>3}" for x in KAYNAK))
kayit: 240  zararli: 93  temiz: 147
sinif: {'temiz': 147, 'dolayli_yonerge': 24, 'gizli_alan_istegi': 17, 'yetki_asimi': 10, 'kaynak_taklidi': 23, 'bozulmus_girdi': 19}
kaynak: {'kullanici': 137, 'erisilen_belge': 72, 'arac_ciktisi': 31}
her metnin gorundugu sinif sayisi: [6, 5, 6, 6, 5, 6]

kurulum         durdurulan  yanlis alarm  kacan  kesinlik  duyarlilik  yanlis eng
savunmasiz               0             0     93    0.0000      0.0000      0.0000
kural suzgeci           74            23     19    0.7629      0.7957      0.1565

bicim      zararli  kural yakaladi  duyarlilik
dogrudan        37              24      0.6486
dolayli         56              50      0.8929

sinif basina kaynak dagilimi
  temiz              kullanici=100  erisilen_belge= 33  arac_ciktisi= 14
  dolayli_yonerge    kullanici=  2  erisilen_belge= 15  arac_ciktisi=  7
  gizli_alan_istegi  kullanici= 13  erisilen_belge=  4  arac_ciktisi=  0
  yetki_asimi        kullanici=  3  erisilen_belge=  2  arac_ciktisi=  5
  kaynak_taklidi     kullanici=  3  erisilen_belge= 16  arac_ciktisi=  4
  bozulmus_girdi     kullanici= 16  erisilen_belge=  2  arac_ciktisi=  1

Dördüncü satır tasarım kararını doğrular: altı metnin dördü altı sınıfın hepsinde, ikisi beşinde görünüyor. Metin sınıfı taşımıyor.

Taban satırı kursun ölçü çerçevesini kurar. Savunmasız kurulumda durdurulan zararlı 0, yanlış alarm 0, kaçan zararlı 93. Kesinlik ve duyarlılık sıfırdır. Bu satırın orada durması gerekir, çünkü savunmasız kurulumun yanlış alarmı da sıfırdır ve tek başına yanlış alarm sayılırsa hiçbir şey yapmamak kusursuz görünür. Bir savunmanın sayısı ancak iki sütun birlikte okunduğunda anlam kazanır.

Kural süzgeci 93 zararlının 74’ünü durduruyor: duyarlılık 0,7957. Bedeli iki sütunda birden yazılı: 23 temiz kayıt yanlışlıkla engellendi, yani 147 temiz kaydın 0,1565’i. Kesinlik 0,7629 demek, süzgecin işaretlediği her dört kayıttan yaklaşık birinin zararsız olması demektir. Kaçan 19 zararlı da tabloda durur; savunmanın ölçüsü yakaladığı kadar kaçırdığıdır.

Doğrudan ve Dolaylı Biçim

İstem enjeksiyonunun iki biçimi metinle değil kaynakla ayrılır. Doğrudan biçimde zararlı içerik kullanıcının kendi yazdığı istekten gelir. Dolaylı yönerge ise kullanıcının yazmadığı bir yerden gelir: erişilen bir belgenin gövdesinden ya da bir aracın döndürdüğü değerden. Kullanıcı burada kurbandır, kaynak değil. Ayrımın önemi yetkidedir: dolaylı biçimde metni sisteme sokan yol, kullanıcının onayladığı bir yoldur ve o yol genellikle daha geniş bir yetkiyle koşar.

Kaynak dağılımı bu ayrımı sayıya çevirir. 93 zararlı kaydın 37’si kullanıcıdan, 56’sı erişilen belge ya da araç çıktısından geliyor — yüzeyin çoğunluğu dolaylı. Sınıf tablosu bunu sınıflara böler: dolayli_yonerge sınıfının 24 kaydından yalnız 2’si kullanıcıdan, kaynak_taklidi sınıfının 23 kaydından 3’ü. Buna karşılık gizli_alan_istegi 17 kaydın 13’üyle ve bozulmus_girdi 19 kaydın 16’sıyla ağırlıklı olarak doğrudan biçimdir.

Süzgecin iki biçimdeki sayısı aynı değildir: dolaylı biçimde duyarlılık 0,8929, doğrudan biçimde 0,6486. Aradaki fark 0,2443 ve kümenin çözünürlüğünün yirmi katından fazla, yani ölçülebilir bir farktır. Nedeni kural listesindedir: dört kuraldan biri kaynak_damgasi_uyusmuyor, dolaylı sınıflarda sık, doğrudan sınıflarda seyrek görülen bir bayraktır. Süzgeç yüzeyin bir yanında öbüründen belirgin biçimde zayıftır ve tek bir ortalama duyarlılık bunu gizler: toplam oran, alt kümelerin farkını yutar.

Ölçünün Bandı

Kural süzgeci örnekleme içermez; aynı küme üzerinde her koşumda tam olarak aynı beş sayıyı verir. Bu yüzden ikinci koşum süzgeci değil kümeyi değiştirir: aynı tanım, ikinci tohumla yeniden üretilir.

def kume(tohum):
    """Ayni tanim, baska tohum: kayit kumesi yeniden uretilir."""
    ks = []
    for i in range(240):
        r = uretec(tohum + 6151 * i)
        s = SINIF[ayrik(r(), [0.62, 0.10, 0.07, 0.07, 0.07, 0.07])]
        kaynak = KAYNAK[ayrik(r(), KAYNAK_PAYI[s])]
        oz = {o: (r() < p) for o, p in zip(OZELLIK, PROFIL[s])}
        ks.append({"no": i + 1, "sinif": s, "kaynak": kaynak, "ozellik": oz,
                   "metin": METIN[int(r() * len(METIN))], "uzunluk": 40 + int(r() * 260)})
    return ks


IKINCI = kume(20260219)
print("kosum    zararli  temiz  durdurulan  yanlis alarm  duyarlilik  yanlis eng")
for ad, ks in (("birinci", KAYIT), ("ikinci ", IKINCI)):
    m = olc(ks, kural_suzgeci)
    print(f"{ad}  {sum(1 for k in ks if zararli(k)):>8} {sum(1 for k in ks if not zararli(k)):>6}"
          f" {m['dp']:>11} {m['yp']:>13} {m['duyarlilik']:>11.4f}"
          f" {m['yanlis_engelleme_payi']:>11.4f}")

print("\nikinci kosumda bicim ayrimi")
for ad, kosul in (("dogrudan", lambda k: k["kaynak"] == "kullanici"),
                  ("dolayli ", lambda k: k["kaynak"] != "kullanici")):
    g = [k for k in IKINCI if zararli(k) and kosul(k)]
    y = sum(1 for k in g if kural_suzgeci(k))
    print(f"  {ad}  zararli {len(g):>3}  yakalanan {y:>3}  duyarlilik {y / len(g):.4f}")
print("\ncozunurluk: duyarlilik adimi", round(1 / 93, 4),
      " yanlis engelleme adimi", round(1 / 147, 4))
kosum    zararli  temiz  durdurulan  yanlis alarm  duyarlilik  yanlis eng
birinci        93    147          74            23      0.7957      0.1565
ikinci         83    157          58            31      0.6988      0.1975

ikinci kosumda bicim ayrimi
  dogrudan  zararli  36  yakalanan  18  duyarlilik 0.5000
  dolayli   zararli  47  yakalanan  40  duyarlilik 0.8511

cozunurluk: duyarlilik adimi 0.0108  yanlis engelleme adimi 0.0068

İkinci koşum tek bir sayıya güvenmenin neden yetmediğini gösterir. Aynı süzgeç, aynı kurallar, aynı üreteç; yalnız kümenin çekilişi değişti ve duyarlılık 0,7957’den 0,6988‘e, yanlış engelleme payı 0,1565’ten 0,1975’e gitti. Bunun nedeni süzgecin kötüleşmesi değil kümenin bileşiminin değişmesidir: ikinci kümede zararlı sayısı 93 yerine 83 ve süzgecin zayıf olduğu bozulmus_girdi sınıfı 19 yerine 25 kayıt taşıyor. Bir savunmanın sayısı, ölçüldüğü kümenin bir özelliğidir. Bu yüzden bu kursta her oranın yanına hangi kümede ölçüldüğü yazılır.

Değişmeyen tek şey biçimler arası sıralamadır: ikinci koşumda da dolaylı biçim (0,8511) doğrudan biçimden (0,5000) belirgin biçimde yüksek. Küme değiştiğinde oranlar kaydı, ilişki durdu. Koşumdan bağımsız olan şey oran değil, iki alt kümenin birbirine göre yeri. Son satır bandın alt sınırını yazar: bu adımlardan küçük hiçbir fark bu kümede bir bulgu değildir.

Özet

  • İstem enjeksiyonu, dil modeli için veri ile yönergenin aynı bağlam penceresinde ayrımsız durmasından doğar; kaynak ne olursa olsun metin aynı biçimde girer.
  • Saldırı bir metin değil bir öznitelik profilidir: kayıtların metni zararsız destek talebidir ve altı metnin dördü altı sınıfın hepsinde görünür.
  • Savunmasız tabanda durdurulan zararlı 0, yanlış alarm 0, kaçan zararlı 93; yanlış alarmı tek başına okumak hiçbir şey yapmamayı kusursuz gösterir.
  • Kural süzgeci 93 zararlının 74’ünü durdurur (duyarlılık 0,7957), 23 temiz kaydı engeller (yanlış engelleme payı 0,1565) ve kesinliği 0,7629’dur.
  • Doğrudan biçimde 37, dolaylı biçimde 56 zararlı vardır; süzgecin duyarlılığı dolaylıda 0,8929, doğrudanda 0,6486 ve tek bir ortalama bu farkı gizler.
  • Kümenin çözünürlüğü duyarlılıkta 0,0108, yanlış engelleme payında 0,0068’dir; ikinci koşumda oranlar kayar, biçimler arası sıralama durur.

Sonraki Adım

Kural süzgecinin en sert yanı keskinliğidir: bir bayrak ya vardır ya yoktur, ara değer yoktur ve listeye yazılmamış her yapı sessizce geçer. Karşısındaki yaklaşım bir puan üretip bir eşikle karar vermektir, ve o eşik bir ayardır. Sonraki ders bu ayarı süpürür ve güvenlik süzgecinin atlatılmasını bir yordam olarak değil bir eşik sorusu olarak ele alır: eşik yükseldikçe kesinlik artıp duyarlılık düşerken savunmanın hangi sınıfta önce çöktüğü ve atlatmaya en açık noktanın hangi eşikte ortaya çıktığı sayılır.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat