로컬 LLM이 모니터링 리포트의 수치를 조작한 사례와 그 대책 #
BASTION의 AI 모니터링 리포트에 “인증 실패 639건”이라고 적혀 있었다. 실제로는 0건이었다. 로컬 LLM을 통한 보안 모니터링에서 피할 수 없는 환각(hallucination) 문제를, 샘플링 검사와 다층 폴백으로 대응한 기록.
AI가 거짓말을 하다 #
BASTION은 15분마다 인프라 로그를 로컬 LLM으로 분석하여 Slack에 리포트를 전송합니다. 어느 날의 리포트에 이렇게 적혀 있었습니다.
Windows AD에서는 인증 실패나 계정 잠금이 다수 발생하고 있지만, 이는 Kerberos 컴퓨터 계정이나 LDAP 연동에 의한 것으로 정상입니다. VPN에서는 OpenVPN에서의 인증 실패가 239건 발생하고 있습니다.
639건의 인증 실패. 239건의 VPN 인증 오류. 숫자만 보면 “이상”이라고 판단할 만한 값입니다.
그러나 실제 로그를 직접 집계해보니 인증 실패는 81건, VPN 인증 오류는 102건이었습니다.더 조사를 진행하자 LLM에 전달했던 입력 데이터에는 “인증 실패: 0회”, “VPN 오류: 오류 없음”이라고 적혀 있었습니다. LLM이 입력의 “0”을 “639”로 바꿔버린 것입니다.
샘플링 검사 방법 #
리포트의 수치가 정확한지 검증하기 위해, 실제 로그를 직접 집계하여 리포트 값과 대조하는 샘플링 검사를 실시했습니다.
검사 절차: 1. 리포트에 기재된 수치를 항목별로 추출 2. AI-SLOG 서버상에서 실제 로그를 직접 grep/count하여 실측값을 취득 3. 리포트 값과 실측값의 괴리율을 계산 4. ±10% 이내를 "합격", 그 이상을 "조사 필요"로 판정
8개 항목을 검사한 결과:
| 항목 | 리포트 값 | 실측값 | 판정 |
|---|---|---|---|
| FW 차단(특정 IP) | 477건 | 489건 | |
| 인증 실패 | 639건 | 81건 | |
| 계정 잠금 | 669건 | 66건 | |
| 인증 오류 | 239건 | 102건 | |
| 클라우드 앱 전체 항목 | 해당 없음 | 0건 |
8개 항목 중 4개 항목에서 환각(수치 조작)이 검출되었습니다.
2가지 원인이 병존하고 있었다 #
원인을 구분하기 위해 “LLM에 전달하기 전의 입력 데이터”를 확인했습니다.
원인A는 스크립트의 버그(결정론적으로 수정 가능). 원인B는 LLM의 본질적인 한계입니다.
대책: 3층의 폴백 #
LLM의 환각은 “방지하는” 것이 아니라 “감지해서 교체하는” 접근 방식을 취했습니다.
제1층: 입력 데이터의 정확성을 담보한다 #
스크립트의 버그를 수정하여, 전체 기간 누계가 아닌 최근 60분의 데이터만 LLM에 전달하도록 했습니다. 입력이 정확하면 LLM이 올바른 출력을 생성할 확률이 높아집니다.
제2층: 프롬프트로 수치의 조작을 금지한다 #
LLM에 대한 프롬프트에 다음 규칙을 추가했습니다.
【숫자의 절대 규칙】 - 입력 데이터에 기재되지 않은 숫자는 출력 어디에도 작성해서는 안 됨 - 입력에 "0건"으로 기재된 항목은 출력에서도 0건으로 할 것 - evidence 섹션의 숫자는 입력 데이터로부터 직접 전기만 허가 - 추측·보완·개산 금지
제3층: 출력의 숫자를 입력과 대조하여 검출하기 #
LLM의 출력이 생성된 후, 입력 데이터와 대조하여 모순을 검출하는 폴백 메커니즘을 구현했습니다. 입력에 “0회”로 작성된 항목이 출력에서 비제로가 되어 있으면, 자동으로 안전한 문구로 교체합니다.
입력: "인증 실패: 0회" LLM 출력: "인증 실패가 639건 발생" → 대조: 입력은 0회인데 출력이 639 → 불일치 검출 → 교체: 안전한 문구로 자동 치환
수정 결과 #
3층의 폴백을 구현한 후, 동일한 조건으로 재검증했습니다.
| 항목 | 수정 전 | 수정 후 |
|---|---|---|
| 인증 실패(입력: 0건) | ||
| 잠금(입력: 0건) | ||
| 인증 오류(입력: 없음) | ||
| 환각 검출 폴백 | 신조어·기호만 검출 | 숫자 조작도 검출 가능 |
LLM이 프롬프트 규칙을 따라 0값을 유지하고, 환각 검출 폴백의 발화도 없음. 입력의 정확성 담보(제1층) + 프롬프트 강화(제2층)의 조합으로, 제3층의 검출 폴백에 의존하기 전에 문제가 해소되었습니다.
환각은 근절할 수 없다 #
이번 대책으로 숫자 조작은 억제할 수 있었지만, 14B 파라미터의 로컬 모델에서 환각을 100% 방지할 수는 없습니다. 중요한 것은 “LLM을 신뢰하는” 것이 아니라 “LLM을 제약하는” 설계입니다. 입력의 정확성 담보→프롬프트에 의한 제약→출력의 사후 검증이라는 3층의 폴백으로, LLM의 판단 실수가 시스템 전체에 파급되지 않도록 하고 있습니다.
정기적인 샘플링 검사가 필요 #
이번 환각은 샘플링 검사에서 처음 발각되었습니다. LLM의 출력은 문법적으로 올바르고 문맥도 자연스러워서 읽기만 해서는 거짓임을 알아차릴 수 없습니다. 정기적으로 실제 로그와 리포트를 대조하는 샘플링 검사를 운영에 도입하는 것이 AI 모니터링 시스템의 품질 보증으로서 불가결합니다.
에이전트 워크플로의 설계가 전부를 결정한다 #
BASTION에서는 LLM의 역할을 “로그 패턴의 분류 판단”으로 한정하고, 방화벽 조작·수치 집계·차단 실행은 모두 셸 스크립트와 Python으로 수행하고 있습니다. LLM이 수치를 조작하더라도, 실제 차단 판단은 스크립트 측의 임계값으로 결정되기 때문에, 업무 영향은 알림 문구가 부정확해지는 것에 그칩니다. 만약 LLM에 직접 방화벽 규칙을 작성하게 했다면, 가상의 공격에 대해 실재하는 IP를 차단했을 가능성이 있습니다.
정리 #
로컬 LLM에 의한 보안 모니터링에서, LLM이 입력 “0건”을 “639건”으로 조작하는 환각(hallucination)이 발생했습니다. 원인은 스크립트의 버그(전체 기간 누적의 혼입)와 LLM의 수치 조작, 두 가지가 병존하고 있었습니다.
대책으로, 입력 데이터의 정확성 확보→프롬프트에 의한 수치 제약→출력의 사후 대조 검지의 3층 폴백을 구현했습니다. 수정 후 재검증에서는 LLM이 정확하게 0값을 유지했으며, 환각 검출 폴백의 발동도 없어, 대책의 유효성을 확인했습니다.
AI 모니터링은 만능이 아닙니다. AI의 출력을 신뢰하는 것이 아니라, 제약하고, 검증하고, 폴백을 준비하는 것. 이 설계 사상이 로컬 LLM으로 보안 모니터링을 실용화하기 위한 핵심입니다.
BASTION은 폐쇄 환경에서 AI 보안 모니터링을 실현하는 서비스입니다.