攻擊者透過惡意輸入竄改動態 SQL 命令,在資料庫伺服器執行任意指令。經典脆弱程式碼:
string cmd = "SELECT * FROM Customers WHERE CompanyName = '" + txtCompanyName.Text + "'";
SqlDataSource1.SelectCommand = cmd;
輸入 Ernst Handel' UNION SELECT CustomerID, ShipName, ShipAddress FROM ORDERS-- 即可竄改查詢,洩露訂單資料。
WHERE CompanyName = @CompanyName。較安全,但需開發者嚴格遵守,存儲程序若動態拼接 SQL 仍有風險。核心機制:LINQ to SQL 將所有查詢參數化。編譯器與 IntelliSense 提供編譯期語法檢查,運行時自動產生參數化 SQL。
Customers 資料表,自動產生 CustomersDataContext 與實體類別。
protected void Page_Load(object sender, EventArgs e) {
string connStr = ConfigurationManager.ConnectionStrings["Northwind"].ConnectionString;
var db = new CustomersDataContext(connStr);
GridView1.DataSource = from c in db.Customers
where c.CompanyName == txtCompanyName.Text
orderby c.CompanyName
select c;
GridView1.DataBind();
}
SELECT [t0].[CustomerID], [t0].[CompanyName], [t0].[ContactName], ...
FROM [dbo].[Customers] AS [t0]
WHERE [t0].[CompanyName] = @p0
ORDER BY [t0].[CompanyName]
@p0 為參數,使用者輸入被視為字面值,無法竄改查詢結構。即使輸入注入字串,查詢只會嘗試比對字面字串,回傳空結果,不會執行額外命令。
唯一攻擊面:誘騙 LINQ 產生非預期 SQL(極難)。語言與編譯器設計即為防範此風險。
暴力破解(窮舉 CompanyName)仍可能,但僅能存取該頁面暴露的資料範圍,無法注入命令存取其他資料表。
採用 LINQ to SQL (或 Entity Framework) 進行資料存取,從架構層面杜絕 SQL 注入。新專案首選;舊專案可模組化遷移。這是構建安全應用程式最高效的選擇。