표현식, 연산자, 기타 구조

다음에서 지원:

이 문서에는 표현식을 사용하여 YARA-L 규칙과 쿼리를 빌드하는 데 도움이 되는 정보가 포함되어 있습니다.

부울 표현식

불리언 표현식은 불리언 유형의 표현식으로, 비교 표현식, 함수 표현식, 참조 목록 또는 데이터 표 표현식이 포함됩니다. YARA-L 규칙 또는 쿼리의 eventsoutcome 섹션에서 불리언 표현식을 사용할 수 있습니다.

비교 표현식

비교 표현식은 두 표현식에 비교 연산자를 적용하는 표현식입니다. 표현식은 이벤트 필드, 변수, 리터럴, 함수 표현식일 수 있습니다.

예: 비교 표현식

$e.source.hostname = "host1234"
$e.source.port < 1024
1024 < $e.source.port
$e1.source.hostname != $e2.target.hostname
$e1.metadata.collected_timestamp.seconds > $e2.metadata.collected_timestamp.seconds
$port >= 25
$host = $e2.target.hostname
"google-test" = strings.concat($e.principal.hostname, "-test")
"email@google.org" = re.replace($e.network.email.from, "com", "org")

함수 표현식

일부 함수는 events 섹션에서 개별 조건자로 사용될 수 있는 부울 값을 반환합니다. 예를 들면 다음과 같습니다.

re.regex()

net.ip_in_range_cidr()

예: 함수 표현식

re.regex($e.principal.hostname, `.*\.google\.com`)
net.ip_in_range_cidr($e.principal.ip, "192.0.2.0/24")

참조 목록 또는 데이터 표

events 또는 outcome 섹션에서 참조 목록 또는 데이터 테이블을 사용할 수 있습니다. 참조 목록 및 데이터 표 동작과 문법에 대한 자세한 내용은 참조 목록데이터 표 사용을 참고하세요.

예: 참조 목록의 구문

다음은 쿼리에서 다양한 유형의 참조 목록에 대한 문법을 보여주는 예입니다.

// STRING reference list
$e.principal.hostname in %string_reference_list

// REGEX reference list
$e.principal.hostname in regex %regex_reference_list

// CIDR reference list
$e.principal.ip in cidr %cidr_reference_list

예: 데이터 테이블의 구문

// STRING data table
$e.target.hostname in %data_table_name.column_name

// REGEX data table
$e.target.hostname in regex %regex_table_name.column_name

// CIDR data table
$e.principal.ip in cidr %cidr_table_name.column_name

예: 참조 목록 구문에서 notnocase 사용

// Exclude events whose hostnames match substrings in my_regex_list.
not $e.principal.hostname in regex %my_regex_list

// Event hostnames must match at least 1 string in my_string_list (case insensitive).
$e.principal.hostname in %my_string_list nocase

nocase 연산자는 STRING 목록 및 REGEX 목록과 호환됩니다.

성능상의 이유로 참조 목록 및 데이터 표 사용에는 다음과 같은 제한사항이 있습니다.

  • 특수 연산자가 있거나 없는 쿼리의 최대 in 문: 7개
  • regex 연산자가 있는 최대 in 문: 4개
  • cidr 연산자가 있는 최대 in 문: 2개

논리식

events 섹션에서 논리적 andor 연산자를 사용할 수 있습니다.

예: 논리식

$e.metadata.event_type = "NETWORK_DNS" or $e.metadata.event_type = "NETWORK_DHCP"
($e.metadata.event_type = "NETWORK_DNS" and $e.principal.ip = "192.0.2.12") or ($e.metadata.event_type = "NETWORK_DHCP" and $e.principal.mac = "AB:CD:01:10:EF:22")
not $e.metadata.event_type = "NETWORK_DNS"

기본적으로 우선순위(가장 높은 것에서 가장 낮은 순)는 not, and, or입니다. 예를 들어 orand 연산자가 표현식에 명시적으로 정의된 경우 'a 또는 b 및 c'는 'a 또는 (b 및 c)'로 평가됩니다.

events 섹션에서 연산자가 명시적으로 정의되지 않은 경우 조건자는 and 연산자를 사용하여 결합됩니다. and 연산자가 표현식에 내포된 경우 평가 순서가 다를 수 있습니다. or이 명시적으로 정의되고 and 연산자가 암시되는 다음 비교 표현식을 고려해 보세요.

$e1.field = "bat"
or $e1.field = "baz" 
$e2.field = "bar"

다음과 같이 해석됩니다.

($e1.field = "bat" or $e1.field = "baz")
and ($e2.field = "bar")

or가 명시적으로 정의되어 있으므로 주변 술어가 그룹화되어 먼저 평가됩니다. 마지막 조건자 $e2.field = "bar" and를 사용하여 암시적으로 결합됩니다. 결과는 평가 순서 변경입니다.

열거형 유형

연산자는 열거형 유형과 함께 사용할 수 있습니다. 규칙에 적용하여 성능을 단순화하고 최적화(참조 목록 대신 연산자 사용)할 수 있습니다.

다음 예시에서 USER_UNCATEGORIZED' 및 'USER_RESOURCE_DELETION'은 15000와 15014에 해당하므로 규칙은 나열된 모든 이벤트를 찾습니다.

$e.metadata.event_type >= "USER_CATEGORIZED" and $e.metadata.event_type <= "USER_RESOURCE_DELETION"

Nocase 수정자

문자열 값 또는 정규 표현식 사이의 비교 표현식에서 대소문자를 무시하려면 다음 예와 같이 표현식 끝에 nocase를 추가합니다.

예: nocase 수정자

$e.principal.hostname != "http-server" nocase
$e1.principal.hostname = $e2.target.hostname nocase
$e.principal.hostname = /dns-server-[0-9]+/ nocase
re.regex($e.target.hostname, `client-[0-9]+`) nocase

필드 유형이 열거된 값인 경우에는 nocase 수정자를 사용할 수 없습니다. 다음 예시는 잘못된 예시이고 컴파일 오류를 일으킵니다.

$e.metadata.event_type = "NETWORK_DNS" nocase
$e.network.ip_protocol = "TCP" nocase

댓글

의견은 쿼리에서 추가 정보를 제공하는 데 사용할 수 있습니다. 슬래시 문자를 사용하여 주석을 나타냅니다.

  • 한 줄 주석의 경우 슬래시 문자 두 개 (// comment)를 사용합니다.
  • 여러 줄 주석의 경우 슬래시 문자 하나와 별표 문자 (/* comment */)를 사용합니다.

리터럴

YARA-L은 음수가 아닌 정수 및 부동 소수점 수, 문자열, 불리언, 정규 표현식 리터럴을 지원합니다. 리터럴은 쿼리 조건에 사용되는 고정 값입니다. YARA-L은 패턴 일치를 위한 정규 표현식 (슬래시로 묶임) 및 논리를 위한 불리언 (true/false)과 같은 다른 리터럴 유사 구조도 사용합니다.

문자열 리터럴

문자열 리터럴은 큰따옴표 (") 또는 역따옴표 (`)로 묶인 문자 시퀀스입니다. 문자열은 사용한 따옴표 유형에 따라 다르게 해석됩니다.

  • 큰따옴표 ("hello\tworld"): 일반 문자열에 사용됩니다. \t가 탭으로 해석되는 이스케이프 문자를 포함해야 합니다.
  • 뒤쪽 인용부호 (`hello\tworld`): 모든 문자를 문자 그대로 해석해야 하는 경우에 사용합니다. 여기서 \t는 탭으로 해석되지 않습니다.

정규 표현식 리터럴

정규 표현식 리터럴에는 두 가지 옵션이 있습니다.

  • re.regex() 함수 없이 정규 표현식을 직접 사용하려면 정규 표현식 리터럴에 /regex/를 사용합니다.

  • 문자열 리터럴을 정규 표현식 리터럴로 사용하려면 re.regex() 함수를 사용하세요. 큰따옴표 문자열 리터럴의 경우 어색해보일 수도 있는 백슬래시 문자로 백슬래시 문자를 이스케이프 처리해야 합니다.

다음 예에서는 동일한 정규 표현식을 보여줍니다.

re.regex($e.network.email.from, `.*altostrat\.com`)

re.regex($e.network.email.from, ".*altostrat\\.com")

$e.network.email.from = /.*altostrat\.com/

가독성을 높이기 위해서는 정규 표현식에서 문자열에 대해 뒤쪽 인용부호 문자를 사용하는 것이 좋습니다.

연산자

연산자 설명
= 같음/선언
!= 같지 않음
< 미만
<= 이하
> 초과
>= 이상

변수

YARA-L에서는 모든 변수가 $<variable name> 구문을 사용합니다. YARA-L에서는 다음 유형의 변수를 사용할 수 있습니다.

이벤트 변수

이벤트 변수는 이벤트 그룹 또는 항목 이벤트를 나타냅니다. 이름, 이벤트 소스, 이벤트 필드를 사용하여 events 섹션에서 이벤트 변수의 조건을 지정합니다.

  • 이벤트 소스는 udm (정규화된 이벤트) 및 graph (항목 이벤트)입니다. 소스가 생략된 경우 udm이 기본 소스로 설정됩니다.

  • 이벤트 필드는 일련의 .<field name> (예: $e.field1.field2)으로 표현되며, 필드 체인은 항상 최상위 소스 (UDM 또는 Entity)로 시작됩니다.

일치 변수

일치 변수는 match 섹션에서 지정된 기간 내의 공통 값을 기반으로 이벤트를 그룹화하는 데 사용됩니다.

일치 변수는 쿼리의 그룹화 필드가 됩니다. 여기에서 일치 변수의 각 고유 집합에 대해 그리고 각 기간에 대해 하나의 행이 반환됩니다. 쿼리에서 일치 항목을 찾으면 일치 변수 값이 반환됩니다.

각 일치 변수가 events 섹션에서 나타내는 대상을 지정합니다.

자리표시자 변수

자리표시자 변수는 UDM 이벤트 필드에서 특정 값을 캡처하고 저장하여 쿼리 전체에서 참조하고 사용하는 데 사용됩니다. 특히 다중 이벤트 쿼리에서 서로 다른 이벤트를 연결하는 데 사용됩니다. 자리표시자에 공통 값 (예: userid 또는 hostname)을 할당하면 match 섹션에서 이 자리표시자를 사용하여 지정된 기간 내에 해당 값을 공유하는 이벤트를 그룹화할 수 있습니다.

events 섹션에서 UDM 필드의 값을 $로 시작하는 변수 이름에 할당하여 자리표시자 변수를 정의합니다 (예: $targetUser = $e.target.user.userid).

다음 섹션에서 자리표시자 변수를 정의할 수도 있습니다.

  • condition 섹션에서 자리표시자 변수를 사용하여 일치 조건을 지정할 수 있습니다.
  • outcome 섹션을 사용하여 계산을 실행하거나, 측정항목을 정의하거나, 일치하는 이벤트에서 특정 데이터 포인트를 추출합니다.
  • match 섹션을 사용하여 공통 값으로 이벤트를 그룹화합니다.

키워드

YARA-L에서 키워드는 감지 쿼리의 구조와 논리를 정의하는 예약어입니다. 쿼리의 여러 섹션을 지정하고, 논리 및 수학 연산을 실행하고, 이벤트 일치 조건을 정의하는 데 사용됩니다. 이러한 키워드는 쿼리, 문자열 또는 변수의 식별자로 사용할 수 없습니다.

키워드는 대소문자를 구분하지 않습니다 (예: and 또는 AND은 동일함).

YARA-L 2.0 키워드의 주요 카테고리

이 목록은 완전하지는 않지만 강력한 감지 쿼리를 구성하기 위해 YARA-L 2.0에서 사용되는 기본 키워드를 포함합니다.

  • 쿼리 정의:
    • rule: 새 YARA-L 쿼리의 정의를 시작합니다.
    • private: 쿼리를 비공개로 지정하여 외부에서 직접 노출되거나 트리거되지 않도록 합니다.
    • global: 쿼리를 전역으로 표시하여 광범위하게 적용해야 함을 나타냅니다.
  • 질문 섹션:
    • meta: 질문에 관한 설명 정보의 메타데이터 섹션을 소개합니다.
    • strings: 문자열 패턴이 정의된 섹션을 나타냅니다.
    • condition: 쿼리 트리거링을 위한 불리언 로직이 포함된 섹션을 지정합니다.
    • events: 이벤트 변수와 조건을 지정하는 섹션을 정의합니다.
    • match: 기간에 걸쳐 값을 집계하는 섹션을 도입합니다.
    • outcome: 트리거된 질문에 컨텍스트를 추가하고 점수를 매기는 섹션을 정의합니다.
  • 문자열 수정자:
    • ascii: 문자열이 ASCII 텍스트로 일치해야 함을 지정합니다.
    • wide: 문자열이 와이드 (UTF-16) 문자로 일치해야 함을 나타냅니다.
    • nocase: 대소문자를 구분하지 않는 문자열 일치를 실행합니다.
    • fullword: 문자열이 완전한 단어로 일치해야 합니다.
    • xor: 일치 전에 문자열에 XOR 변환을 적용합니다.
    • base64, base64wide: 일치시키기 전에 Base64 인코딩을 적용합니다.
  • 논리 연산자:
    • and, or, not: 조건을 결합하는 표준 불리언 논리 연산자입니다.
    • all of, any of: 조건 내에서 여러 표현식을 평가하는 데 사용됩니다.
  • 비교 및 관계 연산자:
    • at: 문자열 일치의 정확한 오프셋을 지정합니다.
    • contains: 문자열에 하위 문자열이 포함되어 있는지 확인합니다.
    • startswith, endswith: 문자열이 하위 문자열로 시작하거나 끝나는지 확인합니다.
    • icontains, istartswith, iendswith, iequals: 대소문자를 구분하지 않는 버전입니다.
    • matches: 정규 표현식 일치에 사용됩니다.
  • 데이터 유형 및 크기 지정자:
    • int8, uint8, int16, uint16, int32, uint32: 지정된 크기의 정수 유형입니다.
    • int8be, uint8be, int16be, uint16be, int32be, uint32be: 정수 유형의 빅엔디언 버전입니다.
    • filesize: 분석 중인 파일의 크기를 나타냅니다.
    • entrypoint: 실행 파일의 진입점을 나타냅니다.

지도

YARA-L은 일부 UDM 필드에서 사용되는 구조체라벨 데이터 유형의 지도를 지원합니다.

구조체와 라벨 데이터 유형에서 특정 키-값 쌍을 검색하려면 표준 맵 문법을 사용합니다.

  • 구조체 필드 문법: $e.udm.additional.fields["pod_name"] = "kube-scheduler"
  • 라벨 필드 구문: $e.metadata.ingestion_labels["MetadataKeyDeletion"] = "startup-script"

예: 지도 사용의 유효한 경우와 유효하지 않은 경우

다음 예시는 지도의 유효한 사용과 잘못된 사용을 보여줍니다.

지도의 올바른 사용

이벤트 섹션에서 구조체 필드 사용:

events:
  $e.udm.additional.fields["pod_name"] = "kube-scheduler"
  

결과 섹션에서 라벨 필드 사용:

outcome:
  $value = array_distinct($e.metadata.ingestion_labels["MetadataKeyDeletion"])
 

자리표시자에 맵 값 할당:

$placeholder = $u1.metadata.ingestion_labels["MetadataKeyDeletion"]

조인 조건에서 맵 필드 사용:

// using a Struct field in a join condition between two udm events $u1 and $u2
$u1.metadata.event_type = $u2.udm.additional.fields["pod_name"]

지도의 지원되지 않는 사용

지도를 사용하여 any 또는 all 키워드 결합

all $e.udm.additional.fields["pod_name"] = "kube-scheduler"

기타 유형의 값

맵 문법은 문자열 값만 반환할 수 있습니다. [구조체](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#struct) 데이터 유형의 경우 맵 문법은 값이 문자열인 키에만 액세스할 수 있습니다. 값이 정수와 같은 다른 기본 유형인 키에는 액세스할 수 없습니다.

지도에서 중복 값 처리

지도 액세스는 특정 키와 연결된 단일 값을 검색하기 위한 것입니다. 이는 표준적이고 예상되는 동작입니다. 하지만 드물고 흔하지 않은 상황에서는 map access의 컨텍스트가 실수로 여러 값을 가리킬 수 있습니다. 드문 경우지만 맵 액세스에서 여러 값을 참조하는 경우 map access는 첫 번째 값을 확정적으로 반환합니다. 라벨에 중복 키가 있거나 라벨에 상위 항목 반복 필드가 있으면 이 문제가 발생할 수 있습니다.

라벨에 중복 키가 있음

라벨 구조는 지도를 나타내지만 키 고유성을 적용하지는 않습니다. 규칙에 따라 지도에는 고유한 키가 있어야 하므로 Google SecOps에서는 라벨을 중복 키로 채우지 않는 것이 좋습니다.

예: 중복 키가 있는 라벨

쿼리 텍스트 $e.metadata.ingestion_labels["dupe-key"]는 다음 데이터 예시를 대상으로 실행되는 경우 첫 번째 가능한 값인 val1을 반환합니다.

    // Disrecommended usage of label with a duplicate key:
    event {
      metadata{
        ingestion_labels{
          key: "dupe-key"
          value: "val1" // This is the first possible value for "dupe-key"
        }
        ingestion_labels{
          key: "dupe-key"
          value: "val2"
        }
      }
    }
  

라벨에 상위 항목 반복 필드가 있음

반복 필드에는 라벨이 하위 필드로 포함될 수 있습니다. 최상위 반복 필드의 서로 다른 두 항목에 동일한 키가 있는 라벨이 포함될 수 있습니다.

예: 상위 항목 반복 필드가 있는 라벨

쿼리 텍스트 $e.security_result.rule_labels["key"]는 다음 데이터 예시를 대상으로 실행되는 경우 첫 번째 가능한 값인 `val3`을 반환합니다.

    event {
      // security_result is a repeated field.
      security_result {
        threat_name: "threat1"
        rule_labels {
          key: "key"
          value: "val3" // This is the first possible value for "key"
        }
      }
      security_result {
        threat_name: "threat2"
        rule_labels {
          key: "key"
          value: "val4"
        }
      }
    }
  

지도에서 결과 변수에 액세스

이 섹션에서는 문자열뿐만 아니라 원래 데이터 유형 (예: 정수, 불리언 또는 이러한 유형의 목록)으로 지도 내 결과 변수에 액세스하는 방법을 설명합니다. 이 기능을 사용하면 쿼리 로직의 유연성과 정확성을 높일 수 있습니다.

결과 데이터는 다음 필드에서 확인할 수 있습니다.

  • 결과 값은 variables 필드에서 원래 유형을 유지합니다.
  • outcomes 필드는 하위 호환성을 위해 string 버전을 저장합니다.

variables 맵을 사용하여 이러한 결과 값에 액세스하여 특정 유형을 검색하거나 배열 색인 생성을 사용하여 시퀀스의 요소에 액세스할 수 있습니다. 색인으로 시퀀스의 특정 항목에 액세스하거나 전체 시퀀스를 선택하여 각 값을 개별적으로 평가할 수 있습니다.

구문:

$d.detection.detection.variables[OUTCOME_NAME].TYPE_SUFFIX

시퀀스 구문:

$d.detection.detection.variables[OUTCOME_NAME].SEQUENCE_TYPE_SUFFIX.TYPE_VALS_SUFFIX

예: 지도에서 결과 변수에 액세스

문자열 결과에 액세스:

    $my_string_outcome = $d.detection.detection.variables["outcome_ip"].string_val
   

이 예시에서는 문자열 값을 직접 가져옵니다 (예: outcome_ip이 단일 문자열인 경우 "1.1.1.1").

정수 결과 액세스

    $my_int_outcome = $d.detection.detection.variables["outcome_port"].int64_value
    

이 예시에서는 정수 값 (예: 30)을 가져옵니다.

Int64Sequence를 사용하여 정수 목록에 액세스

   $my_int_list = $d.detection.detection.variables["outcome_ports"].int64_seq.int64_vals
   

이 예에서는 정수의 전체 목록을 가져와 반복 필드 (예: [2, 3, 4])와 같이 중첩 해제합니다.

정수 목록에서 특정 요소에 액세스

    $first_int = $d.detection.detection.variables["outcome_ports"].int64_seq.int64_vals[0]
    

이 예에서는 목록에서 첫 번째 정수를 가져옵니다 (예: 2).

문자열 목록 (StringSequence) 액세스

    $my_string_list = $d.detection.detection.variables["outcome_ips"].string_seq.string_vals
    

이 예시에서는 문자열의 전체 목록을 가져와 반복 필드 (예: ["1.1.1.1", "2.2.2.2"])와 같이 중첩 해제합니다.

문자열 목록에서 특정 요소에 액세스

    $first_ip = $d.detection.detection.variables["outcome_ips"].string_seq.string_vals[0]
    

이 예시에서는 목록에서 첫 번째 IP 주소 (예: "1.1.1.1")를 가져옵니다.

variables에 사용 가능한 유형 접미사

지원되는 접미사의 전체 목록은 FindingVariable을 참고하세요.

도움이 더 필요하신가요? 커뮤니티 회원 및 Google SecOps 전문가에게 문의하여 답변을 받으세요.