セキュリティ フレーム:入力の検証 | 軽減策
信頼できないスタイル シートを使用したすべての変換の XSLT スクリプトを無効にする
タイトル | 詳細 |
---|---|
コンポーネント | Web アプリケーション |
SDL フェーズ | Build |
適用できるテクノロジ | ジェネリック |
属性 | 該当なし |
参照 | 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 フェーズ | Build |
適用できるテクノロジ | ジェネリック |
属性 | 該当なし |
参照 | IE8 のセキュリティ パート V: 包括的な保護 |
手順 | ユーザーが制御可能なコンテンツが含まれている可能性のある各ページで、 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) が同様の機能を実装したら、この推奨事項を更新して、それらのブラウザー用の構文も含める予定です。 |
例
この必須のヘッダーをアプリケーションのすべてのページでグローバルに有効にするには、次のいずれかを実行します。
- アプリケーションがインターネット インフォメーション サービス (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 フェーズ | Build |
適用できるテクノロジ | ジェネリック |
属性 | 該当なし |
参照 | XML エンティティの展開、XML サービス拒否攻撃と防御策、MSXML のセキュリティの概要、MSXML コードをセキュリティで保護するためのベスト プラクティス、NSXMLParserDelegate プロトコル リファレンス、外部参照の解決 |
手順 | 広く使用されているわけではありませんが、XML パーサーが、ドキュメント内で定義された値または外部ソースの値でマクロ エンティティを展開できる XML の機能があります。 たとえば、ドキュメントでエンティティ "companyname" を値 "Microsoft" と定義すると、ドキュメントに "&companyname;" というテキストが表示されるたびに、自動的に Microsoft というテキストに置き換えられます。 または、Microsoft の現在の株価を取得する外部 Web サービスを参照する "MSFTStock" というエンティティがドキュメントで定義されているとします。 その後、ドキュメントに "&MSFTStock;" が表示されるたびに、自動的に現在の株価に置き換えられます。 ただし、この機能が悪用され、サービス拒否 (DoS) の状況が発生する可能性があります。 攻撃者は、複数のエンティティを入れ子にして、システムの使用可能なすべてのメモリを消費する、指数関数的展開 XML 爆弾を作成する可能性があります。 また、膨大な量のデータをストリーミングする外部参照やスレッドを単にハングさせる外部参照を作成する可能性もあります。 そのため、アプリケーションで内部および外部 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);
XmlReaderSettings
での ProhibitDtd
の既定値は 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 コードでは、NSXMLParser と libXML2 の 2 つの XML パーサーを使用できます。
http.sys を使用するアプリケーションで URL 正規化の検証を実行する
タイトル | 詳細 |
---|---|
コンポーネント | Web アプリケーション |
SDL フェーズ | Build |
適用できるテクノロジ | ジェネリック |
属性 | 該当なし |
参照 | 該当なし |
手順 | http.sys を使用するアプリケーションは、次のガイドラインに従う必要があります。
|
ユーザーからのファイルを受け入れるときは必ず適切な制御を行う
タイトル | 詳細 |
---|---|
コンポーネント | Web アプリケーション |
SDL フェーズ | Build |
適用できるテクノロジ | ジェネリック |
属性 | 該当なし |
参照 | 無制限のファイル アップロード、ファイル シグネチャ テーブル |
手順 | アップロードされたファイルは、アプリケーションにとって重大なリスクとなります。 多くの攻撃の第一段階は、攻撃対象のシステムに対するコードを取得することです。 コードを取得したら、攻撃に必要なのはそのコードを実行する方法を見つけることだけです。 ファイル アップロードを使用すると、攻撃者が第一段階を達成しやすくなります。 ファイル アップロードが制限されていない場合、システムの完全な乗っ取り、ファイル システムやデータベースの過負荷、バックエンド システムへの攻撃の転送、単純な改ざんなど、さまざな結果を招きます。 これは、アップロードされたファイルでアプリケーションが実行する内容と、特にファイルの保存場所に左右されます。 ファイル アップロードのサーバー側の検証はありません。 ファイル アップロード機能に次のセキュリティ制御を実装する必要があります。
|
例
ファイル形式のシグネチャの検証に関する最後の項目の詳細については、次のクラスを参照してください。
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 アプリケーションでデータ アクセスにタイプ セーフなパラメーターが使用されていることを確認する
タイトル | 詳細 |
---|---|
コンポーネント | Web アプリケーション |
SDL フェーズ | Build |
適用できるテクノロジ | ジェネリック |
属性 | 該当なし |
参照 | 該当なし |
手順 | Parameters コレクションを使用している場合、SQL は実行可能コードとしてではなく、リテラル値として入力を処理します。 Parameters コレクションを使用すると、入力データに型と長さの制約を適用できます。 範囲外の値により、例外がトリガーされます。 タイプ セーフな SQL パラメーターを使用していない場合、攻撃者はフィルター処理されていない入力に埋め込まれたインジェクション攻撃を実行できる可能性があります。 フィルター処理されていない入力で発生する可能性のある SQL インジェクション攻撃を防ぐには、SQL クエリを作成するときにタイプ セーフなパラメーターを使用します。 タイプ セーフなパラメーターは、ストアド プロシージャと動的 SQL ステートメントで使用できます。 パラメーターは、実行可能コードとしてではなく、リテラル値としてデータベースで処理されます。 また、パラメーターの型と長さもチェックされます。 |
例
次のコードは、ストアド プロシージャを呼び出すときに、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 フェーズ | Build |
適用できるテクノロジ | MVC5、MVC6 |
属性 | 該当なし |
参照 | メタデータ属性、公開キーのセキュリティの脆弱性と軽減策、ASP.NET MVC の一括割り当ての完全ガイド、 MVC を使用した EF の概要 |
手順 |
|
レンダリングの前に信頼できない Web 出力をエンコードする
タイトル | 詳細 |
---|---|
コンポーネント | Web アプリケーション |
SDL フェーズ | Build |
適用できるテクノロジ | ジェネリック、Web フォーム、MVC5、MVC6 |
属性 | 該当なし |
参照 | ASP.NET でクロスサイト スクリプトを防止する方法、クロスサイト スクリプト、XSS (クロスサイト スクリプト) 防止チート シート |
手順 | クロスサイト スクリプト (一般的な略称は XSS) は、Web からの入力を使用するオンライン サービスやアプリケーション/コンポーネントに対する攻撃ベクトルです。 XSS 脆弱性により、攻撃者が脆弱な Web アプリケーションを使用して別のユーザーのコンピューターでスクリプトを実行できるようになる場合があります。 悪意のあるスクリプトを使用して Cookie を窃取したり、JavaScript を使用して攻撃対象のコンピューターを改ざんしたりする可能性があります。 XSS を防ぐには、ユーザー入力を検証し、形式が適切であることを確認して、Web ページにレンダリングされる前にエンコードします。 入力の検証と出力エンコードは、Web Protection Library を使用して実行できます。 マネージド コード(C#、VB.NET など) の場合、ユーザー入力が使用されるコンテキストに応じて、Web Protection (XSS 対策) Library の適切なエンコード メソッドを 1 つ以上使用します。 |
例
* Encoder.HtmlEncode
* Encoder.HtmlAttributeEncode
* Encoder.JavaScriptEncode
* Encoder.UrlEncode
* Encoder.VisualBasicScriptEncode
* Encoder.XmlEncode
* Encoder.XmlAttributeEncode
* Encoder.CssEncode
* Encoder.LdapEncode
モデルのすべての文字列型プロパティで入力の検証とフィルター処理を実行する
タイトル | 詳細 |
---|---|
コンポーネント | Web アプリケーション |
SDL フェーズ | Build |
適用できるテクノロジ | ジェネリック、MVC5、MVC6 |
属性 | 該当なし |
参照 | 検証の追加、MVC アプリケーションでのモデル データの検証、ASP.NET MVC アプリケーションの基本原則 |
手順 | 悪意のあるユーザー入力からアプリケーションを確実に保護するには、アプリケーションで入力パラメーターが使用される前に、すべての入力パラメーターを検証する必要があります。 サーバー側で許可リスト方式の正規表現の検証を使用して入力値を検証します。 サニタイズされていないユーザー入力やパラメーターがメソッドに渡されると、コード インジェクションの脆弱性が発生する可能性があります。 Web アプリケーションの場合、エントリ ポイントにフォーム フィールド、クエリ文字列、Cookie、HTTP ヘッダー、Web サービス パラメーターが含まれている可能性もあります。 モデル バインド時に、次の入力検証チェックを実行する必要があります。
|
すべての文字を受け入れるフォーム フィールド (リッチ テキスト エディターなど) にはサニタイズを適用する必要がある
タイトル | 詳細 |
---|---|
コンポーネント | Web アプリケーション |
SDL フェーズ | Build |
適用できるテクノロジ | ジェネリック |
属性 | 該当なし |
参照 | 安全でない入力のエンコード、HTML サニタイザー |
手順 | 使用するすべての静的マークアップ タグを特定します。 一般的な方法は、書式設定を安全な HTML 要素 ( データを書き込む前に HTML エンコードします。 これにより、スクリプトは実行可能コードとしてではなく、テキストとして処理されるので、悪意のあるスクリプトが安全になります。
参照のページインにより、 HtmlSanitizer は、XSS 攻撃につながる可能性のある構造から HTML フラグメントや HTML ドキュメントを取り除くための .NET ライブラリです。 HtmlSanitizer では、AngleSharp を使用して HTML と CSS の解析、操作、レンダリングを実行します。 HtmlSanitizer は NuGet パッケージとしてインストールできます。ユーザー入力は、サーバー側で適切な HTML または CSS サニタイズ メソッドを使用して渡すことができます (該当する場合)。 セキュリティ制御としてのサニタイズは、あくまで最後の手段と考える必要があることに注意してください。 入力の検証と出力エンコードの方が優れたセキュリティ制御と見なされます。 |
エンコードが組み込まれていないシンクに DOM 要素を割り当てない
タイトル | 詳細 |
---|---|
コンポーネント | Web アプリケーション |
SDL フェーズ | Build |
適用できるテクノロジ | ジェネリック |
属性 | 該当なし |
参照 | 該当なし |
手順 | 多くの 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 フェーズ | Build |
適用できるテクノロジ | ジェネリック |
属性 | 該当なし |
参照 | OAuth 2.0 承認フレームワーク - オープン リダイレクター |
手順 | ユーザーが指定した場所へのリダイレクトを必要とするアプリケーション設計では、使用可能なリダイレクト ターゲットを、サイトまたはドメインの定義済みの "セーフ" リストに制限する必要があります。 アプリケーション内のすべてのリダイレクトが閉じられているか、安全である必要があります。 これを行うには、次の手順を実行します。
|
コントローラーのメソッドが受け入れるすべての文字列型パラメーターで入力の検証を実装する
タイトル | 詳細 |
---|---|
コンポーネント | Web アプリケーション |
SDL フェーズ | Build |
適用できるテクノロジ | ジェネリック、MVC5、MVC6 |
属性 | 該当なし |
参照 | MVC アプリケーションでのモデル データの検証、ASP.NET MVC アプリケーションの基本原則 |
手順 | 引数としてプリミティブ データ型だけを受け入れ、モデルは受け入れないメソッドでは、正規表現を使用した入力の検証を実行する必要があります。 この場合、有効な regex パターンで Regex.IsMatch を使用します。 入力が指定した正規表現と一致しない場合は、制御を進めないようにし、検証エラーに関する適切な警告を表示する必要があります。 |
正しくない正規表現に起因する DoS を防ぐために正規表現の処理の上限タイムアウトを設定する
タイトル | 詳細 |
---|---|
コンポーネント | Web アプリケーション |
SDL フェーズ | Build |
適用できるテクノロジ | ジェネリック、Web フォーム、MVC5、MVC6 |
属性 | 該当なし |
参照 | DefaultRegexMatchTimeout プロパティ |
手順 | 適切に作成されていない正規表現に対するサービス拒否攻撃により、大量のバックトラッキングが発生します。このようなサービス拒否攻撃を防ぐには、グローバルな既定のタイムアウトを設定します。 処理時間が定義されている上限を超えた場合、タイムアウト例外をスローします。 何も構成されていない場合、タイムアウトが無限になります。 |
例
たとえば、次の構成では、処理時間が 5 秒を超えると、RegexMatchTimeoutException がスローされます。
<httpRuntime targetFramework="4.5" defaultRegexMatchTimeout="00:00:05" />
Razor ビューで Html.Raw を使用しない
タイトル | 詳細 |
---|---|
コンポーネント | Web アプリケーション |
SDL フェーズ | Build |
適用できるテクノロジ | MVC5、MVC6 |
属性 | 該当なし |
参照 | 該当なし |
手順 | ASP.NET WebPages (Razor) は、自動 HTML エンコードを実行します。 埋め込まれたコード ナゲット (@ ブロック) によって出力されるすべての文字列が自動的に 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()
など) を使用してください。
ストアド プロシージャで動的クエリを使用しない
タイトル | 詳細 |
---|---|
コンポーネント | データベース |
SDL フェーズ | Build |
適用できるテクノロジ | ジェネリック |
属性 | 該当なし |
参照 | 該当なし |
手順 | 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 フェーズ | Build |
適用できるテクノロジ | MVC5、MVC6 |
属性 | 該当なし |
参照 | 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 フェーズ | Build |
適用できるテクノロジ | ジェネリック、MVC 5、MVC 6 |
属性 | 該当なし |
参照 | MVC アプリケーションでのモデル データの検証、ASP.NET MVC アプリケーションの基本原則 |
手順 | 引数としてプリミティブ データ型だけを受け入れ、モデルは受け入れないメソッドでは、正規表現を使用した入力の検証を実行する必要があります。 この場合、有効な regex パターンで Regex.IsMatch を使用します。 入力が指定した正規表現と一致しない場合は、制御を進めないようにし、検証エラーに関する適切な警告を表示する必要があります。 |
Web API でデータ アクセスにタイプ セーフなパラメーターが使用されていることを確認する
タイトル | 詳細 |
---|---|
コンポーネント | Web API |
SDL フェーズ | Build |
適用できるテクノロジ | ジェネリック |
属性 | 該当なし |
参照 | 該当なし |
手順 | Parameters コレクションを使用している場合、SQL は実行可能コードとしてではなく、リテラル値として入力を処理します。 Parameters コレクションを使用すると、入力データに型と長さの制約を適用できます。 範囲外の値により、例外がトリガーされます。 タイプ セーフな SQL パラメーターを使用していない場合、攻撃者はフィルター処理されていない入力に埋め込まれたインジェクション攻撃を実行できる可能性があります。 フィルター処理されていない入力で発生する可能性のある SQL インジェクション攻撃を防ぐには、SQL クエリを作成するときにタイプ セーフなパラメーターを使用します。 タイプ セーフなパラメーターは、ストアド プロシージャと動的 SQL ステートメントで使用できます。 パラメーターは、実行可能コードとしてではなく、リテラル値としてデータベースで処理されます。 また、パラメーターの型と長さもチェックされます。 |
例
次のコードは、ストアド プロシージャを呼び出すときに、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 フェーズ | Build |
適用できるテクノロジ | ジェネリック |
属性 | 該当なし |
参照 | Azure Cosmos DB の SQL パラメーター化の発表 |
手順 | Azure Cosmos DB でサポートされているのは読み取り専用クエリだけですが、ユーザー入力と連結してクエリが作成される場合は、SQL インジェクションが可能になります。 ユーザーは、悪意のある SQL クエリを作成することで、同じコレクション内にある、アクセスすべきできないデータにアクセスできるようになる可能性があります。 クエリがユーザー入力に基づいて作成される場合は、パラメーター化 SQL クエリを使用します。 |
WCF - スキーマ バインドを使用した入力の検証
タイトル | 詳細 |
---|---|
コンポーネント | WCF |
SDL フェーズ | Build |
適用できるテクノロジ | ジェネリック、NET Framework 3 |
属性 | 該当なし |
参照 | MSDN |
手順 | 検証が行われていない場合、さまざまな種類のインジェクション攻撃が発生します。 メッセージの検証は、WCF アプリケーションの保護における防御手段の 1 つとなります。 このアプローチでは、悪意のあるクライアントによる攻撃から WCF サービス操作を保護するために、スキーマを使用してメッセージを検証します。 また、悪意のあるサービスによる攻撃からクライアントを保護するために、クライアントが受信したすべてのメッセージを検証します。 メッセージの検証により、操作でメッセージ コントラクトまたはデータ コントラクトが使用されているときに、メッセージを検証することが可能になります。これは、パラメーターの検証では実現できません。 メッセージの検証では、スキーマ内で検証ロジックを作成できるので、柔軟性が向上し、開発時間が短縮されます。 データ表現の標準を作成することで、組織内のさまざまなアプリケーションでスキーマを再利用できます。 さらに、メッセージの検証により、ビジネス ロジックを表すコントラクトを含む複雑なデータ型を使用する操作を保護することもできます。 メッセージの検証を実行するには、まず、サービスの操作とそれらの操作で使用されるデータ型を表すスキーマを作成します。 その後、サービスとの間で送受信されるメッセージを検証するために、カスタム クライアント メッセージ インスペクターとカスタム ディスパッチャー メッセージ インスペクターを実装した .NET クラスを作成します。 次に、クライアントとサービスの両方でメッセージの検証を有効にするカスタム エンドポイント動作を実装します。 最後に、サービスまたはクライアントの構成ファイル内で拡張されたカスタム エンドポイント動作を公開できるようにするためのカスタム構成要素をクラスに実装します。 |
WCF - パラメーター インスペクターを使用した入力の検証
タイトル | 詳細 |
---|---|
コンポーネント | WCF |
SDL フェーズ | Build |
適用できるテクノロジ | ジェネリック、NET Framework 3 |
属性 | 該当なし |
参照 | MSDN |
手順 | 入力とデータの検証は、WCF アプリケーションの保護における重要な防御手段の 1 つとなります。 悪意のあるクライアントによる攻撃からサービスを保護するために、WCF サービス操作で公開されているすべてのパラメーターを検証する必要があります。 逆に、悪意のあるサービスによる攻撃からクライアントを保護するために、クライアントから受信したすべての戻り値も検証する必要があります。 WCF には、カスタムの拡張機能を作成して WCF ランタイムの動作をカスタマイズできる、さまざまな機能拡張ポイントが用意されています。 メッセージ インスペクターとパラメーター インスペクターは、クライアントとサービスの間で受け渡されるデータの制御を強化するために使用する 2 つの拡張メカニズムです。 入力の検証にパラメーター インスペクターを使用し、サービスで送受信されるメッセージ全体を検査する必要がある場合にのみ、メッセージ インスペクターを使用します。 入力の検証を実行するには、サービスにおける操作でパラメーターを検証するために、.NET クラスを作成し、カスタム パラメーター インスペクターを実装します。 次に、クライアントとサービスの両方で検証を有効にするカスタム エンドポイント動作を実装します。 最後に、サービスまたはクライアントの構成ファイル内で拡張されたカスタム エンドポイント動作を公開できるようにするためのカスタム構成要素をクラスに実装します。 |