Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. ASP.NET

Mencegah Injeksi Kode

by
Read Time:12 minsLanguages:

Indonesian (Bahasa Indonesia) translation by Yusuf Samin (you can also view the original English article)

Seringkali, situs web tampaknya ada terutama untuk memasukkan sesuatu ke dalam database untuk menariknya nanti. Sementara metode database lain, seperti NoSQL, telah mendapatkan popularitas dalam beberapa tahun terakhir, data untuk banyak situs web masih berada dalam database SQL tradisional. Data ini seringkali terdiri dari informasi pribadi yang berharga seperti nomor kartu kredit dan informasi pribadi lainnya yang menarik bagi pencuri identitas dan penjahat. Karena itu peretas selalu mencari untuk mendapatkan data ini. Salah satu target paling umum dari serangan ini adalah database SQL yang ada di balik banyak aplikasi web melalui proses SQL Injection.

Serangan injeksi berfungsi dengan meminta aplikasi meneruskan input yang tidak dipercaya ke interpreter. Baru-baru ini, 40.000 record pelanggan diambil dari Bell Canada adalah hasil dari serangan SQL Injection. Pada akhir 2013, peretas mencuri lebih dari $100.000 dari ISP berbasis di California menggunakan injeksi SQL.

Open Web Application Security Project (OWASP) memilih serangan injeksi sebagai risiko keamanan aplikasi nomor satu dalam sepuluh besar 2013 mereka, berdasarkan prevalensinya dan risiko sistem web yang diserang. Sayangnya, ia juga memegang posisi nomor satu dalam laporan sebelumnya dari 2010. Jadi, apa itu serangan SQL Injection? Dalam tutorial ini saya akan membahas cara kerjanya dan apa yang dapat Anda lakukan untuk melindungi aplikasi Anda dari serangan ini.

Apa itu Serangan Injeksi?

Setiap sistem yang diterjemahkan di belakang server web dapat menjadi target serangan injeksi. Target paling umum adalah server database SQL di belakang banyak situs web. Injeksi SQL tidak secara langsung dihasilkan dari kelemahan dalam database, tetapi menggunakan bukaan dalam aplikasi untuk memungkinkan penyerang untuk mengeksekusi pernyataan pilihan penyerang di server. Serangan injeksi SQL membuat database berbagi informasi lebih banyak daripada yang dirancang aplikasi untuk diberikan. Mari kita lihat panggilan basis data SQL yang dapat Anda tulis di ASP.NET.

Apa yang salah dengan kode ini? Mungkin tidak ada. Masalahnya adalah string id yang kita gunakan. Dari mana nilai itu berasal? Jika kami membuatnya secara internal atau dari sumber tepercaya, maka kode ini mungkin berfungsi tanpa masalah. Namun, jika kami mendapatkan nilai dari pengguna dan menggunakan tanpa modifikasi, kami baru saja membuka diri untuk injeksi SQL.

Mari kita ambil kasus umum di mana kita mendapatkan parameter untuk dicari sebagai bagian dari URL. Ambil URL http://www.example.com/user/details?id=123. Di ASP.NET menggunakan C# kita bisa mendapatkan nilai yang dimasukan menggunakan kode ini:

Kode ini dikombinasikan dengan panggilan di atas membuat kita terbuka terhadap serangan. Jika pengguna memasukan id pengguna seperti 123 seperti yang diharapkan, semuanya berfungsi dengan baik. Namun, tidak ada yang kami lakukan di sini untuk memastikan hal ini. Katakanlah penyerang mencoba mengakses URL http://www.example.com/user/details?id=0; PILIH * FROM userdata.

Alih-alih hanya meneruskan nilai seperti yang diharapkan, kami telah memberikan nilai dan kemudian menambahkan tanda titik koma, yang mengakhiri pernyataan SQL. Itu kemudian menambahkan pernyataan SQL kedua bahwa penyerang ingin dijalankan. Dalam hal ini akan mengembalikan semua record dalam tabel userdata. Bergantung pada sisa kode di halaman kami, itu mungkin mengembalikan kesalahan atau mungkin menampilkan setiap record dalam database ke penyerang. Bahkan kesalahan dapat digunakan dengan pertanyaan yang dibangun dengan hati-hati untuk membangun tampilan database. Lebih buruk, bayangkan penyerang pergi ke URL http://www.example.com/user/details?id=0; DROP TABLE userdata. Sekarang semua pengguna Anda hilang.

Dalam contoh ini, penyerang dapat menjalankan kode apa pun yang mereka inginkan di server database. Jika akun yang dijalankan oleh panggilan basis data memiliki kontrol penuh atas database, skenario yang terlalu umum, kemudian menjatuhkan tabel dan menghapus record membuat cara mudah untuk menjatuhkan situs. Sekalipun penyerang hanya bisa membaca dan menulis data dalam database, maka puling data hanya masalah kesabaran dan kepedulian.

database-view

Ambil database sederhana bernama "Products" yang terdiri dari tiga kolom. Kolom pertama memegang id produk, yang kedua memegang nama produk, dan yang ketiga memegang harga produk. Untuk kueri normal kami, kami akan berusaha menemukan setiap produk yang mengandung widget dalam nama. SQL untuk melakukan ini dalam pola yang sama kami tunjukkan akan terlihat seperti ini:

Situs web khas untuk mengakses ini akan terlihat seperti http://www.example.com/product?search=widget. Di sini halaman web hanya akan menggilir setiap record yang dikembalikan dan menampilkannya di layar. Dalam hal ini kita melihat produk widget kita.

Mari kita ubah kueri kami ke http://www.example.com/product?search=widget' OR 1=1;-- dan jalankan kueri yang sama. lihat sesuatu yang lebih. Bahkan kita akan melihat setiap record di tabel.

Kami telah menipu interpreter untuk menjalankan kode SQL pilihan kami. SQL yang dihasilkan dieksekusi adalah:

Hasilnya adalah dua pernyataan:

Dengan menambahkan 1=1, yang selalu benar, klausa di mana akan berlaku untuk setiap baris dalam tabel dan kueri yang dihasilkan akan mengembalikan setiap baris. -- pada awal pernyataan kedua mengubah sisa pernyataan SQL menjadi komentar yang mencegah pesan kesalahan yang seharusnya kita lihat.

Perubahan pada tampilan tidak dapat mencegah pernyataan ini. Seorang penyerang yang sabar dapat menggunakan bahkan tidak lebih dari fakta bahwa nilai dikembalikan atau tidak dan dengan hati-hati membuat kueri untuk memetakan database Anda secara perlahan dan mungkin mengambil data bahkan jika mereka hanya melihat pesan kesalahan. Ada alat seperti sqlmap untuk mengotomatiskan proses.

Mengurangi Injeksi SQL

Anda mencegah injeksi SQL dengan mencegah input yang tidak tepercaya ke database SQL atau interpreter lainnya. Setiap input dari luar sistem harus dianggap tidak tepercaya. Bahkan data dari sistem mitra lain harus dianggap tidak tepercaya karena Anda tidak memiliki cara untuk menjamin sistem lain tidak mengalami masalah keamanan yang memungkinkan penyisipan data semaunya kemudian diteruskan ke aplikasi Anda.

Kembali ke contoh sebelumnya, jika kita tahu bahwa parameter id harus selalu berupa bilangan integer, kita dapat mencoba mengubahnya menjadi bilangan integer dan menunjukkan kesalahan jika gagal. Aplikasi ASP.NET MVC akan melakukan ini menggunakan kode yang mirip dengan ini:

Ini akan berusaha mengubah string menjadi integer. Jika konversi gagal, kode diarahkan ke tindakan yang akan menampilkan pesan yang tidak valid.

Ini dapat dicegah jika kita mencari parameter integer. Tidak akan membantu jika kita mengharapkan teks seperti pada pencarian produk sebelumnya. Teknik yang disukai dalam hal ini adalah dengan menggunakan regular expressions atau penggantian string untuk memungkinkan hanya karakter yang diperlukan dalam nilai yang diteruskan.

Ini dapat dilakukan dengan memasukkan whitelisting, proses menghapus karakter apa pun selain dari set yang ditentukan, atau blacklisting, proses menghapus anggota dari set tertentu dari string. Whitelisting lebih dapat diandalkan karena Anda hanya menentukan karakter yang diizinkan. Untuk menghapus apa pun selain huruf dan angka dalam sebuah string, kita dapat menggunakan kode seperti:

Anda perlu mengevaluasi setiap input. Beberapa kueri basis data mungkin perlu perhatian khusus. Ambil karakter yang bisa bermakna dalam perintah SQL tetapi juga bisa menjadi karakter yang valid dalam panggilan basis data. Misalnya karakter kutipan tunggal 'digunakan untuk memulai dan menyelesaikan string dalam SQL, tetapi juga bisa menjadi bagian dari nama seseorang seperti O'Conner. Dalam hal ini mengganti tanda kutip tunggal 'dengan tanda kutip tunggal berurutan' 'dapat menghilangkan masalah.

Stored Procedure

Stored Procedure sering dianggap sebagai perbaikan untuk masalah ini dan mereka dapat menjadi bagian dari solusi. Namun Stored Procedure yang ditulis dengan buruk tidak akan menyelamatkan Anda. Ambil Stored Procedure ini yang mencakup kode yang mirip dengan yang telah kita lihat untuk membuat kueri:

Rentetan string di sini adalah masalahnya. Mari kita coba upaya sederhana di mana kami mencoba untuk menetapkan kondisi yang selalu benar untuk menampilkan semua baris dalam tabel dan meneruskan `widget 'yang sama OR 1=1; -` `seperti kueri yang kita lihat sebelumnya. Hasilnya juga sama:

Jika data yang tidak dipercaya diteruskan, kami memiliki hasil yang sama seperti jika panggilan dibuat dalam kode kami. Bahwa penggabungan string terjadi di dalam Stored Procedure bukan dalam kode kami tidak memberikan perlindungan.

Parameterisasi

Potongan puzzle berikutnya untuk melindungi dari serangan injeksi datang dengan menggunakan parameterisasi. Membangun kueri SQL dengan merangkai string dan kemudian melewati kode jadi tidak memberikan database ide apa pun bagian string adalah parameter dan apa yang merupakan bagian dari perintah. Kami dapat membantu melindungi terhadap serangan dengan membuat panggilan SQL dengan cara yang membuat pernyataan dan nilai berbeda.

Kami dapat menulis ulang Stored Procedure yang ditunjukkan sebelumnya untuk menggunakan parameter dan menghasilkan panggilan yang lebih aman. Alih-alih menggabungkan karakter % yang mewakili wildcard, kami akan membuat string baru menambahkan karakter ini dan kemudian meneruskan string baru ini sebagai parameter untuk pernyataan SQL. Proecedure tersimpan yang baru terlihat seperti ini:

Menjalankan stored procedure ini hanya dengan kata widget bekerja seperti yang diharapkan.

Dan jika kami memasukan dengan "widget" parameter kami OR 1=1;-- tidak menghasilkan apa-apa yang menunjukkan bahwa kami tidak lagi rentan terhadap serangan ini.

fixed-sp-callfixed-sp-callfixed-sp-call

Parameterisasi tidak memerlukan prosedur tersimpan. Anda juga dapat memanfaatkannya dengan kueri yang dibangun di dalam kode. Berikut adalah segmen pendek dalam C# untuk menghubungkan dan menjalankan kueri terhadap Microsoft SQL server menggunakan parameter.

Privilege Paling Tidak

Hingga saat ini, saya telah menunjukkan cara mengurangi serangan basis data. Lapisan pertahanan penting lainnya, meminimalkan penyebab kerusakan jika penyerang melewati pertahanan lainnya. Konsep privilege paling tidak memberikan bahwa modul kode yang, dalam hal ini panggilan basis data kami, seharusnya hanya memiliki akses ke informasi dan sumber daya yang diperlukan untuk keperluannya.

Ketika perintah basis data berjalan, ia melakukannya di bawah hak akun pengguna. Kami mendapatkan keamanan dengan memberikan akun panggilan basis data berjalan di bawah hanya hak untuk melakukan hal-hal yang biasanya perlu dilakukan. Jika panggilan dari database hanya membaca data dari tabel, maka hanya berikan hak pilih akun ke tabel dan tidak memasukkan atau menghapus. Jika ada tabel tertentu yang perlu diperbarui, katakan tabel orders , lalu berikan sisipan dan perbarui ke tabel itu, tetapi tidak pada tabel lain seperti yang berisi informasi pengguna.

Membatalkan perintah dapat ditangani melalui akun terpisah yang hanya digunakan pada halaman yang melakukan tugas itu. Ini akan mencegah penghapusan pesanan dari tabel di tempat lain lebih sulit. Menggunakan akun basis data terpisah untuk fungsi administratif situs, dengan hak yang lebih besar daripada yang digunakan publik dapat berbuat banyak untuk mencegah kerusakan dari pengguna yang menemukan serangan injeksi terbuka.

Ini tidak akan mencegah semua serangan. Ini tidak akan melakukan apa pun untuk mencegah pengembalian hasil tambahan seperti contoh sebelumnya yang menunjukkan seluruh isi tabel. Itu akan mencegah serangan memperbarui atau menghapus data.

Kesimpulan

Injeksi SQL adalah serangan paling berbahaya, terutama ketika mempertimbangkan seberapa rentan situs web terhadapnya dan seberapa besar potensi serangan jenis ini dalam menyebabkan banyak kerusakan. Di sini saya telah menjelaskan serangan injeksi SQL dan menunjukkan kerusakan yang bisa dilakukan. Untungnya tidak terlalu sulit untuk melindungi proyek web Anda dari kerentanan ini dengan mengikuti beberapa aturan sederhana.

Jangan pernah percaya data luar apa pun yang dibawa ke aplikasi Anda. Ini harus divalidasi terhadap whitelist input yang valid sebelum diproses lebih lanjut. Ini dapat berarti memastikan bahwa parameter integer sebenarnya adalah integer atau tanggal adalah nilai tanggal yang valid. Validasi juga teks untuk hanya memasukkan karakter yang dibutuhkan parameter. Untuk pencarian teks, Anda seringkali hanya mengizinkan huruf dan angka dan memfilter tanda baca yang bisa bermasalah seperti tanda sama dengan atau tanda titik koma.

Gunakan parameterisasi dan hindari penggabungan string ketika membuat panggilan SQL. Stored procedure bukan merupakan obat mujarab karena mereka juga rentan jika penggabungan string sederhana digunakan. Parameterisasi menghindari banyak masalah penggabungan string.

Kode yang mengakses database harus dijalankan dengan hak istimewa yang paling tidak diperlukan untuk menyelesaikan tugas yang diperlukan. Dalam beberapa keadaan seharusnya panggilan basis data yang digunakan oleh aplikasi web perlu membuat perubahan pada struktur basis data seperti drop atau alter tabel. Anda dapat menambahkan lapisan perlindungan tambahan dengan menjalankan bagian terpisah dari situs web di bawah akun yang berbeda. Akun database yang digunakan untuk tindakan pengguna normal kemungkinan tidak memiliki alasan untuk mengubah tabel yang berisi peran atau hak pengguna. Menjalankan bagian administratif dari situs di bawah akun yang lebih istimewa dan bagian pengguna akhir di bawah yang kurang istimewa dapat berbuat banyak untuk mengurangi kemungkinan kode yang lolos dari menyebabkan masalah lain.

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.