WebアプリケーションでXSS攻撃を防ぎたい。出力をHTMLエンコードすることで、XSS攻撃を本当に防ぐことができることがわかりました。問題は、アプリケーションのすべての出力をHTMLでエンコードするにはどうすればよいかということです。これを自動化する方法はありますか?
JSP、ASP.net、PHPの回答に感謝します。
すべきでないことの1 つは、入力データが入ってくるときにそれをフィルター処理することです。これが最も簡単な解決策であるため、よく提案されますが、問題が発生します。
入力データは、HTML として出力するだけでなく、複数の場所に送信できます。たとえば、データベースに格納される場合があります。データベースに送信されるデータをフィルタリングするためのルールは、HTML 出力をフィルタリングするためのルールとは大きく異なります。入力時にすべてを HTML エンコードすると、データベースに HTML が格納されます。(これが、PHP の「マジック クォート」機能が悪い考えである理由でもあります。)
入力データが移動するすべての場所を予測することはできません。安全な方法は、どこかに送信する直前にデータを準備することです。データベースに送信する場合は、一重引用符をエスケープします。HTML を出力する場合は、HTML エンティティをエスケープします。データがどこかに送信された後も、データを操作する必要がある場合は、元のエスケープされていないバージョンを使用してください。
これは手間がかかりますが、テンプレート エンジンまたはライブラリを使用することで軽減できます。
すべてのHTMLをエンコードするのではなく、出力するユーザー入力をHTMLエンコードするだけです。
PHPの場合:htmlentitiesおよびhtmlspecialchars
JSPの場合、デフォルトでXMLをエスケープするc:outタグを使用して、ケーキを持って食べることもできます。これは、プロパティをraw要素としてバインドできることを意味します。
<input name="someName.someProperty" value="<c:out value='${someName.someProperty}' />" />
文字列にバインドされると、someName.somePropertyにはXML入力が含まれますが、ページに出力されると、XMLエンティティを提供するために自動的にエスケープされます。これは、ページ検証用のリンクに特に役立ちます。
すべてのユーザー入力をエスケープするために使用した良い方法は、テンプレートに渡されたすべての変数をエスケープする smarty の修飾子を作成することです。|unescape が付いているものは除きます。そうすれば、明示的にアクセスを許可する要素にのみ HTML アクセスを許可できます。
その修飾子はもうありません。しかし、ほぼ同じバージョンがここにあります:
http://www.madcat.nl/martijn/archives/16-Using-smarty-to-prevent-HTML-injection..html
新しい Django 1.0 リリースでは、これはまったく同じように機能します、jay :)
echo / print などを独自のメソッドでラップして、出力をエスケープするために使用できます。つまり、代わりに
echo "blah";
使用する
myecho('blah');
必要に応じて、エスケープをオフにする 2 番目のパラメーターを設定することもできます。
あるプロジェクトでは、メソッドを通過するすべての出力テキストを非表示にする出力関数にデバッグ モードがありました。その後、画面に残っているものはすべてエスケープされていないことがわかりました。これらのいたずらなエスケープされていないビットを追跡するのに非常に役立ちました:)
私の個人的な好みは、データベース、ビジネス層、またはユーザーから来るものはすべて、入念にエンコードすることです。
ASP.Net では、これは を使用して行われServer.HtmlEncode(string)
ます。
何でもエンコードする理由は、ブール値または数値であると想定されるプロパティでさえ、悪意のあるコードを含む可能性があるためです (たとえば、チェックボックスの値が不適切に行われると、文字列として返される可能性があります。以前にそれらをエンコードしていない場合出力をユーザーに送信すると、脆弱性が発生します)。
実際にすべての出力をHTMLエンコードすると、ユーザーには&lt; html&gt;のプレーンテキストが表示されます。機能しているWebアプリの代わりに。
編集:すべての入力をHTMLエンコードすると、<などを含む外部パスワードを受け入れる際に問題が発生します。
この種の攻撃から身を守る唯一の方法は、アプリケーションのパブリックエリアから、特に(排他的ではありませんが)受け入れるすべての入力を厳密にフィルタリングすることです。Daniel MorrisのPHPフィルタリングクラス(完全なソリューション)とZend_Filterパッケージ(独自のフィルターを作成するために使用できるクラスのコレクション)も確認することをお勧めします。
Web開発に関しては、PHPが私の選択言語であるため、私の答えに偏りがあることをお詫びします。
キエラン。
ハンガリー語表記の正しい使用法をカバーした、ソフトウェアに関する Joel の優れたエッセイ (間違ったコードを間違ったように見せることだと思います。私は電話を使用していると思います。それ以外の場合は URL を提供します) がありました。短いバージョンは次のようになります。
Var dsFirstName, uhsFirstName : String;
Begin
uhsFirstName := request.queryfields.value['firstname'];
dsFirstName := dsHtmlToDB(uhsFirstName);
基本的に、安全でない文字列の場合は"us"、データベースの安全な場合は"ds"、HTML の安全な場合は"hs"などのプレフィックスを変数に付けます。すべてではなく、実際に必要な場所でのみエンコードとデコードを行います。しかし、コードを見て有用な意味を推測する接頭辞を使用することで、何かが正しくない場合にすぐにわかります。とにかく、さまざまなエンコード/デコード機能が必要になります。
OWASP には、HTML テキスト (段落や<textarea>
コンテンツなど) または属性の値 (<input>
フォームを拒否した後のタグなど) として使用するために、HTML 出力をエンコードする優れた API があります。
encodeForHTML($input) // Encode data for use in HTML using HTML entity encoding
encodeForHTMLAttribute($input) // Encode data for use in HTML attributes.
プロジェクト (PHP バージョン) はhttp://code.google.com/p/owasp-esapi-php/でホストされており、.NET などの他の言語でも利用できます。
すべて(ユーザー入力だけでなく)をエンコードし、できるだけ遅く(DB に格納するときではなく、HTTP 応答を出力するとき) エンコードする必要があることに注意してください。
出力エンコーディングは、最良の防御策です。入力の検証は多くの理由で優れていますが、100% 防御できるわけではありません。データベースが攻撃 (ASPROX など)、間違い、または悪意によって XSS に感染した場合、入力の検証は何も行いません。出力エンコーディングは引き続き機能します。