Skip to content
Nov 13 / Greg

Access The Virustotal API Via Ansible

I’ve been doing more security related automation lately(finding it really interesting). Part of a lot of folks process is to get an alert, then do some investigation enrichment. One of the resources people use is a great site called virustotal.com. It allows you to put in a URL or upload a file, and it will check that against it’s database of services to see if anyone has reported malicious activity from it. While it is a pretty fast process, it is still a human one…how can this be made more efficient…well they DO have an API 🙂

They have a free API for non commercial use that has a rate-limit as well as slightly fewer features than the pay version. I’ll be using the free version for my demo.

Demo Video

Ansible Playbook

Security repo here.

This playbook is at the heart of it all.
At the top I’m using a couple of important variables.
One is the api_key which is retrieved from your virustotal account. Here I’m injecting mine at run time via a custom credential in Tower.
Another is test_url, which is the website you want to test against. The malware.wincar URL is a testing one that will show results on a virustotal scan.

The first task that is run uses the uri module. This is really the default module I use when interacting with various APIs. It’s almost too simple; I call the api and variable replace the API key and the URL to be tested. Also notice that I save the returned output as the variable total_out.

1
2
3
4
5
  - name: hit virus total and save results to variable
    uri:
      url: "https://www.virustotal.com/vtapi/v2/url/report?apikey={{ api_key }}&resource={{ test_url }}"
      return_content: yes
    register: total_out

I then do some formatting by using a filter to take the dictionary output and format it to a list:

1
2
3
  - name: set new variable
    set_fact:
      total_scans: "{{ total_out.json.scans | dict2items }}"

Next I loop through the formatted output and count how many virus total malicious hits were made:

1
2
3
4
5
  - name: total_out counts
    when: item.value.detected
    set_fact:
      total_mal: "{{ total_mal | int + 1 }}"
    loop: "{{ total_scans}}"

In the end I simply output how many are matched. In production I would add this to a workflow where if there were 2 or more matches, then I would flag the content for sure. Really once flagged any other operation can be performed; say updating an incident ticket and then notifications sent or a quarantine can be initiated.

What would you do differently or how can you see using this in your environment?
Thanks and happy automating!

Leave a Comment

 

*