
针对VirusTotal API v3进行URL扫描时,许多开发者常混淆分析ID与URL资源ID,导致获取报告失败。本文详细阐述了如何正确使用API提交URL进行扫描,并利用返回的分析ID查询详细的扫描报告,避免常见的“Wrong URL id”错误,确保成功集成安全检测功能。
VirusTotal API v3 URL扫描流程概述
virustotal提供了一套强大的api,允许开发者自动化地提交文件、url等进行恶意软件检测,并获取详细的分析报告。对于url扫描,其api v3通常遵循两阶段模式:
提交URL进行分析: 通过特定的API端点提交一个URL,VirusTotal会将其加入扫描队列并开始分析。查询分析结果: 在提交URL后,API会返回一个“分析ID”(analysis_id),开发者可以使用这个ID来查询分析任务的当前状态和最终报告。
理解两种关键的标识符至关重要:
分析ID (Analysis ID): 这是提交URL(或其他实体)进行扫描后,VirusTotal为该次分析任务分配的唯一标识符。它的格式通常是 u-{hash}-{timestamp},例如 u-dbae2d0204aa489e234eb2f903a0127b17c712386428cab12b86c5f68aa75867-1701503514。URL资源ID (URL Resource ID): 这是URL本身的唯一标识符,通常是该URL的Base64编码字符串。这个ID用于查询关于该URL资源本身的信息(例如,它以前的扫描历史或元数据),而不是特定分析任务的报告。
常见错误分析:混淆ID与API端点
许多开发者在初次使用VirusTotal API v3时,会遇到一个常见的错误:在提交URL后获取到 analysis_id,但尝试使用 GET /urls/{id} 端点来查询分析报告。这会导致API返回 Wrong URL id 的错误信息。
让我们来看一个典型的错误代码示例:
import requestsdef scanurl_incorrect(scan_url, api_key): # 步骤一:提交URL进行分析 submit_url_endpoint = "https://www.virustotal.com/api/v3/urls" payload = { "url": scan_url } headers = { "accept": "application/json", "x-apikey": api_key, } response = requests.post(submit_url_endpoint, data=payload, headers=headers) response.raise_for_status() # 检查HTTP错误 analysis_id = response.json().get('data', {}).get('id', '') print(f"分析ID: {analysis_id}") if not analysis_id: print("未能获取分析ID。") return # 步骤二:尝试使用错误的端点获取报告 # 错误之处:这里应该使用 /analyses/{analysis_id},而不是 /urls/{analysis_id} get_report_endpoint = "https://www.virustotal.com/api/v3/urls/" + analysis_id headers = { "accept": "application/json", "x-apikey": api_key, } response = requests.get(get_report_endpoint, headers=headers) print(response.text)# 示例调用 (请替换为您的实际API Key)# scanurl_incorrect("https://www.youtube.com/", "YOUR_VIRUSTOTAL_API_KEY")
上述代码中,get_report_endpoint 被错误地构建为 https://www.virustotal.com/api/v3/urls/{analysis_id}。然而,GET /urls/{id} 端点期望的 id 是一个URL资源ID(通常是Base64编码的URL),而不是一个 analysis_id。因此,当传入 analysis_id 时,API会识别出这不是一个有效的URL资源ID,从而返回 BadRequestError 和 Wrong URL id 的错误。
正确实现:提交URL与获取分析报告
要正确地获取URL分析报告,关键在于使用正确的API端点:GET /analyses/{analysis_id}。
步骤一:提交URL进行分析
通过 POST /urls 端点提交URL。成功后,响应会包含一个 data 对象,其中 id 字段就是我们需要的 analysis_id。
import requestsimport jsonimport timedef submit_url_for_analysis(scan_url, api_key): """ 提交URL到VirusTotal进行分析。 返回分析ID (analysis_id)。 """ submit_url_endpoint = "https://www.virustotal.com/api/v3/urls" payload = { "url": scan_url } headers = { "accept": "application/json", "x-apikey": api_key, } try: response = requests.post(submit_url_endpoint, data=payload, headers=headers) response.raise_for_status() # 检查HTTP错误 response_data = response.json() analysis_id = response_data.get('data', {}).get('id', '') if analysis_id: print(f"URL '{scan_url}' 已提交,分析ID: {analysis_id}") return analysis_id else: print(f"提交URL失败,未能获取分析ID。响应: {response.text}") return None except requests.exceptions.RequestException as e: print(f"提交URL时发生请求错误: {e}") return None
步骤二:获取URL分析报告
使用从上一步获取到的 analysis_id,通过 GET /analyses/{analysis_id} 端点查询分析报告。由于分析可能需要时间,通常需要进行轮询,直到报告状态变为“完成”(completed)。
def get_analysis_report(analysis_id, api_key, max_retries=10, delay=10): """ 根据分析ID获取VirusTotal的URL分析报告。 会轮询直到分析完成或达到最大重试次数。 """ if not analysis_id: print("分析ID为空,无法获取报告。") return None report_endpoint_base = "https://www.virustotal.com/api/v3/analyses/" headers = { "accept": "application/json", "x-apikey": api_key, } for i in range(max_retries): try: response = requests.get(f"{report_endpoint_base}{analysis_id}", headers=headers) response.raise_for_status() report_data = response.json() status = report_data.get('data', {}).get('attributes', {}).get('status') print(f"尝试 {i+1}/{max_retries} - 分析状态: {status}") if status == 'completed': return report_data elif status == 'queued' or status == 'running': time.sleep(delay) # 等待一段时间后重试 else: print(f"未知或错误状态: {status}. 报告数据: {json.dumps(report_data, indent=2)}") return None # 其他非预期状态 except requests.exceptions.RequestException as e: print(f"获取分析报告时发生请求错误: {e}") return None except json.JSONDecodeError: print(f"无法解析API响应为JSON: {response.text}") return None print(f"达到最大重试次数 ({max_retries}),分析未完成。") return None
完整示例代码
将上述两个步骤整合到一个函数中,可以实现完整的URL扫描和报告获取流程:
import requestsimport jsonimport timedef scan_url_and_get_report(scan_url, api_key, max_retries=10, delay=10): """ 提交URL到VirusTotal进行分析,并轮询获取最终报告。 """ # 步骤一:提交URL进行分析 submit_url_endpoint = "https://www.virustotal.com/api/v3/urls" payload = { "url": scan_url } headers = { "accept": "application/json", "x-apikey": api_key, } try: response = requests.post(submit_url_endpoint, data=payload, headers=headers) response.raise_for_status() response_data = response.json() analysis_id = response_data.get('data', {}).get('id', '') if not analysis_id: print(f"提交URL失败,未能获取分析ID。响应: {response.text}") return None print(f"URL '{scan_url}' 已提交,分析ID: {analysis_id}") except requests.exceptions.RequestException as e: print(f"提交URL时发生请求错误: {e}") return None except json.JSONDecodeError: print(f"提交URL后无法解析API响应为JSON: {response.text}") return None # 步骤二:获取URL分析报告 report_endpoint_base = "https://www.virustotal.com/api/v3/analyses/" headers = { "accept": "application/json", "x-apikey": api_key, } for i in range(max_retries): try: print(f"正在尝试获取报告 (第 {i+1}/{max_retries} 次尝试)...") response = requests.get(f"{report_endpoint_base}{analysis_id}", headers=headers) response.raise_for_status() report_data = response.json() status = report_data.get('data', {}).get('attributes', {}).get('status') if status == 'completed': print("分析完成,报告已获取。") return report_data elif status in ['queued', 'running']: print(f"分析仍在进行中 (状态: {status}),等待 {delay} 秒后重试...") time.sleep(delay) else: print(f"分析状态异常或未知: {status}. 报告数据: {json.dumps(report_data, indent=2)}") return None except requests.exceptions.RequestException as e: print(f"获取分析报告时发生请求错误: {e}") return None except json.JSONDecodeError: print(f"获取报告时无法解析API响应为JSON: {response.text}") return None print(f"达到最大重试次数 ({max_retries}),分析未完成或超时。") return None# --- 使用示例 ---if __name__ == "__main__": YOUR_API_KEY = "YOUR_VIRUSTOTAL_API_KEY" # <<<<<<< 请替换为您的VirusTotal API Key TARGET_URL = "https://www.example.com/" # 替换为你想扫描的URL if YOUR_API_KEY == "YOUR_VIRUSTOTAL_API_KEY": print("请将 'YOUR_VIRUSTOTAL_API_KEY' 替换为您的实际API Key。") else: report = scan_url_and_get_report(TARGET_URL, YOUR_API_KEY) if report: print("n--- 完整分析报告 ---") print(json.dumps(report, indent=2)) # 提取关键信息,例如检测结果 last_analysis_stats = report.get('data', {}).get('attributes', {}).get('last_analysis_stats', {}) print(f"n检测结果概览:") print(f" 恶意: {last_analysis_stats.
以上就是VirusTotal API v3 URL扫描:正确获取分析报告的实践指南的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1371232.html
微信扫一扫
支付宝扫一扫