Kerentanan dalam kode. Bagaimana Anda bisa membedakan kesalahan berbahaya dari kesalahan kecil?

Bagaimana biasanya terlihat seperti memeriksa kode aplikasi untuk mengetahui kerentanan? Spesialis keamanan memulai prosedur, kode dipindai, dan ribuan kerentanan ditemukan dalam aplikasi. Semua orang - baik petugas keamanan dan pengembang - terkejut. Reaksi alami dari pengembang: "Ya, tentu saja separuh adalah positif palsu, dan yang lainnya adalah kerentanan non-kritis!"



Sedangkan untuk positif palsu, semuanya sederhana di sini: Anda dapat melihat langsung ke tempat-tempat dalam kode di mana kerentanan ditemukan dengan kecurigaan sebagai positif palsu. Memang, beberapa dari mereka mungkin berubah menjadi positif palsu (meskipun jelas tidak setengah dari total).



Tapi tentang apa yang kritis dan apa yang tidak, saya ingin berbicara lebih substansial. Jika Anda mengerti mengapa tidak mungkin lagi menggunakan SHA-1 dan mengapa escape ";", mungkin artikel ini tidak akan membuka Anda sesuatu yang baru. Tetapi jika hasil pemindaian dari kerentanan yang ditemukan menyilaukan, selamat datang di bawah cut - kami akan memberi tahu Anda "lubang" apa yang paling sering ditemukan di aplikasi seluler dan web, cara kerjanya, cara memperbaikinya, dan yang paling penting - cara memahami apa yang ada di depan Anda - cacat berbahaya atau kesalahan kecil pada kode.







Penerapan



Jenis kerentanan yang sangat umum. Mereka disematkan di mana-mana: dalam kueri SQL, LDAP, XML, XPath, XSLT, Xquery ... Semua suntikan ini dibedakan dengan penggunaan data yang tidak tepercaya, berkat itu penyerang mendapatkan akses ke informasi atau mengubah perilaku aplikasi. Misalnya dengan input pengguna yang tidak cukup divalidasi.



Menurut klasifikasi internasional kerentanan OWASP , serangan yang menggunakan metode "injeksi" menempati peringkat pertama dalam tingkat kekritisan ancaman keamanan aplikasi web. Mari pertimbangkan jenis penerapan yang paling umum.



Injeksi SQL . Data tidak tepercaya masuk ke kueri SQL ke database.







Jika kueri ke database tidak menerapkan otentikasi yang benar dari data masukan, penyerang dapat merusak kueri SQL:



  • kirim kode berbahaya ke sana;
  • tambahkan simbol "-" atau ";" dan menghentikan perintah SQL yang benar: semua setelah "-" diartikan sebagai komentar, dan karakter ";" menandai akhir dari sebuah perintah;
  • tebak sandi dengan menjalankan serangkaian kueri SQL secara berurutan.


Bagaimana cara membela diri? Berikut beberapa rekomendasi dari OWASP :



  • Gunakan API yang menyediakan antarmuka berparameter, atau alat pemetaan relasional objek (ORM).
  • Menerapkan mekanisme validasi untuk data yang dimasukkan pengguna. Gunakan daftar putih validasi sisi server.
  • Meloloskan diri dari karakter khusus (";", "-", "/ *", "* /", "'"; daftar persisnya bergantung pada database).
  • Gunakan prosedur tersimpan sehubungan dengan mekanisme pemfilteran parameternya untuk memvalidasi masukan pengguna.


Injeksi XML . Aplikasi menggunakan XML untuk menyimpan atau bertukar data, sehingga dapat berisi informasi yang berharga.







Jika penyerang dapat menulis data ke dokumen XML, maka dia dapat mengubah semantiknya. Dalam kasus ini, skenario yang paling tidak berbahaya akan memungkinkan Anda memasukkan tag tambahan ke dalam dokumen, akibatnya pengurai XML akan keluar dengan kesalahan. Tapi Anda bisa menghadapi insiden yang lebih serius: misalnya, dengan substitusi data otentikasi di database pelanggan atau harga di database produk toko. Injeksi XML juga dapat menyebabkan skrip lintas situs (XSS) - injeksi kode berbahaya yang dijalankan di browser pengguna saat halaman dibuka.



Apa yang bisa kami sarankan?



  • Jangan membuat tag dan atribut yang namanya berasal dari data dari sumber yang tidak tepercaya (misalnya, dimasukkan oleh pengguna).
  • Encode (XML entity encode) data yang dimasukkan oleh pengguna sebelum menulisnya ke dokumen XML.


Injeksi XQuery adalah bentuk injeksi SQL klasik, tetapi dalam kasus ini serangan akan menargetkan database XML, dan data yang tidak tepercaya akan berakhir di ekspresi XQuery.



Pada contoh di bawah, aplikasi membuat dan menjalankan ekspresi XQuery berdasarkan parameter usernamedan passworddari permintaan HTTP (sumber tidak tepercaya):



XQDataSource xqs = new XQDataSource();
XQConnection conn = xqs.getConnection();
String query = "for \$user in doc(users.xml)//user[username='" + request.getParameter("username") + "'and pass='" + request.getParameter("password") + "'] return \$user";
XQPreparedExpression xqpe = conn.prepareExpression(query);
XQResultSequence rs = xqpe.executeQuery();


Jika datanya benar, permintaan akan mengembalikan informasi tentang pengguna dengan nama dan kata sandi yang sesuai:



for \$user in doc(users.xml)//user[username='test_user' and pass='pass123'] return \$user


Jika penyerang menentukan string yang berisi karakter khusus (misalnya, admin' or 1=1 or ''=') sebagai parameter , semantik permintaan akan berubah:



//user[username='admin']


Permintaan yang diterima akan mengembalikan data tentang semua pengguna.



Opsi aman (penggunaan prepared statements):



XQDataSource xqs = new XQDataSource();
XQConnection conn = xqs.getConnection();
String query = "declare variable $username as xs:string external; declare variable $password as xs:string external; for \$user in doc(users.xml)//user[username='$username' and pass='$password'] return \$user";
XQPreparedExpression xqpe = conn.prepareExpression(query);
xqpe.bindString(new QName("username"), request.getParameter("username"), null);
xqpe.bindString(new QName("password"), request.getParameter("password"), null);
XQResultSequence rs = xqpe.executeQuery();


Penyematan di XSLT (XML Document Transformation Language) dimungkinkan jika aplikasi menggunakan data dari sumber yang tidak tepercaya saat bekerja dengan XSL.



Aplikasi menggunakan XSL untuk mengubah dokumen XML. File gaya XSL berisi fungsi yang mendeskripsikan transformasi dan, jika diterapkan secara tidak benar, dapat menyertakan kerentanan. Dalam kasus ini, ada peningkatan risiko skenario serangan di mana penyerang mengubah struktur dan konten file gaya XSL, dan oleh karena itu, file XML yang sesuai. Apa yang bisa kita dapatkan di pintu keluar?



Pertama, serangan XSS: memasukkan kode berbahaya ke dalam halaman yang dikeluarkan oleh sistem web dan berinteraksi dengan server penyerang. Kedua, peretas mendapatkan akses ke sumber daya sistem. Ketiga, eksekusi kode arbitrer. Dan untuk makanan penutup - serangan XXE (XML eXternal Entity - injeksi entitas eksternal ke XML).



Menanamkan Lightweight Directory Access Protocol ( LDAP) dalam perintah dapat mengakibatkan hilangnya atau modifikasi data. Dalam kasus ini, data tidak tepercaya masuk ke permintaan LDAP.



Injeksi perintah interpreter yang berbahaya.Data yang tidak dipercaya masuk ke perintah interpreter. Penyerang dapat memilih masukan seperti itu sehingga perintah berhasil dijalankan dan izin tambahan dalam aplikasi menjadi tersedia baginya.



Pada contoh di bawah ini, aplikasi menjalankan skrip untuk membuat backup database. Aplikasi mengambil jenis cadangan sebagai parameter dan menjalankan skrip dengan hak istimewa yang lebih tinggi:



String btype = request.getParameter("backuptype");
String cmd = new String("cmd.exe /K
\"c:\\util\\rmanDB.bat "+btype+"&&c:\\utl\\cleanup.bat\"")
System.Runtime.getRuntime().exec(cmd);


Masalahnya di sini adalah parameter tersebut backuptypetidak divalidasi. Biasanya Runtime.exec()tidak menjalankan banyak perintah, tetapi dalam kasus ini cmd.exe diluncurkan pertama kali untuk menjalankan beberapa perintah dengan memanggil Runtime.exec(). Setelah shell baris perintah dimulai, ia dapat menjalankan beberapa perintah, dipisahkan oleh karakter " &&". Jika penyerang && del c:\\dbms\\*.*menentukan string " " sebagai parameter , aplikasi akan menghapus direktori yang ditentukan.



Kiat Pengembang:



  • Jangan biarkan pengguna memiliki kontrol langsung atas perintah yang dijalankan aplikasi. Jika perilaku aplikasi harus bergantung pada data yang dimasukkan oleh pengguna, tawarkan kepada pengguna pilihan dari daftar perintah tertentu yang diizinkan.
  • , . , . , .
  • , , . . .


Unggahan file tidak aman. Dalam hal ini, tidak hanya data individu yang berasal dari sumber yang tidak tepercaya, tetapi seluruh file. Dengan demikian, penyerang dapat mengunggah data atau kode berbahaya ke server target. Misalnya, jika pengguna di jaringan perusahaan diizinkan mengunggah file ke direktori yang dapat diakses publik, peretas dapat menjalankan kode berbahaya dari jarak jauh di server perusahaan.



Penyertaan file eksternal yang tidak aman dalam HTML.Kerentanan penyertaan file terjadi saat pengguna memasukkan jalur ke file yang disertakan. Faktanya adalah bahwa bahasa skrip modern memungkinkan Anda untuk menautkan kode secara dinamis dari file pihak ketiga untuk menggunakannya kembali. Mekanisme ini digunakan untuk tampilan halaman yang seragam atau untuk membagi kode menjadi modul-modul kecil. Namun, penyertaan ini dapat dimanfaatkan oleh penyerang dengan mengubah jalur dan menghubungkan filenya.



Kami menyarankan profesional keamanan informasi perusahaan membuat "daftar putih" jalur koneksi file yang valid sehingga karyawan dapat menambahkan file hanya sesuai dengan skrip dari daftar ini.



Bookmark



Bookmark adalah bagian yang sengaja dimasukkan ke dalam kode aplikasi, dengan bantuannya, dalam kondisi tertentu, Anda dapat melakukan tindakan yang tidak termasuk dalam aplikasi. Mari pertimbangkan jenis bookmark yang paling umum.



Akun khusus. Jika aplikasi membandingkan nilai sandi atau variabel login dengan nilai yang tidak berubah, waspadalah: akun ini mungkin bagian dari bookmark. Mari kita lihat bagaimana ini terjadi.







Pengembang aplikasi menggunakan akun khusus (mungkin dengan hak istimewa yang ditinggikan) saat men-debug dan meninggalkan bagian kode yang sesuai di versi final, mempertahankan akses ke aplikasi. Penyerang dapat memulihkan kode asli aplikasi, mengekstrak nilai konstan dari akun khusus, dan mendapatkan akses ke aplikasi.

Sangat tidak mungkin untuk menyimpan login, kata sandi, kunci dalam kode sumber aplikasi.
Fungsionalitas tersembunyi (NDV). Kode fungsionalitas tersembunyi dijalankan ketika pemicu tertentu diaktifkan. Dalam aplikasi web, pemicunya sering kali berupa parameter kueri "tidak terlihat". Kadang-kadang, sebagai tambahan, pemeriksaan dilakukan dari IP mana permintaan dengan pemicu berasal, sehingga hanya pembuatnya yang dapat mengaktifkan bookmark. Pemeriksaan semacam itu berfungsi sebagai sinyal untuk kemungkinan bookmark.



Aktivitas jaringan tidak berdokumen. Jenis aktivitas ini meliputi: menghubungkan ke sumber daya pihak ketiga di latar belakang, mendengarkan pada port yang tidak berdokumen, mentransfer informasi melalui SMTP, HTTP, UDP, ICMP.

Jika Anda menemukan koneksi yang mencurigakan dalam kode dengan alamat yang tidak ada dalam daftar alamat aman yang diketahui, kami sangat menyarankan Anda untuk menghapusnya.

Ubah pengaturan keamanan . Aplikasi berisi kode yang mengubah nilai variabel yang menyimpan keberhasilan otentikasi. Kesalahan umum adalah menggunakan assignment (=) daripada perbandingan (==). Dalam metode yang melibatkan otentikasi, ini sangat berbahaya karena dapat menjadi bagian dari pintu belakang:



if (isAuthenticated = true)
{
    someDangerousAction();
}


Pemicu waktu (bom waktu). Penanda yang diaktifkan pada titik waktu tertentu. Aplikasi ini membandingkan tanggal saat ini dengan tahun, bulan, dan hari tertentu: pada 1 Januari 2021, kejutan menanti semua orang:



Date now = java.util.Date();    // current time
if ((now.getYear() == 2021) && (now.getMonth() == 1) && (now.getDate() == 1))
{
    activateNewYearBackdoor();
}


Atau mungkin tidak ... Dalam praktiknya, saat mencari pemicu sementara, sering kali terjadi positif palsu. Misalnya, jika API waktu juga digunakan untuk tujuan yang dimaksudkan: logging, menghitung waktu eksekusi, stempel waktu untuk respons server ke permintaan HTTP.



Tapi! Kami tetap menyarankan untuk tidak menutup mata Anda terhadap semua alarm tersebut, karena kami mengetahui contoh nyata dari kerentanan tersebut.



Kode mati. Potongan kode yang disuntikkan yang tidak berguna. Kode mati itu sendiri tidak berbahaya, tetapi bisa menjadi bagian dari penanda yang telah tersebar di banyak file. Atau, pemicu bookmark direncanakan untuk diterapkan nanti. Bagaimanapun, kode mati harus mencurigakan.



Kurangnya enkripsi dan penggunaan algoritma enkripsi yang lemah



Masalah utama dengan enkripsi adalah enkripsi tidak digunakan sama sekali, atau algoritme yang lemah digunakan, dan kunci serta salt terlalu sederhana atau disimpan dengan tidak aman. Konsekuensi dari semua kerentanan ini sama - lebih mudah untuk mencuri data rahasia.



Contoh tersebut menunjukkan inisialisasi enkripsi menggunakan algoritma DES lama:



Cipher cipher = Cipher.getInstance("DES");


Contoh algoritma enkripsi yang rentan: RC2, RC4, DES. Opsi aman:



Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");


Menurut klasifikasi internasional OWASP , kerentanan seperti "kebocoran data rahasia" menempati peringkat ketiga dalam hal tingkat keparahan ancaman keamanan aplikasi web.



Rekomendasi kami untuk pengembang: Pastikan untuk menggunakan enkripsi dengan mempertimbangkan keamanan.



Menggunakan protokol HTTP yang tidak aman dan bukan HTTPS penuh dengan serangan Man in the middle.



Protokol HTTPS yang aman didasarkan pada HTTP, tetapi juga mendukung enkripsi melalui protokol kriptografi SSL / TLS. HTTPS mengenkripsi semua data yang dikirimkan melaluinya, khususnya, halaman masuk dan entri kata sandi atau data kartu bank pengguna, melindunginya dari akses dan perubahan yang tidak sah. Tidak seperti HTTP, yang tidak melindungi data yang dikirimkan. Akibatnya, penyerang dapat memalsukan situs informasional melalui HTTP dan memaksa pengguna untuk memasukkan data pada halaman palsu (serangan phishing).



Kunci enkripsi ditentukan dalam kode sumber . Hasilnya, kunci tersebut tersedia untuk setiap pengembang aplikasi. Selain itu, setelah menginstal aplikasi, Anda hanya dapat menghapus kunci dari kode dengan memperbarui.



Secara umum, string konstan mudah diekstrak dari file yang dapat dieksekusi menggunakan program pemulihan kode sumber (decompiler). Oleh karena itu, penyerang tidak perlu memiliki akses ke kode sumber untuk mengetahui nilai kunci yang digunakan. Dalam praktik kami, kami sering menjumpai kasus ketika developer menentukan nullstring kosong sebagai nilai kunci , yang tidak dapat diterima.



Saran kami: Buat kunci dengan generator bilangan acak semu (PRNG) yang kuat secara kriptografis dan simpan menggunakan modul khusus.



Algoritme padding tidak aman untuk enkripsi . Jika algoritma enkripsi RSA digunakan tanpa padding OAEP, data yang dienkripsi menjadi rentan .



Algoritma OAEP diperlukan untuk memproses pesan sebelum menggunakan RSA. Pesan pertama-tama dimasukkan ke panjang tetap menggunakan OAEP, kemudian dienkripsi menggunakan RSA. Skema enkripsi ini disebut RSA-OAEP dan merupakan bagian dari standar saat ini .



Ini adalah contoh inisialisasi enkripsi RSA tanpa padding:



rsa = javax.crypto.Cipher.getInstance("RSA/NONE/NoPadding");


Opsi aman:



rsa = javax.crypto.Cipher.getInstance("RSA/ECB/OAEPWithMD5AndMGF1Padding");


Ukuran kunci enkripsi tidak memadai . Jika Anda menggunakan kunci pendek, enkripsi ini rentan terhadap serangan brute force.



Kriptanalisis tidak berhenti, algoritma serangan baru terus bermunculan, komputer mendapatkan kekuatan yang lebih besar. Setelan enkripsi yang sebelumnya dianggap aman tidak digunakan lagi dan tidak lagi direkomendasikan untuk digunakan. Jadi, RSA dengan panjang kunci 1024 bit tidak lagi dianggap aman pada tahun 2010-2015.



Algoritme hashing yang lemah . Untuk alasan yang dijelaskan di paragraf sebelumnya, fungsi hash MD2, MD5, SHA1 tidak aman. Untuk menemukan tabrakan untuk fungsi MD2 dan MD5, tidak diperlukan sumber daya yang signifikan.



Untuk SHA1, ada contoh dua file berbeda dengan hash yang sama. Algoritme peretasan disarankankaryawan Google dan Pusat Matematika dan Ilmu Komputer di Amsterdam.







Jika kata sandi pengguna disimpan sebagai hash, tetapi menggunakan fungsi hash yang tidak aman, penyerang dapat dengan mudah mengaksesnya dengan menerapkan skenario berikut. Mengetahui hash dari kata sandi dan mengeksploitasi kerentanan dari algoritma hashing, adalah mungkin untuk menghitung string yang hashnya sama dengan kata sandinya. Penyerang mengautentikasi menggunakan string yang dihitung.



Fungsi hash untuk menyimpan password harus tahan benturan dan tidak terlalu cepat sehingga serangan brute force tidak dapat dilaksanakan. Algoritma aman PBKDF2, bcrypt, scrypt harus digunakan.



Beberapa nomor menarik: dengan PBKDF2kecepatan tombol pencarian dikurangi menjadi 70 buah per detik untuk Intel Core2 dan sekitar 1.000 untuk FPGA Virtex-4 FX60. Sebagai perbandingan, fungsi hashing kata sandi LANMAN klasik memiliki kecepatan pencarian sekitar ratusan juta opsi per detik.



Algoritme enkripsi yang lemah . Seperti algoritma hashing, keamanan algoritma enkripsi ditentukan oleh waktu dan sumber daya yang harus dihabiskan untuk mendekripsinya. RC2, RC4, DES dianggap sebagai algoritma yang rentan. Yang terakhir, karena panjang kuncinya yang kecil (56 bit), dapat dipecahkan dengan kekerasan.



Generator nomor pseudo-random (PRNG) yang lemah menghasilkan urutan yang dapat diprediksi. Seorang peretas dapat melewati otentikasi dan membajak sesi pengguna.



Mari kita bahas lebih dalam tentang sifat PRNG. Mereka menghasilkan rangkaian angka berdasarkan nilai awal parameter seed. Ada dua jenis PRNG - statistik dan kriptografi.



PRNG statistik menghasilkan urutan yang dapat diprediksi yang secara statistik mirip dengan yang acak. Mereka tidak dapat digunakan untuk tujuan keamanan.



Hasil pengoperasian PRNG kriptografi sebaliknya tidak dapat diprediksi jika nilai parameter seeddiperoleh dari sumber dengan entropi tinggi. Nilai waktu saat ini memiliki sedikit entropi dan juga tidak aman dalam kualitas seed. Di Java, PRNG dari kelas java.util.Randomdan java.lang.Mathmenghasilkan urutan yang dapat diprediksi dan tidak boleh digunakan untuk tujuan keamanan informasi.



Benih lemah dari generator nomor pseudo-acak . Tidak seedaman menggunakan nilai dari sumber yang tidak tepercaya karena menghasilkan urutan yang dapat diprediksi.



Pekerjaan dari banyak algoritma kriptografi didasarkan pada penggunaan PRNG yang tahan kriptanalisis. Beberapa algoritme dapat mengambil nilai sebagai argumen tambahan seeddan menghasilkan urutan yang dapat diprediksi untuk setiap nilai parameter ini. Dalam hal ini, keamanan sistem didasarkan pada asumsi bahwa nilainya seedtidak dapat diprediksi.



Garam ditentukan dalam kode sumber... Mari kita ingat untuk apa garam itu. Untuk memecahkan kata sandi dengan metode brute-force, tabel yang telah dikompilasi dengan nilai fungsi hash dari kata sandi populer digunakan. Salt adalah string arbitrer yang diumpankan ke input fungsi hash bersama dengan kata sandi untuk membuat serangan seperti itu lebih sulit.



Jika salt disimpan dalam kode sumber, masalah yang persis sama akan muncul seperti pada password dan kunci. Nilai garam tersedia untuk pengembang dan dapat dengan mudah diperoleh oleh penyerang, dan garam dapat dihapus dari versi terakhir aplikasi hanya dengan pembaruan aplikasi berikutnya.



Manipulasi dengan log



Berbagai kesalahan dalam log dipenuhi dengan masuknya kode berbahaya ke dalam aplikasi. Kerentanan paling umum yang terkait dengan logging adalah gangguan file log dan logging tidak terstruktur.



Gangguan file log terjadi saat aplikasi menulis data yang tidak tepercaya ke log peristiwa (log). Seorang peretas dapat memalsukan entri log atau menyuntikkan kode berbahaya ke dalamnya.



Biasanya, aplikasi menulis riwayat transaksi ke log untuk pemrosesan lebih lanjut, debugging, atau pengumpulan statistik. Log dapat diurai secara manual atau otomatis.

Jika data ditulis ke log "sebagaimana adanya", penyerang dapat menyuntikkan catatan palsu ke dalam log, melanggar struktur file yang menyebabkan prosesor log gagal, atau memasukkan kode berbahaya yang mengeksploitasi kerentanan yang diketahui di prosesor.



Dalam contoh ini, aplikasi web mencoba membaca nilai integer dari parameter request. Jika nilai yang dimasukkan tidak dapat dikonversi menjadi bilangan bulat, aplikasi mencatat nilai ini bersama dengan pesan kesalahan:



String val = request.getParameter("val");
try {
    int value = Integer.parseInt(val);
}
catch (NumberFormatException nfe) {
    log.info("Failed to parse val = " + val);
}


Penyerang dapat menambahkan entri sewenang-wenang ke log, misalnya, baris twenty-one%0a%0aINFO:+User+logged+out%3dbadguytersebut akan ditampilkan di log sebagai berikut:



INFO: Failed to parse val=twenty-one
INFO: User logged out=badguy


Demikian pula, catatan arbitrer dapat disematkan di log.



Opsi aman (penggunaan NumberFormatException):



public static final String NFE = "Failed to parse val. The input is required to be an integer value."

String val = request.getParameter("val");
try {
    int value = Integer.parseInt(val);
}
catch (NumberFormatException nfe) {
    log.info(NFE);
}


Logging tidak terstruktur , yaitu, mengeluarkan pesan kesalahan ke aliran keluar standar atau aliran yang salah adalah metode yang tidak aman. Sebaiknya gunakan logging terstruktur sebagai gantinya. Yang terakhir memungkinkan Anda untuk menghasilkan log dengan level, stempel waktu, format standar. Jika program mengimplementasikan mekanisme logging terstruktur, tetapi pesan error dikeluarkan ke stream standar, maka log mungkin tidak berisi informasi penting.

Mengeluarkan pesan kesalahan ke aliran standar hanya dapat diterima di tahap awal pengembangan.



Penanganan cookie tidak aman



Kerentanan yang terkait dengan pengumpulan cookie pengguna sangat beragam.



Penanganan cookie yang tidak aman . Aplikasi tersebut menyertakan data dari sumber yang tidak tepercaya dalam cookie, yang dapat menyebabkan keracunan cache, XSS (skrip lintas situs), dan serangan yang memecah respons.



Jika kode berbahaya (skrip lintas situs) dimasukkan ke dalam aplikasi, penyerang dapat mengubah cookie pengguna.



Karena cookie disetel di header respons HTTP, kegagalan untuk mengakui data yang disertakan dalam cookie dapat menyebabkan serangan respons terpisah. "Pemisahan respons HTTP" adalah serangan di mana peretas mengirim permintaan HTTP semacam itu, yang responsnya akan diterima oleh korban dalam dua respons HTTP (bukan yang benar).

Jika penyerang menetapkan authorstring formulir sebagai parameter Hacker \r\nHTTP/1.1 200 OK\r\n..., jawabannya akan dibagi menjadi dua sebagai berikut:



HTTP/1.1 200 OK
...
Set-Cookie: author=Hacker

HTTP/1.1 200 OK
...


Konten dari respons kedua sepenuhnya berada di bawah kendali penyerang, yang menyebabkan keracunan cache, XSS, pengalihan berbahaya, dan serangan lainnya.



Cookies tanpa HttpOnly . Aplikasi ini membuat cookie tanpa bendera httpOnly. Jika httpOnlydisertakan dalam tajuk tanggapan http, penyerang tidak akan bisa mendapatkan cookie menggunakan kode JavaScript. Dan jika pengguna membuka halaman dengan kerentanan skrip lintas situs (XSS), browser tidak akan mengungkapkan cookie kepada pihak ketiga. Jika flag httpOnlytidak disetel, maka cookie (biasanya cookie sesi) dapat dicuri menggunakan skrip.



Contoh pembuatan cookie tanpa bendera httpOnly:



Cookie cookie = new Cookie("emailCookie", email);
response.addCookie(cookie);


Setel bendera httpOnlysaat membuat cookie. Namun, perlu diingat bahwa ada cara untuk melewati serangan, httpOnlyjadi Anda juga harus berhati-hati dalam memvalidasi masukan.



NB Menurut klasifikasi internasional OWASP , kerentanan "kebocoran data rahasia" menempati peringkat ketiga dalam tingkat kekritisan ancaman keamanan aplikasi web.



Cookie untuk domain yang terlalu umum . Jika domain untuk cookie terlalu umum (misalnya .example.com), kerentanan di satu aplikasi membuat aplikasi lain di domain yang sama terkena kerentanan.



Dalam contoh berikut, aplikasi web aman yang dipasang di sebuah alamat http://secure.example.commenyetel cookie dengan nilai domain .example.com:



Cookie cookie = new Cookie("sessionID", sessionID);
cookie.setDomain(".example.com");


Jika http://insecure.example.comaplikasi yang berisi, misalnya, XSS dipasang di alamat tersebut , maka cookie pengguna resmi dari aplikasi aman yang membuka alamat tersebut http://insecure.example.comdapat disusupi.



Penyerang juga dapat melakukan serangan keracunan cookie: cookie dengan domain bersama yang dibuat http://insecure.example.comakan menimpa cookie http://secure.example.com.



Opsi aman:



Cookie cookie = new Cookie("sessionID", sessionID);
cookie.setDomain("secure.example.com");


Cookie dengan parameter terlalu umumpath . Jika jalur dalam cookie tidak akurat (misalnya, /), masalah yang sama akan muncul seperti pada domain bersama: kerentanan dalam satu aplikasi membuat aplikasi lain di domain yang sama berisiko.



Dalam contoh berikut, aplikasi yang dipasang di URL http://pages.example.com/forummenyetel cookie dengan jalur /:



Cookie cookie = new Cookie("sessionID", sessionID);
cookie.setPath("/");


Kemudian aplikasi berbahaya yang dipasang di alamat tersebut http://pages.example.com/evildapat membahayakan cookie pengguna. Penyerang juga dapat melakukan serangan keracunan cookie: cookie dengan jalur bersama yang dibuat /evilakan menimpa cookie /forum.



Opsi aman:



Cookie cookie = new Cookie("sessionID", sessionID);
cookie.setPath("/forum");


Cookie tidak melebihi SSL . Aplikasi membuat cookie tanpa menyetel bendera securesama true. Cookies ini dapat dikirim tanpa enkripsi melalui HTTP. Kerentanan "Menggunakan protokol HTTP yang tidak aman" segera diingat.



Dalam contoh berikut, aplikasi membuat cookie tanpa tanda secure:



Cookie cookie = new Cookie("emailCookie", email);
response.addCookie(cookie);


Jika aplikasi menggunakan HTTPS dan HTTP, jika tidak ada tanda aman, cookie yang dibuat sebagai bagian dari permintaan HTTPS akan dikirim tanpa enkripsi dalam permintaan HTTP berikutnya, yang dapat menyebabkan aplikasi disusupi. Ini sangat berbahaya jika cookie berisi data berharga, khususnya ID sesi.



Opsi aman:



Cookie cookie = new Cookie("emailCookie", email);
cookie.setSecure(true);
response.addCookie(cookie);


Cookie dengan validitas tidak terbatas . Jika Anda menyimpan cookie berharga terlalu lama, penyerang dapat mengaksesnya.



Secara default, cookie non-persisten (sesi) digunakan, yang tidak disimpan ke disk dan dihapus setelah menutup browser. Namun, pengembang aplikasi web dapat menentukan berapa lama cookie disimpan - dalam hal ini, cookie akan ditulis ke disk dan disimpan antara browser restart dan komputer restart. Ini memberi penyerang waktu yang lama untuk mengembangkan rencana serangan.



Rekomendasi pengembang: pastikan aplikasi tidak membuat cookie berumur panjang:



Cookie cookie = new Cookie("longCookie", cookie);
cookie.setMaxAge(5*365*24*3600); // 5 !


Berikan batas waktu maksimum yang wajar dengan mengikuti pedoman OWASP .



Kebocoran informasi



Mungkin jenis kerentanan paling sensitif bagi pengguna aplikasi.



Kebocoran informasi eksternal melalui halaman kesalahan . Aplikasi menggunakan halaman kesalahan standar, yang dapat berisi informasi tentang konfigurasi sistem.



Pesan kesalahan dan informasi debug ditulis ke log, ditampilkan ke konsol, atau dikirim ke pengguna. Dari pesan kesalahan, penyerang dapat mempelajari tentang kerentanan sistem, yang akan membuat hidupnya lebih mudah. Misalnya, kesalahan database mungkin menunjukkan ketidakamanan terhadap injeksi SQL. Informasi mengenai versi sistem operasi, server aplikasi, dan konfigurasi sistem akan memudahkan peretas dalam merencanakan serangan terhadap suatu aplikasi.



Kebocoran eksternal dari informasi berharga... Dalam hal ini, kita berbicara tentang kebocoran informasi teknis tentang aplikasi dengan mentransfernya melalui jaringan ke komputer lain. Secara umum, kebocoran eksternal lebih berbahaya daripada kebocoran internal.







Kebocoran internal informasi berharga . Mekanisme operasinya mirip dengan dua jenis kebocoran sebelumnya, tetapi dalam hal ini informasi tentang sistem ditulis ke log atau ditampilkan di layar pengguna.



Kebocoran data rahasia . Data pribadi berharga pengguna memasuki aplikasi dari berbagai sumber: dari pengguna itu sendiri, dari berbagai database, dari penyimpanan pihak ketiga. Terkadang data ini tidak ditandai sebagai rahasia, atau ternyata tidak berharga itu sendiri, tetapi hanya dalam konteks tertentu.



Ini persis terjadi ketika keamanan aplikasi dan privasi data pribadi saling bertentangan. Untuk alasan keamanan, disarankan untuk merekam informasi rinci tentang aktivitas di sistem untuk mendeteksi aktivitas berbahaya. Dari sudut pandang privasi data, sebaliknya, ketika mencatat informasi rahasia, risiko kebocorannya lebih besar. Secara umum, memastikan kerahasiaan data pribadi pengguna aplikasi adalah prioritas yang lebih tinggi.



Kata Penutup



Jenis kerentanan yang dipertimbangkan dalam artikel ini mencakup sebagian besar celah "universal" dalam aplikasi yang ditulis dalam bahasa pemrograman berbeda. Namun, beberapa bahasa memiliki kerentanan spesifiknya sendiri. Tapi ini sudah menjadi topik untuk artikel terpisah. Dan terakhir, ingat: saat membuat aplikasi, jangan lupa untuk mengikuti rekomendasi di atas, baca dokumentasi dengan cermat, dan periksa kerentanan aplikasi menggunakan perangkat lunak khusus.



Penulis: Elizaveta Kharlamova, Kepala Departemen Analisis, Solar appScreener




All Articles