VirusTotal api を利用してみた
今回は、VirusTotal の API (無料版)を利用してみたのでその記録を記したいと思います。
VirusTotal とは
ウェブサイトやファイルに「マルウェアが含まれていないかどうか」をブラウザ上で検査できるツールです[1]。
検査、いわゆるオンラインスキャンを行うだけであり、マルウェアの除去はできません。
ツールの運営・管理は Google が行っています。
VirusTotalはこちら
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