Fessの管理画面で権限のないコンテンツにアクセスした際、これまではログが出力されずにリダイレクトされるだけだった。セキュリティ監査の観点から、アクセス拒否時にも監査ログを記録するようにした。
背景
Fessの管理画面では、ユーザーのロールに基づいてアクセス制御が行われている。権限のないページにアクセスするとUserRoleLoginExceptionが発生し、トップページへリダイレクトされる。しかし、この時点で監査ログが出力されていなかったため、不正アクセスの試行を検知・追跡できなかった。
変更内容
FessAdminActionでのアクセス拒否ログ出力
FessAdminAction.godHandPrologue()でUserRoleLoginExceptionをキャッチした際に、activityHelper.accessDenied()を呼び出してログを記録するようにした。
@Override
public ActionResponse godHandPrologue(final ActionRuntime runtime) {
try {
return superGodHandPrologue(runtime);
} catch (final UserRoleLoginException e) {
activityHelper.accessDenied(getUserBean(), runtime.getRequestPath());
return redirect(e.getActionClass());
}
}
テスタビリティのため、super.godHandPrologue()の呼び出しをsuperGodHandPrologue()メソッドに抽出している。
ActivityHelperにACCESS_DENIEDアクションを追加
ActivityHelperにaccessDenied()メソッドとACCESS_DENIED列挙値を追加した。ユーザー情報とリクエストパスをログに記録する。
public void accessDenied(final OptionalThing<FessUserBean> user, final String path) {
final Map<String, String> valueMap = new LinkedHashMap<>();
valueMap.put("action", Action.ACCESS_DENIED.name());
valueMap.put("user", user.map(FessUserBean::getUserId).orElse("-"));
valueMap.put("path", path);
log(valueMap);
}
ログ出力例
通常フォーマットの場合:
action:ACCESS_DENIED user:testuser path:/admin/user/
ECSフォーマットの場合:
{
"labels.action": "ACCESS_DENIED",
"labels.user": "testuser",
"labels.path": "/admin/user/"
}
ユーザーが未認証の場合はuserが-として記録される。
まとめ
この変更により、管理画面への不正アクセス試行を監査ログから検知できるようになった。誰が、どのパスにアクセスしようとして拒否されたかが記録されるため、セキュリティインシデントの調査に活用できる。