[實戰紀錄] 掃描紀錄自動化轉化工具

nessus 轉換成 xlsx 開發過程

Last Modified by YuKai on Friday, June 21, 2024

大綱

主要紀錄一下這兩點的開發過程,而這個案子雖然還用到了爬蟲抓取中文翻譯的資料,並且使用了 pandas 來實現 xlsx 的轉換,但因為沒什麼特別的地方,都是很基礎的語法功能而已,這邊就不紀錄了。

  • 讀取 .nessus 檔案(解析 XML 的過程)
  • Command Line 功能(python argparse module 的使用)

讀取 .nessus 檔案

使用第三方函示庫 nessus_file_reader,來讀取 .nessus 檔案。使用到的程式碼如下

import nessus_file_reader as nfr
root = nfr.file.nessus_scan_file_root_element(filename) # 讀入檔案
for case_index, report_host in enumerate(nfr.scan.report_hosts(root)):
    report_items_per_host = nfr.host.report_items(report_host)
    for index, report_item in enumerate(report_items_per_host):
        __risk_factor = nfr.plugin.report_item_value(report_item, 'risk_factor')
        __plugin_id = nfr.plugin.report_item_value(report_item, 'pluginID')

這個套件的解析過程會把 .nessus 當作 XML 來分析,先找出這份 XML 的 root 之後,尋找所有的 ReportHost,這是每一組 ip 的報告結果,接者再從這些報告結果中找出 ReportItem 一筆一筆分析

了解 nessus_file_reader 是如何解析 XML,就換我用 ElementTree 寫一個。

import xml.etree.ElementTree as ET
filename = ""

def main():
    tree = ET.parse(filename)
    root = tree.getroot() # 找出 XML 檔案的 root
    hosts = root.find("Report").findall("ReportHost") # 找出所有的 ReportHost
    report_item_name = "risk_factor"
    for report_host in hosts:
        reports = report_host.findall("ReportItem") # 從每個 ReportHost 找出所有的 ReportItem
        for report_item in reports:
            report_item_content_value = report_item.get(report_item_name)

            if report_item_content_value is None:
                report_item_content = report_item.find(report_item_name)
                if report_item_content is not None:
                    report_item_content_value = report_item_content.text

需要注意的是,在找 report_item_name 的 tag,可能會遇到多層的巢狀結構,所以如果用 get() 的返回值為 None,也就是 tag 的 attribute 沒有 report_item_name,此時就需要用 find() 往內尋找

自訂義 Command Line

這是我第一次挑戰寫 CLI 的工具,直接使用內建的 argparse 來建立指令,一開始需要先宣告 parser

parser = argparse.ArgumentParser(description='CLI描述')

設置預設觸發 function

parser.set_defaults(handle=simple_transform)

參數功能

設置如下,其中 store_true 代表只要出現這個參數就設為 True,這樣就不用特地給將 True Value 打出來

parser.add_argument('-sl', '--show_all_level', action='store_true',
                        help='是否輸出 Critical level 之外等級的漏洞')
parser.add_argument('-info', '--info', action='store_true',
                        help='是否輸出 infomation')
parser.add_argument('-o', '--output', type=str, default=os.getcwd(),
                        help='輸出的位置')

群組功能

這個功能可以用來設置一定要輸入該群組中其中一個指令

group = parser.add_mutually_exclusive_group(required=True)
group.add_argument('-f', '--file', type=str,
                    help='要轉換的 .nessus 檔案')
group.add_argument('-l', '--list', type=str,
                    help='轉換多個 .nessus 檔案')

子命令功能

如果要增加子命令,使用以下方法即可,subparsers 的用法就跟 parser 一樣

subparsers = parser.add_subparsers(metavar='子命令')

資料來源


comments powered by Disqus