[研究]ASP.NET, Fortify SCA 說 SqlCommand command = new SqlCommand(queryString, connection); 的來源不可靠,有 SQL Injection (Security Auditor View: Low) 問題,該如何改 ?
2024-03-18
環境:Visual Studio 2022 + ASP.NET + WebForm + Web Application + C# + SQL Server 2019 + SQL Server Management Studio (SSMS) 19
********************************************************************************
下面程式 Fortify SCA 說 SqlCommand command = new SqlCommand(queryString, connection); 的來源不可靠,該如何改 ?
string queryString = SqlDataSource1.SelectCommand;
using (SqlConnection connection = new SqlConnection(
WebConfigurationManager.ConnectionStrings["pmsConnectionString"].ConnectionString))
{
SqlCommand command = new SqlCommand(queryString, connection);
command.Parameters.Clear();
command.Parameters.AddWithValue("@loginID", loginID);
command.Parameters.AddWithValue("@queryedID", Common.MyAntiXssFilter(DropDownList_id.SelectedValue));
connection.Open();
using (SqlDataReader reader = command.ExecuteReader())
}
|
ChatGPT
Fortify SCA可能提示這段程式碼有安全性風險,因為它可能容易受到SQL注入攻擊。為了改善這個問題,你可以使用參數化查詢來處理輸入,而不是直接將查詢字串與用戶輸入串接在一起。這樣可以防止SQL注入攻擊。以下是修改後的程式碼:
string queryString = "SELECT * FROM YourTable WHERE LoginID = @loginID AND QueryedID = @queryedID";
using (SqlConnection connection = new SqlConnection(WebConfigurationManager.ConnectionStrings["pmsConnectionString"].ConnectionString))
{
SqlCommand command = new SqlCommand(queryString, connection);
command.Parameters.Clear();
command.Parameters.AddWithValue("@loginID", loginID);
command.Parameters.AddWithValue("@queryedID", Common.MyAntiXssFilter(DropDownList_id.SelectedValue));
connection.Open();
using (SqlDataReader reader = command.ExecuteReader())
{
// 在這裡處理讀取的資料
}
}
|
這裡,我們將SQL查詢字串硬編碼到程式碼中,並使用@loginID和@queryedID來代表參數。這些參數將由command.Parameters.AddWithValue方法來設定,這樣可以確保用戶輸入不會被解釋為SQL指令,從而防止SQL注入攻擊。
********************************************************************************
為何不能 string queryString = SqlDataSource1.SelectCommand;
ChatGPT
在ASP.NET Web Forms中,SqlDataSource是用於資料存取的控制項之一。但是,SqlDataSource.SelectCommand屬性在設定時是一個string,而不是一個SQL命令物件(如SqlCommand),因此無法直接使用。
SqlDataSource.SelectCommand是用來指定要在資料庫中執行的SQL查詢字串,它只是一個字串。而且,它通常在ASP.NET控制項的生命週期中,在執行時階段才會被使用,而不是在編譯時。因此,直接將SqlDataSource.SelectCommand賦值給另一個變數是不適當的。
如果您想要在程式碼中使用相同的SQL查詢字串,您應該將查詢字串硬編碼到程式碼中,就像之前示範的那樣。
********************************************************************************
不想 queryString 重寫一次和 SqlDataSource1.SelectCommand 相同的內容,也為了 SqlDataSource1.SelectCommand 變化時,queryString 又重新寫一次,有好方法?
ChatGPT
您可以使用SqlDataSource的SelectParameters屬性來設定查詢的參數,這樣您就可以在程式碼中使用SqlDataSource的SelectCommand而不需要重複寫一次查詢字串。下面是修改後的程式碼:
using (SqlConnection connection = new SqlConnection(WebConfigurationManager.ConnectionStrings["pmsConnectionString"].ConnectionString))
{
SqlCommand command = new SqlCommand(SqlDataSource1.SelectCommand, connection);
// 將 SqlDataSource 的參數設定給 SqlCommand
foreach (Parameter parameter in SqlDataSource1.SelectParameters)
{
command.Parameters.AddWithValue(parameter.Name, parameter.DefaultValue);
}
// 設定其他參數
command.Parameters.AddWithValue("@loginID", loginID);
command.Parameters.AddWithValue("@queryedID", Common.MyAntiXssFilter(DropDownList_id.SelectedValue));
connection.Open();
using (SqlDataReader reader = command.ExecuteReader())
{
// 在這裡處理讀取的資料
}
}
|
********************************************************************************
【實際測試】
Default.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs"
Inherits="WebApplication1.Default" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title></title>
</head>
<body>
<form id="form1" runat="server">
<asp:SqlDataSource ID="SqlDataSource1" runat="server"></asp:SqlDataSource>
<asp:DropDownList ID="DropDownList_id" runat="server"></asp:DropDownList>
<asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />
<asp:Button ID="Button2" runat="server" Text="Button" OnClick="Button2_Click" />
<asp:Button ID="Button3" runat="server" Text="Button" OnClick="Button3_Click" />
</form>
</body>
</html>
|
Default.aspx.cs
using System;
using System.Data.SqlClient;
using System.Web.Configuration;
using System.Web.UI.WebControls;
namespace WebApplication1
{
public partial class Default : System.Web.UI.Page
{
string loginID = "abc";
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button1_Click(object sender, EventArgs e)
{
string queryString = SqlDataSource1.SelectCommand;
using (SqlConnection connection = new SqlConnection(
WebConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString))
{
SqlCommand command = new SqlCommand(queryString, connection);
command.Parameters.Clear();
command.Parameters.AddWithValue("@loginID", loginID);
command.Parameters.AddWithValue("@queryedID", DropDownList_id.SelectedValue);
connection.Open();
using (SqlDataReader reader = command.ExecuteReader())
{
//
}
}
}
protected void Button2_Click(object sender, EventArgs e)
{
string queryString = "SELECT * FROM YourTable WHERE LoginID = @loginID AND QueryedID = @queryedID";
using (SqlConnection connection = new SqlConnection(WebConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString))
{
SqlCommand command = new SqlCommand(queryString, connection);
command.Parameters.Clear();
command.Parameters.AddWithValue("@loginID", loginID);
command.Parameters.AddWithValue("@queryedID", DropDownList_id.SelectedValue);
connection.Open();
using (SqlDataReader reader = command.ExecuteReader())
{
// 在這裡處理讀取的資料
}
}
}
protected void Button3_Click(object sender, EventArgs e)
{
using (SqlConnection connection = new SqlConnection(WebConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString))
{
SqlCommand command = new SqlCommand(SqlDataSource1.SelectCommand, connection);
// 將 SqlDataSource 的參數設定給 SqlCommand
foreach (Parameter parameter in SqlDataSource1.SelectParameters)
{
command.Parameters.AddWithValue(parameter.Name, parameter.DefaultValue);
}
// 設定其他參數
command.Parameters.AddWithValue("@loginID", loginID);
command.Parameters.AddWithValue("@queryedID", DropDownList_id.SelectedValue);
connection.Open();
using (SqlDataReader reader = command.ExecuteReader())
{
// 在這裡處理讀取的資料
}
}
}
}
}
|
Fortify SCA掃描結果
********************************************************************************
User
Fortify SCA 報告 SqlCommand command = new SqlCommand(SqlDataSource1.SelectCommand, connection); 有 SQL Injection 問題
ChatGPT
如果Fortify SCA報告SqlCommand的建構函式中的SqlDataSource1.SelectCommand有SQL注入問題,那麼原因可能是因為Fortify SCA無法直接分析和確定SqlDataSource1.SelectCommand是否是安全的。 即使SqlDataSource1.SelectCommand在設計時是使用了參數化查詢,Fortify SCA也可能無法辨識這一點。
********************************************************************************
目前的解決方法,似乎只能【硬編碼】,有空再研究看看有無其他解法。
(完)
相關

沒有留言:
張貼留言