CS.XSS.PERSIST
クロスサイトスクリプティングの持続型脆弱性
CS.XSS.PERSIST チェッカーは、入力が HTTP リクエストからデータによって直接提供され、そのデータが、後で読み戻すことができるデータベース、メッセージフォーラム、訪問者ログなどの信頼できるデータストアに保存される、そうしたコードのインスタンスにフラグを立てます。
脆弱性とリスク
クロスサイトスクリプティング (XSS) 攻撃は、ユーザーが制御可能な入力を、Web ページとして使用される出力に配置して他のユーザーに供給される前に、ソフトウェアがそれを中立化しないか、間違って中立化するようなタイプの攻撃です。
XSS 脆弱性は、次の場合に発生します。
- 信頼できないデータが、通常では Web リクエストから Web アプリケーションに入力されます。
 - Web アプリケーションは、この信頼できないデータを含む Web ページを動的に生成します。
 - アプリケーションは、ページの生成中に、JavaScript、HTML タグ、HTML 属性、マウスイベント、Flash、ActiveX などの Web ブラウザーによって実行可能なコンテンツを、データに含めないようにはしません。
 - 被害者は、Web ブラウザーを使用することで、信頼できないデータを使用して挿入された悪意のあるスクリプトを含む、生成された Web ページを訪問します。
 - スクリプトは Web サーバーによって送信された Web ページからのものであるため、被害者の Web ブラウザーは、Web サーバーのドメインのコンテキストで悪意のあるスクリプトを実行します。
 - これは、あるドメイン内のスクリプトが、別のドメイン内のリソースにアクセスできたり、コードを実行できたりしてはならないことを宣言する、Web ブラウザーの同一生成元ポリシーの意図に事実上違反しています。
 
XSS には主に次の 3 つの種類があります。
- タイプ 1: 反映型 XSS (または非持続型)
 - タイプ 2: 保存型 XSS (または持続型)
 - タイプ 0: DOM 基準の XSS
 
アプリケーションは、データベース、メッセージフォーラム、訪問者ログなどの信頼できるデータストアに、危険なデータを保存します。後に、危険なデータはアプリケーションに読み戻され、動的コンテンツに含まれるようになります。攻撃者の観点から、悪意のあるコンテンツを挿入するための最適な場所は、多くのユーザーまたは特に関心のあるユーザーのいずれかに表示される領域です。通常、関心のあるユーザーは、アプリケーションで権限が昇格されているか、攻撃者にとって価値のある機密データを操作します。これらのいずれかのユーザーが悪意のあるコンテンツを実行すると、攻撃者は、ユーザーに代わって特権操作を実行できるか、ユーザー所有の機密データにアクセスできるようになる可能性があります。たとえば、攻撃者は XSS をログメッセージに挿入するかもしれず、管理者がログを表示したときに適切に処理されない可能性があります。
軽減と防止
XSS 攻撃を防ぐには、Web ページとして使用される出力にデータを配置する前に、ユーザーが制御可能な入力をすべて中立化します。
脆弱コード例
  protected void Submit_Click(object sender, EventArgs e)
  {
      try
      {
          var txt = MyTextbox.Text;
          saveValueInDataBase( txt );             // CS.XSS.PERSIST
      }
      catch (Exception) { }
  }
   
 void saveValueInDataBase(string val)
 {
     SqlConnection con = new SqlConnection();
     SqlCommand cmd = new SqlCommand("sp_insert1", con);
   
     cmd.CommandType = CommandType.StoredProcedure;
     SqlParameter outpara = new SqlParameter("@id", SqlDbType.Int);
     outpara.ParameterName = "@id";
     outpara.SqlDbType = SqlDbType.Int;
     outpara.Direction = ParameterDirection.Output;
     cmd.Parameters.Add(outpara);
     cmd.Parameters.AddWithValue("@value", val);   
     con.Open();
     cmd.ExecuteNonQuery();
     con.Close();
 }
                                                この例では、Klocwork は 6 行目で欠陥を報告しており、次のことを示しています。「5 行目で未検証の XSS 文字列 'txt' が 'get_Text()' から受け取られます。これは、6 行目で 'saveValueInDataBase()' の呼び出しによって保存されています。これにより、クロスサイトスクリプティングの脆弱性が発生します。」
修正コード例
  protected void Submit_Click(object sender, EventArgs e)
  {
      try
      {
          var txt = MyTextbox.Text;
          saveValueInDataBase(Server.HtmlEncode( txt ));      // no defect
      }
      catch (Exception) { }
  }
   
 void saveValueInDataBase(string val)
 {
     SqlConnection con = new SqlConnection();
     SqlCommand cmd = new SqlCommand("sp_insert1", con);
   
     cmd.CommandType = CommandType.StoredProcedure;
     SqlParameter outpara = new SqlParameter("@id", SqlDbType.Int);
     outpara.ParameterName = "@id";
     outpara.SqlDbType = SqlDbType.Int;
     outpara.Direction = ParameterDirection.Output;
     cmd.Parameters.Add(outpara);
     cmd.Parameters.AddWithValue("@value", val);     
     con.Open();
     cmd.ExecuteNonQuery();
     con.Close();
 }
                                                この修正された例では、Klocwork は欠陥を報告しません。
関連チェッカー
外部参考資料
セキュリティトレーニング
Secure Code Warrior が提供しているアプリケーションセキュリティトレーニング教材。