轉自:http://itscodes.blogspot.tw/2016/08/sql-injection.html
正確防護之道
SQL Injection正確的解決方式為何呢? 下列兩者缺一不可!
- 1. Parameterized Query
- 2. Prepare Statement
String custname = request.getParameter("customerName"); // This should REALLY be validated too
// perform input validation to detect attacks
String query = "SELECT account_balance FROM user_data WHERE user_name = ? ";
PreparedStatement pstmt = connection.prepareStatement( query );
pstmt.setString( 1, custname);
ResultSet results = pstmt.executeQuery( );
這篇文章主要用兩個常見的範例說明無效的編碼防護方式
許多人常認為只要將特殊服務去除或是使用 Store procedure
就自然不會受到 SQL injection的攻擊
筆者舉兩個例子說明這樣的迷思與錯誤的觀念
迷思一: 過濾特殊字元
許多開發人員認為只要將 SQL 特殊符號去除就可以避免SQL injection
常見的簡單方式包含將 ‘ 變成 ”
儘管這樣的方式可以避免大部分的 SQL injection 但是還是會有遺漏的風險
讓我們來看一個例子,
這個例子中productName已經將輸入的字串將單引號 ‘ 變成雙引號” 避免 SQL injection 的攻擊
儘管這樣可以解決大部分的 SQL injection 攻擊, 但是這樣的防護方式如果遇到有數值得輸入時,就會受到 SQL Injection
int price = ...; // price
string productName = ...; // product Name
productName = productName.Replace("'","''");
SqlConnection sql= new SqlConnection(...);
sql.Open();
sqlstring=@"SELECT *" +
" FROM client WHERE name= '" + productName+ "' or price =" + price;
SqlCommand cmd = new SqlCommand(sqlstring,sql);
假設駭客輸入下列攻擊字串
Book’ or 1=1 —,
由於 ‘ 會被轉換成雙引號, 造成整個 SQL 語句無效, 所以攻擊會失敗
因此, 駭客可以透過數值的輸入, 因為數值輸入不需要引號,
例如將價格輸入為 100; shutdown —
select * FROM client WHERE ID = 'Book'' or 1=1 -- ' or price=100; shutdown --
除此之外, 駭客可以使用 char(0x27)來代替單引號, 也可以避開過濾單引號的偵測防護
迷思二: 用 STORED PROCEDURE
使用 Stored procedure 就一定安全嗎?
這個範例 Store procedure 引用一個外部參數 ProductName執行
string ProductName = ...; // Assume get the ProductName input from user
SqlConnection sql= new SqlConnection(...);
sql.Open();
// Execute the Store procedure with the ProductName input
sqlstring=@"exec sp_GetName '" + ProductName + "'";
SqlCommand cmd = new SqlCommand(sqlstring,sql);
駭客輸入字串如下, 造成 SQL 語句無效
exec sp_GetName 'Book' 1=1 -- '
但是駭客可以輸入下列 SQL 語句, 除了會造成查詢Book之外, 還會新增一筆資料
exec sp_GetName 'Book' insert into client values(1000, 'Book2') -- '
最危險的 Store procedure範例就是可以讓使用者自由輸入 SQL 語句, 範例如下
CREATE PROCEDURE sp_myStore @input varchar(256)
AS
exec(@input)
迷思三: 使用 SP_EXECUTESQL就可以自動防護 SQL INJECTION
許多的迷思認為只要使用 SP_executeSQL 就可以避免 SQL injection,
但是如果沒有正確的定義參數
還是會受到 SQL injection:
set @cmd = N‘SELECT * FROM sys.database_principals WHERE name = ”’ + @name + N””
set @parameters = null --沒有定義參數 還是會導致 SQL injection
EXEC sp_executesql @cmd, @parameters
正確的使用方式如下:
set @parameters = ‘@name sysname’
EXEC sp_executesql @cmd, @parameters, @name = @name
Ref:
http://www.qa-knowhow.com/?p=4242