문제
로그를 LLM에 넣어 요약하는 것만으로는 판단에 쓸 수 없었다. 관제 요원에게 필요한 것은 다음 질문의 답이다.
- 이 IP는 어떤 자산인가?
- 그 자산에 아직 조치하지 않은 취약점이 있는가?
- 로그에 나온 지표가 알려진 악성 지표인가?
또 폐쇄망 환경이라 외부 LLM API를 쓸 수 없었다.
해결
LM Studio에서 gpt-oss-20b를 로컬로 구동하고, 그 앞에 자산 대장, 취약점 점검 결과, 위협 인텔리전스 DB를 붙였다. 로그가 들어오면 서버가 먼저 사실 정보를 계산하고, LLM에는 추론만 맡긴다.
로그 업로드 → IP·호스트 추출 → 자산 / 미조치 취약점 / 위협 지표 조회
→ 규칙 기반 상관분석 → 사실 정보를 프롬프트에 주입 → 로컬 LLM 스트리밍 응답 → 결과 저장
주요 기능
- 보안 로그 분석: 스트리밍 응답으로, 정해진 형식의 한국어 보고서를 만든다.
- 자산관리: 서버·네트워크·보안장비를 한 대장으로 관리한다. C/I/A 값을 넣으면 중요도 등급을 자동 계산한다.
- 서버 OS 취약점 점검: AIX, HP-UX, Linux, SunOS, Windows 지원. 점검 결과 파일을 올리면 DB에 반영된다.
- 네트워크·보안장비 점검: 장비 설정 파일을 올리면 LLM이 KISA 기준 항목별(N-01
N-38, S-01S-23)로 판정한다. 장비 종류는 자동으로 감지한다. - 위협 인텔리전스: CSV나 암호화 ZIP을 받아 저장하고 검색한다.
- 엑셀 보고서: 등급 수식이 들어간 점검 결과 양식으로 내보낸다.
설계 포인트
- LLM과 규칙의 역할 분리: 포트와 취약 항목 매칭처럼 확정할 수 있는 판단은 코드가 하고, LLM은 해석만 한다. 환각이 사실 판단에 끼어들 여지를 줄였다.
- 재현성: 장비 점검은
temperature=0, 시드 고정, 항목 단위 호출로 돌린다. 한 항목이 실패해도 나머지는 계속 진행된다. - 폐쇄망 배포: 오프라인 설치 패키지와 Python 런타임을 동봉했다. 재설치·데이터 이관 스크립트와 스키마 검증 SQL도 포함한다.
- 보안: 비밀번호는 PBKDF2-SHA256(20만 회)으로 저장하고 저장 비밀값은 Fernet으로 암호화한다. 경로 탈출을 차단하고 보안 헤더를 붙인다. systemd 샌드박싱(전용 계정,
ProtectSystem,NoNewPrivileges)을 적용했고, 자체 취약점 점검도 수행했다. - 의존성 최소화: 웹 프레임워크 없이 Python 표준
ThreadingHTTPServer와 빌드 도구 없는 Vanilla JS로 만들었다. 폐쇄망 반입 부담을 줄이기 위해서다.
스택
Python 3.12 · PostgreSQL 16 · LM Studio (gpt-oss-20b, OpenAI 호환 API) · paramiko · pywinrm · openpyxl · cryptography · Vanilla JS · nginx (TLS) · systemd