Web アプリケーションのすべての出力を HTML エンコードするにはどうすればよいですか?
質問
Web アプリケーションで XSS 攻撃を防ぎたいと考えています。出力を HTML エンコードすると、XSS 攻撃を実際に防ぐことができることがわかりました。ここで問題は、アプリケーション内のすべての出力を HTML エンコードするにはどうすればよいでしょうか?これを自動化する方法はありますか?
JSP、ASP.net、PHP についての回答に感謝します。
解決
すべての HTML をエンコードするのではなく、出力するユーザー入力のみを HTML エンコードしたいとします。
PHP の場合: htmlエンティティ そして html特殊文字
他のヒント
あなたが一つ言えることは、 すべきではありません 入力データを受信したときにフィルタリングします。これが最も簡単な解決策であるため、よくこれを提案する人がいますが、問題が発生します。
入力データは HTML として出力されるだけでなく、複数の場所に送信することもできます。たとえば、データベースに保存される場合があります。データベースに送信されるデータをフィルタリングするルールは、HTML 出力をフィルタリングするルールとは大きく異なります。入力時にすべてを HTML エンコードすると、データベースには HTML が残ることになります。(これが、PHP の「マジック クオート」機能が悪いアイデアである理由でもあります。)
入力データが送信されるすべての場所を予測することはできません。安全なアプローチはデータを準備することです 直前 どこかに送られてきます。データベースに送信する場合は、一重引用符をエスケープします。HTML を出力している場合は、HTML エンティティをエスケープします。また、データがどこかに送信された後でも、引き続きデータを操作する必要がある場合は、エスケープされていない元のバージョンを使用してください。
これはより多くの作業ですが、テンプレート エンジンまたはライブラリを使用することで作業を軽減できます。
JSP の場合、デフォルトで XML をエスケープする c:out タグを使用すると、ケーキを持って食べることもできます。これは、生の要素としてプロパティにバインドできることを意味します。
<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 リリースでは、これはまったく同じように機能します、ジェイ :)
私の個人的な好みは、熱心にエンコードすることです 何でも それはデータベース、ビジネス層、またはユーザーからのものです。
ASP.Net では、これは次を使用して行われます。 Server.HtmlEncode(string)
.
何でもエンコードする理由は、ブール値または数値であると思われるプロパティにも悪意のあるコードが含まれている可能性があるためです (たとえば、チェックボックスの値が不適切に行われると、文字列として返される可能性があります)。出力をユーザーに送信する前にエンコードしていない場合は、脆弱性があります)。
echo / print などをラップすることもできます。独自のメソッドで出力をエスケープするために使用できます。つまりの代わりに
echo "blah";
使用
myecho('blah');
必要に応じてエスケープをオフにする 2 番目のパラメータを指定することもできます。
あるプロジェクトでは、出力関数にデバッグ モードがあり、メソッドを通過するすべての出力テキストが非表示になりました。そのとき、画面上に残っているものはすべてエスケープされていないことがわかりました。エスケープされていないいたずらなビットを追跡するのに非常に役立ちました:)
実際にすべての出力を HTML エンコードすると、ユーザーには <html> のプレーン テキストが表示されます。機能する Web アプリの代わりに。
編集:すべての入力を HTML エンコードすると、< などを含む外部パスワードを受け入れることができなくなります。
この種の攻撃から身を守る唯一の方法は、アプリケーションのパブリック領域から特に (排他的ではありませんが) 受け入れるすべての入力を厳密にフィルタリングすることです。ダニエル・モリスの作品をぜひご覧ください。 PHPフィルタリングクラス (完全な解決策)そして、 Zend_Filter パッケージ (独自のフィルターを構築するために使用できるクラスのコレクション)。
Web 開発に関しては PHP が私が選んだ言語なので、私の回答に偏りがあることをお詫びします。
キーラン。
OWASP には、HTML テキストとして使用するために HTML 出力をエンコードする優れた API があります (例:段落または <textarea>
コンテンツ)、または属性の値として (例:のために <input>
フォームを拒否した後のタグ):
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/ 他の言語でも利用できます。。ネット。
エンコードする必要があることに注意してください すべて (ユーザー入力だけではありません)、および できるだけ遅くまで (DB保存時ではなくHTTPレスポンス出力時)。
出力エンコーディングは、これまでのところ最善の防御策です。入力の検証はさまざまな理由から有効ですが、100% 防御できるわけではありません。データベースが攻撃によって XSS に感染した場合 (つまり、ASPROX)、間違い、または悪意のある入力検証は何も行いません。出力エンコーディングは引き続き機能します。
ソフトウェアに関する Joel の優れたエッセイ (間違ったコードを間違ったものに見せるということだと思います。今携帯電話を使っているので、そうでない場合は URL をお知らせします) があり、ハンガリー語表記の正しい使用方法について説明していました。短いバージョンは次のようになります。
Var dsFirstName, uhsFirstName : String;
Begin
uhsFirstName := request.queryfields.value['firstname'];
dsFirstName := dsHtmlToDB(uhsFirstName);
基本的に変数に次のようなプレフィックスを付けます "私たち" 安全でない文字列の場合、 「DS」 データベースを安全に保つために、 「はっ」 HTML セーフのため。すべてをエンコードおよびデコードするのではなく、実際に必要な部分のみをエンコードおよびデコードする必要があります。しかし、コードを見て有用な意味を推測するプレフィックスを使用すると、何かが正しくない場合にすぐに気づくことができます。いずれにせよ、別のエンコード/デコード関数が必要になります。