Skip to content

khmandarrin/woori-fisa-backend-audit-log-integrity

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

45 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

감사 로그 변조 방지 (Audit Log Integrity)


개요

금융 시스템에서 감사 로그(Audit Log)는 보안 사고 추적 및 규정 준수의 핵심 요소입니다. 이 프로젝트는 는 금융 거래, 시스템 접근 등 민감한 작업의 로그가 생성된 시점부터 보관되는 동안의 위조, 변조, 삭제, 혹은 순서 변경을 탐지하는 Java 라이브러리입니다.

탐지 가능한 위협

  • 내용 위변조: 로그 메시지의 단 1바이트라도 변경되면 탐지
  • 로그 삭제/삽입: 중간 로그가 사라지거나 끼어들면 체인 붕괴
  • 순서 변경: 로그의 시간적 순서가 뒤바뀌면 탐지

System Architecture

  1. Core (Appender): Logback 환경에서 로그 이벤트를 가로채 해시를 생성하고 기록합니다.
  2. Util (Formatter & Hasher): 데이터 포맷팅과 암호화 연산을 수행합니다.
  3. Verifier: 저장된 로그 파일을 전수 조사하여 무결성을 검증합니다.

Getting Started

1. 설정

  1. 빌드 후 라이브러리를 pom.xml에 추가합니다.
<dependency>
    <groupId>com.service.woori</groupId>
    <artifactId>audit-log</artifactId>
    <version>1.0.1</version>
</dependency>
  1. src/main/resources/audit.properties 파일에 해시 생성에 사용할 비밀키를 설정합니다.
audit.secret.key=top-secret
  1. Logback 설정 파일(logback.xml)에 IntegrityAuditAppender를 등록하고 사용할 Formatter를 주입합니다.
 <configuration>
    <appender name="AUDIT" class="core.IntegrityAuditAppender">
    
    	<!-- 로그 파일 이름, 경로 설정 -->
        <logFileName>audit.log</logFileName>
        
        <!-- 사용자 커스텀 formatter 설정 (비어있으면 default)-->
        <formatterClass></formatterClass>
        
        </appender>
    <root level="INFO">
        <appender-ref ref="AUDIT" />
    </root>
</configuration>

2. 로그 기록

로그를 남기면, IntegrityAuditAppender가 자동으로 해시 체인을 생성하여 기록합니다.

// MDC 설정
MDC.put("userId", "admin001");
MDC.put("clientIp", "192.168.1.100");
        
// 로그인
logger.info("관리자 로그인");

// 조회
logger.info("계좌조회: 계좌번호=110-123-456");

// 이체
logger.info("계좌이체: 출금=110-123-456, 입금=220-456-789, 금액=1,000,000원");

// 로그아웃
logger.info("관리자 로그아웃");
# audit.log
# 접속시각 | userId | clientIP | 메시지(변경/조회 내용) | 현재 해쉬값 | 이전 해쉬값

2026-02-04 15:22:40 | admin001 | 192.168.1.100 | 관리자 로그인 | fa7TqwM9bS... | INIT_SEED_0000
2026-02-04 15:22:40 | admin001 | 192.168.1.100 | 계좌조회: 계좌번호=110-123-456 | 4QT+QxDJe8... | fa7TqwM9bS...
2026-02-04 15:22:40 | admin001 | 192.168.1.100 | 계좌이체: 출금=110-123-456, 입금=220-456-789, 금액=1,000,000 | fTtpJ/p/K1... | 4QT+QxDJe8...
2026-02-04 15:22:40 | admin001 | 192.168.1.100 | 관리자 로그아웃 | LOJlM23cmX... | fTtpJ/p/K1...

3. 무결성 검증

LogVerifier를 실행하여 저장된 로그 파일의 무결성을 검사합니다.

Path auditLogPath = Paths.get("audit.log");

LogVerifier verifier = new LogVerifier(); // default formatter 사용
VerifyResult result = verifier.verify(auditLogPath);

System.out.println(result);
// 검증 성공 시
OK (verifiedLines=4)

// 위변조 감지 시
FAIL (verifiedLines=2, line=3, reason=currentHash 불일치(내용 수정/위조 의심), expected=expectedCurrentHash=vf9isrcipddZvQOe9uNB12XJOjVlFNn7DR291pkAa/g=, actual=actualCurrentHash=fTtpJ/p/K10ahFbpDJjB5RcffKJGsDu/+VQ92EVmCy0=, raw=2026-02-04 15:22:40 | admin001 | 192.168.1.100 | 계좌이체: 출금=110-123-456, 입금=220-456-7891, 금액=11,000,000 | fTtpJ/p/K10ahFbpDJjB5RcffKJGsDu/+VQ92EVmCy0= | 4QT+QxDJe87WPIrR1J3ugvCeacV84c9ndf5zATxdn7M=)
---- 상세 ----
line    : 3
reason  : currentHash 불일치(내용 수정/위조 의심)
expected: expectedCurrentHash=vf9isrcipddZvQOe9uNB12XJOjVlFNn7DR291pkAa/g=
actual  : actualCurrentHash=fTtpJ/p/K10ahFbpDJjB5RcffKJGsDu/+VQ92EVmCy0=
rawLine : 2026-02-04 15:22:40 | admin001 | 192.168.1.100 | 계좌이체: 출금=110-123-456, 입금=220-456-7891, 금액=11,000,000 | fTtpJ/p/K10ahFbpDJjB5RcffKJGsDu/+VQ92EVmCy0= | 4QT+QxDJe87WPIrR1J3ugvCeacV84c9ndf5zATxdn7M=

핵심 원리

해시 체인

각 로그 엔트리가 이전 로그의 해시값을 포함하여 거대한 사슬을 형성합니다.

graph LR
    subgraph Log1 [Log 1 생성]
        Seed[Init Seed]
        Msg1[Message 1]
        Key1[Secret Key]
        Calc1((HMAC))
        Hash1[Hash 1]
        
        Seed & Msg1 & Key1 --> Calc1 --> Hash1
    end

    subgraph Log2 [Log 2 생성]
        Msg2[Message 2]
        Key2[Secret Key]
        Calc2((HMAC))
        Hash2[Hash 2]

        Hash1 -.->|PrevHash로 주입| Calc2
        Msg2 & Key2 --> Calc2 --> Hash2
    end

    subgraph Log3 [Log 3 ...]
        Calc3((HMAC))
        Hash2 -.->|PrevHash로 주입| Calc3
    end
Loading

해시 생성 공식: CurrentHash = HMAC(Message + PreviousHash, SecretKey)

중간에 로그가 하나라도 변경되면, 그 이후의 모든 해시 체인이 붕괴되어 즉각적인 탐지가 가능합니다.


검증 메커니즘

  1. HMAC 기반 단일 로그 무결성 (Integrity)
  • 로그 메시지와 이전 해시를 결합하여 실시간으로 HMAC을 계산합니다.
  • 저장된 currentHash와 계산값이 다를 경우, 해당 로그 내용이 변조된 것으로 판단합니다.
  1. 해시 체인 연결성 검증 (Chain Continuity)
  • 현재 로그의 previousHash가 직전 로그의 currentHash와 일치하는지 확인합니다.
  • 체인 단절 시 로그의 순서 변경, 중간 삭제, 임의 삽입 공격을 탐지합니다.
  1. 파일 끝 삭제 탐지 (Tail Truncation)
  • 별도의 관리 파일(audit.head)에 기록된 최신 해시와 실제 로그 파일의 마지막 해시를 비교합니다.
  • 두 값이 다를 경우 최신 로그 삭제 및 롤백 시도가 있었음을 의미합니다.
  1. 연쇄 오류 식별 및 추적 (Root Cause Analysis)
  • 무결성이 한 번 깨지면 이후의 모든 체인은 자동으로 불일치하게 됩니다.
  • 최초 원인(cascade: false)과 파생된 오류(cascade: true)를 구분하여 실제 변조 지점을 정확히 파악합니다.

Testing

Test Code

JUnit과 Mockito를 사용하여 테스트 코드를 작성하였습니다.

  • LogVerifierExceptionTest: 로그 처리 중 예외(Exception)가 발생하는 케이스들을 검증. 로그 포맷 오류나 HMAC 계산 실패 등 예외 상황에서의 Issue 생성을 테스트합니다.
  • LogVerifierInputValidationTest: 파일 시스템 상태나 입력값 자체의 유효성을 검증합니다.
  • LogVerifierIntegrityTest: 로그 변조, 삭제, 순서 변경 등 보안 위협 상황을 탐지하는 로직을 테스트합니다.
  • LogVerifierSuccessTest: 로그 변조가 없는 정상 상태에서 검증 결과가 성공으로 처리되는 경우(Happy path)를 테스트합니다.

Test Coverage Report

jacoco를 통해 생성한 테스트 리포트는 다음과 같습니다.

Image Image Image Image Image

About

감사 로그(audit.log)가 변조되지 않았는지 파악할 수 있는 보안 메커니즘 프로젝트입니다.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages