カテゴリ: C# 更新日: 2026/06/27

C#のセキュリティ対策!クロスサイトスクリプティング(XSS)を防ぐ基本手法と脆弱性対策

C#のクロスサイトスクリプティング(XSS)対策の基本
C#のクロスサイトスクリプティング(XSS)対策の基本

先生と生徒の会話形式で理解しよう

生徒

「C#を使ってウェブサイトやシステムを作ってみたいのですが、セキュリティ対策も一緒に覚えないといけないと聞きました。特にクロスサイトスクリプティングという問題がよく分からないのですが、どのようなものですか」

先生

「それはとても大切な視点ですね。クロスサイトスクリプティングは、略してエックスエスエスとも呼ばれるウェブの安全性を脅かす代表的な問題です。悪意のある不正なプログラムが、自分の作ったページを通じて他の利用者のパソコンで勝手に動いてしまう現象のことを指します」

生徒

「自分の作ったプログラムのせいで、他の利用者が被害に遭ってしまうのは怖いですね。パソコンに詳しくない私でも、C#で対策をすることは可能でしょうか」

先生

「大丈夫ですよ。基本的な仕組みと対策の手順を一つずつ理解していけば、未経験からでも確実に安全なプログラムを書くことができるようになります。それでは、具体的な仕組みと解決方法を見ていきましょう」

1. クロスサイトスクリプティングとは何か

1. クロスサイトスクリプティングとは何か
1. クロスサイトスクリプティングとは何か

クロスサイトスクリプティングとは、ウェブサイトの入力画面などに悪意のある不正な命令を書き込み、それをそのまま画面に表示してしまうことで、ページを閲覧した他の利用者のパソコン上でその不正な命令を勝手に実行させてしまう現象です。この問題のことを専門用語で脆弱性と呼びます。脆弱性とは、プログラムにおける安全上の欠陥や隙のことです。

例えば、インターネット上の掲示板や、名前を入力して送信するお問い合わせ画面を想像してください。本来であれば、そこにはユーザーの名前や感想といった普通の文章が入力されるはずです。しかし、悪意のある人物が文字の代わりに、パソコンを誤作動させるための特殊な記号や命令の羅列を送信することがあります。これを受け取ったシステムが、そのまま何も確認せずに画面へ出力してしまうと、ページを開いた関係のない別の利用者のブラウザがその命令を本物の指示だと勘違いして処理してしまいます。これが原因で、大切な個人情報が盗まれたり、偽の画面に誘導されたりする被害が発生します。C#でウェブアプリケーションを開発する際には、この問題を未然に防ぐコードを記述することが必須の技能となります。

2. 不正なプログラムが動く仕組みと具体例

2. 不正なプログラムが動く仕組みと具体例
2. 不正なプログラムが動く仕組みと具体例

なぜ文字を入力するだけの場所から、不正なプログラムが実行されてしまうのでしょうか。私たちが普段見ているウェブページは、HTMLという特別な言語で構成されています。このHTMLは、特定の記号を使って文字の大きさや色、表示する形を指定する仕組みになっています。ブラウザという閲覧ソフトは、この記号を解釈して画面を綺麗に整えています。

もし、入力画面にこのHTMLの記号そのものが打ち込まれた場合、プログラムがそれをただの文字ではなく、ウェブページを動かすための命令そのものであると勘違いしてしまうことがあります。これが問題の根本的な原因です。具体的には、画面を制御するためのスクリプトと呼ばれる命令の塊が埋め込まれてしまうことで、利用者が気付かないうちに裏側で悪い処理が動いてしまいます。C#側で、画面から送られてきたデータをそのまま右から左へと無加工で画面に流してしまうと、このような落とし穴にはまることになります。そのため、送られてきたデータの中に危険な要素が混ざっていないかを監視し、適切に処理する工程が必要になります。

3. 最も基本となるサニタイズとエスケープ処理

3. 最も基本となるサニタイズとエスケープ処理
3. 最も基本となるサニタイズとエスケープ処理

この問題を解決するために最も重要で基本となる手段が、エスケープ処理、またはサニタイズと呼ばれる手法です。エスケープ処理とは、プログラムにとって特別な意味を持つ記号を、ただの文字として画面に表示されるように安全な別の文字に変換する作業のことです。サニタイズには無害化や消毒という意味があります。

例えば、HTMLにおいて命令の開始を意味する不等号の記号を、そのまま画面に出力するのではなく、画面上では同じ不等号に見えるけれどプログラムの命令としては機能しない特殊な文字の組み合わせに置き換えます。この置き換えを行うことで、ブラウザはそれを命令として実行することをやめ、単なる飾りとしての文字として認識するようになります。C#には、この変換を自動で行ってくれる便利な機能が標準で備わっています。開発者はその機能を呼び出すだけで、複雑な変換を自分で行うことなく、一瞬で安全な状態を作り出すことができます。まずは、この無害化の処理を必ず挟むという習慣を身につけることが、安全な開発の第一歩です。

4. 画面に出力する文字を安全に変換するC#コード

4. 画面に出力する文字を安全に変換するC#コード
4. 画面に出力する文字を安全に変換するC#コード

それでは、C#を使って実際に文字を安全な形に変換するプログラムの例を見てみましょう。ここでは、標準的な変換機能を提供する部品を使用します。入力された文字の中に含まれる危険な記号を、安全な表現に書き換える処理です。


using System;
using System.Web;

class Program
{
    static void Main()
    {
        string inputData = "<script>badActive();</script>";
        string safeData = HttpUtility.HtmlEncode(inputData);
        
        Console.WriteLine(safeData);
    }
}

上記のプログラムを実行すると、危険な意味を持つ記号が別の文字に置き換わります。その実行結果は以下のようになります。


&amp;lt;script&amp;gt;badActive();&amp;lt;/script&amp;gt;

この実行結果のように、不等号の記号が特殊な英語の組み合わせに変形していることがわかります。これにより、ブラウザはこの行を読んでもプログラムを実行せず、ただの文字列として画面に表示するようになります。これが、C#における最も基本的な防御手段の動き方です。

5. 最新のシステム開発で使われる防御方法

5. 最新のシステム開発で使われる防御方法
5. 最新のシステム開発で使われる防御方法

現在のC#によるウェブ開発では、より新しく洗練された仕組みを使って画面を作成することが一般的です。特に広く使われているシステム開発の土台では、標準の状態のままで、文字を出力する際に自動的にエスケープ処理を施してくれる安全な仕組みが最初から組み込まれています。次の例は、画面を構成する別の記述方法を用いた場合の安全な処理のイメージです。


@* 画面を表示するための記述例 *@
<div>
    @Model.UserComment
</div>

この記述方法では、変数の前に特定の記号をつけるだけで、システムが内部で自動的に安全な文字への変換を実行してくれます。このように、手動で毎回変換の命令を書かなくても、システム自体の仕組みによって安全性が保たれるよう設計されています。ただし、開発者が意図的にこの自動保護を解除する設定にしてしまうと、途端に危険な状態に戻ってしまうため、仕組みを正しく理解して不必要に保護を外さないようにすることが大切です。自動で守られているからと安心せず、常に裏側でどのような無害化が行われているかを意識することが求められます。

6. 数字や決まった形式のみを受け付ける入力制限

6. 数字や決まった形式のみを受け付ける入力制限
6. 数字や決まった形式のみを受け付ける入力制限

安全性を高めるためのもう一つの重要なアプローチは、入り口の段階で変なデータを受け付けないように制限することです。これを入力値検証と呼びます。例えば、年齢を入れる欄には数字だけしか入らないようにし、郵便番号の欄には数字とハイフンだけしか受け付けないようにあらかじめ設定しておきます。これにより、プログラムの命令を書き込もうとする行為そのものを、最初の段階で完全に遮断することができます。

C#では、文字の種類や長さを確認するための機能が豊富に用意されています。入力されたデータが正しい形式に従っているかを判定し、もしおかしな文字が含まれていた場合は、処理を中断してエラー画面を返すように作ります。画面に表示する前の段階で、そもそも危険なデータをシステムの中に引き入れないという二重の防御壁を作ることが、セキュリティをより強固なものにします。以下に、入力された文字が想定された通りの正しい形式かどうかを調べるシンプルなプログラムの例を示します。


using System;
using System.Text.RegularExpressions;

class Program
{
    static void Main()
    {
        string userInput = "12345";
        bool isNumber = Regex.IsMatch(userInput, "^[0-9]+$");
        
        if (isNumber)
        {
            Console.WriteLine("正しい入力です。");
        }
    }
}

このプログラムを実行した結果は以下の通りです。数字だけが入力されているため、正しいデータとして判定されています。


正しい入力です。

このように、あらかじめ決められた文字パターンだけを許可する仕組みを取り入れることで、想定外の危険な記述がシステムに入り込むリスクを大幅に減らすことができます。

7. 属性値にデータを埋め込む場合の注意点

7. 属性値にデータを埋め込む場合の注意点
7. 属性値にデータを埋め込む場合の注意点

文字を画面にそのまま表示する場所以外にも、注意しなければならない状況があります。それは、HTMLのタグと呼ばれる要素の内部の設定値として、ユーザーから受け取ったデータを当てはめる場合です。例えば、リンク先の情報や、画像の保存場所を指定する部分に文字を入れ込むような場面です。

このような場所では、通常の文字変換だけでは防ぎきれない特殊な手法で悪意のある命令が差し込まれる危険性があります。そのため、C#では出力する場所の状況に応じて、適切な変換方法を使い分ける必要があります。リンク先であればURL専用の安全化関数を使い、文字表示であれば通常のHTMLエンコードを使うというように、データの配置先に応じた個別の対策を行うことが、高度な安全性を確保するために必要となります。どのような場所にデータを埋め込もうとしているのかを、開発者は常に意識しなければなりません。


using System;
using System.Text.Encodings.Web;

class Program
{
    static void Main()
    {
        string rawUrl = "javascript:alert(1)";
        string safeUrl = UrlEncoder.Default.Encode(rawUrl);
        
        Console.WriteLine(safeUrl);
    }
}

上記のプログラムを実行すると、URLとして不適切な記述や危険な要素が変換され、安全な文字列として処理されるようになります。実行結果は以下のようになります。


javascript%3Aalert(1)

このように、URLの文脈に合わせて適切なエンコードを行うことで、予期せぬスクリプトの実行を防止することができます。出力する場所がどこであるかによって、適切な武器を選択することが大切です。

8. 未経験者が意識すべき安全なプログラム作りの心構え

8. 未経験者が意識すべき安全なプログラム作りの心構え
8. 未経験者が意識すべき安全なプログラム作りの心構え

セキュリティ対策と聞くと、とても難しく専門的な知識がたくさん必要なように感じられるかもしれません。しかし、最も大切な心構えは「外部から送られてくるデータは、すべて信用できないものである」という前提に立ってプログラムを組み立てることです。これは、自分で作ったシステムを守るための基本原則です。

利用者が入力するデータだけでなく、他のシステムから送られてくるデータや、データベースに一度保存されたデータであっても、画面に出力する直前には必ず無害化の処理を通す、あるいは入力された時点で厳しくチェックするというルールを徹底します。このルールを常に意識して開発を行うだけで、重大な欠陥のほとんどを未然に防ぐことができます。C#が提供している強力な安全機能を正しく使いこなし、手順を省略せずに確実に実装していくことが、多くの利用者に安心して使ってもらえる優れたアプリケーションを形作るための鍵となります。基本を忠実に守ることが、最も効果的な防御につながります。

カテゴリの一覧へ
新着記事
New1
COBOL
COBOLのデバッグ方法を徹底解説!初心者向けDISPLAY活用ガイド
New2
C#
C#のLINQでグループ化と集計!GroupByとCountを初心者向けに解説
New3
C#
C#のシングルトンパターン実装方法と注意点を徹底解説!初心者向け完全ガイド
New4
Azure
Azure WAFの誤検知を解消!除外リスト設定とチューニング方法を初心者向けに徹底解説
人気記事
No.1
Java&Spring記事人気No1
C#
C#の文字列を数値に変換する方法(int.Parse・TryParse)をわかりやすく解説!
No.2
Java&Spring記事人気No2
COBOL
COBOLの数値データ型「PIC 9」の使い方と注意点をやさしく解説!
No.3
Java&Spring記事人気No3
C#
C#のbool型を完全解説!初心者でもわかるtrueとfalseの基本と使い方
No.4
Java&Spring記事人気No4
C#
C#のトランザクション処理を完全ガイド!初心者でもわかるCommit・Rollbackの使い方
No.5
Java&Spring記事人気No5
C#
C#のラムダ式の書き方と構文を初心者向けに完全解説
No.6
Java&Spring記事人気No6
C#
C#のLINQでOrderByを使った並び替えを完全ガイド!初心者でもわかるソート方法
No.7
Java&Spring記事人気No7
Azure
Azureストレージの冗長性比較!LRS/GRS/ZRSの選び方とコストの最適解を完全解説
No.8
Java&Spring記事人気No8
COBOL
COBOLのコンパイラと開発環境を徹底解説!初心者にもわかりやすい入門ガイド