Savunma programlaması - Defensive programming

Savunmacı programlama , öngörülemeyen koşullar altında bir yazılım parçasının devam eden işlevini sağlamayı amaçlayan bir savunma tasarımı biçimidir . Savunma amaçlı programlama uygulamaları genellikle yüksek kullanılabilirlik , güvenlik veya güvenlik gerektiğinde kullanılır.

Savunmacı programlama, yazılımı ve kaynak kodunu aşağıdakiler açısından geliştirmeye yönelik bir yaklaşımdır :

  • Genel kalite – yazılım hatalarının ve problemlerinin sayısını azaltmak .
  • Kaynak kodunu anlaşılır hale getirme – kaynak kodun okunabilir ve anlaşılabilir olması, böylece bir kod denetiminde onaylanması gerekir .
  • Beklenmeyen girdilere veya kullanıcı eylemlerine rağmen yazılımın öngörülebilir bir şekilde davranmasını sağlamak.

Bununla birlikte, aşırı defansif programlama, asla karşılaşılmayacak hatalara karşı koruma sağlayabilir, böylece çalışma süresi ve bakım maliyetleri ortaya çıkar. Ayrıca, kod tuzaklarının çok fazla istisnayı engellemesi ve potansiyel olarak fark edilmeyen, yanlış sonuçlara yol açması riski de vardır .

Güvenli programlama

Güvenli programlama, bilgisayar güvenliğiyle ilgili savunma amaçlı programlamanın alt kümesidir . Güvenlik endişedir, mutlaka güvenlik veya kullanılabilirlik değil ( yazılımın belirli şekillerde başarısız olmasına izin verilebilir). Her türlü savunma programlamasında olduğu gibi, hatalardan kaçınmak birincil hedeftir; bununla birlikte, motivasyon, normal çalışmadaki arıza olasılığını azaltmak kadar (sanki endişe güvenlikmiş gibi) değil, saldırı yüzeyini azaltmaktır - programcı, yazılımın hataları ortaya çıkarmak için aktif olarak kötüye kullanılabileceğini ve bunun Hatalar kötü niyetli olarak kullanılabilir.

int risky_programming(char *input) {
  char str[1000]; 
  
  // ...
  
  strcpy(str, input);  // Copy input.
  
  // ...
}

Giriş 1000 karakterin üzerinde olduğunda işlev tanımsız davranışa neden olur. Bazı acemi programcılar, hiçbir kullanıcının bu kadar uzun bir girdi girmeyeceğini varsayarak bunun bir sorun olduğunu düşünmeyebilir. Bu özel hata, arabellek taşması istismarlarını etkinleştiren bir güvenlik açığını gösterir . İşte bu örneğe bir çözüm:

int secure_programming(char *input) {
  char str[1000+1];  // One more for the null character.

  // ...

  // Copy input without exceeding the length of the destination.
  strncpy(str, input, sizeof(str)); 

  // If strlen(input) >= sizeof(str) then strncpy won't null terminate. 
  // We counter this by always setting the last character in the buffer to NUL,
  // effectively cropping the string to the maximum length we can handle.
  // One can also decide to explicitly abort the program if strlen(input) is 
  // too long.
  str[sizeof(str) - 1] = '\0';

  // ...
}

saldırgan programlama

Saldırgan programlama belli hatalar gerektiğini de sözlerine ekledi durularak, savunma programlama bir kategorisidir değil edilmesi savunmaya ele . Bu uygulamada, yalnızca programın denetimi dışından gelen hatalar ele alınacaktır (kullanıcı girişi gibi); Bu metodolojide yazılımın kendisine ve programın savunma hattındaki verilere güvenilmelidir .

Dahili veri geçerliliğine güvenme

Aşırı defansif programlama
const char* trafficlight_colorname(enum traffic_light_color c) {
    switch (c) {
        case TRAFFICLIGHT_RED:    return "red";
        case TRAFFICLIGHT_YELLOW: return "yellow";
        case TRAFFICLIGHT_GREEN:  return "green";
    }
    return "black"; // To be handled as a dead traffic light.
    // Warning: This last 'return' statement will be dropped by an optimizing
    // compiler if all possible values of 'traffic_light_color' are listed in
    // the previous 'switch' statement...
}
saldırgan programlama
const char* trafficlight_colorname(enum traffic_light_color c) {
    switch (c) {
        case TRAFFICLIGHT_RED:    return "red";
        case TRAFFICLIGHT_YELLOW: return "yellow";
        case TRAFFICLIGHT_GREEN:  return "green";
    }
    assert(0); // Assert that this section is unreachable.
    // Warning: This 'assert' function call will be dropped by an optimizing
    // compiler if all possible values of 'traffic_light_color' are listed in
    // the previous 'switch' statement...
}

Yazılım bileşenlerine güvenmek

Aşırı defansif programlama
if (is_legacy_compatible(user_config)) {
    // Strategy: Don't trust that the new code behaves the same
    old_code(user_config);
} else {
    // Fallback: Don't trust that the new code handles the same cases
    if (new_code(user_config) != OK) {
        old_code(user_config);
    }
}
saldırgan programlama
// Expect that the new code has no new bugs
if (new_code(user_config) != OK) {
    // Loudly report and abruptly terminate program to get proper attention
    report_error("Something went very wrong");
    exit(-1);
}

Teknikler

İşte bazı savunma programlama teknikleri:

Akıllı kaynak kodu yeniden kullanımı

Mevcut kod test edildiyse ve çalıştığı biliniyorsa, yeniden kullanılması hataların ortaya çıkma olasılığını azaltabilir.

Bununla birlikte, kodu yeniden kullanmak her zaman iyi bir uygulama değildir, çünkü ilk koda yönelik olası bir saldırının zararlarını da artırır. Bu durumda yeniden kullanım, ciddi iş süreci hatalarına neden olabilir .

Eski sorunlar

Eski kaynak kodu, kitaplıkları, API'leri, konfigürasyonları vb. yeniden kullanmadan önce, eski çalışmanın yeniden kullanım için geçerli olup olmadığı veya eski sorunlara yatkın olup olmadığı dikkate alınmalıdır .

Eski tasarımlar, özellikle eski tasarımlar bu gereksinimler göz önünde bulundurularak geliştirilmediğinde veya test edilmediğinde, eski tasarımların günümüz gereksinimleriyle çalışması beklendiğinde ortaya çıkan sorunlardır.

Birçok yazılım ürününde eski eski kaynak koduyla ilgili sorunlar yaşanmıştır; Örneğin:

  • Eski kod , savunma amaçlı bir programlama girişimi altında tasarlanmamış olabilir ve bu nedenle yeni tasarlanmış kaynak koddan çok daha düşük kalitede olabilir.
  • Eski kod, artık geçerli olmayan koşullar altında yazılmış ve test edilmiş olabilir. Eski kalite güvence testlerinin artık geçerliliği olmayabilir.
    • Örnek 1 : eski kod ASCII girişi için tasarlanmış olabilir, ancak şimdi giriş UTF-8'dir.
    • Örnek 2 : eski kod 32 bit mimarilerde derlenmiş ve test edilmiş olabilir, ancak 64 bit mimarilerde derlendiğinde yeni aritmetik sorunlar ortaya çıkabilir (örn. geçersiz imza testleri, geçersiz tür atamaları, vb.).
    • Örnek 3 : eski kod çevrimdışı makineler için hedeflenmiş olabilir, ancak ağ bağlantısı eklendiğinde savunmasız hale gelir.
  • Eski kod, yeni sorunlar düşünülerek yazılmaz. Örneğin, 1990'da yazılan kaynak kodun birçok kod yerleştirme güvenlik açığına açık olması muhtemeldir , çünkü bu tür sorunların çoğu o zamanlar geniş çapta anlaşılmamıştı.

Miras sorununun dikkate değer örnekleri:

  • Paul Vixie ve David Conrad tarafından "BINDv9 tam bir yeniden yazmadır" olarak sunulan BIND 9 , "Güvenlik tasarımda önemli bir husustu ", güvenlik, sağlamlık, ölçeklenebilirlik ve yeni protokolleri eski eski kodu yeniden yazmak için temel endişeler olarak adlandırıyor.
  • Microsoft Windows , "" Windows Meta Dosyası güvenlik açığından ve WMF biçimiyle ilgili diğer açıklardan zarar gördü . Microsoft Güvenlik Yanıt Merkezi, WMF özelliklerini "1990 civarında WMF desteği eklendi... Bu güvenlik ortamında farklı bir zamandı... hepsine tamamen güvenildi" şeklinde tanımlıyor ve Microsoft'taki güvenlik girişimleri kapsamında geliştirilmiyor.
  • Oracle , SQL enjeksiyonu ve ayrıcalık yükseltme endişelerini ele almadan yazılan eski kaynak kodu gibi eski sorunlarla mücadele ediyor, bu da düzeltilmesi zaman alan ve aynı zamanda eksik düzeltmeler oluşturan birçok güvenlik açığına neden oluyor. Bu, David Litchfield , Alexander Kornbrust , Cesar Cerrudo gibi güvenlik uzmanlarından ağır eleştirilere yol açtı . Ek bir eleştiri gibi kendi güvenlik önerileri, aynı hizada olmadığı varsayılan tesisat (eski sürümlerden büyük ölçüde eski) olan Oracle Database Güvenlik Kontrol birçok uygulama doğru işlevine daha az güvenli eski ayarları gerektirir olarak değiştirilmesi zordur.

kanonikleştirme

Kötü niyetli kullanıcıların yanlış verilerin yeni temsillerini icat etmeleri muhtemeldir. Örneğin, bir program "/etc/ passwd " dosyasına erişimi reddetmeye çalışırsa , bir cracker bu dosya adının "/etc/./passwd" gibi başka bir türevini iletebilir. Kanonikleştirme kütüphaneleri nedeniyle olmayan etmek önlemek hatalar için kullanılabilir kanonik girdi.

"Potansiyel" hatalara karşı düşük tolerans

Soruna yatkın görünen kod yapılarının (bilinen güvenlik açıklarına benzer, vb.) hatalar ve olası güvenlik kusurları olduğunu varsayın. Başparmak temel kural şudur: "Ben her türlü farkında değilim güvenlik açıkları Ben kişilere karşı korumak zorundadır. Do biliyor ve sonra proaktif olmalı!".

Diğer teknikler

  • En yaygın sorunlardan biri, dinamik boyutlu veriler için sabit boyutlu yapıların ve işlevlerin denetlenmeden kullanılmasıdır ( arabellek taşması sorunu). Bu, özellikle C'deki dize verileri için yaygındır . Girdi arabelleğinin maksimum boyutu bir argüman olarak iletilmediğinden, gibi C kitaplığı işlevleri asla kullanılmamalıdır. Gibi C kitaplığı işlevleri güvenli bir şekilde kullanılabilir, ancak programcının, kullanmadan önce sterilize ederek güvenli biçim dizelerinin seçimine dikkat etmesini gerektirir.getsscanf
  • Ağlar üzerinden iletilen tüm önemli verileri şifreleyin/doğrulayın. Kendi şifreleme düzeninizi uygulamaya çalışmayın, bunun yerine kanıtlanmış bir tane kullanın.
  • Aksi ispatlanana kadar tüm veriler önemlidir.
  • Aksi ispatlanana kadar tüm veriler kusurludur.
  • Aksi ispatlanana kadar tüm kodlar güvensizdir.
    • Sen herhangi bir kodun güvenliğini ispat edemez kullanıcı adasında daha canonically, ya: "müşteri asla güvenme" .
  • Verilerin doğruluğu kontrol edilecekse, yanlış olduğunu değil doğru olduğunu doğrulayın.
  • Sözleşmeye göre tasarım
    • Sözleşmeye göre tasarım , sağlanan verilerin (ve bir bütün olarak programın durumunun) sterilize edilmesini sağlamak için ön koşullar , son koşullar ve değişmezleri kullanır . Bu, kodun varsayımlarını belgelemesine ve bunları güvenli bir şekilde yapmasına olanak tanır. Bu, işlevin gövdesini çalıştırmadan önce bir işleve veya yönteme ilişkin argümanların geçerliliğini kontrol etmeyi içerebilir. Bir fonksiyonun gövdesinden sonra, durum veya diğer tutulan verileri kontrol etmek ve çıkışlardan önceki dönüş değeri (kırma/dönüş/atma/hata kodu) yapmak da akıllıca olur.
  • İddialar (aynı zamanda iddialı programlama olarak da adlandırılır )
    • İşlevler içinde, özellikle tüm geçici/yerel örneklemelerde, öğelere başvurmadan önce geçerli olmayan (yani boş) bir şeye başvurmadığınızı ve dizi uzunluklarının geçerli olup olmadığını kontrol etmek isteyebilirsiniz. İyi bir buluşsal yöntem, yazmadığınız kitaplıklara da güvenmemektir. Bu yüzden onları her aradığınızda, onlardan ne aldığınızı kontrol edin. Yolunuzu izleyebilmeniz ve ilk etapta kapsamlı hata ayıklama döngülerine olan ihtiyacı azaltabilmeniz için bir günlükçü ile birlikte bunu yapmak için küçük bir "iddia etme" ve "kontrol etme" işlevleri kitaplığı oluşturmaya yardımcı olur . Günlük tutma kitaplıklarının ve en boy yönelimli programlamanın ortaya çıkmasıyla, savunma programlamasının sıkıcı yönlerinin çoğu hafifletildi.
  • Kodları döndürmek için istisnaları tercih edin
    • Genel olarak konuşursak, bir istemci programcının hazırlıksız olması muhtemel değerleri döndürmek ve dolayısıyla şikayetlerini en aza indirmek ve yazılımınızın sağlamlığını ve güvenliğini artırmak yerine, API sözleşmenizin bir bölümünü uygulayan ve istemci programcısına rehberlik eden anlaşılır istisna mesajları atmak tercih edilir. .

Ayrıca bakınız

Referanslar

  1. ^ "fogo arşivi: Paul Vixie ve David Conrad, Gerald Oskoboiny tarafından BINDv9 ve Internet Security'de <gerald@impression.net>" . etkileyici.net . 2018-10-27 alındı .
  2. ^ "WMF meselesine baktığımızda, oraya nasıl geldi?" . MSRC . Arşivlenmiş orijinal 2006-03-24 tarihinde . 2018-10-27 alındı .
  3. ^ Litchfield, David. "Bugtraq: Oracle, yamalar nerede ???" . seclists.org . 2018-10-27 alındı .
  4. ^ Alexander, Kornbrust. "Bugtraq: RE: Oracle, yamalar nerede ???" . seclists.org . 2018-10-27 alındı .
  5. ^ Cerrudo, Cesar. "Bugtraq: Re: [Tam açıklama] RE: Oracle, yamalar nerede???" . seclists.org . 2018-10-27 alındı .

Dış bağlantılar