Belajar C Language - Security & Safe Coding
Episode 13 of 24

Belajar C Language - Security & Safe Coding

Episode ini membahas keamanan kode C: buffer overflow dan format string vulnerabilities beserta mitigasinya, secure coding dengan bounds checking memakai strncpy dan snprintf, perbedaan stack dan heap overflow, serta input validation dan defensive programming.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Pendahuluan

C memberi kalian kontrol penuh atas memori, dan kontrol penuh berarti tanggung jawab penuh. Episode 13 membahas kelas bug paling berbahaya dalam pemrograman C: buffer overflow dan format string vulnerabilities, yang selama bertahun-tahun menjadi penyebab exploit paling terkenal di internet.

Kabar baiknya, sebagian besar bug ini bisa dicegah dengan pola yang disiplin: memakai fungsi yang menerima ukuran buffer, memeriksa batas sebelum akses, dan memperlakukan semua input sebagai data yang tidak bisa dipercaya.

Episode ini adalah titik balik: setelah ini, kalian tidak akan lagi menulis fungsi string yang rentan, dan akan membangun kebiasaan defensive programming yang melindungi pengguna program kalian.

Buffer Overflow

Apa Itu Buffer Overflow

Buffer overflow terjadi ketika data ditulis melebihi kapasitas buffer, menginjak memori di sekitarnya. Contoh klasik:

Kode rentan overflow
#include <stdio.h>
#include <string.h>
 
int main(int argc, char *argv[]) {
    char buffer[16];
    strcpy(buffer, argv[1]);
    printf("%s\n", buffer);
    return 0;
}
EOF

strcpy(buffer, argv[1]) menyalin tanpa memeriksa panjang. Jika argv[1] lebih dari 15 karakter, data menimpa memori di sekitar buffer, bisa mengubah alamat kembali fungsi. Penyerang yang mengontrol isi overflow bisa mengeksekusi kode sewenang-wenang.

Mitigasi dari Kompiler dan OS

Sistem modern memasang pertahanan berlapis. Kompiler menambahkan stack protector yang mendeteksi penimpaan; kernel menandai halaman stack dan heap sebagai non-executable. Aktifkan pertahanan saat kompilasi:

Aktifkan mitigasi
gcc -fstack-protector-strong -D_FORTIFY_SOURCE=2 program.c -o program

Bendera -fstack-protector-strong menyisipkan pemeriksaan canary pada fungsi yang memakai buffer. Pertahanan ini memperlambat exploit, tetapi tetap wajib menulis kode yang tidak rentan sejak awal — mitigasi bukan pengganti kode aman.

Format String Vulnerabilities

Memakai Format String sebagai Argumen

Ketika string pengguna dipakai langsung sebagai format string printf, penyerang bisa membaca atau menulis memori. Kode berikut rentan:

Vulnerable dan aman
printf(buffer);
printf("%s", buffer);

Panggilan printf(buffer) memperlakukan isi buffer sebagai format string, sehingga token seperti %x dan %n dieksekusi. Versi aman printf("%s", buffer) selalu memperlakukan buffer sebagai data. Aturan emas: format string harus selalu literal, tidak pernah berasal dari input.

Dampak dan Deteksi

Serangan format string bisa membocorkan isi stack dan menulis ke memori arbitrer melalui %n. Alat seperti -Wformat-security dan clang-tidy memperingatkan ketika format string bukan literal. Kompilasi dengan -Wformat=2 -Wformat-security sejak awal untuk menangkap pola ini lebih dini.

Secure Coding dengan Bounds Checking

Memakai strncpy dan snprintf

Fungsi string lama menyalin tanpa batas. Penggantinya menerima ukuran buffer sebagai parameter:

Salin dan format yang aman
#include <stdio.h>
#include <string.h>
 
int main(void) {
    char nama[16];
    strncpy(nama, "Arman Dwi Pangestu", sizeof(nama) - 1);
    nama[sizeof(nama) - 1] = '\0';
 
    char pesan[64];
    snprintf(pesan, sizeof(pesan), "Halo %s", nama);
    puts(pesan);
    return 0;
}
EOF

strncpy(nama, "...", sizeof(nama) - 1) membatasi jumlah karakter yang disalin, dan baris berikutnya menjamin karakter nol di akhir. snprintf menulis paling banyak sizeof(pesan) byte dan selalu mengakhiri dengan nol. Kedua fungsi ini adalah standar emas untuk menyalin dan memformat string dengan aman.

Menghindari gets dan scanf Tanpa Batas

Fungsi gets tidak memiliki parameter ukuran dan tidak pernah boleh dipakai. Untuk membaca baris, selalu gunakan fgets dengan ukuran buffer. Saat membaca angka dengan scanf, batasi lebar field, misalnya %19s untuk string berukuran 20.

Input Validation dan Defensive Programming

Memperlakukan Input sebagai Musuh

Semua input eksternal — argumen, file, jaringan — harus dianggap tidak dapat dipercaya. Langkah pertamanya adalah memvalidasi sebelum memproses:

Validasi input
if (argc != 2) {
    fprintf(stderr, "gunakan: program <nilai>\n");
    return 1;
}
 
long nilai = strtol(argv[1], NULL, 10);
if (nilai < 0 || nilai > 1000) {
    fprintf(stderr, "nilai di luar jangkauan\n");
    return 1;
}

strtol(argv[1], NULL, 10) mengonversi string ke bilangan dengan pemeriksaan error yang bisa dideteksi lewat errno dan pointer posisi akhir. Validasi jangkauan dilakukan sebelum nilai dipakai. Pola ini mencegah input aneh mencapai logika internal.

Prinsip Defensive Programming

Tiga prinsip yang selalu diterapkan: periksa setiap nilai kembalian, periksa batas setiap akses array, dan asumsikan fungsi lain bisa gagal. Assert memperkuat asumsi internal, sanitizers di episode 11 memvalidasi kebenaran saat pengembangan, dan uji dengan input ekstrem menjadi kebiasaan rutin.

Warning

Validasi bukan hanya tentang keamanan. Input yang tidak terduga juga membuat program crash dengan cara yang tidak elegan. Menolak input sejak awal, dengan pesan jelas, jauh lebih baik daripada gagal di tengah pemrosesan.

Penutup

Inti yang harus dibawa pulang:

  • Buffer overflow menimpa memori di sekitar buffer karena menyalin tanpa batas.
  • Format string harus selalu literal, tidak pernah berasal dari input.
  • strncpy dan snprintf membatasi jumlah karakter dengan parameter ukuran.
  • Jangan pernah memakai gets; gunakan fgets dengan ukuran buffer.
  • Anggap semua input eksternal tidak dapat dipercaya dan validasi lebih dulu.
  • Mitigasi compiler menambah pertahanan, tetapi tidak menggantikan kode aman.

Di episode 14 selanjutnya kita akan membahas cryptography dan data protection — konsep dasar cryptography di C, library OpenSSL dan libsodium untuk enkripsi, hashing, HMAC, dan random number generation, hingga secure key handling dan manajemen data sensitif.

Belajar C Language - Security & Safe Coding | Belajar C Language