๊ทœ์น™์— ํ•ญ๋ชฉ ์œ„ํ—˜ ์ ์ˆ˜ ์ง€์ •

๋‹ค์Œ์—์„œ ์ง€์›:

์ด ๋ฌธ์„œ์—์„œ๋Š” ๊ทœ์น™์—์„œ ํ•ญ๋ชฉ ์œ„ํ—˜ ์ ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. ๊ทœ์น™์—์„œ ํ•ญ๋ชฉ ์œ„ํ—˜ ์ ์ˆ˜๋Š” ํ•ญ๋ชฉ ์ปจํ…์ŠคํŠธ์™€ ๋น„์Šทํ•œ ๋ฐฉ์‹์œผ๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. YARA-L 2.0 ๊ทœ์น™์„ ์ž‘์„ฑํ•˜์—ฌ ์œ„ํ—˜ ์ ์ˆ˜๋ฅผ ๊ธฐ๋ณธ ๊ฐ์ง€ ๋ฐฉ๋ฒ•์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์œ„ํ—˜ ๋ถ„์„ ๊ทœ์น™์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์œ„ํ—˜ ๋ถ„์„ ๊ทœ์น™ ๋งŒ๋“ค๊ธฐ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”. ๋” ๋งŽ์€ ์œ„ํ—˜ ๊ธฐ๋ฐ˜ ์ปจํ…์ŠคํŠธ์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์ปจํ…์ŠคํŠธ ์ธ์‹ ๋ถ„์„ ๋งŒ๋“ค๊ธฐ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

ํ•ญ๋ชฉ ์œ„ํ—˜ ์ ์ˆ˜๋ฅผ ๊ฒ€์ƒ‰ํ•˜๋ ค๋ฉด ํ•ญ๋ชฉ์„ UDM ์ด๋ฒคํŠธ์— ์กฐ์ธํ•˜๊ณ  EntityRisk์—์„œ ์ง€์ •๋œ ํ•„๋“œ๋ฅผ ๊ฒ€์ƒ‰ํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ ์˜ˆ์‹œ์—์„œ๋Š” ์œ„ํ—˜ ์ ์ˆ˜๊ฐ€ 100๋ณด๋‹ค ํฐ ํ•ญ๋ชฉ ํ˜ธ์ŠคํŠธ ์ด๋ฆ„์—์„œ ๊ฐ์ง€๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ทœ์น™์„ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

rule EntityRiskScore {
  meta:
  events:
    $e1.principal.hostname != ""
    $e1.principal.hostname = $hostname

    $e2.graph.entity.hostname = $hostname
    $e2.graph.risk_score.risk_window_size.seconds = 86400 // 24 hours
    $e2.graph.risk_score.risk_score >= 100

    // Run deduplication across the risk score.
    $rscore = $e2.graph.risk_score.risk_score

  match:
    // Dedup on hostname and risk score across a 4 hour window.
    $hostname, $rscore over 4h

  outcome:
    // Force these risk score based rules to have a risk score of zero to
    // prevent self feedback loops.
    $risk_score = 0

  condition:
    $e1 and $e2
}

์ด ์˜ˆ์‹œ ๊ทœ์น™๋„ ์ผ์น˜ ์„น์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ์ž์ฒด ์ค‘๋ณต ์‚ญ์ œ๋ฅผ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ๊ทœ์น™ ๊ฐ์ง€๊ฐ€ ํŠธ๋ฆฌ๊ฑฐ๋  ์ˆ˜ ์žˆ์ง€๋งŒ ํ˜ธ์ŠคํŠธ ์ด๋ฆ„๊ณผ ์œ„ํ—˜ ์ ์ˆ˜๊ฐ€ 4์‹œ๊ฐ„ ์ด๋‚ด์— ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์œผ๋ฉด ์ƒˆ ๊ฐ์ง€๊ฐ€ ์ƒ์„ฑ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

ํ•ญ๋ชฉ ์œ„ํ—˜ ์ ์ˆ˜ ๊ทœ์น™์— ์ง€์›๋˜๋Š” ์œ ์ผํ•œ ์œ„ํ—˜ ๊ธฐ๊ฐ„์€ 24์‹œ๊ฐ„(86,400์ดˆ) ๋˜๋Š” 7์ผ (604,800์ดˆ)์ž…๋‹ˆ๋‹ค. ๊ทœ์น™์— ์œ„ํ—˜ ๊ธฐ๊ฐ„ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ•˜์ง€ ์•Š์œผ๋ฉด ๊ธฐ๋ณธ์ ์œผ๋กœ 24์‹œ๊ฐ„ ๋˜๋Š” 7์ผ๋กœ ์„ค์ •๋ฉ๋‹ˆ๋‹ค.

ํ•ญ๋ชฉ ์œ„ํ—˜ ์ ์ˆ˜ ๋ฐ์ดํ„ฐ๋Š” ํ•ญ๋ชฉ ์ปจํ…์ŠคํŠธ ๋ฐ์ดํ„ฐ์™€ ๋ณ„๊ฐœ๋กœ ์ €์žฅ๋ฉ๋‹ˆ๋‹ค. ๊ทœ์น™์—์„œ ๋‘˜ ๋‹ค ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๋‹ค์Œ ์˜ˆ์‹œ์— ํ‘œ์‹œ๋œ ๊ฒƒ์ฒ˜๋Ÿผ ํ•ญ๋ชฉ ์ปจํ…์ŠคํŠธ์™€ ํ•ญ๋ชฉ ์œ„ํ—˜ ์ ์ˆ˜ ๊ฐ๊ฐ์— ๋Œ€ํ•ด ํ•˜๋‚˜์”ฉ 2๊ฐœ์˜ ๊ฐœ๋ณ„ ํ•ญ๋ชฉ ์ด๋ฒคํŠธ๊ฐ€ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

rule EntityContextAndRiskScore {
  meta:
  events:
    $log_in.metadata.event_type = "USER_LOGIN"
    $log_in.principal.hostname = $host

    $context.graph.entity.hostname = $host
    $context.graph.metadata.entity_type = "ASSET"

    $risk_score.graph.entity.hostname = $host
    $risk_score.graph.risk_score.risk_window_size.seconds = 604800

  match:
    $host over 2m

  outcome:
    $entity_risk_score = max($risk_score.graph.risk_score.normalized_risk_score)

  condition:
    $log_in and $context and $risk_score and $entity_risk_score > 100
}

๋„์›€์ด ๋” ํ•„์š”ํ•˜์‹ ๊ฐ€์š”? ์ปค๋ฎค๋‹ˆํ‹ฐ ํšŒ์› ๋ฐ Google SecOps ์ „๋ฌธ๊ฐ€๋กœ๋ถ€ํ„ฐ ๋‹ต๋ณ€์„ ๋ฐ›์œผ์„ธ์š”.