1. 들어가며 :
이제 API 버전 3이 VirusTotal과 프로그래밍 방식으로 상호 작용하는 기본 및 권장 방법입니다. 이 버전은 API 버전 2를 크게 개선하며, 당분간 더 이상 사용되지 않습니다. 이 새로운 API는 사용 편의성과 통일성을 염두에 두고 설계되었으며 (http://jsonapi.org/) 사양에서 영감을 얻었습니다.
이 API는 REST 원칙을 따르며 예측 가능한 리소스 지향 URL을 사용합니다. 오류를 포함한 요청과 응답에 JSON을 사용합니다.
이전 API 엔드포인트는 계속 사용할 수 있으며 더 이상 사용되지 않지만, 워크로드를 이 새 버전으로 마이그레이션하는 것이 좋습니다. 다음과 같은 측면에서 훨씬 더 풍부한 데이터가 노출됩니다: IoC relationships, sandbox dynamic analysis information, 파일에 대한 static information, YARA Livehunt & Retrohunt management, crowdsourced detection details 등이 포함됩니다.
2. 가장 많이 사용되는 API endpoints :
- Upload a file for scanning: 70개 이상의 안티바이러스 제품, 10개 이상의 동적 분석 샌드박스 및 기타 수많은 보안 도구로 파일을 분석하여 위협 점수 및 관련 컨텍스트를 생성하여 파일을 이해합니다.
- Get a file report by hash: {md5, sha1, sha256} 해시가 주어지면 70개 이상의 안티바이러스 제품, 10개 이상의 동적 분석 샌드박스, 기타 수많은 보안 도구 및 데이터 세트에서 생성된 위협 평판 및 컨텍스트를 포함한 관련 분석 보고서를 검색합니다.
- Scan URL: 70개 이상의 안티바이러스 제품/차단 목록 및 기타 수많은 보안 도구로 URL을 분석하여 위협 점수 및 관련 컨텍스트를 생성하고 이를 이해합니다.
- Get a URL analysis report: URL이 주어지면 70개 이상의 안티바이러스 제품/차단 목록과 수많은 기타 보안 도구 및 데이터 세트에서 생성된 위협 평판 및 컨텍스트를 포함한 관련 분석 보고서를 검색합니다.
- Get a domain report: 도메인이 지정되면 70개 이상의 안티바이러스 제품/차단 목록과 수많은 기타 보안 도구 및 데이터 세트에서 생성된 위협 평판 및 컨텍스트를 포함한 관련 분석 보고서를 검색합니다.
- Get an IP address report: IP 주소가 주어지면 70개 이상의 안티바이러스 제품/차단 목록과 수많은 기타 보안 도구 및 데이터 세트에서 생성된 위협 평판 및 컨텍스트를 포함한 관련 분석 보고서를 검색합니다.
3. Getting Started :
일단 API를 사용하려면 VirusTotla community에 가입을 해야합니다. 유요한 계정이 있으면 개인 설정 섹션에서 개인 API KEY를 찾을 수 있습니다. 이 키만 있으면 VirusTotal API를 사용할 수 있습니다.
4. API response :
VirusTotal API의 대부분의 엔드포인트는 JSON 형식으로 응답을 반환합니다. 별도로 지정하지 않는 한 성공적인 요청의 응답은 200 HTTP 상태 코드를 반환하며 형식은 다음과 같습니다.
{
"data": <response data>
}
<response data>일반적으로 개체 또는 개체 목록이지만 항상 그런 것은 아닙니다.
5. ERROR code :
VirusTotal API는 일반적인 HTTP 응답 코드를 따라 성공 또는 실패를 나타냅니다. 범위의 코드는 성공을 나타냅니다. 범위 의 코드는 요청의 오류를 나타냅니다(예: 누락된 매개변수, 리소스를 찾을 수 없음). 범위 내의 코드는 VirusTotal 서버의 오류를 나타내며 드물게 발생합니다.
실패한 요청은 오류에 대한 추가 정보를 JSON 형식으로 반환합니다.
{
"error": {
"code": "<error code>",
"message": "<a message describing the error>"
}
}
오류 코드는 아래 표에 제공된 값 중 하나가 포함된 문자열입니다. 일반적으로 오류에 대한 정보를 조금 더 제공합니다.
HTTP Code | Error code | Description |
400 | BadRequestError | The API request is invalid or malformed. The message usually provides details about why the request is not valid. |
400 | InvalidArgumentError | Some of the provided arguments are incorrect. |
400 | NotAvailableYet | The resource is not available yet, but will become available later. |
400 | UnselectiveContentQueryError | Content search query is not selective enough. |
400 | UnsupportedContentQueryError | Unsupported content search query. |
401 | AuthenticationRequiredError | The operation requires an authenticated user. Verify that you have provided your API key. |
401 | UserNotActiveError | The user account is not active. Make sure you properly activated your account by following the link sent to your email. |
401 | WrongCredentialsError | The provided API key is incorrect. |
403 | ForbiddenError | You are not allowed to perform the requested operation. |
404 | NotFoundError | The requested resource was not found. |
409 | AlreadyExistsError | The resource already exists. |
424 | FailedDependencyError | The request depended on another request and that request failed. |
429 | QuotaExceededError | You have exceeded one of your quotas (minute, daily or monthly). Daily quotas are reset every day at 00:00 UTC. You may have run out of disk space and/or number of files on your VirusTotal Monitor account. |
429 | TooManyRequestsError | Too many requests. |
503 | TransientError | Transient server error. Retry might work. |
504 | DeadlineExceededError | The operation took too long to complete. |
6. Key concept :
VirusTotal API v3는 objects, collections와 relationships 세 가지 주요 컨셉을 중심으로 합니다.
objects,는 API를 사용하여 검색하거나 조작할 수 있는 모든 항목입니다. 파일, URL, 도메인 이름 및 VT Hunting 규칙 세트는 API에 의해 노출되는 개체 유형 중 일부입니다.
collections은 개체 집합입니다. 컬렉션의 개체는 일반적으로 동일한 유형이지만 해당 규칙에는 몇 가지 예외가 있습니다. 일부 API 작업은 개체에서 수행되는 반면 다른 작업은 컬렉션에서 수행됩니다.
relationships는 개체 간의 링크입니다. 예를 들어 파일 중 하나가 다른 파일을 포함하는 ZIP이기 때문에 파일이 다른 파일과 관련될 수 있고 URL은 파일이 URL에서 다운로드되었기 때문에 파일과 관련될 수 있으며 도메인 이름은 해당 도메인의 모든 URL과 관련됩니다.
6-1. Object
개체는 VirusTotal API의 핵심 개념입니다. 각 객체에는 식별자와 유형이 있습니다. 식별자는 동일한 유형의 개체 간에 고유하며, 이는 (유형, 식별자) 쌍이 API 전체에서 모든 개체를 고유하게 식별한다는 것을 의미합니다. 이러한 (유형, 식별자) 쌍을 객체 설명자라고 합니다.
각 객체에는 다음과 같은 구조로 연결된 URL이 있습니다:
https://www.virustotal.com/api/v3/{collection name}/{object id}
일반적으로 {collection name}은 개체 유형의 복수형입니다 (예: 파일은 파일 유형의 모든 개체를 포함하는 컬렉션이고, analyses은 모든 analyses 개체를 포함하는 컬렉션입니다). {object id} 형식은 개체 유형에 따라 다릅니다.
개체의 URL에 대한 GET 요청은 다음 형식으로 개체에 대한 정보를 반환합니다:
{
"data": {
"type": "{object type}",
"id": "{object id}",
"links": {
"self": "https://www.virustotal.com/api/v3/{collection name}/{object id}"
},
"attributes" : {
"integer_attribute": 1234,
"string_attribute": "this is a string",
"dictionary_attribute": { "one": 1, "two": 2 },
"list_attribute": [ "foo", "bar", "baz" ]
},
"relationships" : {
..
}
}
}
객체에는 ID와 유형 외에도 여러 attributes과 relationships이 있습니다. attributes은 lists과 dictionaries을 포함하여 JSON에서 지원하는 모든 유형이 될 수 있습니다. attributes 필드는 모든 개체에 항상 존재하지만, relationships는 요청할 때 관계를 포함하도록 요청했는지 여부에 따라 선택 사항입니다. 이에 대해서는 relationships 섹션에서 자세히 설명합니다.
각 객체 유형에는 미리 정의된 고유한 attributes 집합이 있으며, attributes을 추가하거나 제거할 수 없고 기존 속성만 수정할 수 있습니다(쓰기 가능한 경우). 객체의 속성을 수정하려면 해당 객체의 URL로 PATCH 요청을 보내야 합니다. 읽기 전용 속성을 수정하려고 하면 오류가 발생합니다. PATCH 요청 본문에는 아래 예시와 같은 구조로 수정하려는 속성이 포함되어야 합니다. 요청에 포함되지 않은 속성은 변경되지 않은 상태로 유지됩니다.
// Example PATCH request
{
"data": {
"type": "{object type}",
"id": "{object id}",
"attributes" : {
"integer_attribute": 1234,
"string_attribute": "this is a new string",
}
}
}
object's ID와 type은 모두 PATCH 요청의 본문에 포함되며, URL에 지정된 것과 일치해야 합니다.
일부 오브젝트 유형은 해당 오브젝트의 URL로 DELETE 요청을 보내 삭제할 수도 있습니다.
6-2. Collection
Collections은 객체의 집합입니다. 대부분의 객체 유형에는 해당 유형의 모든 객체를 나타내는 최상위 컬렉션이 있습니다. 이러한 컬렉션은 다음과 같은 URL을 사용하여 액세스 할 수 있습니다:
https://www.virustotal.com/api/v3/{collection name}
VirusTotal API의 많은 작업은 컬렉션에 요청을 전송하여 수행됩니다. 예를 들어, 파일 컬렉션에 새 항목을 효과적으로 추가하는 /api/v3/files로 POST 요청을 보내 파일을 분석할 수 있습니다. 새로운 VT Hunting 규칙 집합을 만들려면 /api/v3/intelligence/hunting_rulesets로 POST 요청을 보내면 됩니다. 컬렉션에 POST 요청을 보내는 것이 일반적으로 새 개체가 생성되는 방식입니다.
마찬가지로 컬렉션으로 전송된 DELETE 요청은 해당 컬렉션의 모든 개체를 삭제하는 효과가 있습니다. 파일, URL 또는 분석과 같은 특정 컬렉션에 대한 DELETE 메서드는 없지만, hunting_notifications와 같은 다른 컬렉션 유형에 DELETE를 사용하여 모든 VT 헌팅 알림을 제거할 수 있습니다.
또한 많은 컬렉션은 반복이 가능하므로 컬렉션에 연속적인 GET 요청을 보내 컬렉션의 모든 개체를 검색할 수 있습니다. 각 요청마다 여러 개의 객체와 반복을 계속하는 데 사용되는 커서를 가져옵니다. 아래 코드조각은 /api/v3/{컬렉션 이름}에 대한 GET 요청의 응답을 예시합니다.
{
"data": [
{ .. object 1 .. },
{ .. object 2 .. },
{ .. object 3 .. }
],
"meta": {
"cursor": "CuABChEKBGRhdGUSCQjA1.."
},
"links": {
"next": "https://www.virustotal.com/api/v3/{collection name}?cursor=CuABChEKBGRhdGUSCQjA1..",
"self": "https://www.virustotal.com/api/v3/{collection name}"
}
}
링크 섹션의 next 필드에서 알 수 있듯이 응답 메타데이터의 cursor를 다음 객체 집합을 검색하기 위한 후속 호출의 매개변수로 사용할 수 있습니다. 또한 limit 매개변수를 사용하여 각 호출에서 반환되는 개체 수를 제어할 수도 있습니다.
6-3. Relationship
relationship은 VirusTotal API가 개체 간의 링크 또는 종속성을 표현하는 방식입니다. 개체는 동일하거나 다른 유형의 개체와 연관될 수 있습니다. 예를 들어, 파일 개체는 첫 번째 개체를 포함하는 다른 파일 개체와 연관되거나 파일 개체는 파일에 포함된 URL을 나타내는 URL 개체와 연관될 수 있습니다.
관계는 객체가 단일 객체와 연관되어 있는지 또는 여러 객체와 연관되어 있는지에 따라 일대일 또는 일대다일일 수 있습니다.
GET 요청으로 특정 개체를 검색할 때 다른 개체와의 관계도 검색하고 싶을 수 있습니다. 이 경우 관계 매개변수에 검색하려는 관계를 지정하면 됩니다.
https://www.virustotal.com/api/v3/{collection name}/{object id}?relationships={relationship}
쉼표로 구분된 관계 이름 목록을 지정하여 둘 이상의 관계를 응답에 포함할 수 있습니다.
https://www.virustotal.com/api/v3/{collection name}/{object id}?relationships={relationship 1},{relationship 2}
이러한 요청에 의해 반환되는 객체에는 relationships dictionary이 포함되며, 여기서 키는 요청된 관계의 이름이고 값은 object descriptor(관계가 일대일인 경우)이거나 컬렉션 섹션에 설명된 컬렉션(관계가 일대다인 경우)입니다. 그러나 이러한 컬렉션에는 관련 객체 전체가 아니라 해당 객체의 설명자(예: 유형 및 ID)만 포함됩니다.
{
"type": "{object type}",
"id": "{object id}",
"links": {
"self": "https://www.virustotal.com/api/v3/{collection name}/{object id}"
},
"attributes" : {
..
},
"relationships" : {
"{one-to-one relationship}": {
"data": {
"id": "www.google.com",
"type": "domain"
},
"links": {
"related": "https://www.virustotal.com/api/v3/{collection name}/{object id}/{one-to-one relationship}",
"self": "https://www.virustotal.com/api/v3/{collection name}/{object id}/relationships/{one-to-one relationship}"
}
},
"{one-to-many relationship}": {
"data": [
{ .. object descriptor 1 .. },
{ .. object descriptor 2 .. },
{ .. object descriptor 3 .. }
],
"meta": {
"cursor": "CuABChEKBGRhdGUSCQjA1LC...",
},
"links": {
"next": "https://www.virustotal.com/api/v3/{collection name}/{object id}/relationships/{one-to-many relationship}?cursor=CuABChEKBGRhdGUSCQjA1LC...",
"self": "https://www.virustotal.com/api/v3/{collection name}/{object id}/relationships/{one-to-many relationship}"
},
},
"{relationship 2}": { ... },
"{relationship 3}": { ... }
}
}
위 예제에서 관계의 링크 필드를 자세히 살펴보면 자체 URL이 다음과 같이 표시되는 것을 볼 수 있습니다:
https://www.virustotal.com/api/v3/{collection name}/{object id}/relationships/{relationship}
일대다 관계는 기본 개체와 어떤 식으로든 연관된 개체를 포함하는 단순한 컬렉션이므로 일반적으로 컬렉션 섹션에 설명된 대로 URL에 GET 요청을 보내 관련 개체를 반복하는 데 사용할 수 있는 고유한 URL이 있습니다. 실제로 URL에는 두 가지 유형이 있습니다:
https://www.virustotal.com/api/v3/{collection name}/{object id}/relationships/{relationship}
https://www.virustotal.com/api/v3/{collection name}/{object id}/{relationship}
첫 번째 컬렉션은 관련 개체에 대한 설명자(유형 및 ID)만 포함하는 컬렉션이고, 두 번째 컬렉션은 모든 속성을 포함한 전체 개체를 포함합니다. 관련 개체의 유형과 ID에만 관심이 있는 경우 전체 개체보다 설명자만 검색하는 것이 더 효율적이므로 첫 번째 컬렉션을 사용해야 합니다.
두 엔드포인트의 또 다른 중요한 차이점은 {object id}/relationships/{relationship}는 독립적인 엔티티로서 관계를 나타내며, 객체를 변경하지 않고 관계를 변경하는 작업을 지원할 수 있다는 것입니다. 반면 {object id}/{relationship}는 관계가 아닌 관련 객체를 나타냅니다. 예를 들어 사용자에게 그래프에 대한 보기 권한을 부여하려는 경우 아래와 같이 사용합니다:
POST https://www.virustotal.com/api/v3/graphs/{id}/relationships/viewers
이 엔드포인트는 사용자 설명자를 받지만 사용자나 그래프를 수정하지 않고 단순히 둘 사이의 관계를 생성합니다. 반면에 사용하는 파일에 대한 새 comment을 만들 때:
POST https://www.virustotal.com/api/v3/files/{id}/comments
이 경우 파일과 comment 간의 관계를 수정할 뿐만 아니라 새 comment 객체도 생성하기 때문입니다.
Relationships with objects not present in VirusTotal's database
여러 가지 이유로 어떤 객체가 데이터베이스에 존재하지 않는 다른 객체와 연관되어 있을 수 있습니다. 이러한 경우 반환되는 관계에는 요소 ID와 "NotFoundError" 오류 코드만 포함됩니다.
{
"data": [
{
"error": {
"code": "NotFoundError",
"message": "{item type} with id \"{item id}\" not found"
},
"id": "{item id}",
"type": "{item type}"
},
{ .. object 2 .. },
...
],
"links": {
"self": "https://www.virustotal.com/api/v3/{collection name}/{object id}/{one-to-many relationship}"
}
}
객체 설명자만 요청하는 경우(즉, /api/v3/{collection name}/{object id}/**relationships**/{relationship name} 대신 /api/v3/{collection name}/{object id}/{relationship name}을 요청하는 경우) 이 오류는 반환되지 않습니다.
7. 마치며
이번 포스팅에서는 virusTotal API에 대해서 기본적인 개념과 어떤 식으로 사용하면 되는지에 대해서 알아봤습니다. 앞서 설명한 것과 같이 Virustotal은 여러 제휴 업체와 함께 파일, url, domain 등을 사이버 보안 관련해서 큰 도움을 줍니다. 따라서 VirusTotal를 잘 이용하면 큰 도움이 될 수 있을 것 같습니다.