Apakah aman untuk tidak membuat parameter kueri SQL jika parameternya bukan string?

113

Dalam hal injeksi SQL , saya sepenuhnya memahami perlunya parameterisasi stringparameter; itulah salah satu trik tertua dalam buku ini. Tapi kapan bisa dibenarkan untuk tidak membuat parameterisasi SqlCommand? Apakah ada tipe data yang dianggap "aman" untuk tidak dijadikan parameter?

Sebagai contoh: Saya tidak menganggap diri saya berada di dekat seorang ahli dalam SQL, tetapi saya tidak dapat memikirkan kasus apa pun yang berpotensi rentan terhadap injeksi SQL untuk menerima boolatau intdan hanya menggabungkannya langsung ke kueri.

Apakah asumsi saya benar, atau dapatkah hal itu berpotensi meninggalkan kerentanan keamanan yang sangat besar dalam program saya?

Untuk klarifikasi, pertanyaan ini diberi tag yang merupakan bahasa yang diketik dengan kuat; ketika saya mengatakan "parameter", pikirkan sesuatu seperti public int Query(int id) .

johnnyRose
sumber
14
Anda tidak akan mendapatkan keuntungan dari rencana kueri yang di-cache jika tidak menggunakan parameter, itu perlu membuat rencana kueri terpisah untuk setiap kombinasi input baru yang Anda berikan.
Scott Chamberlain
5
@MatthewWhited Bagaimana Anda tahu ini membutuhkan waktu lebih sedikit? Situasi ini terjadi di semua tempat dalam proyek tertentu dari pengembang saat ini dan pengembang sebelumnya. Jika itu benar-benar meningkatkan keamanan, silakan kirim jawaban. Untuk klarifikasi, saya setuju bahwa lebih baik untuk membuat parameter, jelas. Tapi itu bukan pertanyaanku.
johnnyRose
7
Kueri yang diparameterisasi terutama digunakan untuk kinerja dan pengoptimalan. Pencegahan injeksi SQL adalah efek samping.
Salman A
13
Saya pikir OP telah mengajukan pertanyaan yang valid. Dia mencoba mengevaluasi biaya / manfaat dari memperbaiki risiko potensial. persamaan itu berubah dengan potensi risiko itu. jika tidak ada risiko, saya juga tidak akan melakukannya. Dia meminta pertanyaan teknis tentang potensi, bukan untuk penilaian subjektif apakah menurut Anda itu sepadan dengan waktunya. OP adalah satu-satunya yang bisa menelepon.
Sir Swears-a-banyak
10
Untuk menjelaskan diri saya: Saya seorang dba. Saya menghargai dan menghormati praktik terbaik, dan di dunia yang sempurna semua kode akan menjadi sempurna. Sayangnya di dunia tempat saya bekerja, saya memiliki lebih banyak masalah untuk dipecahkan daripada waktu saya untuk menyelesaikannya. Itu berarti memprioritaskan. IMO Menulis ulang kode yang sudah berfungsi, aman, dan bekerja ke tingkat yang dapat diterima terdengar seperti kemewahan. (Bahwa saya tidak mampu)
Sir Swears-a-lot

Jawaban:

101

Saya pikir itu aman ... secara teknis , tapi itu kebiasaan buruk untuk dilakukan. Apakah Anda benar-benar ingin menulis pertanyaan seperti ini?

var sqlCommand = new SqlCommand("SELECT * FROM People WHERE IsAlive = " + isAlive + 
" AND FirstName = @firstName");

sqlCommand.Parameters.AddWithValue("firstName", "Rob");

Ini juga membuat Anda rentan dalam situasi di mana tipe berubah dari integer menjadi string (Pikirkan nomor karyawan yang, terlepas dari namanya - mungkin berisi huruf).

Jadi, kami telah mengubah jenis EmployeeNumber dari intmenjadi string, tetapi lupa memperbarui kueri sql kami. Ups.

Rob
sumber
24
Bisakah kita berhenti menggunakan AddWithValue ? blogs.msmvps.com/jcoehoorn/blog/2014/05/12/...
RemarkLima
5
@RemarkLima Apa solusinya saat Anda secara dinamis membuat kode yang memetakan nilai ke parameter? Entri blog gagal membahas skenario itu. Ya, itu adalah satu baris untuk mengatur tipe SQL ketika diketahui , tetapi jika tidak, maka Anda memiliki masalah (atau Anda harus menggunakan model anotasi dengan informasi itu).
casperOne
1
Kemudian Anda terjebak dengan AddWithValuekecuali Anda memiliki pemetaan tipe database sebagai bagian dari bangunan dinamis pernyataan. Saya berasumsi bahwa Anda memiliki daftar kolom target, dan sebagai bagian dari kamus, Anda dapat memiliki tipe jika Anda mau. Jika tidak, terima saja kinerja yang dipukul. Pada akhirnya, menurut saya, hanya informasi yang baik untuk diketahui.
RemarkLima
8
@RemarkLima Intinya adalah "Bisakah kita sudah berhenti menggunakan AddWithValue?" harus benar-benar "jika Anda tahu tipenya, maka Anda harus menahan diri untuk tidak menggunakan AddWithValue.
casperOne
2
Hei, jangan tembak si pembawa pesan, saya tidak menulisnya ;-) tapi intinya tetap, dan jika dibangun ke dalam desain Anda dari awal, tidak ada alasan Anda tidak harus tahu jenisnya. Praktik terbaik dan semua jazz itu :-)
RemarkLima
65

Bila menggunakan platform kuat-mengetik pada komputer Anda kontrol (seperti web server), Anda dapat mencegah kode injeksi untuk query dengan hanya bool, DateTimeatau int(dan numerik lainnya) nilai-nilai. Yang menjadi perhatian adalah masalah kinerja yang disebabkan oleh memaksa server sql untuk mengkompilasi ulang setiap kueri, dan dengan mencegahnya mendapatkan statistik yang baik tentang kueri apa yang dijalankan dengan frekuensi apa (yang merugikan manajemen cache).

Tetapi bagian "di komputer yang Anda kendalikan" itu penting, karena jika tidak, pengguna dapat mengubah perilaku yang digunakan oleh sistem untuk menghasilkan string dari nilai-nilai tersebut untuk menyertakan teks arbitrer.

Saya juga suka berpikir jangka panjang. Apa yang terjadi ketika basis kode yang diketik kuat yang lama dan rusak saat ini di-porting melalui terjemahan otomatis ke bahasa dinamis baru-panas, dan Anda tiba-tiba kehilangan pemeriksaan jenis, tetapi belum memiliki semua pengujian unit yang tepat untuk kode dinamis ?

Sungguh, tidak ada alasan bagus untuk tidak menggunakan parameter kueri untuk nilai-nilai ini. Ini cara yang benar untuk melakukan ini. Silakan dan nilai kode keras ke dalam string sql ketika mereka benar-benar konstanta, tetapi sebaliknya, mengapa tidak menggunakan parameter saja? Ini tidak sulit.

Pada akhirnya, saya tidak akan menyebut ini bug , tetapi saya akan menyebutnya bau : sesuatu yang tidak termasuk bug dengan sendirinya, tetapi merupakan indikasi kuat bahwa bug ada di sekitar, atau pada akhirnya akan ada. Kode yang baik menghindari meninggalkan bau, dan alat analisis statis yang baik akan menandai ini.

Saya akan menambahkan bahwa ini bukan, sayangnya, jenis argumen yang bisa Anda menangkan langsung. Kedengarannya seperti situasi di mana menjadi "benar" tidak lagi cukup, dan menginjak kaki rekan kerja Anda untuk memperbaiki masalah ini sendiri tidak akan mendorong dinamika tim yang baik; itu pada akhirnya bisa lebih menyakitkan daripada membantu. Pendekatan yang lebih baik dalam kasus ini mungkin mempromosikan penggunaan alat analisis statis. Itu akan memberikan legitimasi dan kredibilitas pada upaya yang ditujukan dan kembali serta memperbaiki kode yang ada.

Joel Coehoorn
sumber
1
Jelas bukan tantangan untuk melakukannya dengan parameter. Pertanyaan saya muncul karena seorang rekan kerja menulis sekumpulan pertanyaan yang menggabungkan nilai integer, dan saya bertanya-tanya apakah membuang-buang waktu saya untuk memeriksa dan memperbaiki semuanya.
johnnyRose
2
Saya pikir pertanyaan "Apakah itu bug" adalah inti dari pertanyaan saya.
johnnyRose
7
Ini adalah "bau": sesuatu yang tidak termasuk serangga dengan sendirinya, tetapi menunjukkan bahwa serangga mungkin ada di sekitar. Kode yang bagus mencoba menghilangkan bau. Alat analisis statis yang baik pasti akan menandainya.
Joel Coehoorn
1
Saya suka istilah "bau". Saya akan menggunakan sesuatu seperti "larva" sebagai gantinya, yang belum sepenuhnya merupakan bug, tetapi pembaruan di masa mendatang dapat menangkapnya sebagai belatung yang akan memakan bagian belakang Anda sampai Anda menghancurkannya atau mengasapi. Anda tentu tidak ingin potensi kode nekrotik muncul di lingkungan produksi, dan memiliki sesuatu yang tidak dikembangkan dengan sejumlah kemahiran tentu dapat menyebabkannya muncul, seperti dalam kasus ini.
CSS
1
Ini salah. Lihat jawaban saya misalnya tentang bagaimana Anda masih dapat membuat injeksi SQL dengan DateTimeatauint
Kaspars Ozols
53

Dalam beberapa kasus, IS mungkin untuk melakukan serangan injeksi SQL dengan variabel non-parametrized (gabungan) selain nilai string - lihat artikel ini oleh Jon: http://codeblog.jonskeet.uk/2014/08/08/the-bobbytables -kultur / .

Masalahnya adalah ketika ToStringdipanggil, beberapa penyedia budaya kustom dapat mengubah parameter non-string menjadi representasi stringnya yang memasukkan beberapa SQL ke dalam kueri.

Maciek
sumber
14
Menurut saya ini adalah satu-satunya postingan yang menjawab pertanyaan, yang pada dasarnya adalah "Bagaimana injeksi bisa dilakukan dengan ints?"
Arturo Torres Sánchez
3
Padahal jika Anda berada dalam posisi untuk menginjeksi kode kustom seperti booby trapped CultureInfosulit untuk mengetahui mengapa Anda tetap membutuhkan SQL injection.
Martin Smith
ditambah 1, satu-satunya jawaban yang benar - benar menjawab pertanyaan
ken2k
@MartinSmith: lihat jawaban saya yang menunjukkan satu cara yang mungkin untuk mengubah CultureInfo dari luar.
pengguna1027167
Jika seseorang dapat menulis kode seperti itu dalam aplikasi, mengapa dia membutuhkan SQL Injection?
Reza Aghaei
51

Ini tidak aman bahkan untuk tipe non-string. Selalu gunakan parameter. Titik.

Pertimbangkan contoh kode berikut:

var utcNow = DateTime.UtcNow;
var sqlCommand = new SqlCommand("SELECT * FROM People WHERE created_on <= '" + utcNow + "'");

Sekilas kode terlihat aman, tetapi semuanya berubah jika Anda membuat beberapa perubahan di Pengaturan Regional Windows dan menambahkan injeksi dalam format tanggal pendek:

Injeksi Datetime

Sekarang teks perintah yang dihasilkan terlihat seperti ini:

SELECT * FROM People WHERE created_on <= '26.09.2015' OR '1'<>' 21:21:43'

Hal yang sama dapat dilakukan untuk inttipe karena pengguna dapat menentukan tanda negatif khusus yang dapat dengan mudah diubah menjadi injeksi SQL.

Orang dapat berargumen bahwa budaya invarian harus digunakan sebagai pengganti budaya saat ini, tetapi saya telah melihat penggabungan string seperti ini berkali-kali dan cukup mudah untuk dilewatkan saat menggabungkan string dengan objek yang digunakan +.

Kaspars Ozols
sumber
10
Siapa yang dapat mengubah pengaturan server? Jika seseorang dapat melakukannya di server Anda, dia tidak memerlukan SQL Injection untuk menghancurkan data.
Reza Aghaei
5
Ini adalah jawaban terbaik, ini menunjukkan salah satu cara yang memvalidasi kekhawatiran OP ini adalah bug / cacat keamanan. Kinerja dan pembuktian masa depan selain menggabungkan waktu data dalam SQL misalnya bukan hanya masalah bau atau utang teknologi . @RezaAghaei pertanyaannya tidak pernah menyebutkan Server-Side, itu bisa menjadi Aplikasi Windows dengan SQLExpress - bagaimanapun itu bukan kriteria untuk pertanyaan tersebut. Siapa pun dapat mengatakan tetapi siapa yang memiliki akses ke pengaturan server untuk membantah jawaban yang luar biasa ini, sama seperti siapa pun dapat mengatakan bagaimana dengan hosting server bersama atau bug Y2K. Saya setuju dengan Anda server yang dikunci - itu bukan prasyarat.
Jeremy Thompson
2
Bisakah Anda memberikan contoh apa yang Anda katakan tentang inttipe tersebut?
johnnyRose
1
Saya tahu sudah beberapa minggu sejak Anda menjawab ini, tetapi apakah mungkin bagi Anda untuk mengedit posting Anda dan menambahkan contoh bagaimana Anda dapat mendefinisikan tanda negatif khusus?
johnnyRose
23

"SELECT * FROM Table1 WHERE Id =" + intVariable.ToString ()


Keamanan
Tidak apa-apa.
Penyerang tidak dapat menginjeksi apapun ke dalam variabel int yang Anda ketik.

Performa
Tidak OK.

Lebih baik menggunakan parameter, sehingga kueri akan dikompilasi sekali dan di-cache untuk penggunaan berikutnya. Lain kali bahkan dengan nilai parameter yang berbeda, kueri di-cache dan tidak perlu dikompilasi di server database.


Praktik Buruk Gaya Pengkodean .

  • Parameter lebih mudah dibaca
  • Mungkin itu membuat Anda terbiasa dengan kueri tanpa parameter, lalu mungkin Anda membuat kesalahan sekali dan menggunakan nilai string dengan cara ini dan kemudian Anda mungkin harus mengucapkan selamat tinggal pada data Anda. Kebiasaan buruk!


"SELECT * FROM Product WHERE Id =" + TextBox1.Text


Meskipun ini bukan pertanyaan Anda, tapi mungkin berguna untuk pembaca selanjutnya:


Bencana Keamanan !
Meskipun Idkolomnya bilangan bulat, kueri Anda mungkin tunduk pada SQL Injection. Misalkan Anda memiliki kueri dalam aplikasi Anda "SELECT * FROM Table1 WHERE Id=" + TextBox1.Text, Penyerang dapat memasukkan ke dalam kotak teks 1; DELETE Table1dan kueri tersebut akan menjadi:

"SELECT * FROM Table1 WHERE Id=1; DELETE Table1"

Jika Anda tidak ingin menggunakan kueri parametrized di sini, Anda harus menggunakan nilai yang diketik:

string.Format("SELECT * FROM Table1 WHERE Id={0}", int.Parse(TextBox1.Text))


Pertanyaanmu


Pertanyaan saya muncul karena seorang rekan kerja menulis sekumpulan pertanyaan yang menggabungkan nilai integer, dan saya bertanya-tanya apakah membuang-buang waktu saya untuk memeriksa dan memperbaiki semuanya.

Saya pikir mengubah kode-kode itu tidak membuang-buang waktu. Memang perubahan itu Direkomendasikan!

jika rekan kerja Anda menggunakan variabel int, itu tidak memiliki risiko keamanan, Tapi menurut saya mengubah kode-kode itu tidak membuang-buang waktu dan memang disarankan untuk mengubah kode-kode itu. Itu membuat kode lebih mudah dibaca, lebih mudah dipelihara dan membuat eksekusi lebih cepat.

Reza Aghaei
sumber
Bahkan opsi pertama tidak sepenuhnya baik untuk keamanan. Perilaku .ToString()ditentukan oleh item konfigurasi sistem operasi yang mudah diubah untuk menyertakan teks arbitrer.
Joel Coehoorn
18

Sebenarnya ada dua pertanyaan dalam satu. Dan pertanyaan dari judul tidak ada hubungannya dengan kekhawatiran yang diungkapkan oleh OP dalam komentar sesudahnya.

Meskipun saya menyadari bahwa untuk OP itu adalah kasus khusus mereka yang penting, bagi pembaca yang berasal dari Google, penting untuk menjawab pertanyaan yang lebih umum, yang dapat diutarakan sebagai "apakah penggabungan seaman pernyataan yang disiapkan jika saya memastikan bahwa setiap literal yang saya gabungkan aman? ". Jadi, saya ingin berkonsentrasi pada yang terakhir ini. Dan jawabannya adalah

Pasti TIDAK.

Penjelasannya tidak langsung seperti yang diinginkan kebanyakan pembaca, tetapi saya akan berusaha sebaik mungkin.

Saya telah merenungkan masalah ini untuk sementara waktu, menghasilkan artikel (meskipun berdasarkan lingkungan PHP) di mana saya mencoba merangkum semuanya. Terpikir oleh saya bahwa pertanyaan tentang perlindungan dari injeksi SQL sering kali luput dari beberapa topik terkait tetapi lebih sempit, seperti string escape, type casting, dan semacamnya. Meskipun beberapa tindakan dapat dianggap aman jika dilakukan sendiri, tidak ada sistem, atau aturan sederhana untuk diikuti. Yang membuatnya sangat licin, memberikan terlalu banyak perhatian dan pengalaman pengembang.

Pertanyaan tentang injeksi SQL tidak dapat disederhanakan menjadi masalah sintaks tertentu. Ini lebih luas dari yang biasa dipikirkan pengembang rata-rata. Ini juga pertanyaan metodologis . Ini tidak hanya "Pemformatan khusus mana yang harus kita terapkan", tetapi juga " Bagaimana hal itu harus dilakukan".

(Dari sudut pandang ini, sebuah artikel dari Jon Skeet yang dikutip dalam jawaban lain melakukan agak buruk daripada baik, karena lagi-lagi membahas beberapa kasus tepi, berkonsentrasi pada masalah sintaks tertentu dan gagal mengatasi masalah secara keseluruhan.)

Saat Anda mencoba menjawab pertanyaan tentang perlindungan tidak secara keseluruhan tetapi sebagai serangkaian masalah sintaksis yang berbeda, Anda menghadapi banyak masalah.

  • daftar kemungkinan pilihan pemformatan sangat besar. Berarti seseorang dapat dengan mudah mengabaikan beberapa. Atau membingungkan mereka (dengan menggunakan string escaping untuk pengenal misalnya).
  • Penggabungan berarti bahwa semua tindakan perlindungan harus dilakukan oleh programmer, bukan oleh program. Masalah ini sendiri menyebabkan beberapa konsekuensi:
    • format seperti itu manual. Manual berarti sangat rawan kesalahan. Seseorang bisa saja lupa untuk melamar.
    • Selain itu, ada godaan untuk memindahkan prosedur pemformatan ke beberapa fungsi terpusat, bahkan lebih mengacaukan, dan merusak data yang tidak masuk ke database.
  • ketika lebih dari satu pengembang terlibat, masalah dikalikan dengan faktor sepuluh.
  • ketika penggabungan digunakan, seseorang tidak dapat mengetahui kueri yang berpotensi berbahaya secara sekilas: semuanya berpotensi berbahaya!

Tidak seperti kekacauan itu, pernyataan yang disiapkan memang The Holy Grail:

  • itu dapat diekspresikan dalam bentuk satu aturan sederhana yang mudah diikuti.
  • itu pada dasarnya adalah ukuran yang tidak dapat dihapus, berarti pengembang tidak dapat mengganggu, dan, dengan sengaja atau tidak, merusak proses.
  • proteksi dari injeksi sebenarnya hanya merupakan efek samping dari statement yang dibuat, yang tujuan sebenarnya adalah menghasilkan statement yang benar secara sintaksis. Dan pernyataan yang benar secara sintaksis adalah bukti injeksi 100%. Namun kami membutuhkan sintaks kami untuk benar meskipun ada kemungkinan injeksi.
  • jika digunakan secara menyeluruh, ini melindungi aplikasi terlepas dari pengalaman pengembangnya. Katakanlah, ada yang namanya injeksi orde dua . Dan khayalan yang sangat kuat yang berbunyi "untuk melindungi, Luput dari Semua Masukan yang Disediakan Pengguna ". Dikombinasikan bersama, mereka mengarah pada injeksi, jika pengembang mengambil kebebasan untuk memutuskan, apa yang perlu dilindungi dan apa yang tidak.

(Berpikir lebih jauh, saya menemukan bahwa set placeholder saat ini tidak cukup untuk kebutuhan kehidupan nyata dan harus diperluas, baik untuk struktur data yang kompleks, seperti array, dan bahkan kata kunci atau pengenal SQL, yang terkadang harus ditambahkan ke kueri secara dinamis juga, tetapi pengembang dibiarkan tidak bersenjata untuk kasus seperti itu, dan dipaksa untuk kembali ke penggabungan string tetapi itu masalah pertanyaan lain).

Menariknya, kontroversi pertanyaan ini dipicu oleh sifat Stack Overflow yang sangat kontroversial. Ide situs adalah memanfaatkan pertanyaan tertentu dari pengguna yang bertanya secara langsung untuk mencapai tujuan memiliki database jawaban tujuan umum yang sesuai untuk pengguna yang datang dari penelusuran . Idenya adalah tidak buruk per se , tetapi gagal dalam situasi seperti ini: ketika pengguna mengajukan pertanyaan yang sangat sempit , terutama untuk mendapatkan sebuah argumen dalam sengketa dengan rekan (atau untuk memutuskan apakah itu layak untuk refactor kode). Sementara sebagian besar peserta berpengalaman mencoba menulis jawaban, ingatlah misinya dari Stack Overflow secara keseluruhan, membuat jawaban mereka bagus untuk pembaca sebanyak mungkin, bukan hanya OP.

Akal Sehat Anda
sumber
10
Tidak menjawab pertanyaan
edc65
Sebagian besar database mendeteksi kueri yang sudah digunakan dan diparameterisasi dengan persamaan string SQL, jadi metode persiapkan dan gunakan yang lama tampaknya sudah ketinggalan zaman bagi saya. Pegangan ini hanya dapat digunakan dalam lingkup tertentu dan memerlukan pengkodean untuk melacak pegangan. Kueri yang diparameterisasi harus, menurut pendapat saya, digunakan secara langsung, sehingga rencana kueri dapat digunakan kembali tanpa menangani pelacakan dan bahkan di berbagai aplikasi.
Erik Hart
15

Mari kita tidak hanya memikirkan tentang keamanan atau pertimbangan keamanan tipe.

Alasan Anda menggunakan kueri parametrized adalah untuk meningkatkan kinerja di tingkat database. Dari perspektif database, kueri parametrized adalah satu kueri di buffer SQL (untuk menggunakan terminologi Oracle meskipun saya membayangkan semua database memiliki konsep yang serupa secara internal). Jadi, database dapat menampung sejumlah query dalam memori, disiapkan dan siap untuk dieksekusi. Kueri ini tidak perlu diurai dan akan lebih cepat. Query yang sering dijalankan biasanya ada di buffer dan tidak perlu diurai setiap kali digunakan.

KECUALI KALAU

Seseorang tidak menggunakan kueri parametrized. Dalam kasus ini, buffer terus-menerus dialirkan melalui aliran kueri yang hampir identik yang masing-masing perlu diurai dan dijalankan oleh mesin database dan kinerja menderita serba guna karena kueri yang sering dijalankan akhirnya diurai ulang berkali-kali a hari. Saya telah menyetel database untuk mencari nafkah dan ini telah menjadi salah satu sumber terbesar dari hasil yang menggantung rendah.

SEKARANG

Untuk menjawab pertanyaan Anda, JIKA kueri Anda memiliki sejumlah kecil nilai numerik yang berbeda, Anda mungkin tidak akan menyebabkan masalah dan bahkan dapat meningkatkan kinerja secara tak terbatas. JIKA ada potensi ratusan nilai dan kueri sering dipanggil, Anda akan memengaruhi kinerja sistem Anda, jadi jangan lakukan itu.

Ya, Anda dapat meningkatkan buffer SQL tetapi pada akhirnya selalu mengorbankan penggunaan lain yang lebih penting untuk memori seperti Caching Indeks atau Data. Moral, gunakan kueri parametrized dengan cukup religius sehingga Anda dapat mengoptimalkan database Anda dan menggunakan lebih banyak memori server untuk hal-hal yang penting ...

mcottle
sumber
8

Untuk menambahkan beberapa info ke jawaban Maciek:

Sangat mudah untuk mengubah info budaya dari aplikasi pihak ketiga .NET dengan memanggil fungsi utama perakitan dengan refleksi:

using System;
using System.Globalization;
using System.Reflection;
using System.Threading;

namespace ConsoleApplication2
{
  class Program
  {
    static void Main(string[] args)
    {
      Assembly asm = Assembly.LoadFile(@"C:\BobbysApp.exe");
      MethodInfo mi = asm.GetType("Test").GetMethod("Main");
      mi.Invoke(null, null);
      Console.ReadLine();
    }

    static Program()
    {
      InstallBobbyTablesCulture();
    }

    static void InstallBobbyTablesCulture()
    {
      CultureInfo bobby = (CultureInfo)CultureInfo.InvariantCulture.Clone();
      bobby.DateTimeFormat.ShortDatePattern = @"yyyy-MM-dd'' OR ' '=''";
      bobby.DateTimeFormat.LongTimePattern = "";
      bobby.NumberFormat.NegativeSign = "1 OR 1=1 OR 1=";
      Thread.CurrentThread.CurrentCulture = bobby;
    }
  }
}

Ini hanya berfungsi jika fungsi Utama BobbysApp bersifat publik. Jika Utama tidak umum, mungkin ada fungsi publik lain yang dapat Anda hubungi.

pengguna1027167
sumber
1
Anda bahkan tidak perlu melakukannya dengan kode. Anda dapat menambahkan injeksi langsung di Pengaturan Regional Windows. Lihat jawaban saya.
Kaspars Ozols
2
Siapa yang dapat mengubah pengaturan server atau siapa yang dapat menggosok kode tersebut di server? Jika seseorang dapat melakukannya di server Anda, dia tidak memerlukan SQL Injection untuk menghancurkan data.
Reza Aghaei
7

Menurut pendapat saya, jika Anda dapat menjamin bahwa parameter yang Anda kerjakan tidak akan pernah berisi string, itu aman tetapi saya tidak akan melakukannya dalam hal apa pun. Selain itu, Anda akan melihat sedikit penurunan kinerja karena Anda melakukan penggabungan. Pertanyaan yang ingin saya tanyakan adalah mengapa Anda tidak ingin menggunakan parameter?

Max
sumber
1
Bukannya saya tidak ingin menggunakan parameter, saya menggunakan parameter. Seorang rekan kerja menulis kode seperti ini yang saya modifikasi menjadi parameter hari ini, yang membuat saya memikirkan pertanyaan itu.
johnnyRose
Baik. Bagus. Ini adalah praktik terbaik untuk menggunakan parameter. Dengan cara ini Anda tidak perlu khawatir tentang hal-hal seperti injeksi sql. Selain itu, jika Anda membangun kueri dinamis, Anda juga dapat menggunakan parameter tidak peduli seberapa kompleks kueri Anda. Cukup gunakan gaya @ 1 ... @ n saat membangunnya. Dan menambahkannya ke koleksi parameter dengan nilai yang diinginkan.
Maks
@johnyRose Ada satu hal lagi untuk menggunakan parameter: program berkembang dan berubah. Anda dapat menggunakan penggabungan hanya untuk string tetapi itu tidak menjamin bahwa seseorang menerapkan pemfaktoran ulang yang mengubah beberapa jenis parameter dan perubahan itu dapat memperkenalkan kerentanan SQL Injection.
lerthe61
3

Tidak apa-apa tetapi tidak pernah aman .. dan keamanan selalu bergantung pada input, misalnya jika objek input adalah TextBox, penyerang dapat melakukan sesuatu yang rumit karena kotak teks dapat menerima string, jadi Anda harus meletakkan semacam validasi / konversi untuk dapat mencegah pengguna salah memasukkan. Tapi masalahnya, itu tidak aman. Sesederhana itu.

japzdivino.dll
sumber
Itu string. Saya berbicara tentang tipe data lain, seperti integer, boolean, atau datetimes.
johnnyRose
@johnnyRose Yup, saya telah melihat contoh yang sangat bagus di atas yang Anda tandai sebagai dijawab oleh Kaspards .. dan jawaban yang bagus karena dia menggunakan tipe data waktu sebagai contoh yang tidak umum. :) Saya harap Anda sudah yakin bahwa tidak aman dan lebih baik menggunakan parameter dalam semua jenis tipe data
japzdivino
Saya tidak pernah benar-benar ragu bahwa lebih aman menggunakan parameter. Pertanyaan saya mengacu pada implementasi yang diketik dengan kuat.
johnnyRose
Yup .. saya setuju. dan itu juga pertanyaan bagus yang dapat membantu pembaca di masa mendatang :)
japzdivino
-2

Tidak, Anda bisa mendapatkan serangan injeksi SQL dengan cara itu. Saya telah menulis artikel lama dalam bahasa Turki yang menunjukkan caranya di sini . Contoh artikel di PHP dan MySQL tetapi konsep berfungsi sama di C # dan SQL Server.

Pada dasarnya Anda menyerang dengan cara berikut. Mari pertimbangkan Anda memiliki halaman yang menampilkan informasi sesuai dengan nilai id integer. Anda tidak mengukur nilai ini, seperti di bawah ini.

http://localhost/sqlEnjeksiyon//instructors.aspx?id=24

Oke, saya asumsikan Anda menggunakan MySQL dan saya menyerang dengan cara berikut.

http://localhost/sqlEnjeksiyon//instructors.aspx?id=ASCII((SELECT%20DATABASE()))

Perhatikan bahwa nilai yang dimasukkan di sini bukanlah string. Kami mengubah nilai karakter menjadi int menggunakan fungsi ASCII. Anda dapat mencapai hal yang sama di SQL Server menggunakan "CAST (YourVarcharCol AS INT)".

Setelah itu saya menggunakan fungsi panjang dan substring untuk mengetahui nama database Anda.

http://localhost/sqlEnjeksiyon//instructors.aspx?id=LEN((SELECT%20DATABASE()))

http://localhost/sqlEnjeksiyon//instructors.aspx?id=ASCII(SUBSTR(SELECT%20DATABASE(),1,1))

Kemudian dengan menggunakan nama database, Anda mulai mendapatkan nama tabel di database.

http://localhost/sqlEnjeksiyon//instructors.aspx?id=ASCII(SUBSTR((SELECT table_name FROM INFORMATION_SCHEMA.TABLES LIMIT 1),1,1))

Tentu saja Anda harus mengotomatiskan proses ini, karena Anda hanya mendapatkan SATU karakter per kueri. Tetapi Anda dapat dengan mudah mengotomatiskannya. Artikel saya menunjukkan satu contoh di watir . Hanya menggunakan satu halaman dan bukan nilai ID berparameter. Saya bisa mempelajari setiap nama tabel di database Anda. Setelah itu saya bisa mencari tabel penting. Ini akan memakan waktu tetapi itu bisa dilakukan.

Atilla Ozgur
sumber
2
Pertanyaan saya mengacu pada bahasa yang diketik dengan kuat. Meskipun penjelasan Anda bagus untuk bahasa dengan pengetikan fleksibel, nilai yang dimasukkan masih berupa string.
johnnyRose
Tidak ada nilai yang dimasukkan adalah integer. Anda mendapatkan char dan mengubahnya menjadi integer menggunakan fungsi ASCII MySQL. Anda melakukan hal yang sama di SQL Server menggunakan CAST (YourCharValue AS INT)
Atilla Ozgur
Maksud saya seperti ini:public void QuerySomething(int id) { // this will only accept an integer }
johnnyRose
-3

Nah ... satu hal yang pasti: Keamanan TIDAK ok, ketika Anda menggabungkan string (diambil oleh pengguna) dengan string perintah SQL Anda. Tidak masalah kapan pun klausa where mengacu pada Integer atau tipe apa pun; suntikan bisa terjadi.

Yang penting dalam SQL Injection adalah tipe data dari variabel yang digunakan untuk mendapatkan nilai dari pengguna.

Misalkan kita memiliki integer di klausa where dan:

  1. variabel pengguna adalah string. Maka ok, tidak mudah untuk menginjeksi (menggunakan UNION) tetapi sangat mudah untuk melewati menggunakan 'OR 1 = 1' - seperti serangan ...

  2. Jika variabel pengguna adalah bilangan bulat. Kemudian lagi kita dapat 'menguji' kekuatan sistem dengan melewati pengujian angka besar yang tidak biasa untuk sistem crash atau bahkan untuk buffer overflow tersembunyi (pada string terakhir) ...;)

Mungkin parameter untuk kueri atau (bahkan lebih baik - imo) ke Prosedur Tersimpan bukanlah 100% Ancaman yang aman, tetapi mereka adalah ukuran yang paling tidak diperlukan (atau yang paling dasar jika Anda lebih suka) untuk meminimalkannya.

Andreas Venieris
sumber
Saya pikir Anda mungkin telah salah memahami pertanyaan itu. Saya berbicara tentang jenis non- string.
johnnyRose
Hai JonnyRose ... terima kasih atas catatan Anda. Saya memahami pertanyaan Anda, tetapi saya hanya memberikan jawaban saya dalam bentuk yang lebih umum. Untuk kasus non-string, silakan periksa poin (2) saya. ;)
Andreas Venieris