🦠

VirusTotal api を利用してみた

に公開

今回は、VirusTotal の API (無料版)を利用してみたのでその記録を記したいと思います。

VirusTotal とは

ウェブサイトやファイルに「マルウェアが含まれていないかどうか」をブラウザ上で検査できるツールです[1]。
検査、いわゆるオンラインスキャンを行うだけであり、マルウェアの除去はできません。
ツールの運営・管理は Google が行っています。
VirusTotalはこちら

[1]:VirusTotal-Wikipedia

VirusTotal API とは

VirusTotal では、ブラウザを使わずにプログラムから利用するための API が提供されています[2]。
VirusTotal API には Public API(無料版)とPremium API(有料版)があり、以下のような違いがあるそうです[3]。

  • Public API(無料版)
    • 制限あり:500リクエスト/日、4リクエスト/分
    • 商用利用やビジネスワークフローでの利用は禁止
    • 複数アカウント作成による制限回避は禁止
  • Premium API(有料版)
    • 利用制限なし(契約プランに応じたリクエスト数・クオータを選択可能)
    • SLA(サービス品質保証)があり、可用性・データ準備が保証される
    • より詳細でリッチな解析情報を取得可能(例:VBAコード警告、Exif情報、IDSログ、SSL証明書情報など)

[2];VirusTotal API Overview
[3]:Public vs Premium API

API を利用してみた

今回は、数ある VirusTotal API のうち、ウェブサイトをスキャンしてくれる Scan URL API[4] と スキャンの結果を取得する Get a URL API[5] を利用してみます。
ブラウザで利用している時は意識していませんでしたが、上記のようにスキャン用の API とスキャン結果を取得する API が分かれているようです。
なお、今回は macOS の zsh(bash互換)シェルで実行しました。

[4];Scan URL
[5]:Get a URL / file analysis

事前準備 1:API キーの取得

VirusTotal API を利用するためには API キーを取得する必要があります。
API キーは VirusTotal へのユーザー登録後、ホーム画面の以下のページから取得可能です。

事前準備 2:分析対象 URL の準備

今回は、私宛に届いた以下の迷惑メールに記載されていた URL を分析の対象にしてみました。

Scan URL

コマンドの実行

bash にて以下のコマンドを実行します。

curl --request POST \
     --url https://www.virustotal.com/api/v3/urls \
     --header "x-apikey: 自身の API キー" \
     --header "accept: application/json" \
     --header "content-type: application/x-www-form-urlencoded" \
     --data-urlencode "url=スキャン対象の URL"

※Scan URL のドキュメントでは、API キーとスキャン対象の URL の入力は省略されていますが、API で実行する場合にはこれらを入力する必要があります。

実行結果

以下の内容を含んだ実行結果が出力されます。

  • id: 解析ジョブの一意な識別子
  • links.self: この解析ジョブの詳細を取得できるAPIエンドポイント。このURLに対して GET API を実行すると実際のスキャン結果が返ってきます。
実行結果(json)
{
  "data": {
    "type": "analysis",
    "id": "u-edca074237e05485ead9caad8f7ddcbc954379de06ae79e730c3fcc79fdba9d5-1758614009",
    "links": {
      "self": "https://www.virustotal.com/api/v3/analyses/u-edca074237e05485ead9caad8f7ddcbc954379de06ae79e730c3fcc79fdba9d5-1758614009"
    }
  }
}

Get a URL

コマンドの実行

bash にて以下のコマンドを実行します。

curl --request GET \
     --url https://www.virustotal.com/api/v3/analyses/u-edca074237e05485ead9caad8f7ddcbc954379de06ae79e730c3fcc79fdba9d5-1758614009 \
     --header "x-apikey: 自身の API キー" \
     --header "accept: application/json" \
 | jq .

実行結果

以下の内容を含んだ実行結果が出力されます。

  • results:セキュリティベンダーごとの判定結果一覧。
    • API によるスキャンでは、ブラウザ版のスキャンでは確認できない「category(大分類・共通化されたカテゴリ)」や「method(判定方法)」などが結果として出力されます。
  • date:解析が行われた時間。
  • stats:判定結果を集計したサマリー。
  • status:スキャンの進行状況(例: queued / in-progress / completed)。
実行結果(json)
{
  "data": {
    "id": "u-edca074237e05485ead9caad8f7ddcbc954379de06ae79e730c3fcc79fdba9d5-1758614009",
    "type": "analysis",
    "links": {
      "self": "https://www.virustotal.com/api/v3/analyses/u-edca074237e05485ead9caad8f7ddcbc954379de06ae79e730c3fcc79fdba9d5-1758614009",
      "item": "https://www.virustotal.com/api/v3/urls/edca074237e05485ead9caad8f7ddcbc954379de06ae79e730c3fcc79fdba9d5"
    },
    "attributes": {
      "results": {
        "Artists Against 419": {
          "method": "blacklist",
          "engine_name": "Artists Against 419",
          "category": "harmless",
          "result": "clean"
        },
        "Acronis": {
          "method": "blacklist",
          "engine_name": "Acronis",
          "category": "harmless",
          "result": "clean"
        },
        "Abusix": {
          "method": "blacklist",
          "engine_name": "Abusix",
          "category": "harmless",
          "result": "clean"
        },
        "ADMINUSLabs": {
          "method": "blacklist",
          "engine_name": "ADMINUSLabs",
          "category": "harmless",
          "result": "clean"
        },
        "Lionic": {
          "method": "blacklist",
          "engine_name": "Lionic",
          "category": "harmless",
          "result": "clean"
        },
        "Criminal IP": {
          "method": "blacklist",
          "engine_name": "Criminal IP",
          "category": "harmless",
          "result": "clean"
        },
        "AILabs (MONITORAPP)": {
          "method": "blacklist",
          "engine_name": "AILabs (MONITORAPP)",
          "category": "harmless",
          "result": "clean"
        },
        "AlienVault": {
          "method": "blacklist",
          "engine_name": "AlienVault",
          "category": "harmless",
          "result": "clean"
        },
        "alphaMountain.ai": {
          "method": "blacklist",
          "engine_name": "alphaMountain.ai",
          "category": "malicious",
          "result": "phishing"
        },
        "AlphaSOC": {
          "method": "blacklist",
          "engine_name": "AlphaSOC",
          "category": "undetected",
          "result": "unrated"
        },
        "Antiy-AVL": {
          "method": "blacklist",
          "engine_name": "Antiy-AVL",
          "category": "harmless",
          "result": "clean"
        },
        "ArcSight Threat Intelligence": {
          "method": "blacklist",
          "engine_name": "ArcSight Threat Intelligence",
          "category": "undetected",
          "result": "unrated"
        },
        "AutoShun": {
          "method": "blacklist",
          "engine_name": "AutoShun",
          "category": "undetected",
          "result": "unrated"
        },
        "Axur": {
          "method": "blacklist",
          "engine_name": "Axur",
          "category": "undetected",
          "result": "unrated"
        },
        "benkow.cc": {
          "method": "blacklist",
          "engine_name": "benkow.cc",
          "category": "harmless",
          "result": "clean"
        },
        "Bfore.Ai PreCrime": {
          "method": "blacklist",
          "engine_name": "Bfore.Ai PreCrime",
          "category": "undetected",
          "result": "unrated"
        },
        "BitDefender": {
          "method": "blacklist",
          "engine_name": "BitDefender",
          "category": "harmless",
          "result": "clean"
        },
        "Bkav": {
          "method": "blacklist",
          "engine_name": "Bkav",
          "category": "undetected",
          "result": "unrated"
        },
        "BlockList": {
          "method": "blacklist",
          "engine_name": "BlockList",
          "category": "harmless",
          "result": "clean"
        },
        "Blueliv": {
          "method": "blacklist",
          "engine_name": "Blueliv",
          "category": "harmless",
          "result": "clean"
        },
        "Certego": {
          "method": "blacklist",
          "engine_name": "Certego",
          "category": "harmless",
          "result": "clean"
        },
        "ChainPatrol": {
          "method": "blacklist",
          "engine_name": "ChainPatrol",
          "category": "undetected",
          "result": "unrated"
        },
        "Chong Lua Dao": {
          "method": "blacklist",
          "engine_name": "Chong Lua Dao",
          "category": "harmless",
          "result": "clean"
        },
        "CINS Army": {
          "method": "blacklist",
          "engine_name": "CINS Army",
          "category": "harmless",
          "result": "clean"
        },
        "Snort IP sample list": {
          "method": "blacklist",
          "engine_name": "Snort IP sample list",
          "category": "harmless",
          "result": "clean"
        },
        "Cluster25": {
          "method": "blacklist",
          "engine_name": "Cluster25",
          "category": "undetected",
          "result": "unrated"
        },
        "CMC Threat Intelligence": {
          "method": "blacklist",
          "engine_name": "CMC Threat Intelligence",
          "category": "harmless",
          "result": "clean"
        },
        "Xcitium Verdict Cloud": {
          "method": "blacklist",
          "engine_name": "Xcitium Verdict Cloud",
          "category": "harmless",
          "result": "clean"
        },
        "CRDF": {
          "method": "blacklist",
          "engine_name": "CRDF",
          "category": "malicious",
          "result": "malicious"
        },
        "CSIS Security Group": {
          "method": "blacklist",
          "engine_name": "CSIS Security Group",
          "category": "undetected",
          "result": "unrated"
        },
        "Cyan": {
          "method": "blacklist",
          "engine_name": "Cyan",
          "category": "undetected",
          "result": "unrated"
        },
        "Cyble": {
          "method": "blacklist",
          "engine_name": "Cyble",
          "category": "harmless",
          "result": "clean"
        },
        "CyRadar": {
          "method": "blacklist",
          "engine_name": "CyRadar",
          "category": "malicious",
          "result": "phishing"
        },
        "desenmascara.me": {
          "method": "blacklist",
          "engine_name": "desenmascara.me",
          "category": "harmless",
          "result": "clean"
        },
        "DNS8": {
          "method": "blacklist",
          "engine_name": "DNS8",
          "category": "harmless",
          "result": "clean"
        },
        "Dr.Web": {
          "method": "blacklist",
          "engine_name": "Dr.Web",
          "category": "harmless",
          "result": "clean"
        },
        "Emsisoft": {
          "method": "blacklist",
          "engine_name": "Emsisoft",
          "category": "harmless",
          "result": "clean"
        },
        "Ermes": {
          "method": "blacklist",
          "engine_name": "Ermes",
          "category": "undetected",
          "result": "unrated"
        },
        "ESET": {
          "method": "blacklist",
          "engine_name": "ESET",
          "category": "harmless",
          "result": "clean"
        },
        "ESTsecurity": {
          "method": "blacklist",
          "engine_name": "ESTsecurity",
          "category": "harmless",
          "result": "clean"
        },
        "EmergingThreats": {
          "method": "blacklist",
          "engine_name": "EmergingThreats",
          "category": "harmless",
          "result": "clean"
        },
        "Feodo Tracker": {
          "method": "blacklist",
          "engine_name": "Feodo Tracker",
          "category": "harmless",
          "result": "clean"
        },
        "Fortinet": {
          "method": "blacklist",
          "engine_name": "Fortinet",
          "category": "suspicious",
          "result": "spam"
        },
        "G-Data": {
          "method": "blacklist",
          "engine_name": "G-Data",
          "category": "harmless",
          "result": "clean"
        },
        "Google Safebrowsing": {
          "method": "blacklist",
          "engine_name": "Google Safebrowsing",
          "category": "harmless",
          "result": "clean"
        },
        "GCP Abuse Intelligence": {
          "method": "blacklist",
          "engine_name": "GCP Abuse Intelligence",
          "category": "undetected",
          "result": "unrated"
        },
        "GreenSnow": {
          "method": "blacklist",
          "engine_name": "GreenSnow",
          "category": "harmless",
          "result": "clean"
        },
        "Gridinsoft": {
          "method": "blacklist",
          "engine_name": "Gridinsoft",
          "category": "suspicious",
          "result": "suspicious"
        },
        "Heimdal Security": {
          "method": "blacklist",
          "engine_name": "Heimdal Security",
          "category": "harmless",
          "result": "clean"
        },
        "Hunt.io Intelligence": {
          "method": "blacklist",
          "engine_name": "Hunt.io Intelligence",
          "category": "undetected",
          "result": "unrated"
        },
        "IPsum": {
          "method": "blacklist",
          "engine_name": "IPsum",
          "category": "harmless",
          "result": "clean"
        },
        "Juniper Networks": {
          "method": "blacklist",
          "engine_name": "Juniper Networks",
          "category": "harmless",
          "result": "clean"
        },
        "Kaspersky": {
          "method": "blacklist",
          "engine_name": "Kaspersky",
          "category": "harmless",
          "result": "clean"
        },
        "Lumu": {
          "method": "blacklist",
          "engine_name": "Lumu",
          "category": "undetected",
          "result": "unrated"
        },
        "Malwared": {
          "method": "blacklist",
          "engine_name": "Malwared",
          "category": "harmless",
          "result": "clean"
        },
        "MalwareURL": {
          "method": "blacklist",
          "engine_name": "MalwareURL",
          "category": "undetected",
          "result": "unrated"
        },
        "MalwarePatrol": {
          "method": "blacklist",
          "engine_name": "MalwarePatrol",
          "category": "harmless",
          "result": "clean"
        },
        "malwares.com URL checker": {
          "method": "blacklist",
          "engine_name": "malwares.com URL checker",
          "category": "harmless",
          "result": "clean"
        },
        "Mimecast": {
          "method": "blacklist",
          "engine_name": "Mimecast",
          "category": "undetected",
          "result": "unrated"
        },
        "Netcraft": {
          "method": "blacklist",
          "engine_name": "Netcraft",
          "category": "undetected",
          "result": "unrated"
        },
        "OpenPhish": {
          "method": "blacklist",
          "engine_name": "OpenPhish",
          "category": "harmless",
          "result": "clean"
        },
        "0xSI_f33d": {
          "method": "blacklist",
          "engine_name": "0xSI_f33d",
          "category": "undetected",
          "result": "unrated"
        },
        "Phishing Database": {
          "method": "blacklist",
          "engine_name": "Phishing Database",
          "category": "harmless",
          "result": "clean"
        },
        "PhishFort": {
          "method": "blacklist",
          "engine_name": "PhishFort",
          "category": "undetected",
          "result": "unrated"
        },
        "PhishLabs": {
          "method": "blacklist",
          "engine_name": "PhishLabs",
          "category": "undetected",
          "result": "unrated"
        },
        "Phishtank": {
          "method": "blacklist",
          "engine_name": "Phishtank",
          "category": "harmless",
          "result": "clean"
        },
        "PREBYTES": {
          "method": "blacklist",
          "engine_name": "PREBYTES",
          "category": "harmless",
          "result": "clean"
        },
        "PrecisionSec": {
          "method": "blacklist",
          "engine_name": "PrecisionSec",
          "category": "undetected",
          "result": "unrated"
        },
        "Quick Heal": {
          "method": "blacklist",
          "engine_name": "Quick Heal",
          "category": "harmless",
          "result": "clean"
        },
        "Quttera": {
          "method": "blacklist",
          "engine_name": "Quttera",
          "category": "harmless",
          "result": "clean"
        },
        "Rising": {
          "method": "blacklist",
          "engine_name": "Rising",
          "category": "harmless",
          "result": "clean"
        },
        "SafeToOpen": {
          "method": "blacklist",
          "engine_name": "SafeToOpen",
          "category": "undetected",
          "result": "unrated"
        },
        "Sangfor": {
          "method": "blacklist",
          "engine_name": "Sangfor",
          "category": "harmless",
          "result": "clean"
        },
        "Sansec eComscan": {
          "method": "blacklist",
          "engine_name": "Sansec eComscan",
          "category": "undetected",
          "result": "unrated"
        },
        "Scantitan": {
          "method": "blacklist",
          "engine_name": "Scantitan",
          "category": "harmless",
          "result": "clean"
        },
        "SCUMWARE.org": {
          "method": "blacklist",
          "engine_name": "SCUMWARE.org",
          "category": "harmless",
          "result": "clean"
        },
        "Seclookup": {
          "method": "blacklist",
          "engine_name": "Seclookup",
          "category": "malicious",
          "result": "malicious"
        },
        "SOCRadar": {
          "method": "blacklist",
          "engine_name": "SOCRadar",
          "category": "undetected",
          "result": "unrated"
        },
        "Sophos": {
          "method": "blacklist",
          "engine_name": "Sophos",
          "category": "malicious",
          "result": "phishing"
        },
        "Spam404": {
          "method": "blacklist",
          "engine_name": "Spam404",
          "category": "harmless",
          "result": "clean"
        },
        "StopForumSpam": {
          "method": "blacklist",
          "engine_name": "StopForumSpam",
          "category": "harmless",
          "result": "clean"
        },
        "Sucuri SiteCheck": {
          "method": "blacklist",
          "engine_name": "Sucuri SiteCheck",
          "category": "harmless",
          "result": "clean"
        },
        "securolytics": {
          "method": "blacklist",
          "engine_name": "securolytics",
          "category": "harmless",
          "result": "clean"
        },
        "Threatsourcing": {
          "method": "blacklist",
          "engine_name": "Threatsourcing",
          "category": "harmless",
          "result": "clean"
        },
        "ThreatHive": {
          "method": "blacklist",
          "engine_name": "ThreatHive",
          "category": "harmless",
          "result": "clean"
        },
        "Trustwave": {
          "method": "blacklist",
          "engine_name": "Trustwave",
          "category": "harmless",
          "result": "clean"
        },
        "Underworld": {
          "method": "blacklist",
          "engine_name": "Underworld",
          "category": "undetected",
          "result": "unrated"
        },
        "URLhaus": {
          "method": "blacklist",
          "engine_name": "URLhaus",
          "category": "harmless",
          "result": "clean"
        },
        "URLQuery": {
          "method": "blacklist",
          "engine_name": "URLQuery",
          "category": "undetected",
          "result": "unrated"
        },
        "Viettel Threat Intelligence": {
          "method": "blacklist",
          "engine_name": "Viettel Threat Intelligence",
          "category": "harmless",
          "result": "clean"
        },
        "VIPRE": {
          "method": "blacklist",
          "engine_name": "VIPRE",
          "category": "undetected",
          "result": "unrated"
        },
        "ViriBack": {
          "method": "blacklist",
          "engine_name": "ViriBack",
          "category": "harmless",
          "result": "clean"
        },
        "VX Vault": {
          "method": "blacklist",
          "engine_name": "VX Vault",
          "category": "harmless",
          "result": "clean"
        },
        "Webroot": {
          "method": "blacklist",
          "engine_name": "Webroot",
          "category": "malicious",
          "result": "malicious"
        },
        "Forcepoint ThreatSeeker": {
          "method": "blacklist",
          "engine_name": "Forcepoint ThreatSeeker",
          "category": "harmless",
          "result": "clean"
        },
        "Yandex Safebrowsing": {
          "method": "blacklist",
          "engine_name": "Yandex Safebrowsing",
          "category": "harmless",
          "result": "clean"
        },
        "ZeroCERT": {
          "method": "blacklist",
          "engine_name": "ZeroCERT",
          "category": "harmless",
          "result": "clean"
        },
        "ZeroFox": {
          "method": "blacklist",
          "engine_name": "ZeroFox",
          "category": "undetected",
          "result": "unrated"
        }
      },
      "date": 1758614009,
      "stats": {
        "malicious": 6,
        "suspicious": 2,
        "undetected": 28,
        "harmless": 62,
        "timeout": 0
      },
      "status": "completed"
    }
  },
  "meta": {
    "url_info": {
      "id": "edca074237e05485ead9caad8f7ddcbc954379de06ae79e730c3fcc79fdba9d5",
      "url": "スキャンした URL"
    },
    "file_info": {
      "sha256": null
    }
  }
}

まとめ

今回は VirusTotal API を利用して、Webサイトのスキャンとスキャン結果の取得を試しました。
スキャンと結果取得の API が分かれている点は、新しい発見でした。
また、API 経由でしか確認できない「category(大分類・共通カテゴリ)」や「method(判定方法)」などもあり、興味深かったです。

一方で、実際に使ってみると「ただスキャン結果を見たいだけ」の場合はブラウザ版の方が便利で手軽だと感じました。
API は自動化やワークフローへの組み込みにこそ価値があり、個人で単発利用するだけならブラウザで十分だと思います。

今後は API を使った自動処理や分析の仕組みに挑戦してみたいです。

Discussion