JVMログの偽造
1. 概要
この簡単な記事では、JVMの世界で最も一般的なセキュリティ問題の1つであるログ偽造について説明します。 また、このセキュリティ上の懸念から私たちを保護できるテクニックの例も示します。
2. ログフォージングとは
OWASPによると、ログの偽造は最も一般的な攻撃手法の1つです。
ログフォージングの脆弱性は、信頼できないソースからアプリケーションにデータが入力されるか、外部エンティティによってデータがアプリケーション/システムログファイルに書き込まれるときに発生します。
OWASP guidelinesによると、ログの偽造または挿入は、未検証のユーザー入力をログファイルに書き込む手法であり、攻撃者がログエントリを偽造したり、悪意のあるコンテンツをログに挿入したりできるようにします。
簡単に言えば、攻撃者はログ偽造によって、アプリケーションのセキュリティ抜け穴を探ることにより、記録内容を追加/変更しようとします。
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.example.logforging.LogForgingDemo - Amount credited = 300
ここで、攻撃者が入力を“ web – 2017-04-12 17:47:08,957 [main] INFO Amount reversed successfully”,として提供すると、ログは次のようになります。
web - 2017-04-12 17:52:14,124 [main] INFO com.example.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. データベースロギング
別のオプションは、データをデータベースに記録することです。 ‘ 'または改行はこのコンテキストには何の意味もないため、これは他のアプローチよりも安全です。 ただし、ユーザーデータのログ記録には膨大な数のデータベース接続が使用されるため、これによりパフォーマンス上の別の懸念が生じます。
さらに、この手法は別のセキュリティの脆弱性、つまりSQL Injectionをもたらします。 これに取り組むために、多くの余分なコード行を書くことになります。
4.3. ESAPI
ESAPIを使用することは、このコンテキストに従って最も共有され、推奨される手法です。 ここでは、ログに書き込む前に、すべてのユーザーデータがエンコードされます。 ESAPIは、OWASPから入手できるオープンソースAPIです。
org.owasp.esapi
esapi
2.1.0.1
Central Maven Repositoryで利用できます。
ESAPIのEncoderインターフェースを使用してデータをエンコードできます。
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.example.logforging.
LogForgingDemo - Amount credited = 300
__web - 2017-04-12 17:47:08,957 [main] INFO Amount reversed successfully
ここでは、破損した文字列フラグメントがエンコードされており、簡単に識別できます。
注意すべき重要な点は、ESAPIを使用するには、クラスパスにESAPI.propertiesファイルを含める必要があるということです。そうしないと、ESAPIAPIが実行時に例外をスローします。 利用可能なhereです。
5. 結論
この簡単なチュートリアルでは、ログの偽造とこのセキュリティ上の懸念を克服するためのテクニックについて学びました。
いつものように、完全なソースコードはover on GitHubで入手できます。