Neler yeni

Yazılım Forum

Tüm özelliklerimize erişmek için şimdi bize katılın. Kayıt olduktan ve giriş yaptıktan sonra konu oluşturabilecek, mevcut konulara yanıt gönderebilecek, itibar kazanabilecek, özel mesajlaşmaya erişebilecek ve çok daha fazlasını yapabileceksiniz! Bu hizmetlerimiz ise tamamen ücretsiz ve kurallara uyulduğu sürece sınırsızdır, o zaman ne bekliyorsunuz? Hadi, sizde aramıza katılın!

C/C++ Güvenlik Kodlama Pratikleri: Sağlam ve Güvenli Yazılım Geliştirme Rehberi

Giriş: Neden C/C++ Güvenliği Bu Kadar Önemli?

C/C++ dilleri, sistem programlama, gömülü sistemler, oyun motorları ve yüksek performanslı uygulamalar gibi alanlarda yaygın olarak kullanılmaktadır. Ancak, düşük seviyeli bellek yönetimi ve donanıma yakın erişim imkanı sunmaları, beraberinde ciddi güvenlik riskleri getirmektedir. Hatalı bellek yönetimi, tam sayı taşmaları veya format string zafiyetleri gibi konular, sistemlerin çökmesine, veri sızdırmalarına veya uzaktan kod yürütülmesine yol açabilir. Bu rehber, C/C++ ile güvenli kodlama pratiklerini derinlemesine inceleyerek, geliştiricilerin daha sağlam ve güvenli yazılımlar oluşturmasına yardımcı olmayı amaçlamaktadır. Güvenli yazılım geliştirme, sadece fonksiyonel gereksinimleri karşılamakla kalmaz, aynı zamanda potansiyel saldırılara karşı dayanıklılığı da artırır.

Yaygın C/C++ Güvenlik Zafiyetleri

Birçok C/C++ uygulaması, aşağıdaki zafiyet türlerinden bir veya daha fazlasını barındırabilir. Bu zafiyetleri anlamak, önleyici tedbirler almak için ilk adımdır:
  • Bellek Taşmaları (Buffer Overflows/Underflows): Programın, kendisine ayrılan bellek bölgesinin dışına veri yazması veya okuması durumudur. Özellikle C dilindeki `strcpy`, `sprintf` gibi güvensiz fonksiyonların kullanımıyla ortaya çıkar ve saldırganlara kod yürütme veya bilgi sızdırma imkanı tanır. Bu, C/C++ güvenlik açıklarının en yaygın ve tehlikeli türlerinden biridir.
  • Tam Sayı Taşmaları (Integer Overflows/Underflows): Bir tam sayı değişkeninin temsil edebileceği maksimum veya minimum değeri aşması sonucu beklenmedik, genellikle çok küçük veya çok büyük, bir değer almasıdır. Bu durum, bellek tahsisi boyutlarının yanlış hesaplanmasına veya döngü sınırlarının hatalı çalışmasına yol açarak güvenlik zafiyetlerine zemin hazırlayabilir.
  • Format String Zafiyetleri: `printf`, `sprintf`, `scanf` gibi format string parametresi alan fonksiyonların, format string'in kullanıcı kontrolünde olması durumunda ortaya çıkan zafiyetlerdir. Saldırganlar bu zafiyeti kullanarak yığından (stack) bilgi okuyabilir, rastgele bellek adreslerine veri yazabilir veya program akışını değiştirebilir.
  • Kullanım Sonrası Serbest Bırakma (Use-After-Free): Daha önce serbest bırakılmış (free edilmiş) bir bellek alanına yeniden erişim sağlanmaya çalışılması durumudur. Bu, genellikle bellek bozulmasına, programın çökmesine (segmentation fault) veya saldırganın bu bellek alanını ele geçirerek kendi kodunu çalıştırmasına olanak tanır.
  • Çift Serbest Bırakma (Double-Free): Aynı bellek alanının birden fazla kez serbest bırakılmasıdır. Bu da bellek yapısının bozulmasına ve programın kararsız çalışmasına veya saldırganlar tarafından kötüye kullanılabilecek durumlara yol açabilir.
  • Yarış Koşulları (Race Conditions): Çoklu iş parçacıklı (multithreaded) veya çoklu süreçli (multiprocess) uygulamalarda, birden fazla iş parçacığının/sürecin aynı paylaşılan kaynağa aynı anda erişmeye çalışması ve bu erişimlerin sırasının kritik olması durumunda ortaya çıkan beklenmedik davranışlardır. Doğru senkronizasyon mekanizmalarının kullanılmamasıyla ortaya çıkar.
  • Geçersiz Giriş Doğrulama: Kullanıcıdan veya dış kaynaklardan (ağ, dosya sistemi, veritabanı) alınan verilerin, uygulamanın beklediği format, boyut veya değer aralığına uygun olup olmadığının yeterince kontrol edilmemesi. Bu, enjeksiyon (SQL injection, command injection) veya dosya yolu geçişi gibi birçok farklı saldırıya kapı aralayabilir.

Güvenli Kodlama Prensipleri

Bu zafiyetleri önlemek için yazılım geliştirme sürecinin temelinde yer alması gereken genel güvenlik prensiplerini benimsemek hayati önem taşır:
  • En Az Yetki Prensibi (Principle of Least Privilege): Her bir bileşen, süreç veya kullanıcı, görevini yerine getirmesi için kesinlikle gerekli olan en az yetkiye sahip olmalıdır. Gereksiz yetkilerin kısıtlanması, bir güvenlik ihlali durumunda sistem üzerindeki etkiyi minimize eder.
  • Derinlemesine Savunma (Defense in Depth): Güvenliği sağlamak için tek bir kontrol veya katmana güvenmek yerine, çoklu ve bağımsız güvenlik kontrolleri katmanları oluşturulmalıdır. Bir katman başarısız olsa bile diğer katmanlar sistemi korumaya devam eder.
  • Varsayılan Olarak Güvenli (Fail-Safe Defaults): Bir sistem veya uygulama, bir hata durumunda, beklenmedik bir girişle karşılaştığında veya yapılandırma eksikliği olduğunda varsayılan olarak güvenli bir duruma geçmelidir. Örneğin, dosya erişim izinleri varsayılan olarak kısıtlı olmalı, erişim reddedilmelidir.
  • Güvenli Varsayılanlar (Secure Defaults): Yazılımı dağıtırken, varsayılan yapılandırmaların en güvenli şekilde ayarlandığından emin olun. Kullanıcıların güvenlik ayarlarını manuel olarak yükseltmek yerine, bunları düşürmeleri gerekmelidir.

Pratik Güvenlik Kodlama Yöntemleri

Şimdi C/C++ geliştiricilerinin uygulayabileceği somut pratiklere geçelim:

1. Giriş Doğrulama (Input Validation)
Kullanıcıdan gelen veya dış kaynaklardan (dosya, ağ, ortam değişkenleri) alınan tüm veriler, uygulamada kullanılmadan önce dikkatlice doğrulanmalı, temizlenmeli ve sanite edilmelidir. Asla güvenilir olmayan bir girdiyi doğrudan kullanmayın.
Kod:
// Kötü pratik: Girişi doğrulamadan kullanma - Buffer Overflow riski
void print_user_input_bad(char* input) {
    char buffer[256];
    strcpy(buffer, input); // Hedef tamponun boyutunu kontrol etmeden kopyalama
    printf("Girişiniz: %s\n", buffer);
}

// İyi pratik: Giriş boyutunu kontrol etme ve güvenli fonksiyon kullanma
void print_user_input_good(const char* input) {
    char buffer[256];
    size_t input_len = strlen(input);

    // Girişin hedef tampona sığacağından emin olun
    if (input_len >= sizeof(buffer)) {
        fprintf(stderr, "Hata: Giriş çok uzun! Kısaltılıyor veya reddediliyor.\n");
        // Güvenlik açısından daha iyi bir yaklaşım, girdiyi reddetmek veya kesmektir.
        strncpy(buffer, input, sizeof(buffer) - 1); // Güvenli kopyalama
        buffer[sizeof(buffer) - 1] = '\0'; // Null sonlandırmayı garanti et
    } else {
        strncpy(buffer, input, sizeof(buffer) - 1);
        buffer[sizeof(buffer) - 1] = '\0';
    }
    printf("Girişiniz: %s\n", buffer);
}
Unutmayın: Güvenilir olmayan her veri, potansiyel bir saldırı vektörüdür. Girdiyi her zaman en az ayrıcalık prensibiyle ele alın.

2. Bellek Yönetimi (Memory Management)
C/C++'da manuel bellek yönetimi, hatalara ve dolayısıyla güvenlik açıklarına en açık alandır. Dikkatli ve prensipli bir yaklaşım gerektirir.
  • Dinamik bellek kullanımında hata kontrolleri: `malloc`, `calloc`, `realloc` veya `new` gibi bellek tahsis fonksiyonlarının dönüş değerlerini daima kontrol edin. Bellek tahsisinin başarısız olması (örneğin sistemde yeterli bellek kalmaması durumunda) `NULL` veya `std::bad_alloc` istisnası döndürecektir. Bu durumları ele almamak, programın çökmesine veya bellek bozulmasına yol açabilir.
    Kod:
    // Kötü pratik: malloc sonucunu kontrol etmeme
    char* buf = (char*)malloc(1024);
    // buf NULL olabilir. NULL bir işaretçiye erişmeye çalışmak tanımsız davranışa yol açar.
    // Program çökebilir veya kritik bir güvenlik açığına neden olabilir.
    
    // İyi pratik: malloc sonucunu kontrol etme
    char* buf = (char*)malloc(1024);
    if (buf == NULL) {
        // Bellek tahsis hatası durumunu uygun şekilde ele alın.
        fprintf(stderr, "Bellek tahsis hatası! Programdan çıkılıyor.\n");
        exit(EXIT_FAILURE); // Güvenli bir şekilde çıkış yapın
    }
    // Belleği güvenli bir şekilde kullanın
    // ...
    free(buf); // Belleği serbest bırakmayı unutmayın
    buf = NULL; // Serbest bırakılan işaretçiyi NULL'a ayarlayın (dangling pointer'ı önlemek için)
  • Akıllı İşaretçiler (Smart Pointers) Kullanımı: C++11 ve sonraki sürümlerde `std::unique_ptr`, `std::shared_ptr` ve `std::weak_ptr` gibi akıllı işaretçiler, RAII (Resource Acquisition Is Initialization) prensibini uygulayarak bellek sızıntılarını, kullanım sonrası serbest bırakma (use-after-free) ve çift serbest bırakma (double-free) hatalarını büyük ölçüde azaltır. Akıllı işaretçiler, kapsama alanı dışına çıktıklarında veya referans sayımları sıfıra düştüğünde belleği otomatik olarak serbest bırakır.
    Kod:
    // C++'da std::unique_ptr örneği
    #include <memory>
    #include <iostream>
    
    void process_data_secure() {
        // Bellek tahsisini std::unique_ptr'a bırakıyoruz
        std::unique_ptr<int[]> data(new (std::nothrow) int[100]); // std::nothrow ile NULL döndürür
        if (!data) {
            std::cerr << "Bellek tahsis edilemedi!\n";
            return;
        }
        // 'data' kullanıldıktan sonra otomatik olarak serbest bırakılır, manuel 'delete' gerekmez.
        for (int i = 0; i < 100; ++i) {
            data[i] = i * 2;
        }
        std::cout << "Veri işlendi.\n";
    }
  • Sıfırlama ve Serbest Bırakma: Hassas veri (parola, kriptografik anahtarlar vb.) içeren bellek alanlarını `free` etmeden önce sıfırlamak (örneğin `memset` ile), bu bilgilerin daha sonra bellek dökümlerinde veya saldırganlar tarafından erişilebilir olmasını engelleyebilir.

3. Tam Sayı İşleme (Integer Handling)
Tam sayı taşmaları (overflow/underflow), genellikle güvenlik sorunlarına ve beklenmedik program davranışlarına yol açar. Özellikle bellek tahsisi boyutları, döngü sayıları veya dizin hesaplamaları gibi kritik yerlerde dikkatli olunmalıdır.
  • Taşma Kontrolü: Hesaplama yapmadan önce olası taşmaları kontrol edin. Özellikle çarpma veya toplama işlemlerinde sonuç, değişkenin alabileceği maksimum değeri aşabilir.
    Kod:
    // Kötü pratik: Taşma kontrolü yok
    size_t count = get_user_count(); // Kullanıcıdan gelen büyük bir sayı (örn: SIZE_MAX / sizeof(int) + 1)
    size_t size = count * sizeof(int); // Taşma olursa 'size' yanlış (küçük) bir değer alabilir
    int* arr = (int*)malloc(size); // Yanlış boyut tahsis edilir, buffer overflow'a yol açabilir
    
    // İyi pratik: Taşma kontrolü - Önleyici yaklaşım
    size_t count = get_user_count();
    // 'count * sizeof(int)' işleminin taşmasını önlemek için kontrol
    if (count > SIZE_MAX / sizeof(int)) { // SIZE_MAX, size_t tipinin maksimum değeridir
        fprintf(stderr, "Hata: Hesaplanan boyut taşması!\n");
        exit(EXIT_FAILURE);
    }
    size_t size = count * sizeof(int);
    int* arr = (int*)malloc(size);
    if (arr == NULL) {
        fprintf(stderr, "Hata: Bellek tahsis edilemedi!\n");
        exit(EXIT_FAILURE);
    }
    // Belleği güvenli bir şekilde kullanın
    // ...
    free(arr);
  • İşaretsiz Tam Sayılara Dikkat: İşaretsiz tam sayılar (unsigned integers) kullanırken underflow (alt akma) durumlarına dikkat edin. Örneğin, `unsigned int x = 0; x--;` işlemi `x`'in çok büyük bir değere (tipinin maksimum değerine) ulaşmasına neden olur. Bu durum, döngülerin sonsuz çalışmasına veya yanlış dizin erişimlerine yol açabilir.

4. Dizgi İşleme (String Handling)
C'deki standart dizgi fonksiyonları (`strcpy`, `strcat`, `sprintf`, `gets`) boyut güvenli değildir ve buffer overflow'a yol açabilir. Bu fonksiyonların kullanımı mümkün olduğunca kaçınılmalı veya çok dikkatli bir şekilde kullanılmalıdır.
  • Güvenli Dizgi Fonksiyonları: Boyut sınırlamalı ve daha güvenli alternatifler kullanın: `strncpy`, `strncat`, `snprintf`. Bu fonksiyonlar, hedef tamponun boyutunu belirterek taşmaları önlemeye yardımcı olur. Ancak `strncpy`'nin her zaman null sonlandırma garantisi vermediğini unutmayın.
    Kod:
    // Kötü pratik: strcpy kullanımı - Bellek taşması
    char buffer[10];
    char* user_input = "Bu çok uzun bir string örneğidir, 10 karakterden fazla.";
    strcpy(buffer, user_input); // Hedef tamponu aşar, bellek bozulması veya güvenlik açığı
    
    // İyi pratik: snprintf kullanımı - Boyut güvenli dizgi biçimlendirme
    char buffer_good[10];
    char* user_input_good = "Kısa string.";
    // snprintf, hedef tampona sığacak kadar yazar ve her zaman null sonlandırır (alan varsa).
    // Eğer formatlanan string tampona sığmazsa, kesilir.
    snprintf(buffer_good, sizeof(buffer_good), "%s", user_input_good);
    printf("Güvenli kopyalama: %s\n", buffer_good); // Çıktı: "Kısa string."
    
    char* long_user_input = "Bu da biraz daha uzun bir stringtir.";
    snprintf(buffer_good, sizeof(buffer_good), "%s", long_user_input);
    printf("Kesilmiş kopyalama: %s\n", buffer_good); // Çıktı: "Bu da bir"
  • Null Sonlandırma: C dizgileri her zaman null ( `\0` ) karakteri ile sonlandırılmalıdır. `strncpy` gibi bazı fonksiyonlar, kaynak dizgi hedef tamponun tamamını doldurursa null sonlandırma garantisi vermez. Bu durumda, manuel olarak null sonlandırma yapmak önemlidir.

5. Eşzamanlılık (Concurrency) ve Yarış Koşulları
Çoklu iş parçacıklı (multithreaded) veya çoklu süreçli uygulamalarda paylaşılan kaynaklara erişim, yarış koşullarına ve bellek bozulmalarına yol açabilir. Doğru senkronizasyon mekanizmalarının kullanılması hayati önem taşır.
  • Mutex ve Kilitler: Paylaşılan verilere eşzamanlı erişimi senkronize etmek için mutex (karşılıklı dışlama), okuyucu-yazıcı kilitleri veya spinlock gibi mekanizmalar kullanın. Bu, kritik bölümlere aynı anda birden fazla iş parçacığının erişmesini engeller.
  • Atomik İşlemler: Basit, tek işlemde tamamlanan güncellemeler (örneğin sayaç artırma) için `std::atomic` (C++11+) gibi atomik operasyonları tercih edin. Bu işlemler, kilit mekanizmalarına göre daha hafif ve performanslı olabilir.
  • Kilitlenme (Deadlock) ve Canlı Kilitlenme (Livelock) Önleme: Kilitlerin tutarlı bir sırada edinilmesini sağlayın (kilit hiyerarşisi). Kilitlenmeleri önlemek için kaynak tahsisi algoritmalarını veya zaman aşımı mekanizmalarını kullanın.
  • Paylaşılan Verilerin Doğru Yönetimi: Paylaşılan verileri mümkün olduğunca azaltın veya immutable (değiştirilemez) hale getirin. Değiştirilebilir paylaşılan durum, karmaşık senkronizasyon gereksinimleri doğurur.

6. Hata İşleme (Error Handling)
Uygulamaların beklenmedik durumları (bellek tahsisi hatası, dosya okuma hatası, ağ bağlantı kesilmesi vb.) güvenli ve öngörülebilir bir şekilde ele alması çok önemlidir. Hatalı veya eksik hata işleme, bilgi sızıntılarına veya hizmet reddi saldırılarına yol açabilir.
  • Dönüş Değerlerini Kontrol Etme: Fonksiyonların hata kodlarını veya dönüş değerlerini her zaman kontrol edin. Örneğin, `fopen`'dan sonra `NULL` kontrolü veya `read`'den sonra okunan bayt sayısını kontrol etmek.
  • Güvenli Çıkış Noktaları: Hata durumunda programın güvenli bir şekilde sonlanmasını veya hata durumundan kurtulmasını sağlayın. Hassas verileri bellekte veya log dosyalarında bırakmadan temizleyin.
  • Anlamlı Hata Mesajları: Hata mesajları, sorun giderme için yeterli bilgi sağlamalıdır ancak saldırganlara sistem hakkında gereksiz bilgi vermemelidir. Detaylı hata bilgileri sadece geliştirme/debug ortamlarında veya güvenli log dosyalarında bulunmalıdır.

7. Derleyici Uyarıları ve Statik/Dinamik Analiz Araçları
Kod kalitesini ve güvenliğini artırmak için geliştirme sürecinde çeşitli araçları kullanmak kritik öneme sahiptir.
  • Derleyici Uyarılarını Ciddiye Alma: Derleyicileri en yüksek uyarı seviyesinde (`-Wall -Wextra -Werror` GCC/Clang için, `/W4` veya `/WAll` MSVC için) kullanın ve tüm uyarıları düzeltin. Derleyici uyarıları genellikle potansiyel güvenlik açıklarını, tanımsız davranışları veya programlama hatalarını gösterir ve asla göz ardı edilmemelidir. `-Werror` kullanmak, uyarıların hata olarak kabul edilmesini sağlayarak, derlenmeye devam etmemesini garanti eder.
  • Statik Analiz Araçları: Kod çalıştırmadan önce kaynak kodda güvenlik açıklarını, hataları ve potansiyel zafiyetleri bulmak için SonarQube, PVS-Studio, Coverity, Clang-Tidy, Cppcheck gibi araçları kullanın. Bu araçlar, geliştirme döngüsünün erken aşamalarında sorunları tespit ederek düzeltme maliyetini düşürür.
  • Dinamik Analiz Araçları: Çalışma zamanında bellek hatalarını (bellek sızıntıları, kullanım sonrası serbest bırakma, sınır dışı erişimler) ve tanımsız davranışları tespit etmek için Valgrind, AddressSanitizer (ASan), UndefinedBehaviorSanitizer (UBSan) gibi araçları kullanın. Bu araçlar, kodun gerçek çalışma koşullarında nasıl davrandığını gözlemleyerek kritik hataları ortaya çıkarabilir.
  • Fuzzing (Fuzz Testing): Uygulamanıza rastgele veya yarı-rastgele, beklenmedik girdiler sağlayarak, uygulamanın çökmesine, kilitlenmesine veya güvenlik açıklarına neden olan durumları bulmak için fuzzing araçları (örn. AFL++, libFuzzer) kullanın.

"Güvenlik, bir özellik değil, bir süreçtir. Sürekli iyileştirme ve adaptasyon gerektirir."
Bu alıntı, güvenliğin tek seferlik bir işlem olmadığını, yazılım geliştirme yaşam döngüsünün her aşamasında sürekli bir çaba gerektirdiğini vurgular.

8. Güvenli Geliştirme Yaşam Döngüsü (SDL)
Güvenliği, yazılım geliştirme sürecinin her aşamasına entegre etmek, proaktif bir yaklaşımla zafiyetleri en baştan ele almanızı sağlar:
  • Tasarım Aşaması: Tehdit modellemesi yapın, potansiyel saldırı vektörlerini belirleyin ve güvenlik gereksinimlerini tanımlayın.
  • Kodlama Aşaması: Güvenli kodlama standartlarına uyun, kod incelemeleri (peer reviews) yapın ve statik analiz araçlarını kullanın.
  • Test Aşaması: Birim testlerinin yanı sıra, güvenlik testleri (sızma testleri, zafiyet taramaları, fuzzing) uygulayın.
  • Dağıtım ve Bakım: Güvenlik güncellemelerini takip edin ve uygulayın. Loglamayı ve izlemeyi etkinleştirin. Ortaya çıkan yeni zafiyetlere karşı yamaları hızla dağıtın.

Ek Kaynaklar ve Standartlar
C/C++ güvenliği konusunda daha fazla bilgi edinmek ve en güncel pratikleri takip etmek için aşağıdaki güvenilir kaynakları inceleyebilirsiniz:
  • OWASP (Open Web Application Security Project) - Web uygulamaları güvenliği alanında lider bir kuruluştur, ancak sunduğu genel güvenlik prensipleri C/C++ uygulamaları için de geçerlidir.
  • CERT Secure Coding Guidelines (C and C++) - Carnegie Mellon Üniversitesi Yazılım Mühendisliği Enstitüsü (SEI) tarafından yayınlanan, C ve C++ dilleri için özel olarak hazırlanmış detaylı güvenli kodlama kılavuzlarıdır. Pratik örneklerle doludur.
  • ISO C++ Standard - C++ dilinin kendisini ve standart kütüphanesini tanımlayan resmi belgedir. Doğrudan güvenlik pratiklerini ele almasa da, dilin davranışlarını derinlemesine anlamak için önemlidir.
  • CWE (Common Weakness Enumeration) - Yazılım zafiyetlerinin sınıflandırılmış, hiyerarşik bir listesidir. Güvenlik analizi araçları ve danışmanlık hizmetleri tarafından referans alınır.
  • BSI IT-Grundschutz (Bilgi Güvenliği Temel Koruma) - Alman Federal Bilgi Güvenliği Ofisi (BSI) tarafından yayınlanan, kurumsal bilgi güvenliği için kapsamlı bir standarttır. Yazılım güvenliğini de kapsar.
728x90

*Yukarıdaki görsel, güvenli yazılım geliştirme sürecinin önemini ve devamlılığını temsil etmektedir.*

Sonuç

C/C++ dilleri, sistemlere derinlemesine erişim ve yüksek performans sunarken, aynı zamanda geliştiricilere büyük sorumluluk yükler. Bu dillerle yazılım geliştirirken güvenliği göz ardı etmek, telafisi zor güvenlik açıkları ve sistem zafiyetlerine yol açabilir. Bu rehberde ele alınan güvenli kodlama pratiklerini benimsemek, potansiyel güvenlik zafiyetlerini proaktif olarak ele almak ve sürekli öğrenmek, daha sağlam, güvenilir ve saldırılara dayanıklı yazılımlar geliştirmek için hayati öneme sahiptir.

Unutmayın, güvenlik bir varış noktası değil, sürekli bir yolculuktur. Her zaman kodunuzu şüpheyle inceleyin ve her zaman "Peki ya bir saldırgan bunu nasıl kullanır?" sorusunu sorun. Bu sürekli sorgulama ve iyileştirme döngüsü, yazılımınızı daha güvenli hale getirecektir. Güvenlik bilincine sahip bir geliştirme kültürü oluşturmak, başarılı ve güvenli projelerin temelidir.

Umarım bu kapsamlı rehber, C/C++ ile daha güvenli kod yazma yolculuğunuzda size yardımcı olur. Sorularınız veya eklemek istedikleriniz olursa, yorumlarda paylaşmaktan çekinmeyin.
 
shape1
shape2
shape3
shape4
shape5
shape6
Üst

Bu web sitenin performansı Hazal Host tarafından sağlanmaktadır.

YazilimForum.com.tr internet sitesi, 5651 sayılı Kanun’un 2. maddesinin 1. fıkrasının (m) bendi ve aynı Kanun’un 5. maddesi kapsamında Yer Sağlayıcı konumundadır. Sitede yer alan içerikler ön onay olmaksızın tamamen kullanıcılar tarafından oluşturulmaktadır.

YazilimForum.com.tr, kullanıcılar tarafından paylaşılan içeriklerin doğruluğunu, güncelliğini veya hukuka uygunluğunu garanti etmez ve içeriklerin kontrolü veya araştırılması ile yükümlü değildir. Kullanıcılar, paylaştıkları içeriklerden tamamen kendileri sorumludur.

Hukuka aykırı içerikleri fark ettiğinizde lütfen bize bildirin: lydexcoding@gmail.com

Sitemiz, kullanıcıların paylaştığı içerik ve bilgileri 6698 sayılı KVKK kapsamında işlemektedir. Kullanıcılar, kişisel verileriyle ilgili haklarını KVKK Politikası sayfasından inceleyebilir.

Sitede yer alan reklamlar veya üçüncü taraf bağlantılar için YazilimForum.com.tr herhangi bir sorumluluk kabul etmez.

Sitemizi kullanarak Forum Kuralları’nı kabul etmiş sayılırsınız.

DMCA.com Protection Status Copyrighted.com Registered & Protected