HackerOne 로그 수집
이 문서에서는 Webhooks를 사용하여 로그를 Google Security Operations로 푸시하도록 HackerOne을 구성하는 방법을 설명합니다.
HackerOne은 조직과 보안 연구원을 연결하여 보안 취약점을 식별하고 해결하는 취약점 조정 및 버그 바운티 플랫폼입니다. 이 플랫폼은 소프트웨어 개발 수명 주기 전반에서 버그 바운티 프로그램, 취약점 공개 프로그램, 침투 테스트, 지속적인 보안 테스트를 제공합니다.
시작하기 전에
다음 기본 요건이 충족되었는지 확인합니다.
- Google SecOps 인스턴스
- Professional 또는 Enterprise 등급의 HackerOne 프로그램 (웹훅은 이러한 등급에서만 사용 가능)
- HackerOne 프로그램 설정에 대한 관리 액세스 권한
Google SecOps에서 웹훅 피드 만들기
피드 만들기
- SIEM 설정> 피드로 이동합니다.
- 새 피드 추가를 클릭합니다.
- 다음 페이지에서 단일 피드 구성을 클릭합니다.
- 피드 이름 필드에 피드 이름을 입력합니다(예:
HackerOne Vulnerability Reports). - 소스 유형으로 웹훅을 선택합니다.
- 로그 유형으로 HackerOne을 선택합니다.
- 다음을 클릭합니다.
- 다음 입력 파라미터의 값을 지정합니다.
- 분할 구분 기호 (선택사항): 비워 둡니다. 각 웹훅 요청에는 단일 JSON 이벤트가 포함됩니다.
- 애셋 네임스페이스: 애셋 네임스페이스입니다.
- 수집 라벨: 이 피드의 이벤트에 적용할 라벨입니다.
- 다음을 클릭합니다.
- 확정 화면에서 새 피드 구성을 검토한 다음 제출을 클릭합니다.
보안 비밀 키 생성 및 저장
피드를 만든 후 인증을 위한 보안 비밀 키를 생성해야 합니다.
- 피드 세부정보 페이지에서 보안 비밀 키 생성을 클릭합니다.
- 대화상자에 보안 비밀 키가 표시됩니다.
- 보안 비밀번호를 안전하게 복사하여 저장합니다.
피드 엔드포인트 URL 가져오기
- 피드의 세부정보 탭으로 이동합니다.
- 엔드포인트 정보 섹션에서 피드 엔드포인트 URL을 복사합니다.
URL 형식은 다음과 같습니다.
https://malachiteingestion-pa.googleapis.com/v2/unstructuredlogentries:batchCreate또는
https://<REGION>-malachiteingestion-pa.googleapis.com/v2/unstructuredlogentries:batchCreate다음 단계를 위해 이 URL을 저장합니다.
완료를 클릭합니다.
Google Cloud API 키 만들기
Chronicle에는 인증을 위한 API 키가 필요합니다. Google Cloud 콘솔에서 제한된 API 키를 만듭니다.
API 키 만들기
- Google Cloud 콘솔 사용자 인증 정보 페이지로 이동합니다.
- 프로젝트 (Chronicle 인스턴스와 연결된 프로젝트)를 선택합니다.
- 사용자 인증 정보 만들기 API 키를 클릭합니다.
- API 키가 생성되어 대화상자에 표시됩니다.
- API 키 수정을 클릭하여 키를 제한합니다.
API 키 제한
- API 키 설정 페이지에서 다음을 수행합니다.
- 이름: 설명이 포함된 이름을 입력합니다 (예:
Chronicle HackerOne Webhook API Key).
- 이름: 설명이 포함된 이름을 입력합니다 (예:
- API 제한사항에서 다음을 수행합니다.
- 키 제한을 선택합니다.
- API 선택 목록에서 Google SecOps API (또는 Chronicle API)를 검색하여 선택합니다.
- 저장을 클릭합니다.
- 페이지 상단의 API 키 필드에서 API 키 값을 복사합니다.
API 키를 안전하게 저장합니다.
HackerOne 웹훅 구성
웹훅 URL 구성
Chronicle 엔드포인트 URL과 API 키를 결합합니다.
<ENDPOINT_URL>?key=<API_KEY>예:
https://malachiteingestion-pa.googleapis.com/v2/unstructuredlogentries:batchCreate?key=AIzaSyD...
HackerOne에서 웹훅 만들기
- HackerOne에 로그인하고 프로그램으로 이동합니다.
- 참여로 이동하여 구성하려는 프로그램의 더보기 메뉴를 클릭한 다음 설정을 클릭합니다.
- 자동화 > 웹훅으로 이동합니다.
- 새 웹훅을 클릭합니다.
- 다음 구성 세부정보를 제공합니다.
- 페이로드 URL: 위의 API 키가 포함된 전체 엔드포인트 URL을 붙여넣습니다.
- Secret: Chronicle 피드 생성에서 보안 비밀 키를 붙여넣습니다.
- 웹훅을 트리거할 이벤트 선택: 다음 중 하나를 선택합니다.
- 모두 보내기: 모든 이벤트가 웹훅을 트리거합니다.
- 개별 이벤트 직접 지정: Chronicle로 전송할 특정 이벤트를 선택합니다. 보안 모니터링을 위한 추천 이벤트:
- report_created: 해커가 새로운 취약점 신고를 제출하는 경우
- report_triaged: 신고가 분류된 경우
- report_resolved: 신고가 해결된 경우
- report_bounty_awarded: 보상이 지급된 경우
- report_swag_awarded: 상품이 지급된 경우
- program_hacker_joined: 해커가 프로그램에 가입하는 경우
- program_hacker_left: 해커가 프로그램에서 나가는 경우
- 웹훅 추가를 클릭합니다.
웹훅 테스트
- 웹훅 구성 페이지에서 테스트 요청을 선택하여 구성된 페이로드 URL에 예시 요청을 보냅니다.
- 응답이 HTTP 200인지 확인합니다.
- 1~2분 이내에 테스트 이벤트에 대한 Chronicle 피드를 확인합니다.
웹훅이 작동하는지 확인
HackerOne 웹훅 상태 확인
- HackerOne 콘솔에 로그인합니다.
- 참여로 이동하여 프로그램의 케밥 메뉴를 클릭한 다음 설정을 클릭합니다.
- 자동화 > 웹훅으로 이동합니다.
- 웹훅을 클릭하여 세부정보를 확인합니다.
- 최근 전송 섹션에서 최근 전송이 성공 상태 (HTTP 200)로 표시되는지 확인합니다.
- 배송을 클릭하여 POST 페이로드 요청을 확인합니다.
Chronicle 피드 상태 확인
- Chronicle에서 SIEM 설정 > 피드로 이동합니다.
- HackerOne 웹훅 피드를 찾습니다.
- 상태 열을 확인합니다 (활성이어야 함).
- 수신된 이벤트 수를 확인합니다 (증가해야 함).
- 최종 성공 시간 타임스탬프를 확인합니다 (최근이어야 함).
Chronicle에서 로그 확인
- 검색 > UDM 검색으로 이동합니다.
다음 쿼리를 사용하세요.
metadata.vendor_name = "HACKERONE" AND metadata.product_name = "HACKERONE"기간을 지난 1시간으로 조정합니다.
이벤트가 결과에 표시되는지 확인합니다.
인증 방법 참조
Chronicle 웹훅 피드는 여러 인증 방법을 지원합니다. HackerOne 웹훅은 쿼리 매개변수와 서명 검증을 함께 사용합니다.
방법 1: 서명 유효성 검사가 포함된 쿼리 매개변수 (HackerOne에 권장)
HackerOne은 구성된 페이로드 URL로 웹훅을 전송합니다. 인증은 다음을 통해 처리됩니다.
- URL의 API 키: Chronicle API 키가 페이로드 URL에 쿼리 매개변수로 추가됩니다.
보안 비밀 서명 유효성 검사: HackerOne은 구성된 보안 비밀로 서명된 요청 본문의 HMAC SHA256 hexdigest가 포함된 X-H1-Signature 헤더를 생성합니다.
URL 형식:
<ENDPOINT_URL>?key=<API_KEY>요청 형식:
POST <ENDPOINT_URL>?key=<API_KEY> HTTP/1.1 Content-Type: application/json X-H1-Signature: sha256=<HMAC_HEXDIGEST> X-H1-Event: <EVENT_TYPE> X-H1-Delivery: <DELIVERY_ID> { "data": { "activity": {...}, "report": {...} } }
장점:
- 이중 인증: Chronicle 액세스용 API 키 및 페이로드 검증용 서명
- HackerOne은 기본 서명 생성을 제공합니다.
- 보안 페이로드 무결성 확인
서명 유효성 검사
HackerOne은 각 웹훅 요청에 다음 헤더를 포함합니다.
- X-H1-Signature: 요청 본문의 HMAC SHA256 16진수 다이제스트 (형식:
sha256=<hexdigest>) - X-H1-Event: 웹훅을 트리거한 이벤트 유형
- X-H1-Delivery: 배송의 고유 식별자
- X-H1-Signature: 요청 본문의 HMAC SHA256 16진수 다이제스트 (형식:
수신 엔드포인트에서 서명을 검증하려면 다음 단계를 따르세요.
import hmac import hashlib def validate_request(request_body, secret, signature): _, digest = signature.split('=') generated_digest = hmac.new( secret.encode(), request_body.encode(), hashlib.sha256 ).hexdigest() return hmac.compare_digest(digest, generated_digest)
웹훅 이벤트 유형
HackerOne은 다음 웹훅 이벤트 유형을 지원합니다.
| 이벤트 유형 | 설명 |
|---|---|
| report_created | 해커가 새로운 취약점 보고서를 제출할 때 트리거됩니다. |
| report_triaged | 보고서가 분류될 때 트리거됩니다. |
| report_resolved | 신고가 해결될 때 트리거됩니다. |
| report_bounty_awarded | 보고서에 대한 보상이 지급될 때 트리거됩니다. |
| report_swag_awarded | 보고서에 대한 상품이 지급될 때 트리거됩니다. |
| report_became_public | 보고서가 공개되면 트리거됩니다. |
| program_hacker_joined | 해커가 프로그램에 참여할 때 트리거됩니다. |
| program_hacker_left | 해커가 프로그램을 나갈 때 트리거됩니다. |
UDM 매핑 테이블
| 로그 필드 | UDM 매핑 | 논리 |
|---|---|---|
| attributes.cleared, attributes.rules_of_engagement_signed, attributes.identity_verified, attributes.background_checked, attributes.citizenship_verified, attributes.residency_verified, type, attributes.title, attributes.main_state, attributes.state, relationships.reporter.data.type, relationships.reporter.data.attributes.reputation, relationships.reporter.data.attributes.signal, relationships.reporter.data.attributes.impact, relationships.reporter.data.attributes.disabled, relationships.reporter.data.attributes.profile_picture.62x62, relationships.reporter.data.attributes.profile_picture.82x82, relationships.reporter.data.attributes.profile_picture.110x110, relationships.reporter.data.attributes.profile_picture.260x260, relationships.reporter.data.attributes.hackerone_triager, relationships.program.data.id, relationships.program.data.type, relationships.program.data.attributes.handle, relationships.severity.data.type, relationships.severity.data.attributes.rating, relationships.severity.data.attributes.author_type, relationships.severity.data.attributes.calculation_method, relationships.weakness.data.id, relationships.weakness.data.type, relationships.weakness.data.attributes.name, relationships.weakness.data.attributes.description, relationships.weakness.data.attributes.external_id, relationships.structured_scope.data.id, relationships.structured_scope.data.type, relationships.structured_scope.data.attributes.asset_type, relationships.structured_scope.data.attributes.eligible_for_bounty, relationships.structured_scope.data.attributes.eligible_for_submission, relationships.structured_scope.data.attributes.instruction, relationships.structured_scope.data.attributes.max_severity, relationships.structured_scope.data.attributes.confidentiality_requirement, relationships.structured_scope.data.attributes.integrity_requirement, relationships.structured_scope.data.attributes.availability_requirement, relationships.inboxes.data.id, relationships.inboxes.data.type, relationships.inboxes.data.attributes.name, relationships.inboxes.data.attributes.type | additional.fields | 키-값 라벨로 병합됨 |
| 타임스탬프 | metadata.event_timestamp | yyyy-MM-dd'T'HH:mm:ss.SSSZ 형식의 날짜 필터를 사용하여 파싱됨 |
| metadata.event_type | has_principal이 true이면 'STATUS_UPDATE', has_principal_user_user가 true이면 'USER_UNCATEGORIZED', 그 밖의 경우에는 'GENERIC_EVENT'로 설정됩니다. | |
| id | metadata.product_log_id | 값이 직접 복사됨 |
| relationships.structured_scope.data.attributes.asset_identifier | principal.asset.asset_id | 'ASSET:'으로 시작합니다. |
| attributes.email_alias | principal.user.email_addresses | 병합됨 |
| relationships.reporter.data.id | principal.user.employee_id | 값이 직접 복사됨 |
| relationships.reporter.data.attributes.name | principal.user.first_name | 값이 직접 복사됨 |
| attributes.username, relationships.reporter.data.attributes.username | principal.user.user_display_name | 비어 있지 않은 경우 relationships.reporter.data.attributes.username의 값, 그렇지 않은 경우 attributes.username |
| relationships.severity.data.attributes.user_id | principal.user.userid | 값이 직접 복사됨 |
| relationships.severity.data.id | security_result.rule_id | 값이 직접 복사됨 |
| relationships.severity.data.attributes.max_severity | security_result.severity | 대문자로 변환됨 |
| attributes.vulnerability_information | security_result.summary | 값이 직접 복사됨 |
도움이 더 필요하신가요? 커뮤니티 회원 및 Google SecOps 전문가에게 문의하여 답변을 받으세요.