1. 程式人生 > >基於Python的nessus API簡析——登入&進行一次掃描

基於Python的nessus API簡析——登入&進行一次掃描

前言

最近在開發一個基於Nessus的自動化漏掃工具,來和大家分析一下關於Nessus API的使用心得。
Nessus提供了非常完善的API,可以幫助我們實現很多事情,無論是對接其他運維繫統,還是用來編寫自動化的漏掃工具都十分方便。
Nessus為這些api提供了詳細的文件,你可以在Settings->My Account->API Keys->API documentation裡看到。
這裡寫圖片描述

一、登入

無論是發起一次掃描,還是獲取掃描的結果,首先都需要進行登入,nessus在這裡提供了兩種登入方式。相關內容可以在API文件的https://localhost:8834/api#/resources/session

條目中找到。

1、session create

第一種方式是使用Nessus的使用者名稱密碼,使用/session介面:
POST /session
/session介面傳送post請求,請求的payload引數為使用者名稱和密碼。程式碼如下:

# coding=utf-8
import requests
import json
def login_create():
    # 登入成功則返回token,否則返回空
    token = ''
    # 呼叫/session介面
    url = "https://localhost:8834/session"
    # nessus的使用者名稱密碼作為post的payload
data = { 'username': 'admin', 'password': 'admin' } # 傳送請求 respon = requests.post(url, data=data, verify=False) # 如果請求成功則返回token值 if respon.status_code == 200: # 返回值是一個json字串,用json.loads解析成字典取值 token = json.loads(respon.text)['token'] return
token

若使用者名稱和密碼正確,/session介面會返回一個token,將這個token放入請求的頭資訊中,之後的請求中帶上這個頭資訊就可以使用了。舉一個例子:

def get_scans_list():
    # 返回結果
    result = ''
    # 首先獲取一下token
    token = login_create()
    if token != '':
        # 呼叫/folders介面
        url = "https://localhost:8834/scans"
        # 組裝一個請求的頭,把剛剛拿到的token放入請求頭
        header = {'X-Cookie': 'token={token};'.format(token=token),
                  'Content-type': 'application/json',
                  'Accept': 'text/plain'}
        respon = requests.get(url, headers=header, verify=False)
        # 請求成功,則返回結果,否則返回空值
        if respon.status_code == 200:
            result = json.loads(respon.text)
    return result

2、API Key

除了使用使用者名稱密碼的方式,Nessus還提供了API key的方式,只需將Nessus生成的accessKey和secretKey放入請求頭資訊中即可。之後的例子都會使用API key的方式來呼叫。
API key可以通過Settings->My Account->API Keys->Generate獲取
這裡寫圖片描述
還是用get_scans_list做例子:

def get_scans_list():
    # 返回結果
    result = ''
    # 呼叫/folders介面
    url = "https://localhost:8834/scans"
    # Nessus生成的API key
    accesskey = 'b901cfe7e184801952db08795fa23f48f1f6c50732f0765e229975354aa58f92'
    secretkey = '860ad22d0536dd8fd88d3f93901d78cfe4cbc4dbd37bc17ba72a7e989f160739'
    # 組裝請求頭
    header = {'X-ApiKeys': 'accessKey={accesskey};secretKey={secretkey}'.format(accesskey=accesskey, secretkey=secretkey),
              'Content-type': 'application/json',
              'Accept': 'text/plain'}
    respon = requests.get(url, headers=header, verify=False)
    # 請求成功,則返回結果,否則返回空值
    if respon.status_code == 200:
        result = json.loads(respon.text)
    return result

二、開始一次掃描

1、定位掃描任務

發起掃描的API介面為:
POST /scans/{scan_id}/launch
可以看到,進行掃描需要提供一個scan_id。如何獲取scan_id呢?
這裡給大家分享一種利用任務名獲取scan_id的方法。
首先,利用介面/scans介面獲取一個所有任務的列表,可以參看剛才的get_scans_list()函式,這裡就不重複了,讓我們看一下它的返回值,可以看到返回值中有一個sacns的字典列表, 裡面有name和id這兩個欄位

{
    "folders": [
        folder Resource
    ],
    "scans": [
        {
            "id": {integer},
            …
            "name": {string},
            …
        }
    ],
    "timestamp": {integer}
}
def get_scan_id(scanname):
    # 任務ID
    scan_id = 0
    # 獲取任務列表
    scans_list = get_scans_list()['scans']
    if scans_list != '':
        # 遍歷任務列表
        for scan in scans_list:
            # 判斷是否是指定的任務
            if scan['name'] == scanname:
                scan_id = scan['id']
                break
    # 如果未找到,則返回0
    return scan_id

由於不同的資料夾下允許存在同名的任務,所以為了更精確的定位任務,也可以加入folder_id來查詢,呼叫介面/scan時加入查詢字串folder_id=3即可。folder_id也可以用和scan_id相同的方法獲取,大家可以自己試一下。

2、發起任務

有了scan_id,我們就可以使用/scans/{scan_id}/launch介面來發起一個任務了。
另外這個介面需要用POST方法呼叫,掃描的目標需要放在請求的payload裡。程式碼如下:

# iplist為掃描目標IP的列表
 def scan_luanch(iplist):
    # header資訊在全域性變數中,之後的例項中將不再重複
    # 呼叫/scans/{scan_id}/launch
    url = 'https://localhost:8834/scans/{scan_id}/launch'.format(scan_id=get_scan_id('default'))
    # 掃描目標放在請求的payload裡
    data = {
        'alt_targets': iplist
    }
    # 傳送請求
    respon = requests.post(url, headers=header, data=data, verify=False)
    # 是否請求成功
    if respon.status_code == 200:
        return True
    else:
        return False

我們可以呼叫一下scan_launch()看看效果

scan_luanch(['1.1.1.0', '1.1.1.1'])

這裡寫圖片描述

可以看到我們已經成功的發起了一次任務了。

至此我們就完成了登入和發起任務的工作,之後還有許多內容可以完善,例如監聽任務狀態,獲取任務結果,以及動態建立任務等,將在後續的文章中為大家分享。