IDS03-J. ユーザ入力を無害化せずにログに保存しない
ログインジェクションの脆弱性は、ログエントリに無害化されていないユーザ入力が含まれる場合に発生する。悪意あるユーザは、偽のログデータをプログラムに入力し、それがシステムの動作であるかのようにシステム管理者を欺くことができる[OWASP 2008]。たとえば、攻撃者はキャリッジリターンとラインフィード(CRLF)を入力することで、ある正当なログエントリを2つのログエントリに分割してしまうかもしれない。ログに保存するすべての信頼できない入力を無害化し検証することで、ログインジェクション攻撃を防ぐことができる。
ユーザ入力を無害化せずに保存すると、信頼境界 (trust boundary) を越えてセンシティブなデータが漏えいしてしまうことも考えられる。たとえば、攻撃者がログファイルにスクリプトを保存させた場合、そのファイルがウェブブラウザで表示された際に管理者のクッキーのコピーが攻撃者に送信され、管理者としてアクセスされてしまうかもしれない。
違反コード
以下の違反コードは、認証されていないユーザからの信頼できないデータを、無害化せずログに保存する。
if (loginSuccessful) {
logger.severe("User login succeeded for: " + username);
} else {
logger.severe("User login failed for: " + username);
}
入力値が無害化されていないため、ログインジェクション攻撃が可能である。username
が david
であるときの通常のログメッセージは以下のようになる。
May 15, 2011 2:19:10 PM java.util.logging.LogManager$RootLogger log
SEVERE: User login failed for: guest
ログメッセージに使用されるusername
がdavid
ではなく以下のような複数行からなる文字列になると、
guest
May 15, 2011 2:25:52 PM java.util.logging.LogManager$RootLogger log
SEVERE: User login succeeded for: administrator
ログには以下のような不正なデータが含まれてしまうだろう。
May 15, 2011 2:19:10 PM java.util.logging.LogManager$RootLogger log
SEVERE: User login failed for: guest
May 15, 2011 2:25:52 PM java.util.logging.LogManager log
SEVERE: User login succeeded for: administrator
適合コード (ユーザの無害化)
以下の適合コードは、ログを保存する前にusername
を無害化し、インジェクション攻撃を防いでいる。
if (loginSuccessful) {
logger.severe("User login succeeded for: " + sanitizeUser(username));
} else {
logger.severe("User login failed for: " + sanitizeUser(username));
}
ユーザ名の無害化は、以下のように専用の方法で行われる。
public String sanitizeUser(String username) {
return Pattern.matches("[A-Za-z0-9_]+", username))
? username : "unauthorized user";
}
適合コード (ロガーの無害化)
以下の適合コードでは、入力値を自動で無害化するロガーを使っている。無害化用ロガーを使うと、開発者は無害化されていないログメッセージについて心配する必要がなくなる。
Logger sanLogger = new SanitizedTextLogger(logger);
if (loginSuccessful) {
sanLogger.severe("User login succeeded for: " + username);
} else {
sanLogger.severe("User login failed for: " + username);
}
無害化用ロガー(SanitizedTextLogger
)は、実際のロガー(Logger
)を委譲先として受け取る。ここでは、ロガーがログメッセージをファイルやネットワーク、コンソールに出力し、それぞれのログメッセージに字下げが含まれないものと想定する。無害化用ロガーは、最初以外のすべての行を2文字のスペースで字下げすることですべてのテキストを無害化する。悪意あるユーザはテキストをより多く字下げできるものの、本当のログ出力以外はすべて字下げされるため、偽のログエントリを作ることはできない。
class SanitizedTextLogger extends Logger {
Logger delegate;
public SanitizedTextLogger(Logger delegate) {
super(delegate.getName(), delegate.getResourceBundleName());
this.delegate = delegate;
}
public String sanitize(String msg) {
Pattern newline = Pattern.compile("\n");
Matcher matcher = newline.matcher(msg);
return matcher.replaceAll("\n ");
}
public void severe(String msg) {
delegate.severe(sanitize(msg));
}
// .. 他のLoggerのメソッドも同様にログメッセージを無害化する。
}
リスク評価
ユーザ入力を検証しないでログに保存すると、ログエントリが偽装されたり、センシティブなデータが漏えいしたり、法規制に違反してセンシティブなデータの保存を行ってしまう恐れがある。
ルール |
深刻度 |
可能性 |
修正コスト |
優先度 |
レベル |
---|---|---|---|---|---|
IDS03-J |
中 |
中 |
中 |
P8 |
L2 |
自動検出
ツール | バージョン | チェッカー | 説明 |
---|---|---|---|
The Checker Framework |
2.1.3 |
Tainting Checker | Trust and security errors (see Chapter 8) |
CodeSonar |
8.1p0
|
JAVA.IO.TAINT.LOG |
Tainted Log (Java) |
Fortify |
|
Log_Forging | Implemented |
Klocwork |
2024.3 |
SVLOG_FORGING | Implemented |
Parasoft Jtest |
2024.1
|
CERT.IDS03.TDLOG | Protect against log forging |
関連ガイドライン
ISO/IEC TR 24772:2013 |
Injection [RST] |
CWE-144, Improper neutralization of line delimiters |
|
MITRE CAPEC |
CAPEC-93, Log Injection-Tampering-Forging |
参考文献
[API 2006] |
Java Platform, Standard Edition 6 API Specification |
[OWASP 2008] |
|
[Seacord 2015] |
IDS03-J. Do not log unsanitized user input LiveLesson
|
翻訳元
これは以下のページを翻訳したものです。
IDS03-J. Do not log unsanitized user input (revision 127)