1. 概要

この簡単な記事では、JVMの世界で最も一般的なセキュリティ問題の1つであるログの偽造について説明します。 また、このセキュリティ上の懸念から私たちを守ることができるテクニックの例も示します。

2. ログ鍛造とは何ですか?

OWASP によると、ログの偽造は最も一般的な攻撃手法の1つです。

ログ偽造の脆弱性は、データが信頼できないソースからアプリケーションに入力された場合、またはデータが外部エンティティによってアプリケーション/システムログファイルに書き込まれた場合に発生します。

OWASPガイドラインによると、ログの偽造または挿入は、攻撃者がログエントリを偽造したり、悪意のあるコンテンツをログに挿入したりできるように、未検証のユーザー入力をログファイルに書き込む手法です。

簡単に言うと、攻撃者はログを偽造することで、アプリケーションのセキュリティの抜け穴を調べてレコードコンテンツを追加/変更しようとします。

3. 例

ユーザーがWebから支払い要求を送信する例を考えてみましょう。 アプリケーションレベルから、このリクエストが処理されると、1つのエントリが次の金額でログに記録されます。

private final Logger logger 
  = LoggerFactory.getLogger(LogForgingDemo.class);

public void addLog( String amount ) {
    logger.info( "Amount credited = {}" , amount );
}

public static void main( String[] args ) {
    LogForgingDemo demo = new LogForgingDemo();
    demo.addLog( "300" );
}

コンソールを見ると、次のようなものが表示されます。

web - 2017-04-12 17:45:29,978 [main] 
  INFO  com.baeldung.logforging.LogForgingDemo - Amount credited = 300

ここで、攻撃者が「\ n \ nweb– 2017-04-12 17:47:08,957 [main] INFO金額が正常に取り消されました」、として入力を提供すると、ログは次のようになります。

web - 2017-04-12 17:52:14,124 [main] INFO  com.baeldung.logforging.
  LogForgingDemo - Amount credited = 300

web - 2017-04-12 17:47:08,957 [main] INFO Amount reversed successfully

意図的に、攻撃者はアプリケーションログに偽造されたエントリを作成することができました。これにより、ログの値が破損し、将来の監査タイプのアクティビティが混乱します。 これが丸太鍛造の本質です。

4. 防止

最も明白な解決策は、ユーザー入力をログファイルに書き込まないことです。

ただし、ユーザーが指定したデータは将来のアプリケーションアクティビティのデバッグまたは監査に必要であるため、すべての状況でそれが可能であるとは限りません。

この種のシナリオに取り組むには、他の方法を使用する必要があります。

4.1. 検証を導入する

最も簡単な解決策の1つは、ログに記録する前に常に入力を検証することです。 このアプローチの問題の1つは、実行時に大量のデータを検証する必要があり、システム全体のパフォーマンスに影響を与えることです。

また、検証が失敗した場合、データはログに記録されず、永久に失われます。これは、多くの場合、許容できるシナリオではありません。

4.2. データベースロギング

もう1つのオプションは、データをデータベースにログインすることです。 ‘\ n’または改行はこのコンテキストには何の意味もないため、これは他のアプローチよりも安全です。 ただし、ユーザーデータのログ記録に大量のデータベース接続が使用されるため、これによりパフォーマンス上の問題が発生します。

さらに、この手法は別のセキュリティの脆弱性、つまりSQLインジェクションをもたらします。 これに取り組むために、私たちは多くの余分なコード行を書くことになるかもしれません。

4.3. ESAPI

ESAPI の使用は、このコンテキストで最も共有され、推奨される手法です。 ここでは、すべてのユーザーデータがログに書き込まれる前にエンコードされます。 ESAPI は、OWASPから入手できるオープンソースAPIです。

<dependency>
    <groupId>org.owasp.esapi</groupId>
    <artifactId>esapi</artifactId>
    <version>2.5.0.0</version>
</dependency>

CentralMavenリポジトリで入手できます。

ESAPIエンコーダーインターフェースを使用してデータをエンコードできます。

public String encode(String message) {
    message = message.replace( '\n' ,  '_' ).replace( '\r' , '_' )
      .replace( '\t' , '_' );
    message = ESAPI.encoder().encodeForHTML( message );
    return message;
}

ここでは、すべてのキャリッジリターンとラインフィードをアンダースコアに置き換え、変更されたメッセージをエンコードする1つのラッパーメソッドを作成しました。

前の例では、このラッパー関数を使用してメッセージをエンコードすると、ログは次のようになります。

web - 2017-04-12 18:15:58,528 [main] INFO  com.baeldung.logforging.
  LogForgingDemo - Amount credited = 300
__web - 2017-04-12 17:47:08,957 [main] INFO Amount reversed successfully

ここでは、破損した文字列フラグメントがエンコードされており、簡単に識別できます。

注意すべき重要な点は、 ESAPI を使用するには、クラスパスに ESAPI.properties ファイルを含める必要があることです。そうしないと、 ESAPIAPIが実行時に例外をスローします。 こちらでご利用いただけます。

5. 結論

このクイックチュートリアルでは、ログの偽造と、このセキュリティ上の懸念を克服するための手法について学びました。

いつものように、完全なソースコードはGitHubで入手できます。