Skip to content

MobSF still uses deprecated VirusTotal API v2 #2560

@weizenspreu

Description

@weizenspreu

I enabled the VirusTotal integration of MobSF today and had to learn that it doesn't support files larger than 32MiB. It seems that MobSF never implemented the upload URL scheme of the VirusTotal API. While I looked into the code, I noticed that MobSF still uses the deprecated v2 of the VirusTotal API instead of the v3 API.

Not migrating to v3 API will likely break the integration in the future.

I tested the new v3 API and wrote a Bash script that implements support for files up to 640MiB (compared to the limited 32MiB of MobSF's current implementation) as well as report polling. Maybe this helps to rework the VirusTotal integration implemented in MobSF:

#!/usr/bin/env bash

##### CONFIGURATION

if [[ -z "${1}" ]]; then
  echo "File must be set." >&2
  exit
fi

if [[ -z "${MOBSF_VT_API_KEY}" ]]; then
  echo "MOBSF_VT_API_KEY must be set." >&2
  exit
fi

if [[ -z "${VIRUS_TOTAL_BASE_URL}" ]]; then
  VIRUS_TOTAL_BASE_URL="https://www.virustotal.com/api/v3/files"
fi

##### EXECUTION

# preset result
RESULT=""

echo "Calculating artifact hash..." >&2
HASH=$(md5sum "${1}" | head -c 32)

# check exit code
if [[ "${?}" -eq "0" ]] && [[ -n "${HASH}" ]]; then
  echo "Retrieving VirusTotal report of artifact hash ${HASH}..." >&2
  TEMP=$(curl \
           -f \
           -G \
           -s \
           -H "accept: application/json" \
           -H "x-apikey: ${MOBSF_VT_API_KEY}" \
           "${VIRUS_TOTAL_BASE_URL}/${HASH}")

  # check exit code
  if [[ "${?}" -eq "0" ]] && [[ -n "${TEMP}" ]]; then
    # store JSON report
    RESULT="${TEMP}"
  else
    echo "No VirusTotal report available, uploading artifact to VirusTotal..." >&2
    echo "Retrieving VirusTotal upload URL..." >&2
    TEMP=$(curl \
             -f \
             -G \
             -s \
             -H "accept: application/json" \
             -H "x-apikey: ${MOBSF_VT_API_KEY}" \
             "${VIRUS_TOTAL_BASE_URL}/upload_url")

    # check exit code
    if [[ "${?}" -eq "0" ]] && [[ -n "${TEMP}" ]]; then
      echo "Extracting VirusTotal upload URL..." >&2
      UPLOAD_URL=$(echo -n "${TEMP}" | jq -er ".data" 2>/dev/null)

      # check exit code
      if [[ "${?}" -eq "0" ]] && [[ -n "${UPLOAD_URL}" ]]; then 
        echo "Uploading artifact to VirusTotal..." >&2
        TEMP=$(curl \
                 -f \
                 -s \
                 -X POST \
                 -F "file=@${1}" \
                 -H "accept: application/json" \
                 -H "content-type: multipart/form-data" \
                 -H "x-apikey: ${MOBSF_VT_API_KEY}" \
                 "${UPLOAD_URL}")

        # check exit code
        if [[ "${?}" -eq "0" ]] && [[ -n "${TEMP}" ]]; then
          echo "Extracting VirusTotal analysis URL..." >&2
          ANALYSIS_URL=$(echo -n "${TEMP}" | jq -er ".data.links.self" 2>/dev/null)

          # check exit code
          if [[ "${?}" -eq "0" ]] && [[ -n "${ANALYSIS_URL}" ]]; then
            echo "Waiting for VirusTotal analysis..." >&2
            sleep 60

            # poll analysis URL
            DONE="0"
            while [[ "${DONE}" -eq "0" ]]; do
              echo "Retrieving VirusTotal analysis..." >&2
              TEMP=$(curl \
                       -f \
                       -G \
                       -s \
                       -H "accept: application/json" \
                       -H "x-apikey: ${MOBSF_VT_API_KEY}" \
                       "${ANALYSIS_URL}")

              # check exit code
              if [[ "${?}" -eq "0" ]] && [[ -n "${TEMP}" ]]; then
                echo "Extracting VirusTotal analysis status..." >&2
                STATUS=$(echo -n "${TEMP}" | jq -er ".data.attributes.status" 2>/dev/null)

                # check exit code
                if [[ "${?}" -eq "0" ]] && [[ -n "${STATUS}" ]]; then
                  # check status
                  if [[ "${STATUS}" == "completed" ]]; then
                    # success
                    DONE="1"
                  else
                    # wait a bit
                    sleep 15
                  fi
                else
                  # some error occurred
                  break
                fi
              else
                # some error occurred
                break
              fi
            done

            # retrieve scan result again
            if [[ "${DONE}" -eq "1" ]]; then
              echo "Waiting for VirusTotal report of artifact hash ${HASH}..." >&2
              sleep 60

              # poll report URL
              DONE="0"
              while [[ "${DONE}" -eq "0" ]]; do
                echo "Retrieving VirusTotal report of artifact hash ${HASH}..." >&2
                TEMP=$(curl \
                         -f \
                         -G \
                         -s \
                         -H "accept: application/json" \
                         -H "x-apikey: ${MOBSF_VT_API_KEY}" \
                         "${VIRUS_TOTAL_BASE_URL}/${HASH}")

                # check exit code
                if [[ "${?}" -eq "0" ]] && [[ -n "${TEMP}" ]]; then
                  # store JSON report
                  RESULT="${TEMP}"

                  # success
                  DONE="1"
                else
                  # wait a bit
                  sleep 15
                fi
              done
            fi
          fi
        fi
      fi
    fi
  fi
fi

# output result if it is set
if [[ -n "${RESULT}" ]]; then
  echo "${RESULT}"
fi

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementMobSF enhancements and feature requests

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions