YARA-L 2.0 윈도우 로직
이 가이드는 보안 엔지니어가 쿼리에 적합한 창 유형을 선택하여 '변수가 바운드되지 않음' 컴파일러 오류를 방지하는 데 도움이 됩니다. 슬라이딩 기간에서 텀블링 기간으로 전환하면 누락된 하트비트나 실패한 로그 소스와 같이 이벤트가 없는 경우에 따라 로직을 빌드할 수 있습니다.
시작하기 전에
YARA-L 쿼리를 만들고 수정할 수 있는 다음 역할 중 하나가 계정에 있는지 확인합니다.
- 감지 엔진 관리자 (
roles/chronicle.detectionEngineAdmin) - SecOps 편집자 (
roles/chronicle.editor)
지원되는 창 유형
YARA-L 2.0은 다양한 기간 설정 동작을 사용하여 시간이 어떻게 분할되고 이벤트가 어떻게 그룹화되는지 결정합니다. 다음과 같은 지원되는 기간을 사용하여 match 섹션의 이벤트 필드와 자리표시자를 지정된 시간 세분성으로 그룹화할 수 있습니다.
| 지원되는 창 유형 | 구문 | 설명 | 일반적인 사용 사례 |
|---|---|---|---|
| 홉 | $key over <duration> |
고정된 겹치는 시간 간격을 만듭니다. 시스템은 경계 근처의 이벤트를 포착하기 위해 오버랩과 정렬을 정의합니다. | 정확한 시작 시간과 관계없이 여러 이벤트의 일반적인 상관관계입니다. |
| 텀블링 | $key by <duration> |
데이터를 고정 크기의 연속된 중복되지 않는 블록으로 분할합니다. 이벤트 도착과 관계없이 평가됩니다. | 고정된 슬롯에서 활동을 정량화하거나 (예: $user by 30m) 이벤트가 없는지 감지합니다. |
| 슬라이딩 | $key over <duration> [before|after] $pivot |
창을 특정 "pivot" 이벤트에 고정합니다. 뒤돌아보기 또는 앞으로 보기를 트리거하려면 피벗이 있어야 합니다. |
이벤트 순서가 중요한 엄격한 순서 지정 (예: File Download after Login) |
window_start 및 window_end 논리 이해
Google Security Operations는 쿼리 내에서 사용할 수 있도록 GoogleSQL 타임스탬프로 직접 변환되는 두 개의 범용 예약 키워드를 제공합니다. 이러한 키워드를 사용하면 시간 버킷의 경계에 액세스할 수 있습니다.
window_start: 시간 버킷의 시작 경계입니다.window_end: 시간 버킷의 종료 경계입니다.
사용 제약
- 일치 요구사항: 이러한 키워드를 사용하려면
match섹션에서 기간 (by또는over)을 정의해야 합니다. - 섹션 제한:
condition,order또는outcome에서 이러한 키워드를 사용합니다.events섹션에서는 유효하지 않습니다. - 네임스페이스: 이러한 이름을 맞춤 변수 이름 (예:
$window_start)으로 사용하지 마세요.
창 유형 및 문법 확인
감지 규칙에 사용할 기간 유형과 구문을 결정할 때 이 표를 간단한 참고 자료로 사용하세요.
| 시나리오 | 추천 기간 | 추천 키워드 | 주요 이점 |
|---|---|---|---|
| 빈도가 높은 감지 (예: 무작위 대입 공격) | 슬라이딩 기간 (over) |
window_start, window_end |
이동 기간 내에 기준이 충족되면 즉시 트리거됩니다. |
| 부재/비존재 (예: 하트비트 누락) | 텀블링 윈도우 (by) |
window_start, window_end |
이벤트가 0개 발생하더라도 고정 시간 블록을 평가하여 변수가 경계되지 않음 오류를 방지합니다. |
| 시간순 보고 | 미끄러지거나 굴러 떨어짐 | order: window_start asc |
Chronicle UI에서 타임라인 분석을 더 쉽게 할 수 있도록 알림 출력을 표준화합니다. |
| 시간 제한 필터링 | 미끄러지거나 굴러 떨어짐 | condition: window_start > "2026-01-01 00:00:00Z" |
GoogleSQL 타임스탬프 강제 변환을 사용하여 규칙 평가를 특정 날짜로 제한합니다. |
타임스탬프 유형 및 시간대 비교
YARA-L은 GoogleSQL 타임스탬프 형식의 문자열과 window_start 및 window_end를 직접 비교하는 기능을 지원합니다. 이를 통해 수동 유형 변환 없이 정확한 필터링을 실행할 수 있습니다.
참고: UDM 이벤트 타임스탬프와 일치하도록 항상 Z 접미사 (예: "2026-03-17T17:35:00Z")를 사용하여 UTC를 지정하세요.
타임스탬프 필터를 사용하여 실적을 확인합니다. 한 이벤트가 다른 이벤트 다음에 발생했는지 확인하기만 하면 되는 경우 condition 섹션의 타임스탬프 비교가 더 효율적인 경우가 많습니다($e1.metadata.event_timestamp.seconds < $e2.metadata.event_timestamp.seconds).
match 섹션 구문 및 condition 섹션 구문에 대해 자세히 알아보세요.
예: window_end 및 window_start
window_end < "2026-01-01T12:30:00Z"(날짜, 시간, UTC 접미사)window_start != "2026-01-01 15:00:00+00"(UTC 오프셋 포함)
비교가 실패하면 문자열이 GoogleSQL 표준 타임스탬프 형식을 따르는지 확인합니다.
홉 기간
홉 창은 겹치는 시간 간격을 만들어 창의 경계 근처에서 발생하는 이벤트가 누락되지 않도록 합니다.
- 사용 사례: 창 간격의 시작 또는 종료 시점과 관계없이 특정 시나리오를 포착해야 하는 감지에 가장 적합합니다.
- 지원: 검색 및 대시보드에서 집계에 지원됩니다.
match 섹션이 있는 YARA-L 쿼리는 홉 기간을 사용하여 시간 경과에 따른 여러 이벤트를 연결합니다. 시스템은 쿼리 실행 기간을 고정된 겹치는 홉 기간 집합으로 나눕니다. match 섹션에서 이러한 기간의 지속 시간을 지정하면 시스템에서 중복 간격과 기간 정렬을 정의합니다. 그런 다음 이러한 사전 정의된 창 내에서 이벤트에 대해 상관관계가 지정됩니다.
match 섹션 구문에 대해 자세히 알아보세요.
예: 연속 상관관계를 위한 중복 홉 창
다음 예시에서는 [1:00, 2:00] 기간에 실행된 쿼리를 보여주며, match 섹션은 $user over 30m입니다. 시스템에서 생성할 수 있는 중복 홉 창 집합은 [1:00, 1:30], [1:03, 1:33], [1:06, 1:36]입니다.
규칙
rule hop_window_brute_force_example {
meta:
description = "Detects multiple failed logins within a shifting 30-minute window."
severity = "Medium"
events:
$login.metadata.event_type = "USER_LOGIN"
$login.extensions.auth.auth_status = "FAILURE"
$login.principal.user.userid = $user
match:
// This creates the overlapping windows (e.g., 1:00-1:30, 1:03-1:33)
$user over 30m
condition:
// This will trigger if 10 or more failures fall into any single 30m hop
#login >= 10
}
검색
metadata.event_type = "USER_LOGIN"
security_result.action = "FAIL"
principal.user.userid = $user
match:
// This creates the overlapping windows (e.g., 1:00-1:30, 1:03-1:33)
$user over 30m
```
대시보드
metadata.event_type = "USER_LOGIN"
security_result.action = "FAIL"
principal.user.userid = $user
match:
// This creates the overlapping windows (e.g., 1:00-1:30, 1:03-1:33)
$user over 30m
예시: 홉 창을 사용한 멀티 이벤트 상관관계
다음 예에서는 동일한 일반적인 기간 내에 발생하는 이벤트를 캡처합니다.
규칙
rule hop_window_example {
meta:
description = "Detect a user with a failed login followed by a success within 30m"
events:
// Event 1: Capture failed login attempts
$fail.metadata.event_type = "USER_LOGIN"
$fail.security_result.action = "FAIL"
$fail.principal.user.userid = $user
// Event 2: Capture successful login attempts
$success.metadata.event_type = "USER_LOGIN"
$success.security_result.action = "ALLOW"
$success.principal.user.userid = $user
match:
// Correlate events for the SAME $user within a rolling 30-minute window.
$user over 30m
condition:
// Ensure both a failed ($fail) and a successful ($success) login event occurred for the same user within the 30m window.
$fail and $success
}
검색
// Event 1: Capture failed login attempts
metadata.event_type = "USER_LOGIN"
security_result.action = "FAIL"
principal.user.userid = $user // Assign user ID to a placeholder
// Event 2: Capture successful login attempts
metadata.event_type = "USER_LOGIN"
security_result.action = "ALLOW"
principal.user.userid = $user // Link to the same user placeholder
match:
// Correlate events for the SAME $user within a rolling 30-minute window.
$user over 30m
대시보드
// Event 1: Capture failed login attempts
metadata.event_type = "USER_LOGIN"
security_result.action = "FAIL"
principal.user.userid = $user // Assign user ID to a placeholder
// Event 2: Capture successful login attempts
metadata.event_type = "USER_LOGIN"
security_result.action = "ALLOW"
principal.user.userid = $user // Link to the same user placeholder
match:
// Correlate events for the SAME $user within a rolling 30-minute window.
$user over 30m
예: 홉 윈도우 비교
무차별 대입 시도를 식별하기 위해 10m 창은 모든 USER_LOGIN 실패를 그룹화합니다. 그런 다음 조건은 해당 특정 10분 버킷 내의 개수 (#e)가 임곗값을 초과하는지 평가합니다.
규칙
rule failed_logins
{
meta:
author = "Security Team"
description = "Detects multiple failed user logins within 10-minute windows."
severity = "HIGH"
events:
$e.metadata.event_type = "USER_LOGIN"
$e.security_result.action = "FAIL"
$user = $e.target.user.userid
match:
$user over 10m
condition:
#e >= 5
}
검색
metadata.event_type = "USER_LOGIN"
security_result.action = "FAIL"
$user = target.user.userid
match:
$user over 10m
대시보드
metadata.event_type = "USER_LOGIN"
security_result.action = "FAIL"
$user = target.user.userid
match:
$user over 10m
텀블링 윈도우
참고: 일부 리전의 일부 고객은 이 기능을 사용할 수 없습니다.
텀블링 윈도우는 데이터를 고정 크기의 겹치지 않는 연속 시간 간격으로 분할합니다. 각 이벤트의 타임스탬프는 정확히 하나의 윈도우에 속합니다. 텀블링 윈도우 간에는 겹치는 부분이 없습니다. 이는 시간 간격이 겹칠 수 있는 홉 윈도우 또는 슬라이딩 윈도우와 대조됩니다.
텀블링 윈도우를 구현하려면 match 섹션에서 by 연산자를 사용하세요. 텀블링 윈도우는 시간을 연속적인 블록으로 나눕니다. 예를 들면 다음과 같습니다.
by 1h: 시간별 윈도우를 만듭니다 (예:[00:00:00-00:59:59],[01:00:00-01:59:59]).by 10m: 각 10분 간격의 윈도우를 만듭니다 (예:[00:00:00-00:09:59],[00:10:00-00:19:59]).
일반적인 사용 사례
다음과 같은 경우 텀블링 기간을 사용하세요.
- 중복되지 않는 별도의 시간 블록에서 이벤트를 분석합니다.
- 이벤트 발생 횟수와 관계없이 각 고정 시간 간격 내에서 지정된 항목 (일치 변수로 정의됨)에 대해 하나의 감지만 생성합니다.
- 고정된 기간 동안 고유한 항목을 집계합니다.
중복 삭제 동작
텀블링 윈도우의 주요 특징은 엔진이 동일한 일치 변수 집합에 대해 각 윈도우 내에서 감지를 처리하는 방식입니다.
- 기간당 하나의 감지: 일치 변수 (예: 특정
$userid)의 지정된 값 집합에 대해 엔진은 단일 텀블링 윈도우에 대해 최대 하나의 감지를 생성합니다. - 먼저 도착한 이벤트가 우선: 특정 기간 내에 해당 일치 변수 집합의 규칙 조건을 충족하는 첫 번째 이벤트가 감지를 트리거합니다.
- 중복 삭제: 동일한 기간 인스턴스 내에서 기준과 일치하는 후속 이벤트는 추가 감지를 생성하지 않습니다.
구문
match 섹션의 구문은 match: $variable by <duration>입니다.
$variable은(는) 일치시키는 자리표시자 변수입니다.duration은 숫자 뒤에 시간 단위(m(분),h(시간),d(일))가 붙은 값입니다.- 최소 1분, 최대 72시간 또는 3일을 지정합니다.
예: 고정 간격 그룹화
다음 규칙은 겹치지 않는 1시간 윈도우 내에서 $userid별로 로그인을 그룹화합니다.
규칙
rule TumblingWindowExample {
meta:
description = "Example using a 1-hour tumbling window"
events:
$e.metadata.event_type = "USER_LOGIN"
$e.principal.user.userid = $userid
match:
$userid by 1h
condition:
$e
}
검색
metadata.event_type = "USER_LOGIN"
principal.user.userid = $userid
match:
$userid by 1h
대시보드
metadata.event_type = "USER_LOGIN"
principal.user.userid = $userid
match:
$userid by 1h
예: 감지 동작 (사용자 = 'Alex')
- 이벤트 1: 알렉스가 00시 30분에 로그인합니다. 이 값은
[00:00:00-00:59:59]윈도우에 속합니다. 엔진은 이 기간에 대해 Alex의 감지를 생성합니다. - 이벤트 2: 다른 사용자 'Taylor'가 00:45에 로그인합니다. 이 경우도
[00:00:00-00:59:59]에 해당하지만$userid이 다르므로 엔진에서 Taylor에 대한 별도의 감지를 생성합니다. - 이벤트 3: Alex가 00시 40분에 다시 로그인합니다. 이 경우에도
[00:00:00-00:59:59]기간 내에 있습니다. Alex에 대한 감지가 이미 있으므로 이 이벤트는 중복 제거됩니다. 새로운 감지가 생성되지 않습니다. - 이벤트 4: Alex가 01:20에 로그인합니다. 이 경우 다음 기간인
[01:00:00-01:59:59]에 포함됩니다. 엔진에서 Alex에 대한 새로운 감지를 생성합니다.
Alex의 이벤트 1과 이벤트 4는 1시간 미만의 간격으로 발생했지만 이벤트 4가 고정 기간 경계를 넘기기 때문에 별도의 감지로 분류됩니다.
부재 감지를 위한 텀블링 윈도우 구성
개수가 0일 때 알리고 컴파일러 오류를 방지하려면 다음 단계를 완료하세요.
- 감지 목표를 파악합니다. 활동이 자주 발생하는지 아니면 활동이 부족한지 확인합니다.
window키워드를 선택합니다. 빈도에는over을 사용하고 부재에는by을 사용합니다.- 참조 창 경계.
window_start및window_end키워드를 사용하여 시간 버킷의 특정 경계를 참조합니다.
컨텍스트: outcome: $ext_window_end = window_end를 사용하여 알림 메타데이터에 누락된 하트비트의 정확한 종료 시간을 포함합니다.
예: 메타데이터를 사용하여 누락된 하트비트 감지
텀블링 윈도우를 사용하면 0개에 대한 알림을 받을 수 있으므로 활동 부족을 검색할 때 컴파일러 오류를 방지할 수 있습니다.
규칙
rule missing_heartbeat_detection {
meta:
description = "Alert when a system fails to check in within a 24h block"
events:
$e.metadata.event_type = "STATUS_UPDATE"
$host = $e.principal.hostname
match:
$host by 24h // Tumbling window lets you detect zero counts
outcome:
$event_count = count($e.metadata.id)
$missing_window_start = window_start
$missing_window_end = window_end
condition:
$event_count = 0 and window_start > "2026-01-01T12:30:00Z"
}
검색
metadata.event_type = "STATUS_UPDATE"
$host = principal.hostname
match:
$host by 24h // Tumbling window lets you detect zero counts
outcome:
$event_count = count(metadata.id)
$missing_window_start = window_start
$missing_window_end = window_end
대시보드
metadata.event_type = "STATUS_UPDATE"
$host = principal.hostname
match:
$host by 24h // Tumbling window lets you detect zero counts
outcome:
$event_count = count(metadata.id)
$missing_window_start = window_start
$missing_window_end = window_end
슬라이딩 기간
슬라이딩 창은 특정 피벗 이벤트에 고정되어 있으며 앞으로 (after) 또는 뒤로 (before) 이동합니다.
일반적인 사용 사례
이벤트 순서가 중요한 경우 슬라이딩 윈도우를 사용합니다.
- 엄격한 순서 지정: 공격 체인을 감지합니다 (예:
e1가e2후 최대 2분 이내에 발생). - 상대적 타이밍: 트리거의 특정 오프셋 내에서 발생하는 이벤트를 찾습니다 (예:
Process Start에서 30초 이내의Network Connection). - 부재 감지: 시작 이벤트 후 필요한 '정리' 또는 '하트비트' 이벤트가 발생하지 않는 시점을 식별합니다.
구문
match: <grouping_keys> over <duration> [before|after] <$pivot_event>
| 구성요소 | 설명 | 예 |
|---|---|---|
| 그룹화 키 | 이벤트를 서로 연결하는 데 사용되는 공통 필드입니다. | $host, $user |
| 기간 | 기준 이벤트로부터의 시간 오프셋입니다. | 5m, 1h, 30s |
| 방향 | 창이 앞으로 또는 뒤로 확장되는지 여부입니다. | after, before |
| 방향 전환 이벤트 | 창을 고정하는 이벤트 변수입니다. | $proc, $alert |
다음은 유효한 슬라이딩 구간 예시입니다.
$var1, $var2 over 5m after $e1$user over 1h before $e2$host, $ip over 1h before $e2
요구사항 및 제한사항
- 성능: 슬라이딩 창은 홉 창보다 더 많은 처리 능력이 필요합니다. 이벤트 순서가 엄격하게 필요한 경우 (예: 한 이벤트가 다른 이벤트 후 5분 이내에 발생해야 하는 경우)에만 사용하세요.
- 단일 이벤트 쿼리: 단일 이벤트 로직에 슬라이딩 윈도우를 사용하지 마세요. 대신
condition섹션에서 여러 이벤트 변수를 사용하세요.
예: 미래 지향적 상관관계 (after)
규칙
rule sliding_window_after_example {
meta:
description = "Detect a network connection occurring within 1 minute after a suspicious process launch."
severity = "High"
events:
$proc.metadata.event_type = "PROCESS_LAUNCH"
$proc.principal.hostname = $host
$net.metadata.event_type = "NETWORK_HTTP"
$net.principal.hostname = $host
match:
// $proc is the pivot; the 1-minute window starts at the $proc timestamp
$host over 1m after $proc
condition:
$proc and $net
}
검색
after은(는) 검색에서 지원되지 않습니다.
대시보드
after은 대시보드에서 지원되지 않습니다.
예: 과거 상관관계 (before)
"before" 슬라이딩 창을 사용하여 특정 알림이 발생하기 전의 활동을 조사합니다. 이는 근본 원인 분석에서 심각한 감지 직전에 발생한 상황을 식별하는 데 자주 사용됩니다.
규칙
rule sliding_window_before_example {
meta:
description = "Identify file modifications occurring in the 5 minutes before a ransomware alert."
severity = "Critical"
events:
$file.metadata.event_type = "FILE_MODIFICATION"
$file.principal.hostname = $host
$alert.metadata.event_type = "ANTIVIRUS_DETECTION"
$alert.metadata.product_name = "Premium_AV"
$alert.principal.hostname = $host
match:
// $alert is the pivot; the 5-minute window ends at the $alert timestamp
$host over 5m before $alert
condition:
$file and $alert
}
검색
before은(는) 검색에서 지원되지 않습니다.
대시보드
before은 대시보드에서 지원되지 않습니다.
문제 해결
이 섹션을 사용하여 YARA-L의 지연 시간, 제한, 일반적인 윈도우 문제 해결 방법을 알아보세요.
지연 시간 및 제한
텀블링 기간 (
by)을 사용하는 규칙은 고정된 시간 블록이 끝날 때만 트리거됩니다. 예를 들어match: $user by 24h이 포함된 규칙은 24시간이 완전히 지나야 평가됩니다.알림 지연 시간:
by(텀블링)을 사용하는 규칙은 고정된 시간 블록이 경과한 후에만 트리거됩니다.by 24h규칙은 창 중간에 알림을 표시하지 않습니다.UI 불일치: 검색 및 대시보드에서
window_start키워드는TIME_BUCKET필드를 직접 참조합니다.window_start로 필터링하거나 그룹화하면 UI에 열 헤더가TIME_BUCKET로 표시됩니다.이는 알려진 UI 표시 제한사항이며 로직은 유효합니다.
오류 해결
| 오류 코드 | 설명 | 수정 |
|---|---|---|
| Variable Not Bounded(변수가 바운드되지 않음) | 규칙에서 $count = 0 조건과 함께 over (슬라이딩 기간)를 사용합니다. |
기간 설정 키워드를 by (텀블링 윈도우)로 변경합니다. 슬라이딩 윈도우는 윈도우를 고정하기 위해 이벤트가 있어야 하지만 텀블링 윈도우는 그렇지 않습니다. |
| UI 헤더 불일치 | 사용자에게 UI에 window_start 대신 TIME_BUCKET이 표시됩니다. |
수정이 필요하지 않습니다. 필터링 및 정렬 로직은 키워드를 사용하여 계속 올바르게 작동합니다. |
알 수 없는 식별자: window_start |
키워드가 사용되었지만 match에 정의된 창이 없습니다. |
match 섹션 (예: $hostname by 1h)에 윈도우 처리 문을 추가합니다. |
이벤트에서 window_start을 잘못 사용함 |
키워드는 events 섹션에서 참조됩니다. |
논리를 condition 또는 outcome 섹션으로 이동합니다. 윈도우 경계는 매치 단계에서 이벤트가 그룹화된 후에만 계산됩니다. |
다음 단계
도움이 더 필요하신가요? 커뮤니티 회원 및 Google SecOps 전문가에게 문의하여 답변을 받으세요.