Skip to content

API reference

This is a Python 3 library for the Vulners Perimeter Scanner. It provides basic project management and data retrieval API for automation and integration purposes.

Requirements

  • Python: Library was tested on python3.

  • API key: Please sign up to Vulners. Go to your personal menu by clicking on your name at the top right corner. Click on the API KEYS tab. Generate API key with the scope "api" and apply it to the library.

Disclaimer

In the examples below, localhost is used as an IP address, but Perimeter Scanner works only with public hosts. Also, uuides are shortened for the sake of examples, this is not the case in real data.

Getting started

All the callable methods use Vulners REST API. Automate your audit routines with Vulners. To get started you need to know your license id and control api quota left:

from vulners import vscanner

api = vscanner.VScannerApi(api_key="YOUR_API_KEY_HERE")

license_id = api.get_licenses()
license_quota = api.get_quota(license_id=license_id[0])
{
    "licenseList": [
        {
            "id": "e0671ce0-..-bbb",
            "type": "free",
            "expiration": "2999-01-01T00:00:00"
        },
        {
            "id": "d4657eb6-..-9d7",
            "type": "vnmap-professional",
            "expiration": "2022-04-15T00:00:00"
        },
        {
            "id": "319b1ad1-..-45d",
            "type": "professional",
            "expiration": "2022-04-15T00:00:00"
        }
    ]
}
{
    "daily_quota": 102400, 
    "hourly_quota": 10240
}

Project management

To get started, you should create a new project. The project has three required parameters: name, notification, and license id. Notification is an object, containing options such as period ("disabled", "asap", "hourly", or "daily") and method (via either or both email and slack). You can use the notification method to create a notification object, or the disablednotification method if you do not want to get notifications. So create a new project with this code:

Creating new project

notification = vscanner.VScannerApi.Notification(period='asap', emails=['[email protected]'])
# if no notifications needed
# notification = vscanner.VScannerApi.DisabledNotification()

project = api.create_project(name="my project", 
                              license="0305fbd1-..-8a7", 
                              notification=notification)
{
    "_id": "4e0a9778-..-4d0",
    "name": "my project",
    "owner": "e5bc65b8-..-675",
    "license": {
        "id": "0305fbd1-..-8a7",
        "name": "vnmap-professional:7a11ad6558a7",
        "exp": 1649970000.0,
        "max_hosts": 256,
        "max_tasks": 5,
        "daily_quota": 102400,
        "hourly_quota": 10240,
        "timing": 3,
        "ports": "False"
    },
    "tasks_count": 0,
    "tasks": [],
    "admins": [],
    "viewers": [],
    "notification": {
        "period": "daily", 
        "email": ["[email protected]"],  
        "slack": ["https://hooks.slack.com/services/..."]
    }
}

Editing project

With method update_project you can edit existing project parameters. To set new values you should additionally specify project id. You should specify all parameters explicitly, otherwise it will be overwritten:

project = api.update_project(project_id=project['_id'],
                              project_name="new project name",
                              license=project['license']['id'],
                              notification = project['notification']
                              )
{
    "_id": "4e0a9778-..-4d0",
    "name": "new project name",
    "owner": "e5bc65b8-..-675",
    "license": {
        "id": "0305fbd1-..-8a7",
        "name": "vnmap-professional:7a11ad6558a7",
        "exp": 1649970000.0,
        "max_hosts": 256,
        "max_tasks": 5,
        "daily_quota": 102400,
        "hourly_quota": 10240,
        "timing": 3,
        "ports": "False"
    },
    "tasks_count": 0,
    "tasks": [],
    "admins": [],
    "viewers": [],
    "notification": {
        "period": "daily", 
        "email": ["[email protected]"],  
        "slack": ["https://hooks.slack.com/services/..."]
    }
}

Getting project data

Using this method, you can get data about existing projects:

projects = api.get_projects()
[{
    "_id": "4e0a9778-..-4d0",
    "name": "new project name",
    "owner": "e5bc65b8-..-675",
    "license": {
        "id": "0305fbd1-..-8a7",
        "name": "vnmap-professional:7a11ad6558a7",
        "exp": 1649970000.0,
        "max_hosts": 256,
        "max_tasks": 5,
        "daily_quota": 102400,
        "hourly_quota": 10240,
        "timing": 3,
        "ports": "False"
    },
    "tasks_count": 0,
    "tasks": [],
    "admins": [],
    "viewers": [],
    "notification": {
        "period": "daily", 
        "email": ["[email protected]"],  
        "slack": ["https://hooks.slack.com/services/..."]
    }
}]

Deleting project

To delete project you can use this method:

result = api.delete_project(project['_id'])
None in case of success, or error message

Task Management

The second step is to create tasks. The task schedules a network scan. To create the task you should specify the parent project id, task name, list of networks, enable flag and schedule string.

The schedule string is a crontab string. It is a set of 5 fields, which represent the time to execute the task. The crontab string contains following fields:

minutes[0-59] hours[0-23] day_of_month[1-31] month[1-12] day_of_week[1-7]

The crontab string construction is quite complicated for our API reference, so you can use this guide and generator: crontab guru.

Below are some examples:

'*/10 * * * *' means "Task will start every 10th minute"
'0 10 * * *' means "Task will start at 10am every day"
'0 10 1 5 *' means "Task will start at 10am every first day of May"
'0 10 * * 1' means "Task will start at 10am every monday"

Creating new task

To create a new task use the method below:

first_task = project.create_task(
                     name="first task",
                     networks=['example.com', '127.0.0.1'],
                     schedule='* 10 * * 1',
                     enabled=True
                     )
{
    "_id": "52d0f18b-..-b60",
    "name": "first task",
    "schedule": "* 10 * * 1",
    "networks": [
        "example.com",
        "127.0.0.1"
    ],
    "validated_networks": [
        "127.0.0.1/32",
        "127.0.0.1/32"
    ],
    "enabled": "False",
    "valid": "True",
    "total_hosts": 1,
    "project_id": "4e0a9778-..-4d0",
    "license": {
        "id": "0305fbd1-..-8a7",
        "name": "vnmap-professional:7a11ad6558a7",
        "exp": 1649970000.0,
        "max_hosts": 256,
        "max_tasks": 5,
        "daily_quota": 102400,
        "hourly_quota": 10240,
        "timing": 3,
        "ports": "False"
    },
    "next_run": 1621850400.0,
    "last_run": 0,
    "resolved": [
        "127.0.0.1",
        "example.com"
    ],
    "state": "disabled"
}

Editing task

To modify the task parameters you should also specify the existing task id:

first_task = project.update_task(
                     name="first task",
                     networks=['example.com', '127.0.0.1'],
                     schedule='* 10 * * 2',
                     enabled=True
                     )
{
    "_id": "52d0f18b-..-b60",
    "name": "first task",
    "schedule": "* 10 * * 2",
    "networks": [
        "example.com",
        "127.0.0.1"
    ],
    "validated_networks": [
        "127.0.0.1/32",
        "127.0.0.1/32"
    ],
    "enabled": "False",
    "valid": "True",
    "total_hosts": 1,
    "project_id": "4e0a9778-..-4d0",
    "license": {
        "id": "0305fbd1-..-8a7",
        "name": "vnmap-professional:7a11ad6558a7",
        "exp": 1649970000.0,
        "max_hosts": 256,
        "max_tasks": 5,
        "daily_quota": 102400,
        "hourly_quota": 10240,
        "timing": 3,
        "ports": "False"
    },
    "next_run": 1621850400.0,
    "last_run": 0,
    "resolved": [
        "127.0.0.1",
        "example.com"
    ],
    "state": "disabled"
}

Forcing task

When a task is enabled, it will initiate according to the set schedule. If needed, a task can be forced using the start_task method, shown below:

first_task = task.start_task()
{
    "_id": "52d0f18b-..-b60",
    "name": "first task",
    "schedule": "* 10 * * 2",
    "networks": [
        "example.com",
        "127.0.0.1"
    ],
    "validated_networks": [
        "127.0.0.1/32",
        "127.0.0.1/32"
    ],
    "enabled": "False",
    "valid": "True",
    "total_hosts": 1,
    "project_id": "4e0a9778-..-4d0",
    "license": {
        "id": "0305fbd1-..-8a7",
        "name": "vnmap-professional:7a11ad6558a7",
        "exp": 1649970000.0,
        "max_hosts": 256,
        "max_tasks": 5,
        "daily_quota": 102400,
        "hourly_quota": 10240,
        "timing": 3,
        "ports": "False"
    },
    "next_run": 1621850400.0,
    "last_run": 0,
    "resolved": [
        "127.0.0.1",
        "example.com"
    ],
    "state": "disabled"
}

Deleting task

You can delete a task using the delete_task method:

result = task.delete_task()
None in case of success, or error message

Reporting

Getting results

The final step is to obtain results. When a task finishes, you can get the scanning results. Just call the results method with the project id:

result = project.get_results(
            search="Search text occurrence in fields: name, ip or resolved.",
            ip_address='91.218.85.0/24,91.218.86.99',
            include_ports='80,8080'
            exclude_ports='81,8084',
            min_cvss=3.0,
            max_cvss=9.0,
            not_older_then='5h', #or use datetime '2021-07-21T12:00:00Z'
            sort='max_cvss', # allowed values are 'ip', 'name', 'published', 'resolved','min_cvss', 'max_cvss'
                             # use '-' to sort descending
                             # default value is '-published'
            offset=0,
            limit=100)
{
    "_id": "62d6eab7-..-92b",
    "project_id": "4e0a9778-..-4d0",
    "ip": "127.0.0.1",
    "addr": 846214729,
    "name": "example.com",
    "resolved": "",
    "published": "2021-04-15T13:59:03Z",
    "scan_info": [
        {
            "port": "22",
            "protocol": "tcp",
            "service": "ssh",
            "product": "OpenSSH",
            "version": "8.2p1 Ubuntu 4ubuntu0.1",
            "ostype": "Linux",
            "extrainfo": "Ubuntu Linux; protocol 2.0",
            "cpe": "cpe:/a:openbsd:openssh:8.2p1",
            "vulnerabilities": [
                {
                    "id": "CVE-2020-12062",
                    "cvss": 5.0
                },
                {
                    "id": "CVE-2020-14145",
                    "cvss": 4.3
                },
                {
                    "id": "CVE-2020-15778",
                    "cvss": 6.8
                },
                {
                    "id": "CVE-2021-28041",
                    "cvss": 4.6
                },
                {
                    "id": "MSF:AUXILIARY/SCANNER/SSH/FORTINET_BACKDOOR/",
                    "cvss": 0.0
                }
            ]
        }
    ]
}

Cleaning up results

Sometimes, it may be useful to clean up your data. You can delete the scan results using the delete_results method:

result = project.delete_result(result_id='62d6eab7-...2b')
None in case of success, or error message
Back to top