본문 바로가기
Security

Splunk Phantom REST API 기본 사용

by 올엠 2021. 8. 19.
반응형

최근 Splunk를 사용하는 회사가 늘고 있다. 여기에 Splunk회사에서 인수한 Phantom이라는 SOAR(Security Orchestration, Automation, and Response) 솔류션이 있는데, 사용법이 초반에 익숙해 지는데 시간이 좀 필요하다.

기본적인 개념은 Container라는 것이 하나의 인스턴스이고 여기에 Artifact(인스턴스 관련증적)을 넣은 사전에 만들어 놓은 App등을 통해  조사를 진행하는 방식이 기본 구조라 할 수 있다. 여기에 최근 필자가 REST API를 사용할 일이 있어 여기에 정리해 본다.

기본적으로는 https://docs.splunk.com/Documentation/Phantom/4.10.4/PlatformAPI/Using 에 어떻게 활용할 수 있는지 예제가 나와있고, 여기에서는 핵심 부분만 정리해 보았다.

Basic

먼저 Phantom은 기본적으로 Get/Post 호출로 구분되는데, Get은 검색 Post는 생성으로 이용된다.

그리고 Get 을 통한 검색에는 ?_filter_를 이용하여 사용할 수 있다.

 

주요하게 사용할 수 있는 구분 URI  경로는 다음과 같다.

  • action_run
  • artifact
  • asset
  • app
  • app_run
  • container
  • playbook_run
  • cluster_node

굵게 표시한 부분은 제일 많이 사용이 될 것으로 보이는 항목이라고 이해하면 된다.

기본적인 호출은 위 URI를 포함하여 만약 phantom 주소 기준으로 https://localhost/rest/{구분URI}/ 가 된다. container를 조회한다면 다음과 같이 입력할 수 있다.

https://phantom.localhost/rest/container

이후 생성/실행이라면 Post 메소드를 통해 JSON을 통한 data를 입력해주고, 값을 가져오는 것이라면 Get 메소드를 통해 URI에 검색 값을 넣어주거나, 넣지 않는 경우 전체 값을 가져오는 방식으로 이해하면 된다.

파이썬 기준으로 Container를 만들고 해당 Container에 Artifact를 넣는 Code는 다음과 같이 만들 수 있다.

def add_container(name):
  url = 'https://{}/rest/container'.format(PHANTOM_SERVER)

  post_data = container_common.copy()
  post_data['name'] = '{} ({})'.format(name, sid)
  post_data['source_data_identifier'] = sid
  json_blob = json.dumps(post_data)

  # set verify to False when running with a self signed certificate
  r = requests.post(url, data=json_blob, headers=headers, verify=False)
  if (r is None or r.status_code != 200):
    if r is None:
      print('error adding container')
    else:
      print('error {} {}'.format(r.status_code,json.loads(r.text)['message']))
    return False

  return r.json().get('id')
  
def add_artifact(row, container_id):
  url = 'https://{}/rest/artifact'.format(PHANTOM_SERVER)

  post_data = {}
  post_data['name'] = 'artifact for {}'.format(row[4])
  post_data['label'] = ARTIFACT_LABEL
  post_data['container_id'] = container_id
  post_data['source_data_identifier'] = "source data primary key for artifact or other identifier"

  # The cef key is intended for structured data that can be used when
  # dealing with product agnostic apps or playbooks. Place any standard
  # CEF fields here.
  cef = {
    'sourceAddress': row[0],
    'sourcePort': row[1],
    'hash': row[2],
  }

  # The "data" key can contain arbitrary json data. This is useful for
  # keeping data that does not comfortably fit into CEF fields or is highly
  # product specific
  data = cef.copy()
  data['score'] = row[3]
  data['comment'] = row[4]

  post_data['cef'] = cef
  post_data['data'] = data

  json_blob = json.dumps(post_data)

  # set verify to False when running with a self signed certificate
  r = requests.post(url, data=json_blob, headers=headers, verify=False)

  if (r is None or r.status_code != 200):
    if (r is None):
      print('error adding artifact')
    else:
      error = json.loads(r.text)
      print('error {} {}'.format(r.status_code, error['message']))
    return False

  resp_data = r.json()
  return resp_data.get('id')
 
if __name__ == '__main__':
  temp_artifact = ['127.0.0.1','3386','1122341234','temp','test']
  container_id = add_container("New Container")
  artifact_id = add_artifact("Temp Artifact", container_id)
  print('Make container: %s, Artifact: %s', container_id, artifact_id)
  sys.exit(0)

 

Phantom에 만들어진 특정 액션을 실행하고자 한다면, 다음과 같이 진행할 수 있다. 액션을 수행할 때 주의점은 Action 을 실행할 app의 name과 app_id, assets 번호가 Phantom에서 지정되어있는 값과 동일해야 한다는 것이다. 여기에서는 App name이 whois_ip 이고 app_id는 112, assets 은 322이다.

(POST Method)
https://phantom.localhost/rest/action_run/ 
{
    "action": "whois ip",
    "container_id": 51165,
    "name": "whois_ip",
    "targets": [
        {
            "app_id": 112,
            "assets": [
                323
            ],
            "parameters": [
                {
                    "ip": "192.241.211.91"
                }
            ]
        }
    ],
    "type": "investigative"
}

Filter

추가로 필터를 이용해서는 검색이 가능하다.

Get 메소드를 이용하여 검색을 할 수 있으며, ?_filter를 통해 특정 필드를 지정하고 이후 조건을 걸수 있다.

아래는 container가 특정 날짜가 포함된 조건으로 검색을 진행하게 된다. 

https://phantom.localhost/rest/container?_filter_start_time__contains="2021-08-03"

같은 값을 검색하는 경우 = 를 통해서 가능하다.

https://phantom.localhost/rest/artifact?_filter_container_id=11111111

 

반응형