Apa risiko / kerentanan keamanan yang harus diperhatikan oleh setiap programmer C? [Tutup]

13

Ada banyak risiko keamanan yang berasal dari kontak dekat dengan perangkat keras yang bertentangan dengan penggunaan API yang teruji dan terbukti dari bahasa pemrograman tingkat tinggi. Jauh lebih mudah untuk menyebabkan buffer overflow dalam C daripada dalam bahasa seperti Java.

Apa risiko atau kerentanan (misalnya buffer overflows) yang harus diperhatikan oleh setiap programmer C (kerentanan IE yang relevan dengan programmer C)? Masalah apa yang bisa menyebabkan ini? Bagaimana menghindarinya, dan kesalahan umum apa yang menyebabkan ini terjadi dalam program?

Anto
sumber
Bagaimana dengan daftar ini: owasp.org/index.php/Category:OWASP_Top_Ten_Project Apa yang lebih dibutuhkan dari ini?
S.Lott
2
@ S.Lott: Tampaknya sangat banyak tentang masalah keamanan dalam pengembangan web. Tampaknya ada lebih banyak sumber daya tentang itu secara umum daripada apa yang sebenarnya saya minta, tampaknya.
Anto
@Anto: Perbarui pertanyaan untuk membedakan antara semua sumber daya tentang keamanan dan keamanan yang Anda tanyakan.
S.Lott
@ S.Lott: Saya tidak yakin apa yang Anda maksud. Saya meminta keamanan yang penting bagi sebagian besar programmer C, yaitu, hal-hal seperti buffer overflows dan hal-hal lain yang mungkin dalam C.
Anto
@Anto: "Tampaknya ada lebih banyak sumber daya pada [keamanan web?] Secara umum daripada apa yang sebenarnya saya minta" Sepertinya Anda bertanya tentang beberapa keamanan yang bukan keamanan web. Benar? Jika demikian, harap perbarui pertanyaan untuk menjelaskan apa yang Anda cari. Salah? Maka Anda sedang bertanya tentang keamanan web, dalam hal ini, mengapa tidak daftar OWASP disebutkan dalam pertanyaan Anda?
S.Lott

Jawaban:

13

Buffer overflow adalah hal yang besar. Tidak ada dalam C yang dicentang kisaran secara default, jadi sangat mudah untuk menimpa buffer. Ada fungsi pustaka standar gets(),, yang tidak dapat berhenti meluap dari buffer, dan hampir tidak boleh digunakan.

Ada beberapa teknik tingkat implementasi untuk menghambat eksploitasi, seperti pengacakan tumpukan blok, tetapi itu tidak akan menghentikan buffer overflows di buffer lokal, yang sering dapat melakukan hal-hal menarik seperti mengubah alamat tempat fungsi akan kembali.

Tidak ada solusi umum yang baik dalam C. Banyak fungsi perpustakaan memiliki versi yang akan membatasi jumlah yang akan mereka tulis. meski menghitung itu bisa canggung. Ada perangkat lunak yang dapat mendeteksi tumpukan buffer berlebih dalam pengujian, selama pengujian yang sesuai dijalankan, dan stack overflow sering muncul sebagai crash dalam pengujian. Selain itu, ini adalah masalah pengkodean dan tinjauan kode yang cermat.

Masalah terkait adalah masalah penulisan ke buffer terlalu kecil oleh satu karakter, lupa bahwa string C yang panjang n karakter memerlukan n +1 karakter dalam memori, karena '\0'terminator. Jika penyerang dapat mengelola untuk menyimpan string tanpa terminator, fungsi C apa pun yang mengharapkan string akan terus memproses hingga mencapai nol byte, yang dapat mengakibatkan menyalin atau mengeluarkan informasi lebih banyak dari yang diinginkan (atau memukul memori yang dilindungi untuk serangan DOS) ). Solusinya, sekali lagi, adalah kesadaran, kepedulian, dan ulasan kode.

Ada risiko lain dengan printf()keluarga. Jika Anda pernah menulis char * str; ... printf(str);, Anda sedang mengatur diri sendiri untuk masalah jika strberisi '%' saat dicetak. The %nFormat direktif memungkinkan printf()untuk menulis ke memori. Solusinya adalah printf("%s", str);atau puts(str);. (Juga, gunakan C99 snprintf()sebagai ganti sprintf().)

Menggunakan bilangan bulat yang tidak ditandatangani, terutama sebagai indeks loop, dapat menyebabkan masalah. Jika Anda menetapkan nilai negatif kecil untuk yang tidak ditandatangani, Anda mendapatkan nilai positif yang besar. Itu dapat merusak hal-hal seperti hanya memproses N contoh sesuatu, atau dalam fungsi terbatas seperti strncpy(). Periksa semua bilangan bulat yang tidak ditandatangani. Anda mungkin ingin menghindari unsigned short, karena nilai besar di salah satu dari mereka akan dikonversi ke nilai positif besar dalam int.

Jangan lupa bahwa konstanta karakter, dalam C, sebenarnya adalah int. Menulis sesuatu seperti char c; while((c = getchar()) != EOF) ...dapat dengan mudah gagal, karena EOFtidak dapat diwakili dalam char.

Ada banyak kesalahan karakteristik C yang bisa saya pikirkan, tetapi ini bisa menyebabkan masalah keamanan.

David Thornley
sumber
Tidak perlu menggunakan printf("%s", str)string telanjang saat puts(str)akan melakukan pekerjaan yang sama.
Blrfl
@ Blrfl tetapi putsmenambahkan karakter baris baru sementara printftidak.
rightfold
Bisa juga fputs(str, stdout), yang tidak.
Blrfl
Mengenai integer overflow: Menggunakan int yang ditandatangani bukanlah solusi, karena melimpahi mereka akan menyebabkan UB. Satu-satunya solusi (menyakitkan) adalah dengan membuktikan secara formal bahwa Anda tidak akan pernah overflow, atau periksa saat runtime (tetapi periksa dengan benar, yang juga rumit tanpa meluap di cek).
sleske
@ Davidvidhorn: C11 & C ++ 14 standar dihapus mendapat () fungsi dari perpustakaan standar karena bahayanya.
Destructor
5

Beberapa risiko spesifik-C meliputi: buffer overflows , pemformatan serangan string, dan integer overflows .

Nemanja Trifunovic
sumber
1
Tidak ada yang spesifik-C tentang buffer overflows - bahasa apa pun dengan pointer dapat memiliki ini. Overflow bilangan bulat berlaku untuk hampir semua bahasa, dan dapat dengan mudah terjadi dalam kode terkelola juga.
Steve
1
@Steve, itu bukan pointer yang menyebabkan masalah itu tetapi bagaimana bahasa tidak menegakkan batasan array.
Doug T.
2
@ Katakan pertanyaan itu bukan menanyakan tentang hal-hal yang hanya menyangkut C, tetapi sesuatu yang harus diperhatikan oleh programmer C.
AttackingHobo
1
@Steve: C sangat rentan terhadap buffer overflow, sebagian karena kurangnya dukungan untuk pemeriksaan rentang, dan jumlah fungsi pustaka yang dengan senang hati akan melimpah buffer untuk Anda.
David Thornley
Saya mengerti pertanyaannya adalah menanyakan tentang C secara khusus, tetapi saya pikir perlu diklarifikasi jika jawabannya dibacakan di luar konteks bahwa risiko ini lebih umum. Khususnya pengembang kode terkelola (IMHO) terlalu puas dengan keamanan, dan kelebihan integer mempengaruhi sebagian besar bahasa.
Steve
4

Berikut ini adalah risiko yang mudah terlewatkan yang dapat menyebabkan masalah yang membutuhkan waktu berjam-jam untuk diperbaiki.

Pertimbangkan kode berikut, yang akan dikompilasi tanpa masalah.

if(lpstr_current_state = CONST_EMERGENCY_STATE_HOLY_CRAP)
{
    do_warn_joint_chiefs_of_staff_of_nuclear_attack();
}

Ketika Anda memeriksa untuk melihat apakah lpstr_current_stateada di dalam CONST_EMERGENCY_STATE_HOLY_CRAPAnda sebenarnya menugaskan. Lebih baik untuk selalu meletakkan variabel konstan di sebelah kiri. Ketika Anda meletakkan konstanta di sebelah kiri, maka kompiler akan gagal karena Anda tidak dapat menetapkan nilai ke variabel.

if(CONST_EMERGENCY_STATE_HOLY_CRAP = lpstr_current_state)
{
    do_warn_joint_chiefs_of_staff_of_nuclear_attack();
}

Maka Anda dapat dengan mudah berkata pada diri sendiri, "Aduh, itu bisa saja buruk", sambil memperbaiki kode untuk membaca ...

if(CONST_EMERGENCY_STATE_HOLY_CRAP == lpstr_current_state)
{
    do_warn_joint_chiefs_of_staff_of_nuclear_attack();
}
Kristofer Hoch
sumber
7
Itu mudah bagi kompiler untuk menangkap dan menandai sebagai peringatan, tidak seperti beberapa masalah lainnya. Sayangnya, tidak semua kompiler membuatnya mudah dilakukan.
David Thornley
2
Itu bisa terjadi dalam bahasa selain C, bahasa apa pun yang menggunakan =dan ==.
FrustratedWithFormsDesigner
3
Ini juga bukan kerentanan keamanan, ini bug.
Chris Pitman
1
Ini disebut kondisi Yoda.
2
@Kristofer Hoch: Jika kita akan menyebut kemungkinan bug C sebagai risiko, dan pertimbangkan di sini, kita akan membutuhkan forum yang jauh lebih besar.
David Thornley
0

Hanya ada satu risiko keamanan: Fakta bahwa ada orang di luar yang akan melakukan yang terbaik untuk menangkap kerentanan apa pun dalam perangkat lunak Anda dan memanfaatkannya untuk keuntungan mereka sendiri. Segala sesuatu yang lain mengikuti dari sana.

Jadi, ketika Anda berpikir "tidak ada orang waras yang akan ...", maka Anda harus segera berpikir "kecuali seseorang yang ingin meretas komputer orang lain akan melakukan hal itu".

Konsekuensi terbesar adalah bahwa setiap kali Anda bereaksi terhadap peristiwa di luar (misalnya, dengan memproses data yang dikirim dari luar), Anda harus menganggap bahwa data ini berada di bawah kendali musuh terburuk Anda.

gnasher729
sumber
Sementara saya akan setuju dengan paragraf dua dan tiga, menyalahkan semua penyerang agak tebal di mata saya. Selalu butuh dua untuk serangan yang sukses: Seorang programmer yang gagal, dan seorang penyerang yang menangkap programmer dalam tindakan. Namun, kerentanan keamanan ada sebelum penyerang dapat mengeksploitasinya. Dan untuk itu, programmer harus disalahkan.
cmaster - mengembalikan monica