安全性架構︰輸入驗證 | 風險降低
針對使用未受信任樣式表的所有轉換停用 XSLT 指令碼
標題 | 詳細資料 |
---|---|
元件 | Web 應用程式 |
SDL 階段 | 組建 |
適用的技術 | 泛型 |
屬性 | N/A |
參考 | XSLT 安全性、XsltSettings.EnableScript 屬性 |
步驟 | XSLT 支援在使用 <msxml:script> 元素的樣式表內編寫指令碼。 這可讓自訂函式用於 XSLT 轉換。 指令碼會在執行轉換的程序內容下執行。 在未受信任的環境時必須停用 XSLT 指令碼,以防止執行未受信任的程式碼。 如果使用 .NET:預設會停用 XSLT 指令碼;不過,您必須確認它尚未透過 XsltSettings.EnableScript 屬性加以明確啟用。 |
範例
XsltSettings settings = new XsltSettings();
settings.EnableScript = true; // WRONG: THIS SHOULD BE SET TO false
範例
如果使用 MSXML 6.0,預設會停用 XSLT 指令碼;不過,您必須確認它尚未透過 XML DOM 物件屬性 AllowXsltScript 加以明確啟用。
doc.setProperty("AllowXsltScript", true); // WRONG: THIS SHOULD BE SET TO false
範例
如果您使用 MSXML 5 或較低版本,預設會啟用 XSLT 指令碼,因此您必須明確地加以停用。 請將 XML DOM 物件屬性 AllowXsltScript 設為 false。
doc.setProperty("AllowXsltScript", false); // CORRECT. Setting to false disables XSLT scripting.
確定可能包含使用者可控制內容的每個頁面都選擇不要自動探查 MIME
標題 | 詳細資料 |
---|---|
元件 | Web 應用程式 |
SDL 階段 | 組建 |
適用的技術 | 泛型 |
屬性 | N/A |
參考 | IE8 安全性單元五 - 完善的保護 |
步驟 | 對於可能包含使用者可控制內容的每個頁面,您必須使用 HTTP 標頭 從 Web 伺服器傳遞過來之檔案的每個類型都有相關聯的 MIME 類型 (也稱為「內容類型」),以描述內容的本質 (也就是影像、文字、應用程式等) X-Content-Type-Options 標頭是可讓開發人員指定不應對其內容探查 MIME 的 HTTP 標頭。 此標頭是設計用來降低 MIME 探查攻擊的風險。 Internet Explorer 8 (IE8) 已新增對此標頭的支援 只有 Internet Explorer 8 (IE8) 的使用者能夠受益於 X-Content-Type-Options。 舊版 Internet Explorer 目前不採用 X-Content-Type-Options 標頭 Internet Explorer 8 (和更新版本) 是主要瀏覽器中唯一實作了可選擇不要 MIME 探查功能的瀏覽器。 當其他主要瀏覽器 (Firefox、Safari、Chrome) 實作了類似功能時,我們會更新這項建議,使其也包含這些瀏覽器的語法 |
範例
若要為應用程式中的所有頁面全域啟用必要標頭,您可以執行下列其中一項︰
- 如果應用程式是由 Internet Information Services (IIS) 7 所裝載,請在 web.config 檔案中新增標頭
<system.webServer>
<httpProtocol>
<customHeaders>
<add name=""X-Content-Type-Options"" value=""nosniff""/>
</customHeaders>
</httpProtocol>
</system.webServer>
- 透過全域 Application_BeginRequest 新增標頭
void Application_BeginRequest(object sender, EventArgs e)
{
this.Response.Headers[""X-Content-Type-Options""] = ""nosniff"";
}
- 實作自訂 HTTP 模組
public class XContentTypeOptionsModule : IHttpModule
{
#region IHttpModule Members
public void Dispose()
{
}
public void Init(HttpApplication context)
{
context.PreSendRequestHeaders += newEventHandler(context_PreSendRequestHeaders);
}
#endregion
void context_PreSendRequestHeaders(object sender, EventArgs e)
{
HttpApplication application = sender as HttpApplication;
if (application == null)
return;
if (application.Response.Headers[""X-Content-Type-Options ""] != null)
return;
application.Response.Headers.Add(""X-Content-Type-Options "", ""nosniff"");
}
}
- 您可以透過將必要標頭新增至個別回應,來單獨針對特定頁面啟用此標頭︰
this.Response.Headers[""X-Content-Type-Options""] = ""nosniff"";
強化或停用 XML 實體解析
標題 | 詳細資料 |
---|---|
元件 | Web 應用程式 |
SDL 階段 | 組建 |
適用的技術 | 泛型 |
屬性 | N/A |
參考 | XML 實體擴充、XML 阻斷服務攻擊與防禦、MSXML 安全性概觀、保護 MSXML 程式碼的最佳作法、NSXMLParserDelegate 通訊協定參考、解析外部參考 |
步驟 | 雖然未被廣泛使用,但有一項 XML 功能可讓 XML 剖析器使用在文件本身內或從外部來源所定義的值,來擴充巨集實體。 例如,文件可能會使用值 "Microsoft" 定義實體 "companyname",以便在每次文件中出現文字 "&companyname" 時,就會自動將其取代為文字 Microsoft。 或者,文件可能會定義參考外部 Web 服務的實體 "MSFTStock",以擷取 Microsoft 股票的目前股價。 然後,每當文件中出現 "&MSFTStock" 時,就會自動將其取代為目前股價。 不過,這項功能可能會遭到濫用,來造成阻斷服務 (DoS) 狀況。 攻擊者可將多個實體進行巢狀處理,來製造會以指數方式擴張的 XML 炸彈 (XML bomb),以耗用系統上所有可用的記憶體。 或者,他也可以建立外部參考,以往回串流無限量的資料,或讓執行緒停止回應。 因此,所有小組必須完全停用其應用程式並未使用的內部及/或外部 XML 實體解析,或以手動方式限制可供應用程式取用來解析實體的記憶體和時間量 (如果這項功能有其絕對必要)。 如果應用程式不需要解析實體,則請停用。 |
範例
針對 .NET Framework 程式碼,您可以使用下列方法︰
XmlTextReader reader = new XmlTextReader(stream);
reader.ProhibitDtd = true;
XmlReaderSettings settings = new XmlReaderSettings();
settings.ProhibitDtd = true;
XmlReader reader = XmlReader.Create(stream, settings);
// for .NET 4
XmlReaderSettings settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Prohibit;
XmlReader reader = XmlReader.Create(stream, settings);
請注意,ProhibitDtd
在 XmlReaderSettings
中的預設值為 true,但在 XmlTextReader
中則為 false。 如果您使用 XmlReaderSettings,則不需要將 ProhibitDtd 明確設為 true,但為了安全起見,建議您這麼做。 也請注意,XmlDocument 類別預設會允許解析實體。
範例
若要停用 XmlDocuments 的實體解析,請使用 Load 方法的 XmlDocument.Load(XmlReader)
多載,並在 XmlReader 引數中設定適當屬性以停用解析,如下列程式碼所示︰
XmlReaderSettings settings = new XmlReaderSettings();
settings.ProhibitDtd = true;
XmlReader reader = XmlReader.Create(stream, settings);
XmlDocument doc = new XmlDocument();
doc.Load(reader);
範例
如果應用程式無法停用實體解析,請根據應用程式的需求將 XmlReaderSettings.MaxCharactersFromEntities 屬性設為合理的值。 這會限制潛在指數擴張 DoS 攻擊所會造成的影響。 下列程式碼提供此方法的範例︰
XmlReaderSettings settings = new XmlReaderSettings();
settings.ProhibitDtd = false;
settings.MaxCharactersFromEntities = 1000;
XmlReader reader = XmlReader.Create(stream, settings);
範例
如果您需要解析內嵌實體,但不需要解析外部實體,請將 XmlReaderSettings.XmlResolver 屬性設為 null。 例如:
XmlReaderSettings settings = new XmlReaderSettings();
settings.ProhibitDtd = false;
settings.MaxCharactersFromEntities = 1000;
settings.XmlResolver = null;
XmlReader reader = XmlReader.Create(stream, settings);
請注意,在 MSXML6 中,ProhibitDTD 預設會設為 true (停用 DTD 處理)。 針對 Apple OSX/iOS 程式碼,您可以使用的 XML 剖析器有兩個︰NSXMLParser 和 libXML2。
利用 http.sys 的應用程式會執行 URL 標準化驗證
標題 | 詳細資料 |
---|---|
元件 | Web 應用程式 |
SDL 階段 | 組建 |
適用的技術 | 泛型 |
屬性 | N/A |
參考 | N/A |
步驟 | 任何使用 http.sys 的應用程式皆應遵循下列指導方針︰
|
確定在接受使用者的檔案時已備妥適當的控制
標題 | 詳細資料 |
---|---|
元件 | Web 應用程式 |
SDL 階段 | 組建 |
適用的技術 | 泛型 |
屬性 | N/A |
參考 | 不受限制的檔案上傳、檔案簽章資料表 |
步驟 | 對應用程式來說,上傳的檔案就代表著重大風險。 許多攻擊的第一步就是將一些程式碼放到所要攻擊的系統。 然後,攻擊行動只需要找到方法來執行程式碼即可。 使用檔案上傳可幫助攻擊者完成第一步。 檔案上傳不受限制的後果各不相同,可能是系統遭到完整接管、檔案系統或資料庫超載、將攻擊行動轉送到後端系統,或者就只是損毀這麼簡單。 一切取決於應用程式會怎麼處理上傳的檔案,尤其是會儲存在哪裡。 伺服器端缺少驗證上傳檔案的動作。 請針對檔案上傳功能實作下列安全性控制︰
|
範例
如需上述最後一點關於檔案格式簽章驗證的資訊,請參閱下面的類別以了解詳情︰
private static Dictionary<string, List<byte[]>> fileSignature = new Dictionary<string, List<byte[]>>
{
{ ".DOC", new List<byte[]> { new byte[] { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 } } },
{ ".DOCX", new List<byte[]> { new byte[] { 0x50, 0x4B, 0x03, 0x04 } } },
{ ".PDF", new List<byte[]> { new byte[] { 0x25, 0x50, 0x44, 0x46 } } },
{ ".ZIP", new List<byte[]>
{
new byte[] { 0x50, 0x4B, 0x03, 0x04 },
new byte[] { 0x50, 0x4B, 0x4C, 0x49, 0x54, 0x55 },
new byte[] { 0x50, 0x4B, 0x53, 0x70, 0x58 },
new byte[] { 0x50, 0x4B, 0x05, 0x06 },
new byte[] { 0x50, 0x4B, 0x07, 0x08 },
new byte[] { 0x57, 0x69, 0x6E, 0x5A, 0x69, 0x70 }
}
},
{ ".PNG", new List<byte[]> { new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A } } },
{ ".JPG", new List<byte[]>
{
new byte[] { 0xFF, 0xD8, 0xFF, 0xE0 },
new byte[] { 0xFF, 0xD8, 0xFF, 0xE1 },
new byte[] { 0xFF, 0xD8, 0xFF, 0xE8 }
}
},
{ ".JPEG", new List<byte[]>
{
new byte[] { 0xFF, 0xD8, 0xFF, 0xE0 },
new byte[] { 0xFF, 0xD8, 0xFF, 0xE2 },
new byte[] { 0xFF, 0xD8, 0xFF, 0xE3 }
}
},
{ ".XLS", new List<byte[]>
{
new byte[] { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 },
new byte[] { 0x09, 0x08, 0x10, 0x00, 0x00, 0x06, 0x05, 0x00 },
new byte[] { 0xFD, 0xFF, 0xFF, 0xFF }
}
},
{ ".XLSX", new List<byte[]> { new byte[] { 0x50, 0x4B, 0x03, 0x04 } } },
{ ".GIF", new List<byte[]> { new byte[] { 0x47, 0x49, 0x46, 0x38 } } }
};
public static bool IsValidFileExtension(string fileName, byte[] fileData, byte[] allowedChars)
{
if (string.IsNullOrEmpty(fileName) || fileData == null || fileData.Length == 0)
{
return false;
}
bool flag = false;
string ext = Path.GetExtension(fileName);
if (string.IsNullOrEmpty(ext))
{
return false;
}
ext = ext.ToUpperInvariant();
if (ext.Equals(".TXT") || ext.Equals(".CSV") || ext.Equals(".PRN"))
{
foreach (byte b in fileData)
{
if (b > 0x7F)
{
if (allowedChars != null)
{
if (!allowedChars.Contains(b))
{
return false;
}
}
else
{
return false;
}
}
}
return true;
}
if (!fileSignature.ContainsKey(ext))
{
return true;
}
List<byte[]> sig = fileSignature[ext];
foreach (byte[] b in sig)
{
var curFileSig = new byte[b.Length];
Array.Copy(fileData, curFileSig, b.Length);
if (curFileSig.SequenceEqual(b))
{
flag = true;
break;
}
}
return flag;
}
確定在 Web 應用程式中使用 type-safe 參數存取資料
標題 | 詳細資料 |
---|---|
元件 | Web 應用程式 |
SDL 階段 | 組建 |
適用的技術 | 泛型 |
屬性 | N/A |
參考 | N/A |
步驟 | 如果您使用參數集合,SQL 會將輸入視為常值而非可執行程式碼。 參數集合可用來對輸入資料強制執行類型和長度條件約束。 超出範圍的值會觸發例外狀況。 如果未使用 type-safe SQL 參數,攻擊者或許就能執行內嵌於未經篩選之輸入中的插入式攻擊。 請在建構 SQL 查詢時使用 type-safe 參數,以避免未經篩選的輸入中可能發生的 SQL 插入式攻擊。 type-safe 參數可與預存程序和動態 SQL 陳述式搭配使用。 資料庫會將參數視為常值而非可執行程式碼。 參數的類型和長度也會受到檢查。 |
範例
下列程式碼示範如何在呼叫預存程序時,搭配使用 type-safe 參數與 SqlParameterCollection。
using System.Data;
using System.Data.SqlClient;
using (SqlConnection connection = new SqlConnection(connectionString))
{
DataSet userDataset = new DataSet();
SqlDataAdapter myCommand = new SqlDataAdapter("LoginStoredProcedure", connection);
myCommand.SelectCommand.CommandType = CommandType.StoredProcedure;
myCommand.SelectCommand.Parameters.Add("@au_id", SqlDbType.VarChar, 11);
myCommand.SelectCommand.Parameters["@au_id"].Value = SSN.Text;
myCommand.Fill(userDataset);
}
在上述程式碼範例中,輸入值不能超過 11 個字元。 如果資料不符合參數所定義的類型或長度,SqlParameter 類別就會擲回例外狀況。
使用個別的模型繫結類別或繫結篩選清單來防止 MVC 大量指派弱點
標題 | 詳細資料 |
---|---|
元件 | Web 應用程式 |
SDL 階段 | 組建 |
適用的技術 | MVC5、MVC6 |
屬性 | N/A |
參考 | 中繼資料屬性、公用金鑰安全性弱點和風險降低、在 ASP.NET MVC 中大量指派的完整指南、使用 MVC 開始使用 EF |
步驟 |
|
先將未受信任的 Web 輸出編碼再進行轉譯
標題 | 詳細資料 |
---|---|
元件 | Web 應用程式 |
SDL 階段 | 組建 |
適用的技術 | 泛型、Web Form、MVC5、MVC6 |
屬性 | N/A |
參考 | 如何在 ASP.NET 中防止跨網站指令碼、跨網站指令碼、XSS (跨網站指令碼) 防護功能提要 |
步驟 | 跨網站指令碼 (通常縮寫為 XSS) 是針對線上服務或從 Web 取用輸入之任何應用程式/元件的攻擊媒介。 XSS 弱點可能會讓攻擊者透過易受攻擊的 Web 應用程式,對其他使用者的電腦執行指令碼。 惡意指令碼可用來竊取 Cookie 或是透過 JavaScript 竄改受害者的電腦。 若要預防 XSS,您可以驗證使用者輸入、確保其格式正確無誤並先加以編碼,再轉譯於網頁中。 使用 Web Protection Library 即可進行輸入驗證和輸出編碼。 若為受控碼 (C#、VB.NET 等),請根據為使用者輸入建立資訊清單的內容,使用一或多個來自 Web Protection (Anti-XSS) Library 的適當編碼方法: |
範例
* Encoder.HtmlEncode
* Encoder.HtmlAttributeEncode
* Encoder.JavaScriptEncode
* Encoder.UrlEncode
* Encoder.VisualBasicScriptEncode
* Encoder.XmlEncode
* Encoder.XmlAttributeEncode
* Encoder.CssEncode
* Encoder.LdapEncode
對所有字串類型的模型屬性執行輸入驗證和篩選
標題 | 詳細資料 |
---|---|
元件 | Web 應用程式 |
SDL 階段 | 組建 |
適用的技術 | 泛型、MVC5、MVC6 |
屬性 | N/A |
參考 | 新增驗證、驗證 MVC 應用程式中的模型資料、ASP.NET MVC 應用程式的指導原則 |
步驟 | 所有輸入參數都必須先驗證再用於應用程式,以確保應用程式不受惡意使用者輸入所危害。 請採取允許清單驗證策略,在伺服器端上使用規則運算式驗證來驗證輸入值。 傳遞至方法的未清理使用者輸入/參數會造成程式碼插入弱點。 對於 Web 應用程式,進入點還可能包括表單欄位、QueryStrings、Cookie、HTTP 標頭和 Web 服務參數。 在繫結模型時,必須執行下列輸入驗證檢查︰
|
應該對接受所有字元的表單欄位 (例如 RTF 編輯器) 套用清理
標題 | 詳細資料 |
---|---|
元件 | Web 應用程式 |
SDL 階段 | 組建 |
適用的技術 | 泛型 |
屬性 | N/A |
參考 | 將不安全的輸入編碼, HTML 清理程式 |
步驟 | 找出您想要使用的所有靜態標記標籤。 常見的作法是將格式限制為安全的 HTML 元素,例如 在寫入資料前,先對它進行 HTML 編碼。 此動作可讓惡意指令碼變得安全,因為這會讓它以文字形式進行處理,而不是以可執行程式碼的形式。
參考中的頁面會藉由設定 HtmlSanitizer 是用來從可能會導致 XSS 攻擊的建構中清理 HTML 片段和文件的 .NET 程式庫。 它會使用 AngleSharp 來剖析、操作及轉譯 HTML 與 CSS。 HtmlSanitizer 可使用 NuGet 套件的形式來安裝,並可視需要透過相關 HTML 或 CSS 清理方法,在伺服器端上傳遞使用者輸入。 請注意,只有在迫不得已時才可考慮使用清理做為安全性控制方法。 輸入驗證和輸出編碼會是較佳的安全性控制方法。 |
請勿將 DOM 元素指派給沒有內建編碼的接收器
標題 | 詳細資料 |
---|---|
元件 | Web 應用程式 |
SDL 階段 | 組建 |
適用的技術 | 泛型 |
屬性 | N/A |
參考 | N/A |
步驟 | 許多 JavaScript 函式都預設為不會進行編碼。 透過這類函式將不受信任的輸入指派至 DOM 元素時,可能會導致執行跨網站指令碼 (XSS)。 |
範例
以下是不安全的範例︰
document.getElementByID("div1").innerHtml = value;
$("#userName").html(res.Name);
return $('<div/>').html(value)
$('body').append(resHTML);
請勿使用 innerHtml
;而應使用 innerText
。 同樣地,不要使用 $("#elm").html()
,而應使用 $("#elm").text()
驗證應用程式內的所有重新導向皆已關閉或安全完成
標題 | 詳細資料 |
---|---|
元件 | Web 應用程式 |
SDL 階段 | 組建 |
適用的技術 | 泛型 |
屬性 | N/A |
參考 | OAuth 2.0 授權架構 - 開啟重新導向程式 |
步驟 | 要求重新導向至使用者所提供位置的應用程式設計,必須將可能的重新導向目標限制在預先定義的「安全」網站或網域清單。 應用程式中的所有重新導向都必須是封閉/安全的。 若要這樣做:
|
對控制器方法所接受的所有字串類型參數實作輸入驗證
標題 | 詳細資料 |
---|---|
元件 | Web 應用程式 |
SDL 階段 | 組建 |
適用的技術 | 泛型、MVC5、MVC6 |
屬性 | N/A |
參考 | 驗證 MVC 應用程式中的模型資料、ASP.NET MVC 應用程式的指導原則 |
步驟 | 對於只接受基本資料類型而不接受模型來做為引數的方法,應該使用規則運算式進行輸入驗證。 在此,Regex.IsMatch 應搭配使用有效的 regex 模式。 如果輸入不符合指定的規則運算式,就不該再繼續進行控制,而且應該顯示關於驗證失敗的適當警告。 |
為規則運算式處理設定逾時上限以防止因規則運算式不正確而導致 DoS
標題 | 詳細資料 |
---|---|
元件 | Web 應用程式 |
SDL 階段 | 組建 |
適用的技術 | 泛型、Web Form、MVC5、MVC6 |
屬性 | N/A |
參考 | DefaultRegexMatchTimeout 屬性 (機器翻譯) |
步驟 | 若要確保以錯誤格式建立的規則運算式不會遭受阻斷服務攻擊,而造成大量回溯,請設定全域的預設逾時。 如果處理時間超過所定義的上限,便會擲回逾時例外狀況。 若未做任何設定,則逾時時間是無限。 |
範例
例如,下列組態會在處理時間超過 5 秒時擲回 RegexMatchTimeoutException︰
<httpRuntime targetFramework="4.5" defaultRegexMatchTimeout="00:00:05" />
避免在 Razor 檢視中使用 Html.Raw
標題 | 詳細資料 |
---|---|
元件 | Web 應用程式 |
SDL 階段 | 組建 |
適用的技術 | MVC5、MVC6 |
屬性 | N/A |
參考 | N/A |
步驟 | ASP.NET 網頁 (Razor) 會執行自動 HTML 編碼。 內嵌程式碼區塊 (@ blocks) 所列印的所有字串會自動進行 HTML 編碼。 不過,在叫用 HtmlHelper.Raw 方法時,它會傳回非 HTML 編碼的標記。 如果使用 Html.Raw() 協助程式方法,它會略過 Razor 所提供的自動編碼保護。 |
範例
以下是不安全的範例︰
<div class="form-group">
@Html.Raw(Model.AccountConfirmText)
</div>
<div class="form-group">
@Html.Raw(Model.PaymentConfirmText)
</div>
</div>
除非您需要顯示標記,否則請勿使用 Html.Raw()
。 這個方法不會隱含執行輸出編碼。 請使用其他 ASP.NET 協助程式,例如 @Html.DisplayFor()
請勿在預存程序中使用動態查詢
標題 | 詳細資料 |
---|---|
元件 | Database |
SDL 階段 | 組建 |
適用的技術 | 泛型 |
屬性 | N/A |
參考 | N/A |
步驟 | SQL 插入式攻擊利用輸入驗證弱點在資料庫中執行任意命令。 當您的應用程式使用輸入來建構動態 SQL 陳述式以存取資料庫時,便可能發生此弱點。 如果您的程式碼使用預存程序來傳遞包含原始使用者輸入的字串,也可能發生此弱點。 攻擊者使用 SQL 插入式攻擊,即可在資料庫中執行任意命令。 所有 SQL 陳述式 (包括預存程序的 SQL 陳述式) 都必須予以參數化。 參數化的 SQL 陳述式會接受對 SQL 具有特殊意義的字元 (例如單引號) 而不會有任何問題,因為它們屬於強型別。 |
範例
以下是不安全的動態預存程序範例︰
CREATE PROCEDURE [dbo].[uspGetProductsByCriteria]
(
@productName nvarchar(200) = NULL,
@startPrice float = NULL,
@endPrice float = NULL
)
AS
BEGIN
DECLARE @sql nvarchar(max)
SELECT @sql = ' SELECT ProductID, ProductName, Description, UnitPrice, ImagePath' +
' FROM dbo.Products WHERE 1 = 1 '
PRINT @sql
IF @productName IS NOT NULL
SELECT @sql = @sql + ' AND ProductName LIKE ''%' + @productName + '%'''
IF @startPrice IS NOT NULL
SELECT @sql = @sql + ' AND UnitPrice > ''' + CONVERT(VARCHAR(10),@startPrice) + ''''
IF @endPrice IS NOT NULL
SELECT @sql = @sql + ' AND UnitPrice < ''' + CONVERT(VARCHAR(10),@endPrice) + ''''
PRINT @sql
EXEC(@sql)
END
範例
以下是以安全方式實作的相同預存程序︰
CREATE PROCEDURE [dbo].[uspGetProductsByCriteriaSecure]
(
@productName nvarchar(200) = NULL,
@startPrice float = NULL,
@endPrice float = NULL
)
AS
BEGIN
SELECT ProductID, ProductName, Description, UnitPrice, ImagePath
FROM dbo.Products where
(@productName IS NULL or ProductName like '%'+ @productName +'%')
AND
(@startPrice IS NULL or UnitPrice > @startPrice)
AND
(@endPrice IS NULL or UnitPrice < @endPrice)
END
確定 Web API 方法已完成模型驗證
標題 | 詳細資料 |
---|---|
元件 | Web API |
SDL 階段 | 組建 |
適用的技術 | MVC5、MVC6 |
屬性 | N/A |
參考 | ASP.NET Web API 中的模型驗證 (機器翻譯) |
步驟 | 當用戶端傳送資料到 Web API 時,必須先驗證資料再進行任何處理。 對於可接受模型做為輸入的 ASP.NET Web API,請在模型上使用資料註解,以對模型屬性設定驗證規則。 |
範例
下列程式碼示範相同案例︰
using System.ComponentModel.DataAnnotations;
namespace MyApi.Models
{
public class Product
{
public int Id { get; set; }
[Required]
[RegularExpression(@"^[a-zA-Z0-9]*$", ErrorMessage="Only alphanumeric characters are allowed.")]
public string Name { get; set; }
public decimal Price { get; set; }
[Range(0, 999)]
public double Weight { get; set; }
}
}
範例
在 API 控制器的動作方法中,模型的有效性必須明確檢查,如下所示:
namespace MyApi.Controllers
{
public class ProductsController : ApiController
{
public HttpResponseMessage Post(Product product)
{
if (ModelState.IsValid)
{
// Do something with the product (not shown).
return new HttpResponseMessage(HttpStatusCode.OK);
}
else
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}
}
}
}
對 Web API 方法所接受的所有字串類型參數實作輸入驗證
標題 | 詳細資料 |
---|---|
元件 | Web API |
SDL 階段 | 組建 |
適用的技術 | 泛型、MVC 5、MVC 6 |
屬性 | N/A |
參考 | 驗證 MVC 應用程式中的模型資料、ASP.NET MVC 應用程式的指導原則 |
步驟 | 對於只接受基本資料類型而不接受模型來做為引數的方法,應該使用規則運算式進行輸入驗證。 在此,Regex.IsMatch 應搭配使用有效的 regex 模式。 如果輸入不符合指定的規則運算式,就不該再繼續進行控制,而且應該顯示關於驗證失敗的適當警告。 |
確定 Web API 有使用 type-safe 參數來存取資料
標題 | 詳細資料 |
---|---|
元件 | Web API |
SDL 階段 | 組建 |
適用的技術 | 泛型 |
屬性 | N/A |
參考 | N/A |
步驟 | 如果您使用參數集合,SQL 會將輸入視為常值而非可執行程式碼。 參數集合可用來對輸入資料強制執行類型和長度條件約束。 超出範圍的值會觸發例外狀況。 如果未使用 type-safe SQL 參數,攻擊者或許就能執行內嵌於未經篩選之輸入中的插入式攻擊。 請在建構 SQL 查詢時使用 type-safe 參數,以避免未經篩選的輸入中可能發生的 SQL 插入式攻擊。 type-safe 參數可與預存程序和動態 SQL 陳述式搭配使用。 資料庫會將參數視為常值而非可執行程式碼。 參數的類型和長度也會受到檢查。 |
範例
下列程式碼示範如何在呼叫預存程序時,搭配使用 type-safe 參數與 SqlParameterCollection。
using System.Data;
using System.Data.SqlClient;
using (SqlConnection connection = new SqlConnection(connectionString))
{
DataSet userDataset = new DataSet();
SqlDataAdapter myCommand = new SqlDataAdapter("LoginStoredProcedure", connection);
myCommand.SelectCommand.CommandType = CommandType.StoredProcedure;
myCommand.SelectCommand.Parameters.Add("@au_id", SqlDbType.VarChar, 11);
myCommand.SelectCommand.Parameters["@au_id"].Value = SSN.Text;
myCommand.Fill(userDataset);
}
在上述程式碼範例中,輸入值不能超過 11 個字元。 如果資料不符合參數所定義的類型或長度,SqlParameter 類別就會擲回例外狀況。
針對 Azure Cosmos DB 使用參數化 SQL 查詢
標題 | 詳細資料 |
---|---|
元件 | Azure Document DB |
SDL 階段 | 組建 |
適用的技術 | 泛型 |
屬性 | N/A |
參考 | 在 Azure Cosmos DB 中宣佈 SQL 參數化 |
步驟 | 雖然 Azure Cosmos DB 只支援唯讀查詢,但如果查詢是藉由串連使用者輸入來建構,仍可發動 SQL 插入式攻擊。 使用者只要藉由編寫惡意 SQL 查詢,即可在相同集合內存取其不應能夠存取的資料。 如果查詢是根據使用者輸入所建構而成,請使用參數化的 SQL 查詢。 |
透過結構描述繫結驗證 WCF 輸入
標題 | 詳細資料 |
---|---|
元件 | WCF |
SDL 階段 | 組建 |
適用的技術 | 泛型、NET Framework 3 |
屬性 | N/A |
參考 | MSDN |
步驟 | 缺少驗證機制會導致不同類型的插入式攻擊。 訊息驗證代表 WCF 應用程式保護措施中的一條防禦線。 利用這個方法,您可以使用結構描述來驗證訊息,以防止惡意用戶端攻擊 WCF 服務作業。 驗證用戶端所收到的所有訊息可防止用戶端遭到惡意服務攻擊。 訊息驗證可讓您在作業取用訊息合約或資料合約時驗證訊息,使用參數驗證則無法這麼做。 訊息驗證可讓您在結構描述內建立驗證邏輯,進而提供更大的彈性並縮減開發時間。 結構描述可以重複使用到組織中的不同應用程式,而為如何代表資料建立標準。 此外,在它們取用涉及代表商務邏輯之合約的更複雜資料類型時,訊息驗證可讓您保護作業。 若要執行訊息驗證,您可以先建置結構描述來代表服務的作業和這些作業所取用的資料類型。 然後,您可以建立 .NET 類別來實作自訂用戶端訊息偵測器和自訂發送器訊息偵測器,以驗證服務所傳送/接收的訊息。 接下來,您可以實作自訂端點行為,在用戶端和服務上啟用訊息驗證。 最後,您可以對類別實作自訂組態元素,以便您可以在服務或用戶端的組態檔中,公開擴充的自訂端點行為 |
透過參數偵測器驗證 WCF 輸入
標題 | 詳細資料 |
---|---|
元件 | WCF |
SDL 階段 | 組建 |
適用的技術 | 泛型、NET Framework 3 |
屬性 | N/A |
參考 | MSDN |
步驟 | 輸入和資料驗證代表 WCF 應用程式保護措施中的一條重要防禦線。 您應該驗證 WCF 服務作業中公開的所有參數,以防止服務遭受惡意用戶端攻擊。 相反地,您還應該驗證用戶端所收到的所有傳回值,以防止用戶端遭受惡意服務攻擊 WCF 會提供不同的擴充點,讓您藉由建立自訂擴充功能來自訂 WCF 執行階段行為。 訊息偵測器和參數偵測器這兩個擴充性機制可用來加強對用戶端和服務之間所傳遞之資料的控制力。 您應該使用參數偵測器來驗證輸入,而只將訊息偵測器用於當您需要檢查流入及流出服務的整個訊息時。 若要執行輸入驗證,您需要建置 .NET 類別,並實作自訂參數偵測器,以對服務中的作業參數進行驗證。 接著,您需要實作自訂端點行為,在用戶端和服務上啟用驗證。 最後,您可以對類別實作自訂組態元素,以便您可以在服務或用戶端的組態檔中,公開擴充的自訂端點行為 |