보안 점검 모니터(secwatch) 가이드
조직(csn)으로 라우팅된 SQL 인젝션 2차 판정 결과(통지/검토/기록)를 화면에서 보고, 동일한 내용을 조직 SK로 읽는 읽기 전용 API로 조회해 AI가 이상징후를 정기 점검할 수 있게 합니다.
📋 개요
GIIP의 secwatch(Jev 기반 SQL 인젝션 2차 판정)는 수집기(lssn)가 보낸 의심 사건을 게이트웨이가 1차 결정론 룰 + 2차 AI 판정으로 분류해 tKVSSecurityCheck에 적재하고, 각 판정을 라우팅 대상으로 나눕니다.
라우팅(kscRoutedTo) | 화면 표기 | 의미 |
|---|---|---|
alert | 통지 | 유출/쓰기 시도 의심 또는 고신뢰 공격 — 즉시 통지 대상 |
review | 검토 | 공격 가능성은 있으나 자동 통지 임계값 미만 — 사람 검토 대상 |
log | 기록 | 정상/노이즈로 판정 — 통지하지 않고 건수만 기록 |
화면(/ko/admin/secwatch-monitor)은 이 결과를 기간(최근 1시간/6시간/24시간/7일)과 라우팅 대상(전체/통지/검토/기록)으로 필터해 보여줍니다. 이 화면은 로그인 유저에게 공개되며, 자기 조직(csn)으로 라우팅된 결과만 보입니다(서버 SP가 보장).
🔎 화면 읽는 법
화면은 두 영역으로 구성됩니다.
- 수집 커버리지 패널 — "무엇을 검사하고 있고, 어디만 이상이었나". 소스별로 검사 건수(scanned)·탐지 건수(flagged)·마지막 검사 시각을 보여주며, flagged가 0이면 🟢 정상, 1건 이상이면 🔴 이상입니다. 탐지가 없어도 "검사는 돌고 있다"를 확인할 수 있습니다.
- 판정 결과 카드 — 각 판정 1건이 카드 1장. 표시 항목:
| 화면 항목 | 필드 | 의미 |
|---|---|---|
| 시각 | kscRegdt | 판정 적재 시각 |
| 라우팅 배지 | kscRoutedTo | 통지(alert)/검토(review)/기록(log) |
| 이벤트 유형 | kscFactor | 사건 종류(secevt_*) |
| 주입 확률 | kscIsInjection | SQL 인젝션/공격 준비 확률(0~1, 화면은 %) |
| 심각도 | kscSeverity | 0 노이즈 · 1 정찰 · 2 열거·읽기 · 3 인증정보·개인정보 읽기 · 4 쓰기·권한 조작 |
| 공격 유형 | kscAttackType | 분류된 공격 종별 |
| 패턴 | kscPatternNo | 같은 방법(csn 내 패턴 일련번호) — 반복 공격 추적용 |
| 공격자 IP | kscActorIp | 공격 출처 IP(추적·차단용) |
| 플래그 | kscIsInjection/kscDataExtracted/kscWriteAttempt | 각 확률 0.7 이상이면 주입/데이터유출/쓰기시도 배지 |
| 신뢰도 | kscConfidence | 분류/심각도 판정 신뢰도(0~1) |
| 엔진 | kscEngine | 판정 엔진 |
| 수집기 | kscKey | 결과를 올린 수집기(lssn) |
| 라우팅 이유 | kscWhy | 게이트웨이가 남긴 라우팅 사유 |
주입 확률·데이터유출·쓰기시도는 0~1 확률값이며, 화면은 0.7 이상을 "성립"으로 보고 배지를 띄웁니다.
🔌 API 참조 (읽기 전용 — AI/외부 클라이언트용)
화면과 같은 내용을 조직 식별값(csn)과 그 조직의 비밀 키(SK)로 읽는 읽기 전용 API입니다. 범용 디스패처 giipApiSk4를 통해 두 개의 SP를 호출합니다. 데이터 적재·판정·차단 기능은 포함하지 않습니다.
공통 호출 규약
| 항목 | 값 |
|---|---|
| 메서드 | POST (또는 GET) |
| URL | https://giipfaw.azurewebsites.net/api/giipApiSk4 |
| 본문(form-urlencoded) 또는 쿼리 | text=<명령>, token=<SK>, jsondata=<JSON> |
text의 첫 토큰이 명령 이름이고, 이후 토큰은jsondata의 키와 1:1로 매칭되는 필드명입니다. 토큰을 적지 않으면 그 파라미터는 SP 기본값을 씁니다(아래 예시가 가장 안전한 형태).token에는 조직의 SK를 넣습니다. SK는 그 SK가 속한 조직(csn)의 결과만 반환합니다(csn을 따로 넘기지 않아도 자동으로 그 조직으로 스코프).- 응답은 항상 HTTP 200이며 본문은
{ "data": [ ... ], "debug": { ... } }형식입니다. 인증/파라미터 오류도 HTTP 200으로 오고,data[0]에{ "RstVal": 401|403, "RstMsg": "..." }가 담깁니다 — AI는data[0].RstVal을 먼저 확인해야 합니다.
(1) 판정 결과 조회 — KVSSecurityCheckWindow
| 필드(jsondata) | 필수 | 의미 |
|---|---|---|
minutes | 선택 | 조회 시간창(분). 기본 60, 최대 10080(7일). 1시간=60 / 6시간=360 / 24시간=1440 / 7일=10080 |
routedTo | 선택 | alert/review/log 중 하나. 생략하면 전체 |
요청 예시 (최근 24시간 전체 — 가장 안전한 기본형)
export GIIP_API_BASE_URL="https://giipfaw.azurewebsites.net"
export GIIP_SK="런타임에만_설정"
curl --fail-with-body -X POST "${GIIP_API_BASE_URL}/api/giipApiSk4" \
--data-urlencode "text=KVSSecurityCheckWindow minutes" \
--data-urlencode "token=${GIIP_SK}" \
--data-urlencode 'jsondata={"minutes":1440}'
요청 예시 (최근 24시간 중 통지 대상만)
curl --fail-with-body -X POST "${GIIP_API_BASE_URL}/api/giipApiSk4" \
--data-urlencode "text=KVSSecurityCheckWindow minutes routedTo" \
--data-urlencode "token=${GIIP_SK}" \
--data-urlencode 'jsondata={"minutes":1440,"routedTo":"alert"}'
성공 응답 (판정 1건당 data[] 한 행)
{
"data": [
{
"kscsn": 0, "kscKey": "12345", "kscFactor": "secevt_...",
"kscIsInjection": 0.97, "kscAttackType": "...", "kscSeverity": 4,
"kscDataExtracted": 0.10, "kscWriteAttempt": 0.95, "kscConfidence": 0.9,
"kscEngine": "...", "kscRoutedTo": "alert", "kscActorIp": "...",
"kscPatternNo": 1, "kscStatus": "...", "kscRegdt": "...", "kscWhy": "..."
}
],
"debug": { }
}
- 각 행은 화면 카드의 항목과 그대로 대응합니다(위 "화면 읽는 법" 표 참조).
- SK/AK/키/DB 연결정보는 어떤 응답에도 포함되지 않습니다.
(2) 수집 커버리지 조회 — KVSSecurityCoverageWindow
"검사했지만 안 보낸(정상 포함)" 소스별 집계입니다. 화면 상단 커버리지 패널과 같은 내용입니다.
| 필드(jsondata) | 필수 | 의미 |
|---|---|---|
minutes | 선택 | 조회 시간창(분). 기본 1440, 최대 10080 |
요청 예시
curl --fail-with-body -X POST "${GIIP_API_BASE_URL}/api/giipApiSk4" \
--data-urlencode "text=KVSSecurityCoverageWindow minutes" \
--data-urlencode "token=${GIIP_SK}" \
--data-urlencode 'jsondata={"minutes":1440}'
성공 응답
{
"data": [
{ "ksvSource": "...", "ksvSystem": "...", "scanned": 1200, "flagged": 0, "lastTs": "...", "status": "normal" }
],
"debug": { }
}
status는flagged가 0이면normal, 1건 이상이면anomaly입니다.
오류 응답(두 API 공통)
data[0]에 담겨 옵니다(HTTP 상태코드는 항상 200).
| 조건 | RstVal | RstMsg |
|---|---|---|
| SK 누락 또는 유효하지 않음 | 401 | Invalid sk |
| 요청 csn이 SK의 csn과 다름(교차 csn 차단) | 403 | csn mismatch (sk 의 csn 과 다름) |
⚠️ 보안: SK를 URL, 이슈, 저장소, 프롬프트 본문, 로그에 넣지 마세요. 실행 환경변수 또는 비밀 저장소에서만 전달합니다.
🤖 AI 호출 고정 절차 (이상징후 판정)
- 조직별 조회: 점검할 각 조직의 SK로
KVSSecurityCheckWindow를 호출한다. 시간창은 점검 주기에 맞춘다(예: 매시 점검이면minutes=60, 하루 1회면minutes=1440). - 인증 확인: 응답
data[0].RstVal이 401/403이면 그 조직은 SK가 잘못됐거나 접근 불가로 보고하고 다음 조직으로 넘어간다. - 이상징후 판정:
data[]에서kscRoutedTo가alert(통지) 또는review(검토)인 행이 하나라도 있으면 이상징후로 보고한다.log(기록)만 있으면 정상 기록으로 본다. - 우선순위화: 보고 시
kscSeverity(심각도 0~4)와kscIsInjection(주입 확률)이 높은 순으로 정렬하고,kscActorIp·kscPatternNo로 같은 공격자/같은 방법의 반복 여부를 함께 적는다. - 커버리지 교차 확인:
KVSSecurityCoverageWindow로 각 소스가 실제로 검사되고 있는지 확인한다. 어떤 소스의status가anomaly면 그 소스를 우선 점검하고, 기대한 소스가 커버리지에 아예 없으면 "수집 누락 가능"으로 함께 보고한다. - 전 조직 스윕: 계정으로 접근 가능한 각 조직(csn)에 대해 1~5를 반복한다. SK는 조직 단위이므로, 여러 조직을 점검하려면 각 조직의 SK로 각각 호출한다.
🛠 문제 해결
| 증상 | 원인 | 해결 |
|---|---|---|
| 화면에 "접근 거부" | 로그인했지만 그 조직(csn) 컨텍스트/소속이 없음 | 해당 조직 소속 계정으로 로그인. API로는 그 조직 SK를 쓰면 화면 없이도 조회 가능 |
API data[0].RstVal=401 | SK 누락 또는 무효 | token에 올바른 조직 SK 전달(환경변수) |
API data[0].RstVal=403 | 요청 csn이 SK의 csn과 다름 | csn을 따로 넘기지 말고 그 조직 SK만 사용(SK가 csn을 결정) |
data가 빈 배열 | 그 시간창에 해당 조직 판정 결과가 없음 | 정상(이상징후 없음)으로 본다. minutes를 늘려 재조회 가능 |
| 커버리지가 비어 있음 | 그 시간창에 수집 커버리지 집계가 없음 | 수집기가 도는지 확인하고 minutes를 늘려 재조회 |
API 참조
이 가이드는 API 상세(엔드포인트·파라미터·응답·오류)를 위 "🔌 API 참조" 절에 자체 완결적으로 포함합니다. 별도 API 가이드는 없습니다.
버전: 1.0
최종 업데이트: 2026-10-30
변경 이력: giip 4314 — secwatch 보안 점검 모니터 유저 가이드 신규 작성. 판정 결과(KVSSecurityCheckWindow)·수집 커버리지(KVSSecurityCoverageWindow) SK 읽기 전용 API 문서화, AI 이상징후 판정 고정 절차 포함.
소스 파일: giipv3/public/help/secwatch.ko.md