検索
ホームページバックエンド開発XML/RSS チュートリアルXML インジェクションとコード防御の詳細な紹介


0x01 はじめに

一部の Web アプリケーションは、構成から完全なデータベース機能まで、さまざまな目的で XML ファイルを使用します。 ユーザー入力は通常、構成のカスタマイズやアプリケーション データベースの更新のために、これらのファイルに

されます。 ユーザー入力が使用前にサニタイズまたは検証されていない場合、セキュリティ リスクになる可能性があります。 予防策が講じられていない場合、悪意のあるユーザーは設定手順を変更し、新しいユーザーを追加する可能性があります(ユーザーリストが合格した場合) メンテナンス用の XML ファイル)、より高い権限の取得など。 以下は脆弱な J2EE アプリケーションを示しています:

  		Document doc = docBuilder.newDocument();
  		Element rootElement = doc.createElement("root");
  		doc.appendChild(rootElement);
  		Element firstElement = doc.createElement("first");
  		rootElement.appendChild(firstElement);
  		Element childElement = doc.createElement("child");
  		childElement.appendChild(doc.createTextNode(--User_Supplied_Text--)); // un-sanitized text
  		rootElement.appendChild(childElement);

以下は同様の脆弱な .NET アプリケーションを示しています:

  		String nodeText = request.getParameter("node");
  		XmlWriterSettings settings = new XmlWriterSettings();
  		writer = XmlWriter.Create(m_Document, settings);
  		writer.WriteElementString("newNode", nodeText); // un-sanitized text
  		 writer.WriteEndElement();

このコードを例として使用すると、ユーザー入力は適切なクリーンアップなしで XML ファイルに伝播されます。この脆弱性は、アプリケーションによる XML ファイルの使用方法に応じて、さまざまな方法で悪用される可能性があります。

0x02 脅威の影響

ユーザー入力時の危険な文字の不適切なサニタイズが原因で、 この攻撃の最悪のシナリオは、クライアントで変更されているページコンテキストによって異なります。側、アプリケーションのロジックを壊す可能性があります

0x03 修復のアイデア いくつかの問題の解決策は、ユーザー入力をクリーンアップすることです。ユーザー入力に危険な文字が含まれていないことを確認することで、悪意のあるユーザーがアプリケーションに意図しないタスク (任意の SQL

クエリ

の起動、クライアント上で実行される Javascript コードの埋め込み) を実行させることを防ぐことができます。各種オペレーティングシステムの実行 注文など

1 推奨されるフィルター文字

[1] | (縦棒記号)

[2] & (& アンパサンド)

[3] (セミコロン)

; [5] % (パーセント記号)

[6] @ (アットマーク)

[7] ' (一重引用符)

[8] " (引用符)

🎜[9] ' (バックスラッシュ エスケープ シングル引用)🎜

[10] " (バックスラッシュでエスケープされた引用符)

[11] (山括弧)

[12] () (括弧)

[13] + (プラス記号)

[14 ] CR (キャリッジリターン、ASCII 0x0d)

[15] LF (ラインフィード、ASCII 0x0a)

[16] 、(カンマ)

[17] (バックスラッシュ)

以下のセクションでは、さまざまな問題について説明します。問題の改訂に関する提案およびそれらを引き起こす可能性のある危険な文字:

2 SQL インジェクションとブラインド SQL インジェクション

A. ユーザーが入力した値と型 (整数、日付など) が有効であり、期待どおりであることを確認します。アプリケーション

. B. ストアド プロシージャを使用して、ユーザーがテーブルやビューに直接アクセスしないようにします。ストアド プロシージャを使用する場合は、変数の型を強制する

C. コンテキストを除外する。記号は次のとおりです。

[1] ' (一重引用符)

[2] " (引用符)

[3] ' (バックスラッシュでエスケープされた一重引用符)

[4] " (バックスラッシュでエスケープされた一重引用符) )

[5] ) (閉じ括弧)

[6] ; (セミコロン)

3 クロスサイト スクリプティング

A. 次の文字をフィルタリングして除外することをお勧めします。 :

[1] (山括弧)

[2] " (引用符)

[3] ' (一重引用符)

[4] % (パーセント記号)

[5] ; (セミコロン)

[6] () (括弧)

[7] & (アンパサンド)

[8] + (プラス記号)

B。 のバリアントを修正する場合は、MS の記事 821349 を参照してください。

C. UTF-7 攻撃の場合: [-] 可能であれば、特定の

Characterset エンコーディングを実装することをお勧めします (「Content-Type」ヘッダーまたは タグを使用)。

4 HTTP 応答の分割

ユーザー入力 (少なくとも後で HTTP 応答に埋め込まれる入力) をサニタイズします。入力に次のような悪意のある文字が含まれていないことを確認してください。

[1] CR (Carriage Return、ASCII) 0x0d)

[2] LF (改行、ASCII 0x0a) リモート コマンド実行: 入力をサニタイズして、次のようなオペレーティング システム コマンドの実行に意味のある記号を除外します。 ] & (& Symbol)

[3]; (セミコロン)

5 シェルコマンドを実行します

A. チェックされていないユーザー入力を eval()、open()、sysopen()、system() などに渡さないでください。 Perl

コマンド。

B. 入力に次のような悪意のある文字が含まれていないことを確認してください:

[1] $ (ドル記号) [2] % (パーセント記号)

[3] @ (アットマーク)

XPath

インジェクション: 入力をサニタイズして、次のようなコンテキストを変更するシンボルを除外します。

[1] ' (一重引用符)

[2] " (引用符) など。 6 LDAP インジェクション

A. ポジティブ検証を使用します。英数字フィルタリング (A. .Z,a..z,0..9) ほとんどの LDAP クエリに適しています

B. フィルタリングまたはエスケープする必要がある特殊な LDAP 文字:

[1] 文字列の先頭にあるスペースまたは「#」文字

[2] 文字列の末尾にあるスペース文字

[3] 、(カンマ)

[4] + (プラス記号)

[5] " (引用符)

[6] (バックスラッシュ)

[7] (山括弧)

[8] ; (セミコロン)

[9] () (括弧)

7 MX インジェクション

は特殊な MX 文字を除外する必要があります:

[1] CR (復帰、ASCII 0x0d)

[2] LF (改行、ASCII 0x0a) レコード偽造:

特殊なレコード文字を除外する必要があります:

[1] CR (キャリッジリターン、ASCII 0x0d)

[2] LF (ラインフィード、ASCII 0x0a)

[3] BS (バックスペース、ASCII 0x08)

8 ORM インジェクション

Aユーザーが入力した値と型 (整数、日付など) は有効であり、アプリケーションの期待を満たします。

B. ユーザーがテーブルやビューに直接アクセスしないように、ストアド プロシージャを使用します。パラメータ化を使用します。クエリ API

D。例: (*):

[1] '(single quote)

[ 3] '(バックスラッシュでエスケープされた一重引用符)

[4] " (バックスラッシュでエスケープされた引用符)

[5] ) (終了括弧)

[6] ; (セミコロン)

(*) これは SQL で機能します。高度なクエリ言語では、異なるサニタイズ メカニズムが必要になる場合があります。

0x04 Asp.Net

1 一般的な推奨事項

[1] サーバーを .NET Framework 2.0 (またはそれ以降) にアップグレードすることをお勧めします。これには、本質的にクロスサイト スクリプティング攻撃に対する保護が含まれています。保護セキュリティチェック。

[2] 検証コントロールを使用して、Web フォーム ページに入力検証を追加できます。 検証コントロールは、すべての一般的なタイプの標準検証 (たとえば、日付が有効であることを検証するテストや、値が範囲内にあることを検証する) に使いやすいメカニズムを提供します。 さらに、検証コントロールはカスタム作成された検証もサポートしており、エラー メッセージをユーザーに表示する方法を完全にカスタマイズできます。 検証コントロールは、HTML や Web サーバー コントロールなど、Web フォーム ページ クラス ファイルで処理される任意のコントロールとともに使用できます。

2 ユーザー入力に有効な値のみが含まれていることを確認します

[1] "RangeValidator": ユーザー入力 (値) が指定された上限と下限の範囲内にあるかどうかを確認します。日付内の数字、アルファベット、範囲が一致するかどうかを確認できます。

[2] " RegularExpressionValidator ": エントリが 正規表現 で定義されたパターンと一致するかどうかを確認します。このタイプの検証により、社会保障番号、電子メール アドレス、電話番号、郵便番号などに含まれる予測可能な文字シーケンスをチェックできます。クロスサイト スクリプティングの防止に役立つ正規表現の例:

- 基本的なクロスサイト スクリプティングのバリエーションを拒否できる正規表現は次のようになります: ^([^

1. 一般的なエラー ステータスをテストする:

コードで、ページの IsValid プロパティをテストします。このプロパティは、ページ上のすべての検証コントロールの IsValid プロパティ値を集計します。 (論理積を使用します)。検証コントロールの 1 つが無効に設定されている場合、ページ プロパティは false を返します

2. 個々のコントロールのエラー ステータスをテストします。

在页面的“验证器”集合中循环,该集合包含对所有验证控件的引用。 然后,您就可以检查每个验证控件的 IsValid 属性。

3 编码输入

        建议使用 Microsoft Anti-Cross Site Scripting Library(V1.5 更高版本)对不受信任的用户输入进行编码。

Anti-Cross Site Scripting Library 显现下列方法:

[1] HtmlEncode - 将在 HTML 中使用的输入字符串编码

[2] HtmlAttributeEncode - 将在 HTML 属性中使用的输入字符串编码

[3] JavaScriptEncode - 将在 JavaScript 中使用的输入字符串编码

[4] UrlEncode - 将在“统一资源定位器 (URL)”中使用的输入字符串编码

[5] VisualBasicScriptEncode - 将在 Visual Basic 脚本中使用的输入字符串编码

[6] XmlEncode - 将在 XML 中使用的输入字符串编码

[7] XmlAttributeEncode - 将在 XML 属性中使用的输入字符串编码

如果要适当使用 Microsoft Anti-Cross Site Scripting Library 来保护 ASP.NET Web 应用程序,您必须运行下列操作:

第 1 步:复查生成输出的 ASP.NET 代码

第 2 步:判断是否包括不受信任的输入参数

第 3 步:判断不受信任的输入的上下文是否作为输出,判断要使用哪个编码方法

第 4 步:编码输出

第 3 步骤的示例:

注意:如果要使用不受信任的输入来安装 HTML 属性,便应该使用 Microsoft.Security.Application.HtmlAttributeEncode 方法,将不受信任的输入编码。另外,如果要在 JavaScript 的上下文中使用不受信任的输入,便应该使用 Microsoft.Security.Application.JavaScriptEncode 来编码。

  // Vulnerable code
  // Note that untrusted input is being treated as an HTML attribute
  Literal1.Text = "<hr noshade size=[untrusted input here]>";
  // Modified code
  Literal1.Text = "<hr noshade size="+Microsoft.Security.Application.AntiXss.HtmlAttributeEncode([untrusted input here])+">";

第 4 步骤的示例:将输出编码时,必须记住的一些重要事项:

[1] 输出应该编码一次。

[2] 输出的编码与实际撰写,应该尽可能接近。 例如,如果应用程序读取用户输入、处理输入,再用某种形式将它重新写出,便应该紧接在撰写输出之前进行编码。

  // Incorrect sequence
  protected void Button1_Click(object sender, EventArgs e)
  {
      // Read input
      String Input = TextBox1.Text;
      // Encode untrusted input
      Input = Microsoft.Security.Application.AntiXss.HtmlEncode(Input);
      // Process input
      ...
      // Write Output
      Response.Write("The input you gave was"+Input);
  }
  // Correct Sequence
  protected void Button1_Click(object sender, EventArgs e)
  {
      // Read input
      String Input = TextBox1.Text;
      // Process input
      ...
      // Encode untrusted input and write output
      Response.Write("The input you gave was"+ 
          Microsoft.Security.Application.AntiXss.HtmlEncode(Input));
  }

0x05 J2EE

1 输入数据验证

     虽然为了用户的方便,可以提供“客户端”层数据的数据验证,但必须使用 Servlet 在服务器层执行验证。 客户端验证本身就不安全,因为这些验证可轻易绕过,例如,通过禁用 Javascript。一份好的设计通常需要 Web 应用程序框架,以提供服务器端实用程序例程,从而验证以下内容:[1] 必需字段[2] 字段数据类型(缺省情况下,所有 HTTP 请求参数都是“字符串”)[3] 字段长度[4] 字段范围[5] 字段选项[6] 字段模式[7] cookie 值[8] HTTP 响应好的做法是将以上例程作为“验证器”实用程序类中的静态方法实现。以下部分描述验证器类的一个示例。

[1] 必需字段

       必需字段“始终”检查字段不为空,并且其长度要大于零,不包括行距和后面的空格。如何验证必需字段的示例:

  // Java example to validate required fields
  public Class Validator {
      ...
      public static boolean validateRequired(String value) {
          boolean isFieldValid = false;
          if (value != null && value.trim().length() > 0) {
              isFieldValid = true;
          }
          return isFieldValid;
      }
  }
  String fieldValue = request.getParameter("fieldName");
  if (Validator.validateRequired(fieldValue)) {
      // fieldValue is valid, continue processing request
  }

[2] 字段数据类型

       输入的 Web 应用程序中的字段数据类型和输入参数欠佳。例如,所有 HTTP 请求参数或 cookie 值的类型都是“字符串”。开发者负责验证输入的数据类型是否正确。 使用 Java 基本包装程序类,来检查是否可将字段值安全地转换为所需的基本数据类型。验证数字字段(int 类型)的方式的示例:

  // Java example to validate that a field is an int number
  public Class Validator {
      public static boolean validateInt(String value) {
          boolean isFieldValid = false;
          try {
              Integer.parseInt(value);
              isFieldValid = true;
          } catch (Exception e) {
              isFieldValid = false;
          }
          return isFieldValid;
      }
  }
  // check if the HTTP request parameter is of type int
  String fieldValue = request.getParameter("fieldName");
  if (Validator.validateInt(fieldValue)) {
      // fieldValue is valid, continue processing request
  }

         好的做法是将所有 HTTP 请求参数转换为其各自的数据类型。例如,开发者应将请求参数的“integerValue”存储在请求属性中,并按以下示例所示来使用:

  // Example to convert the HTTP request parameter to a primitive wrapper data type
  // and store this value in a request attribute for further processing
  String fieldValue = request.getParameter("fieldName");
  if (Validator.validateInt(fieldValue)) {
      // convert fieldValue to an Integer
      Integer integerValue = Integer.getInteger(fieldValue);
      // store integerValue in a request attribute
      request.setAttribute("fieldName", integerValue);
  }
  // Use the request attribute for further processing
  Integer integerValue = (Integer)request.getAttribute("fieldName");

应用程序应处理的主要 Java 数据类型:

- Byte

- Short

- Integer

- Long

- Float

- Double

- Date

[3] 字段长度

       “始终”确保输入参数(HTTP 请求参数或 cookie 值)有最小长度和/或最大长度的限制。以下示例验证 userName 字段的长度是否在 8 至 20 个字符之间:

  // Example to validate the field length
  public Class Validator {
      public static boolean validateLength(String value, int minLength, int maxLength) {
          String validatedValue = value;
          if (!validateRequired(value)) {
              validatedValue = "";
          }
          return (validatedValue.length() >= minLength &&
                      validatedValue.length() <= maxLength);
      }
  }
  String userName = request.getParameter("userName");
  if (Validator.validateRequired(userName)) {
      if (Validator.validateLength(userName, 8, 20)) {
          // userName is valid, continue further processing
      }
  }

[4] 字段范围

     始终确保输入参数是在由功能需求定义的范围内。以下示例验证输入 numberOfChoices 是否在 10 至 20 之间:

  // Example to validate the field range
  public Class Validator {
      ...
      public static boolean validateRange(int value, int min, int max) {
          return (value >= min && value <= max);
      }
  }
  String fieldValue = request.getParameter("numberOfChoices");
  if (Validator.validateRequired(fieldValue)) {
      if (Validator.validateInt(fieldValue)) {
          int numberOfChoices = Integer.parseInt(fieldValue);
          if (Validator.validateRange(numberOfChoices, 10, 20)) {
              // numberOfChoices is valid, continue processing request
          }
      }
  }

[5] 字段选项

        Web 应用程序通常会为用户显示一组可供选择的选项(例如,使用 SELECT HTML 标记),但不能执行服务器端验证以确保选定的值是其中一个允许的选项。请记住,恶意用户能够轻易修改任何选项值。始终针对由功能需求定义的受允许的选项来验证选定的用户值。以下示例验证用户针对允许的选项列表进行的选择:

  // Example to validate user selection against a list of options
  public Class Validator {
      public static boolean validateOption(Object[] options, Object value) {
          boolean isValidValue = false;
          try {
              List list = Arrays.asList(options);
              if (list != null) {
                  isValidValue = list.contains(value);
              }
          } catch (Exception e) {
          }
          return isValidValue;
      }
  }
  // Allowed options
  String[] options = {"option1", "option2", "option3");
  // Verify that the user selection is one of the allowed options
  String userSelection = request.getParameter("userSelection");
  if (Validator.validateOption(options, userSelection)) {
      // valid user selection, continue processing request
  }

[6] 字段模式

       始终检查用户输入与由功能需求定义的模式是否匹配。例如,如果 userName 字段应仅允许字母数字字符,且不区分大小写,那么请使用以下正则表达式:^[a-zA-Z0-9]*$

       Java 1.4 引进了一种新的正则表达式包(java.util.regex)。以下是使用新的 Java 1.4 正则表达式包的 Validator.matchPattern 修订版:

  // Example to validate that a given value matches a specified pattern
  // using the Java 1.4 regular expression package
  import java.util.regex.Pattern;
  import java.util.regexe.Matcher;
  public Class Validator {

      public static boolean matchPattern(String value, String expression) {
          boolean match = false;
          if (validateRequired(expression)) {
              match = Pattern.matches(expression, value);
          }
          return match;
      }
  }

         使用 javax.servlet.http.Cookie 对象来验证 cookie 值。适用于 cookie 值的相同的验证规则(如上所述)取决于应用程序需求(如验证必需值、验证长度等)。验证必需 cookie 值的示例:

  // Example to validate a required cookie value
  // First retrieve all available cookies submitted in the HTTP request
  Cookie[] cookies = request.getCookies();
  if (cookies != null) {
      // find the "user" cookie
      for (int i=0; i<cookies.length; ++i) {
          if (cookies[i].getName().equals("user")) {
              // validate the cookie value
              if (Validator.validateRequired(cookies[i].getValue()) {
                  // valid cookie value, continue processing request
                  ...
              }
          }    
      }
  }

[8] HTTP 响应

[8-1] 过滤用户输入

要保护应用程序免遭跨站点脚本编制的攻击,请通过将敏感字符转换为其对应的字符实体来清理 HTML。这些是 HTML 敏感字符: " ' % ; ) ( & +

以下示例通过将敏感字符转换为其对应的字符实体来过滤指定字符串:

  // Example to filter sensitive data to prevent cross-site scripting
  public Class Validator {
      public static String filter(String value) {
          if (value == null) {
              return null;
          }        
          StringBuffer result = new StringBuffer(value.length());
          for (int i=0; i<value.length(); ++i) {
              switch (value.charAt(i)) {
              case &#39;<&#39;:
                  result.append("<");
                  break;
              case &#39;>&#39;: 
                  result.append(">");
                  break;
              case &#39;"&#39;: 
                  result.append(""");
                  break;
              case &#39;\&#39;&#39;: 
                  result.append("&#39;");
                  break;
              case &#39;%&#39;: 
                  result.append("&#37;");
                  break;
              case &#39;;&#39;: 
                  result.append("&#59;");
                  break;
              case &#39;(&#39;: 
                  result.append("&#40;");
                  break;
              case &#39;)&#39;: 
                  result.append("&#41;");
                  break;
              case &#39;&&#39;: 
                  result.append("&");
                  break;
              case &#39;+&#39;:
                  result.append("&#43;");
                  break;
              default:
                  result.append(value.charAt(i));
                  break;
          }        
          return result;
      }
  }
  // Filter the HTTP response using Validator.filter
  PrintWriter out = response.getWriter();
  // set output response
  out.write(Validator.filter(response));
  out.close();

Java Servlet API 2.3 引进了过滤器,它支持拦截和转换 HTTP 请求或响应。以下示例使用 Validator.filter 来用“Servlet 过滤器”清理响应:

  // Example to filter all sensitive characters in the HTTP response using a Java Filter.
  // This example is for illustration purposes since it will filter all content in the response, including HTML tags!
  public class SensitiveCharsFilter implements Filter {
      ...
      public void doFilter(ServletRequest request,
                      ServletResponse response,
                      FilterChain chain)
              throws IOException, ServletException {
          PrintWriter out = response.getWriter();
          ResponseWrapper wrapper = new ResponseWrapper((HttpServletResponse)response);
          chain.doFilter(request, wrapper);
          CharArrayWriter caw = new CharArrayWriter();
          caw.write(Validator.filter(wrapper.toString())); 
          response.setContentType("text/html");
          response.setContentLength(caw.toString().length());
          out.write(caw.toString());
          out.close();
      }
      public class CharResponseWrapper extends HttpServletResponseWrapper {
          private CharArrayWriter output;
          public String toString() {
              return output.toString();
          }
          public CharResponseWrapper(HttpServletResponse response){
              super(response);
              output = new CharArrayWriter();
          }
          public PrintWriter getWriter(){
              return new PrintWriter(output);
          }
      }
  } 
  }

[8-2] 保护 cookie

在 cookie 中存储敏感数据时,确保使用 Cookie.setSecure(布尔标志)在 HTTP 响应中设置 cookie 的安全标志,以指导浏览器使用安全协议(如 HTTPS 或 SSL)发送 cookie。

保护“用户”cookie 的示例:

  // Example to secure a cookie, i.e. instruct the browser to
  // send the cookie using a secure protocol
  Cookie cookie = new Cookie("user", "sensitive");
  cookie.setSecure(true);
  response.addCookie(cookie);

2 错误处理

      许多 J2EE Web 应用程序体系结构都遵循“模型视图控制器MVC)”模式。在该模式中,Servlet 扮演“控制器”的角色。Servlet 将应用程序处理委派给 EJB 会话 Bean(模型)之类的 JavaBean。然后,Servlet 再将请求转发给 JSP(视图),以呈现处理结果。Servlet 应检查所有的输入、输出、返回码、错误代码和已知的异常,以确保实际处理按预期进行。

数据验证可保护应用程序免遭恶意数据篡改,而有效的错误处理策略则是防止应用程序意外泄露内部错误消息(如异常堆栈跟踪)所不可或缺的。好的错误处理策略会处理以下项:

[1] 定义错误

[2] 报告错误

[3] 呈现错误

[4] 错误映射

[1] 定义错误

         应避免在应用程序层(如 Servlet)中硬编码错误消息。 相反地,应用程序应该使用映射到已知应用程序故障的错误密钥。好的做法是定义错误密钥,且该错误密钥映射到 HTML 表单字段或其他 Bean 属性的验证规则。例如,如果需要“user_name”字段,其内容为字母数字,并且必须在数据库中是唯一的,那么就应定义以下错误密钥:

(a) ERROR_USERNAME_REQUIRED:该错误密钥用于显示消息,以通知用户需要“user_name”字段;

(b) ERROR_USERNAME_ALPHANUMERIC:该错误密钥用于显示消息,以通知用户“user_name”字段应该是字母数字;

(c) ERROR_USERNAME_DUPLICATE:该错误密钥用于显示消息,以通知用户“user_name”值在数据库中重复;

(d) ERROR_USERNAME_INVALID:该错误密钥用于显示一般消息,以通知用户“user_name”值无效;

好的做法是定义用于存储和报告应用程序错误的以下框架 Java 类:

- ErrorKeys:定义所有错误密钥

      // Example: ErrorKeys defining the following error keys:    
      //    - ERROR_USERNAME_REQUIRED
      //    - ERROR_USERNAME_ALPHANUMERIC
      //    - ERROR_USERNAME_DUPLICATE
      //    - ERROR_USERNAME_INVALID
      //    ...
      public Class ErrorKeys {
          public static final String ERROR_USERNAME_REQUIRED = "error.username.required";
          public static final String ERROR_USERNAME_ALPHANUMERIC = "error.username.alphanumeric";
          public static final String ERROR_USERNAME_DUPLICATE = "error.username.duplicate";
          public static final String ERROR_USERNAME_INVALID = "error.username.invalid";
      }


- Error:封装个别错误

      // Example: Error encapsulates an error key.
      // Error is serializable to support code executing in multiple JVMs.
      public Class Error implements Serializable {
          
          // Constructor given a specified error key
          public Error(String key) {
              this(key, null);
          }
          // Constructor given a specified error key and array of placeholder objects
          public Error(String key, Object[] values) {
              this.key = key;
              this.values = values;
          }
          // Returns the error key
          public String getKey() {
              return this.key;
          }
          // Returns the placeholder values
          public Object[] getValues() {
              return this.values;
          }
          private String key = null;
          private Object[] values = null;
      }

- Errors:封装错误的集合

      // Example: Errors encapsulates the Error objects being reported to the presentation layer.
      // Errors are stored in a HashMap where the key is the bean property name and value is an
      // ArrayList of Error objects.
      public Class Errors implements Serializable {
      
          // Adds an Error object to the Collection of errors for the specified bean property.
          public void addError(String property, Error error) {
              ArrayList propertyErrors = (ArrayList)errors.get(property);
              if (propertyErrors == null) {
                  propertyErrors = new ArrayList();
                  errors.put(property, propertyErrors);
              }
              propertyErrors.put(error);            
          }
          // Returns true if there are any errors
          public boolean hasErrors() {
              return (errors.size > 0);
          }
          // Returns the Errors for the specified property
          public ArrayList getErrors(String property) {
              return (ArrayList)errors.get(property);
          }
          private HashMap errors = new HashMap();
      }

以下是使用上述框架类来处理“user_name”字段验证错误的示例:

  // Example to process validation errors of the "user_name" field.
  Errors errors = new Errors();
  String userName = request.getParameter("user_name");
  // (a) Required validation rule
  if (!Validator.validateRequired(userName)) {
      errors.addError("user_name", new Error(ErrorKeys.ERROR_USERNAME_REQUIRED));
  } // (b) Alpha-numeric validation rule
  else if (!Validator.matchPattern(userName, "^[a-zA-Z0-9]*$")) {
      errors.addError("user_name", new Error(ErrorKeys.ERROR_USERNAME_ALPHANUMERIC));
  }
  else
  {
      // (c) Duplicate check validation rule
      // We assume that there is an existing UserValidationEJB session bean that implements
      // a checkIfDuplicate() method to verify if the user already exists in the database.
      try {
          ...        
          if (UserValidationEJB.checkIfDuplicate(userName)) {
              errors.addError("user_name", new Error(ErrorKeys.ERROR_USERNAME_DUPLICATE));
          }
      } catch (RemoteException e) {
          // log the error
          logger.error("Could not validate user for specified userName: " + userName);
          errors.addError("user_name", new Error(ErrorKeys.ERROR_USERNAME_DUPLICATE);
      }
  }
  // set the errors object in a request attribute called "errors"
  request.setAttribute("errors", errors);

[2] 报告错误

有两种方法可报告 web 层应用程序错误:

(a) Servlet 错误机制、(b) JSP 错误机制

[2-a] Servlet 错误机制

Servlet 可通过以下方式报告错误:

- 转发给输入 JSP(已将错误存储在请求属性中),或

- 使用 HTTP 错误代码参数来调用 response.sendError,或

- 抛出异常

          好的做法是处理所有已知应用程序错误(如 [1] 部分所述),将这些错误存储在请求属性中,然后转发给输入 JSP。输入 JSP 应显示错误消息,并提示用户重新输入数据。以下示例阐明转发给输入 JSP(userInput.jsp)的方式:

  // Example to forward to the userInput.jsp following user validation errors
  RequestDispatcher rd = getServletContext().getRequestDispatcher("/user/userInput.jsp");
  if (rd != null) {
      rd.forward(request, response);
  }

    如果 Servlet 无法转发给已知的 JSP 页面,那么第二个选项是使用 response.sendError 方法,将 HttpServletResponse.SC_INTERNAL_SERVER_ERROR(状态码 500)作为参数,来报告错误。 请参阅 javax.servlet.http.HttpServletResponse 的 Javadoc,以获取有关各种 HTTP 状态码的更多详细信息。返回 HTTP 错误的示例:

  // Example to return a HTTP error code
  RequestDispatcher rd = getServletContext().getRequestDispatcher("/user/userInput.jsp");
  if (rd == null) {
      // messages is a resource bundle with all message keys and values
      response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
                              messages.getMessage(ErrorKeys.ERROR_USERNAME_INVALID));
  }

作为最后的手段,Servlet 可以抛出异常,且该异常必须是以下其中一类的子类:

- RuntimeException

- ServletException

- IOException

[2-b] JSP 错误机制

JSP 页面通过定义 errorPage 伪指令来提供机制,以处理运行时异常,如以下示例所示:

      <%@ page errorPage="/errors/userValidation.jsp" %>

未捕获的 JSP 异常被转发给指定的 errorPage,并且原始异常设置在名称为 javax.servlet.jsp.jspException 的请求参数中。错误页面必须包括 isErrorPage 伪指令:

      <%@ page isErrorPage="true" %>

isErrorPage 伪指令导致“exception”变量初始化为所抛出的异常对象。

[3] 呈现错误

J2SE Internationalization API 提供使应用程序资源外部化以及将消息格式化的实用程序类,其中包括:

(a) 资源束、(b) 消息格式化

[3-a] 资源束

资源束通过将本地化数据从使用该数据的源代码中分离来支持国际化。每一资源束都会为特定的语言环境存储键/值对的映射。

java.util.PropertyResourceBundle 将内容存储在外部属性文件中,对其进行使用或扩展都很常见,如以下示例所示:

  ################################################
  # ErrorMessages.properties
  ################################################
  # required user name error message
  error.username.required=User name field is required
  # invalid user name format
  error.username.alphanumeric=User name must be alphanumeric
  # duplicate user name error message
  error.username.duplicate=User name {0} already exists, please choose another one

         可定义多种资源,以支持不同的语言环境(因此名为资源束)。例如,可定义 ErrorMessages_fr.properties 以支持该束系列的法语成员。如果请求的语言环境的资源成员不存在,那么会使用缺省成员。在以上示例中,缺省资源是 ErrorMessages.properties。应用程序(JSP 或 Servlet)会根据用户的语言环境从适当的资源检索内容。

[3-b] 消息格式化

        J2SE 标准类 java.util.MessageFormat 提供使用替换占位符来创建消息的常规方法。MessageFormat 对象包含嵌入了格式说明符的模式字符串,如下所示:

  // Example to show how to format a message using placeholder parameters
  String pattern = "User name {0} already exists, please choose another one";
  String userName = request.getParameter("user_name");
  Object[] args = new Object[1];
  args[0] = userName;
  String message = MessageFormat.format(pattern, args);

以下是使用 ResourceBundle 和 MessageFormat 来呈现错误消息的更加全面的示例:

  // Example to render an error message from a localized ErrorMessages resource (properties file)
  // Utility class to retrieve locale-specific error messages
  public Class ErrorMessageResource {   
      // Returns the error message for the specified error key in the environment locale
      public String getErrorMessage(String errorKey) {
          return getErrorMessage(errorKey, defaultLocale);
      }  
      // Returns the error message for the specified error key in the specified locale
      public String getErrorMessage(String errorKey, Locale locale) {
          return getErrorMessage(errorKey, null, locale);
      } 
      // Returns a formatted error message for the specified error key in the specified locale
      public String getErrorMessage(String errorKey, Object[] args, Locale locale) {    
          // Get localized ErrorMessageResource
          ResourceBundle errorMessageResource = ResourceBundle.getBundle("ErrorMessages", locale);
          // Get localized error message
          String errorMessage = errorMessageResource.getString(errorKey);
          if (args != null) {
              // Format the message using the specified placeholders args
              return MessageFormat.format(errorMessage, args);
          } else {
              return errorMessage;
          }
      }
      // default environment locale
      private Locale defaultLocale = Locale.getDefaultLocale();
  }
  // Get the user&#39;s locale
  Locale userLocale = request.getLocale();
  // Check if there were any validation errors
  Errors errors = (Errors)request.getAttribute("errors");
  if (errors != null && errors.hasErrors()) {
      // iterate through errors and output error messages corresponding to the "user_name" property
      ArrayList userNameErrors = errors.getErrors("user_name");
      ListIterator iterator = userNameErrors.iterator();
      while (iterator.hasNext()) {
          // Get the next error object
          Error error = (Error)iterator.next();
          String errorMessage = ErrorMessageResource.getErrorMessage(error.getKey(), userLocale);
          output.write(errorMessage + "\r\n");
      }
  }

建议定义定制 JSP 标记(如 displayErrors),以迭代处理并呈现错误消息,如以上示例所示。

[4] 错误映射

通常情况下,“Servlet 容器”会返回与响应状态码或异常相对应的缺省错误页面。可以使用定制错误页面来指定状态码或异常与 Web 资源之间的映射。好的做法是开发不会泄露内部错误状态的静态错误页面(缺省情况下,大部分 Servlet 容器都会报告内部错误消息)。该映射配置在“Web 部署描述符(web.xml)”中,如以下示例所指定:

  <!-- Mapping of HTTP error codes and application exceptions to error pages -->
  <error-page>
    <exception-type>UserValidationException</exception-type>
    <location>/errors/validationError.html</error-page>
  </error-page>
  <error-page>
    <error-code>500</exception-type>
    <location>/errors/internalError.html</error-page>
  </error-page>
  <error-page>
  ...
  </error-page>


0x06 PHP

1  输入数据验证

      虽然为方便用户而在客户端层上提供数据验证,但仍必须始终在服务器层上执行数据验证。客户端验证本身就不安全,因为这些验证可轻易绕过,例如,通过禁用 Javascript。一份好的设计通常需要 Web 应用程序框架,以提供服务器端实用程序例程,从而验证以下内容:[1] 必需字段[2] 字段数据类型(缺省情况下,所有 HTTP 请求参数都是“字符串”)[3] 字段长度[4] 字段范围[5] 字段选项[6] 字段模式[7] cookie 值[8] HTTP 响应好的做法是实现一个或多个验证每个应用程序参数的函数。以下部分描述一些检查的示例。

[1] 必需字段

    “始终”检查字段不为空,并且其长度要大于零,不包括行距和后面的空格。如何验证必需字段的示例:

  // PHP example to validate required fields
  function validateRequired($input) {
      ...
      $pass = false;
      if (strlen(trim($input))>0){
          $pass = true;
      }
      return $pass;
  }
  if (validateRequired($fieldName)) {
      // fieldName is valid, continue processing request
  }

[2] 字段数据类型

        输入的 Web 应用程序中的字段数据类型和输入参数欠佳。例如,所有 HTTP 请求参数或 cookie 值的类型都是“字符串”。开发者负责验证输入的数据类型是否正确。

[3] 字段长度

       “始终”确保输入参数(HTTP 请求参数或 cookie 值)有最小长度和/或最大长度的限制。

[4] 字段范围

        始终确保输入参数是在由功能需求定义的范围内。

[5] 字段选项

          Web 应用程序通常会为用户显示一组可供选择的选项(例如,使用 SELECT HTML 标记),但不能执行服务器端验证以确保选定的值是其中一个允许的选项。请记住,恶意用户能够轻易修改任何选项值。始终针对由功能需求定义的受允许的选项来验证选定的用户值。

[6] 字段模式

       始终检查用户输入与由功能需求定义的模式是否匹配。例如,如果 userName 字段应仅允许字母数字字符,且不区分大小写,那么请使用以下正则表达式:^[a-zA-Z0-9]+$

       适用于 cookie 值的相同的验证规则(如上所述)取决于应用程序需求(如验证必需值、验证长度等)。

[8] HTTP 响应

[8-1] 过滤用户输入要保护应用程序免遭跨站点脚本编制的攻击,开发者应通过将敏感字符转换为其对应的字符实体来清理 HTML。这些是 HTML 敏感字符: " ' % ; ) ( & +PHP 包含一些自动化清理实用程序函数,如 htmlentities():

  $input = htmlentities($input, ENT_QUOTES, &#39;UTF-8&#39;);

此外,为了避免“跨站点脚本编制”的 UTF-7 变体,您应该显式定义响应的 Content-Type 头,例如:

  <?php
  header(&#39;Content-Type: text/html; charset=UTF-8&#39;);
  ?>

[8-2] 保护 cookie

         在 cookie 中存储敏感数据且通过 SSL 来传输时,请确保先在 HTTP 响应中设置 cookie 的安全标志。这将会指示浏览器仅通过 SSL 连接来使用该 cookie。为了保护 cookie,您可以使用以下代码示例:

  <$php
      $value = "some_value";
      $time = time()+3600;
      $path = "/application/";
      $domain = ".example.com";
      $secure = 1;
      setcookie("CookieName", $value, $time, $path, $domain, $secure, TRUE);
  ?>


以上がXML インジェクションとコード防御の詳細な紹介の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
RSSドキュメント:お気に入りのコンテンツをどのように配信するかRSSドキュメント:お気に入りのコンテンツをどのように配信するかApr 15, 2025 am 12:01 AM

RSSドキュメントは、XMLファイルを介してコンテンツの更新を公開することで機能し、ユーザーはRSSリーダーを介して通知をサブスクライブして受信します。 1。コンテンツパブリッシャーは、RSSドキュメントを作成および更新します。 2。RSSリーダーは、XMLファイルに定期的にアクセスして解析します。 3.ユーザーは、更新されたコンテンツを閲覧および読み取ります。使用例:TechCrunchのRSSフィードを購読するには、RSSリーダーへのリンクをコピーするだけです。

XMLを使用したフィードの構築:RSSの実践ガイドXMLを使用したフィードの構築:RSSの実践ガイドApr 14, 2025 am 12:17 AM

XMLを使用してRSSFeedを構築する手順は次のとおりです。1。ルート要素を作成してバージョンを設定します。 2.チャネル要素とその基本情報を追加します。 3.タイトル、リンク、説明を含むエントリ要素を追加します。 4. XML構造を文字列に変換して出力します。これらの手順を使用すると、有効なRSSFeedをゼロから作成し、リリース日や著者情報などの追加要素を追加することにより、機能を強化できます。

RSSドキュメントの作成:ステップバイステップのチュートリアルRSSドキュメントの作成:ステップバイステップのチュートリアルApr 13, 2025 am 12:10 AM

RSSドキュメントを作成する手順は次のとおりです。1。要素を含むルート要素を使用して、XML形式で書き込みます。 2。チャネル情報を説明する要素など。 3.要素を追加します。それぞれがコンテンツエントリを表します。 4.オプションで、コンテンツを濃縮するための要素を追加します。 5. XML形式が正しいことを確認し、オンラインツールを使用してパフォーマンスを最適化し、コンテンツを更新します。

RSSにおけるXMLの役割:シンジケートコンテンツの基礎RSSにおけるXMLの役割:シンジケートコンテンツの基礎Apr 12, 2025 am 12:17 AM

RSSにおけるXMLの中心的な役割は、標準化された柔軟なデータ形式を提供することです。 1. XMLの構造とマークアップ言語の特性により、データ交換とストレージに適しています。 2。RSSはXMLを使用して標準化された形式を作成して、コンテンツの共有を容易にします。 3. RSSでのXMLの適用には、タイトルやリリース日などのフィードコンテンツを定義する要素が含まれます。 4.利点には標準化とスケーラビリティが含まれ、課題にはドキュメントの冗長および厳密な構文要件が含まれます。 5.ベストプラクティスには、XMLの有効性の検証、シンプルな状態を維持し、CDATAの使用、定期的に更新されます。

XMLから読み取り可能なコンテンツまで:RSSフィードを分類しますXMLから読み取り可能なコンテンツまで:RSSフィードを分類しますApr 11, 2025 am 12:03 AM

rssfeedsarexmldocumentsusedforcontentaggregationanddistribution.totransformthemintoreadablecontent:1)parsethexmlusinglibrarieslibrarieslibrarieslibrarieslibrarieslibrarieslibrarieslibraries.2)heandlederentrssiversions andpotentialparsingerrors.3)変換された拡張型拡張型のfienderidederidrederidederidederidedionderiondiontiontiontiontiontiontiontiontional

JSONに基づいたRSSの代替品はありますか?JSONに基づいたRSSの代替品はありますか?Apr 10, 2025 am 09:31 AM

JSonFeedは、JSONベースのRSSの代替品であり、その利点のシンプルさと使いやすさがあります。 1)JSonFeedはJSON形式を使用しますが、これは簡単に生成して解析できます。 2)動的生成をサポートし、最新のWeb開発に適しています。 3)JSonFeedを使用すると、コンテンツ管理の効率とユーザーエクスペリエンスが向上する可能性があります。

RSSドキュメントツール:フィードの構築、検証、公開RSSドキュメントツール:フィードの構築、検証、公開Apr 09, 2025 am 12:10 AM

RSSFeedsを構築、検証、公開する方法は? 1。ビルド:Pythonスクリプトを使用して、タイトル、リンク、説明、リリース日など、RSSFeedを生成します。 2。検証:FeedValidator.orgまたはPythonスクリプトを使用して、RSSFeedがRSS2.0標準に準拠しているかどうかを確認します。 3.公開:RSSファイルをサーバーにアップロードするか、フラスコを使用してRSSFeedを動的に生成および公開します。これらの手順を通じて、コンテンツを効果的に管理および共有できます。

XML/RSSフィードのセキュリティ:包括的なセキュリティチェックリストXML/RSSフィードのセキュリティ:包括的なセキュリティチェックリストApr 08, 2025 am 12:06 AM

XML/RSSFeedsのセキュリティを確保する方法には、次のものが含まれます。1。データ検証、2。暗号化された伝送、3。アクセス制御、4。ログと監視。これらの測定値は、ネットワークセキュリティプロトコル、データ暗号化アルゴリズム、アクセス制御メカニズムを介して、データの整合性と機密性を保護します。

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

SecLists

SecLists

SecLists は、セキュリティ テスターの究極の相棒です。これは、セキュリティ評価中に頻繁に使用されるさまざまな種類のリストを 1 か所にまとめたものです。 SecLists は、セキュリティ テスターが必要とする可能性のあるすべてのリストを便利に提供することで、セキュリティ テストをより効率的かつ生産的にするのに役立ちます。リストの種類には、ユーザー名、パスワード、URL、ファジング ペイロード、機密データ パターン、Web シェルなどが含まれます。テスターはこのリポジトリを新しいテスト マシンにプルするだけで、必要なあらゆる種類のリストにアクセスできるようになります。

DVWA

DVWA

Damn Vulnerable Web App (DVWA) は、非常に脆弱な PHP/MySQL Web アプリケーションです。その主な目的は、セキュリティ専門家が法的環境でスキルとツールをテストするのに役立ち、Web 開発者が Web アプリケーションを保護するプロセスをより深く理解できるようにし、教師/生徒が教室環境で Web アプリケーションを教え/学習できるようにすることです。安全。 DVWA の目標は、シンプルでわかりやすいインターフェイスを通じて、さまざまな難易度で最も一般的な Web 脆弱性のいくつかを実践することです。このソフトウェアは、

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

Eclipse を SAP NetWeaver アプリケーション サーバーと統合します。