Microsoft Sentinel에서 인시던트 작업의 변경 내용 감사 및 추적

인시던트 작업을 통해 모든 SOC 담당자의 인시던트를 포괄적이고 균일하게 처리할 수 있습니다. 작업 목록은 일반적으로 선임 분석가 또는 SOC 관리자의 결정에 따라 정의되며 자동화 규칙 또는 플레이북을 사용하여 실제로 적용됩니다.

분석가는 인시던트 세부 정보 페이지에서 특정 인시던트에 대해 수행해야 하는 작업 목록을 보고 완료된 것으로 표시할 수 있습니다. 분석가는 인시던트 내에서 즉각적으로 직접 작업을 만들 수도 있습니다.

이 문서에서는 SOC 관리자로서 Microsoft Sentinel 인시던트 작업의 기록을 감사하고 수명 주기 동안 변경한 내용을 추적하여 작업 할당의 효율성과 SOC의 효율성 및 적절한 기능에 대한 기여도를 측정하는 방법을 설명합니다.

SecurityIncident 테이블의 작업 배열 구조

SecurityIncident 테이블은 감사 테이블로, 인시던트 자체가 아니라 인시던트의 수명 기록(생성 및 변경 내용)을 저장합니다. 인시던트가 생성되거나 인시던트가 변경될 때마다 현재 인시던트 상태를 보여주는 레코드가 이 테이블에 생성됩니다.

이 테이블의 스키마에 작업 세부 정보를 추가하면 작업을 보다 심층적으로 감사할 수 있습니다.

작업 필드에 추가된 자세한 정보는 다음 구조를 갖는 키-값 쌍으로 구성됩니다.

값 설명
createdBy 작업을 만든 ID:
- email: ID의 이메일 주소
- name: ID의 이름
- objectId: ID의 GUID
- userPrincipalName: ID의 UPN
createdTimeUtc 작업이 만들어진 시간(UTC)입니다.
lastCompletedTimeUtc 작업이 완료로 표시된 시간(UTC)입니다.
lastModifiedBy 작업을 마지막으로 수정한 ID:
- email: ID의 이메일 주소
- name: ID의 이름
- objectId: ID의 GUID
- userPrincipalName: ID의 UPN
lastModifiedTimeUtc 작업이 마지막으로 수정된 시간(UTC)입니다.
status 작업의 현재 상태: 신규, 완료됨, 삭제됨.
taskId 작업의 리소스 ID입니다.
title 작업 작성자가 작업에 부여한 식별 이름입니다.

SecurityIncident 테이블에서 인시던트 작업 보기

인시던트 작업 통합 문서 외에도 로그에서 SecurityIncident 테이블을 쿼리하여 작업 활동을 감사할 수 있습니다. 이 문서의 나머지 부분에서는 이를 수행하는 방법과 쿼리 결과를 읽고 이해하여 작업 활동 정보를 얻는 방법을 보여줍니다.

  1. 로그 페이지의 쿼리 창에 다음 쿼리를 입력하고 실행합니다. 이 쿼리는 작업이 할당된 모든 인시던트를 반환합니다.

    SecurityIncident
    | where array_length( Tasks) > 0
    

    쿼리에 원하는 만큼의 명령문을 추가하여 결과를 필터링하고 범위를 좁힐 수 있습니다. 결과를 보고 이해하는 방법을 보여주기 위해 단일 인시던트에 대한 작업만 볼 수 있도록 결과를 필터링하는 명령문을 추가하고 많은 혼란 없이 목적에 유용한 필드만 볼 수 있도록 project 문을 추가하겠습니다.

    Kusto 쿼리 언어 사용에 대해 자세히 알아봅니다.

    SecurityIncident
    | where array_length( Tasks) > 0
    | where IncidentNumber == "405211"
    | sort by LastModifiedTime desc 
    | project IncidentName, Title, LastModifiedTime, Tasks
    
  2. 이 인시던트에 대한 최신 레코드를 살펴보고 관련 작업 목록을 찾아보겠습니다.

    1. 쿼리 결과(최신순으로 내림차순으로 정렬됨)의 맨 위 행 옆에 있는 확장기를 선택합니다.

      Screenshot of query results showing an incident with its tasks.

    2. Tasks 필드는 이 인시던트에 있는 모든 작업의 현재 상태 배열입니다. 확장기를 선택하여 배열의 각 항목을 자체 행에 표시합니다.

      Screenshot of query results showing an incident with its tasks expanded.

    3. 이제 이 인시던트에 두 가지 작업이 있습니다. 각각은 확장 가능한 배열로 차례로 표시됩니다. 단일 작업의 확장기를 선택하여 해당 정보를 봅니다.

      Screenshot of query results showing an incident with a single task expanded.

    4. 여기서는 배열의 첫 번째 작업에 대한 세부 정보를 볼 수 있습니다("0"은 배열에서 작업의 인덱스 위치임). title 필드에는 인시던트에 표시된 작업의 이름이 표시됩니다.

목록에 추가된 작업 보기

  1. 인시던트에 작업을 추가한 다음, 여기로 돌아와서 쿼리를 다시 실행하고 결과의 변경 내용을 살펴보겠습니다.

    1. 인시던트 페이지의 검색 창에 인시던트 ID 번호를 입력합니다.

    2. 인시던트 세부 정보 페이지를 열고 도구 모음에서 작업을 선택합니다.

    3. 새 작업을 추가하고 "이 작업은 테스트 작업입니다!"라는 이름을 지정한 다음, 저장을 선택합니다. 아래에 표시된 마지막 작업은 다음으로 끝나야 합니다.

      Screenshot shows incident tasks panel.

  2. 이제 로그 페이지로 돌아가서 쿼리를 다시 실행해 보겠습니다.

    결과에서 이 동일한 인시던트에 대한 테이블에 새 레코드가 있음을 알 수 있습니다(타임스탬프 참고). 레코드를 확장하면 이전에 본 레코드의 Tasks 배열에 두 개의 작업이 있는 반면 새 레코드에는 세 개가 있는 것을 볼 수 있습니다. 최신 작업은 제목에서 알 수 있듯이 방금 추가한 작업입니다.

    Screenshot of query results showing an incident with its newly created task.

작업의 상태 변경 내용 보기

이제 인시던트 세부 정보 페이지에서 새 작업으로 돌아가서 완료로 표시한 다음, 로그로 다시 돌아와서 쿼리를 다시 실행하면 동일한 인시던트에 대한 또 다른 새 레코드가 표시됩니다. 이번에는 작업의 새 상태가 완료됨으로 표시됩니다.

Screenshot of query results showing an incident task with its new status.

작업 삭제 보기

인시던트 세부 정보 페이지의 작업 목록으로 돌아가서 앞서 추가한 작업을 삭제해 보겠습니다.

로그로 돌아가 쿼리를 다시 실행하면 또 다른 새 레코드가 표시됩니다. 이번에는 작업("이 작업은 테스트 작업입니다!"라는 작업) 상태가 삭제됨입니다.

그러나— 작업이 배열에 한 번 나타나면(삭제됨 상태) SecurityIncident 테이블의 해당 인시던트에 대한 새 레코드의 Tasks 배열에 더 이상 표시되지 않습니다. 위에서 본 것과 같은 기존 레코드는 이 작업이 한때 존재했다는 증거를 계속해서 보존합니다.

닫힌 인시던트에 속하는 활성 작업 보기

다음 쿼리를 사용하면 인시던트가 닫혔지만 할당된 작업 중 일부가 완료되지 않았는지 확인할 수 있습니다. 이런 지식은 조사의 나머지 미진한 부분이 결론에 도달했는지(모든 관련 당사자에게 통보되고, 모든 의견이 입력되고, 모든 응답이 확인되었는지) 확인하는 데 도움이 될 수 있습니다.

SecurityIncident
| summarize arg_max(TimeGenerated, *) by IncidentNumber
| where Status == 'Closed'
| mv-expand Tasks
| evaluate bag_unpack(Tasks)
| summarize arg_max(lastModifiedTimeUtc, *) by taskId
| where status !in ('Completed', 'Deleted')
| project TaskTitle = ['title'], TaskStatus = ['status'], createdTimeUtc, lastModifiedTimeUtc = column_ifexists("lastModifiedTimeUtc", datetime(null)), TaskCreator = ['createdBy'].name, lastModifiedBy, IncidentNumber, IncidentOwner = Owner.userPrincipalName
| order by lastModifiedTimeUtc desc

다음 단계