Materi Basic SQL
SQL Injection merupakan salah satu risiko aplikasi/situs web yang paling sering ditemukan. Berdasarkan laporan keamanan aplikasi yang dikeluarkan oleh Veracode, 32% dari aplikasi web paling tidak memiliki satu kerentanan SQL Injection.
Pernahkah Anda memikirkan apa yang terjadi dalam kode ketika seseorang memasukkan kueri DB (Data Base) ke dalam parameter? Mari masuk ke kodenya.
-Kasus 1
String sqlString = "SELECT * FROM db_user WHERE username = '"
+ username +
"' AND password = '" + pwd + "'";
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(sqlString);
Alasan utama dibalik setiap SQL Injection adalah pembentukan query. Jika salah satu parameter digabungkan dalam kueri, kemungkinan besar parameter tersebut rentan terhadap SQL Injection.
Perhatikan kode sederhana di atas di sini, nama pengguna dan pwd dapat menjadi parameter permintaan login. Kedua parameter tersebut digabungkan dalam kueri, sehingga rentan terhadap SQL Injection. Mari kita lihat bagaimana kueri dirusak. Anggap saja username=test'+or+1=1+--+&pwd=mypasssebagai masukan dari frontend.
Mari kita tafsirkan kuerinya, bagaimana kuerinya dengan masukan ini. SELECT * FROM db_user WHERE username = 'test' or 1=1 -- ' AND password = 'mypass'. Dalam database SQL, --digunakan untuk berkomentar. Jadi apa pun setelahnya --dikomentari. Jadi database tidak akan memeriksa kata sandi. Ini hanya akan memeriksa apakah nama pengguna dengan testada atau tidak, dan sisanya 1=1adalah kondisi benar yang membuat seluruh kueri menjadi benar.
Untuk memitigasi SQL Injection, disarankan agar pengembang menggunakan kueri yang telah dikompilasi sebelumnya menggunakan kueri berparameter atau pernyataan yang telah disiapkan.
-Kasus 2
Mari kita ambil contoh serupa dari kueri yang telah dikompilasi sebelumnya
String sqlString = "SELECT * FROM db_user WHERE username=" +
username + " AND password =" + pwd;
PreparedStatement stmt = connection.prepareStatement(sqlString);
ResultSet rs = stmt.executeQuery();
Dalam contoh di atas, PreparedStatementdigunakan untuk membuat kueri yang telah dikompilasi sebelumnya. Namun masalahnya lagi-lagi penggabungan nama pengguna dan pwd. Sebelum membuat kueri yang telah dikompilasi sebelumnya, ia akan menggabungkan data dan melanjutkan lebih jauh, menghasilkan SQL Injection.
Seringkali, pengembang mencoba menggunakan pembersih khusus atau validasi khusus pada masukan pengguna.
-Kasus 3
Mari kita ambil contoh dari validasi khusus
public boolean isBlackListed(String parameter) {
List<String> blackList = Arrays.asList("--", ";", "or", "and", "@@", "@", "char", "nchar", "varchar", "nvarchar",
"table", "alter", "begin", "cast", "create", "cursor", "declare", "delete", "drop", "end", "exec",
"union", "execute", "fetch", "select", "insert", "kill", "open", "sys", "sysobjects", "syscolumns",
"update");
for (int i = 0; i < blackList.size(); i++) {
String pattern = blackList.get(i);
Pattern p = Pattern.compile(pattern);
Matcher m = p.matcher(parameter);
if (m.find()) {
return true;
}
}
return false;
}
public void Login(String username, String pwd)
{
if(isBlackListed(username) || isBlackListed(pwd))
return;
String sqlString = "SELECT * FROM db_user WHERE username = '"
+ username +
"' AND password = '" + pwd + "'";
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(sqlString);
}
Pada pandangan pertama, tampaknya masuk akal jika ia memeriksa semua hal yang diperlukan untuk memitigasi SQL Injection. Tapi tidak. Bagaimana dengan kata kunci lainnya? Bagaimana dengan kombinasi CaPS dan SMalL?
Tidak ada pemeriksaan.
-Kesimpulan dan Mitigasi
Yang pasti, kueri yang telah dikompilasi sebelumnya dapat memitigasi SQL Injection, namun harus digunakan dengan benar. Disarankan untuk tidak menggabungkan apa pun dalam kueri. Mari kita lihat bagaimana seseorang harus melakukannya.
String sqlString ="SELECT * FROM db_user WHERE username=? AND password=?";
PreparedStatement stmt = connection.prepareStatement(sqlString);
stmt.setString(1, username);
stmt.setString(2, pwd);
ResultSet rs = stmt.executeQuery();
Agar dapat dimengerti, saya akan mengatakan itu akan menambahkan parameter sebagai string dan kemudian menjalankan kueri. Selain solusi di atas, seseorang juga dapat menggunakan prosedur DB.
-Next Penjelasan Query
Query adalah syntax atau perintah yang digunakan untuk mengakses dan menampilkan data pada sistem database. Query memiliki kemampuan untuk mengatur data mana yang perlu ditampilkan sesuai dengan yang Anda inginkan. Selain itu, query dapat dipakai untuk membuat data dapat saling berinteraksi.
-Tiga Jenis Query Database pada SQL
Terdapat tiga jenis query database pada SQL, yaitu:
DDL (Data Definition Language)
DML (Data Manipulation Language)
DCL (Data Control Language).
Ketiga query ini berfungsi untuk membuat/mendefinisikan objek-objek database seperti membuat tabel, memanipulasi database, dan mengontrol database.
-Dan Untuk Parameter itu
Parameter digunakan untuk bertukar data antara prosedur dan fungsi yang disimpan dan aplikasi atau alat yang disebut prosedur atau fungsi tersimpan:
-Parameter input memungkinkan penelepon untuk meneruskan nilai data ke prosedur atau fungsi tersimpan.
Parameter output memungkinkan prosedur tersimpan untuk meneruskan nilai data atau variabel kursor kembali ke pemanggil. Fungsi yang ditentukan pengguna tidak dapat menentukan parameter output.
Setiap prosedur tersimpan mengembalikan kode pengembalian bilangan bulat ke pemanggil. Jika prosedur tersimpan tidak secara eksplisit menetapkan nilai untuk kode pengembalian, kode pengembalian adalah 0
-- Create a procedure that takes one input parameter and returns one output parameter and a return code.
CREATE PROCEDURE SampleProcedure @EmployeeIDParm INT,
@MaxTotal INT OUTPUT
AS
-- Declare and initialize a variable to hold @@ERROR.
DECLARE @ErrorSave INT
SET @ErrorSave = 0
-- Do a SELECT using the input parameter.
SELECT FirstName, LastName, JobTitle
FROM HumanResources.vEmployee
WHERE EmployeeID = @EmployeeIDParm
-- Save any nonzero @@ERROR value.
IF (@@ERROR <> 0)
SET @ErrorSave = @@ERROR
-- Set a value in the output parameter.
SELECT @MaxTotal = MAX(TotalDue)
FROM Sales.SalesOrderHeader;
IF (@@ERROR <> 0)
SET @ErrorSave = @@ERROR
-- Returns 0 if neither SELECT statement had an error; otherwise, returns the last error.
RETURN @ErrorSave
GO
-Ketika prosedur atau fungsi tersimpan dijalankan, parameter input dapat mengatur nilainya ke konstanta atau menggunakan nilai variabel. Parameter output dan kode pengembalian harus mengembalikan nilainya ke dalam variabel. Parameter dan kode pengembalian dapat bertukar nilai data dengan variabel Transact-SQL atau variabel aplikasi.
Jika prosedur tersimpan dipanggil dari batch atau skrip, parameter dan nilai kode pengembalian dapat menggunakan variabel Transact-SQL yang ditentukan dalam batch yang sama. Contoh berikut adalah batch yang menjalankan prosedur yang dibuat sebelumnya. Parameter input ditentukan sebagai parameter konstanta dan output dan kode pengembalian menempatkan nilainya dalam variabel Transact-SQL:
-- Declare the variables for the return code and output parameter.
DECLARE @ReturnCode INT
DECLARE @MaxTotalVariable INT
-- Execute the stored procedure and specify which variables
-- are to receive the output parameter and return code values.
EXEC @ReturnCode = SampleProcedure @EmployeeIDParm = 19,
@MaxTotal = @MaxTotalVariable OUTPUT
-- Show the values returned.
PRINT ' '
PRINT 'Return code = ' + CAST(@ReturnCode AS CHAR(10))
PRINT 'Maximum Quantity = ' + CAST(@MaxTotalVariable AS CHAR(10))
GO
Komentar
Posting Komentar