Visualizing, organizing, and processing information on large networks can be a difficult task. Often I find myself being given incomplete data or large amounts of scan results that can take forever to analyze. Recently I was handed a large collection of Nessus scan files for a network assessment and was overwhelmed with the magnitude of network and host system data they contained. I started to think about how I could most efficiently ingest and share this data with my team during the assessment.

After a little research, I decided that this might be a perfect job for Maltego. Maltego is an excellent tool for visualizing and correlating large amounts of data. It also provides a space for my team members to share notes about each piece of information displayed(entities). This research resulted in a Python Maltego transform that processes raw Nessus scan files and creates native and custom entities representing hosts and outcome data

Maltego Transforms

Maltego transforms are configurations that allow you to specify an executable block of code to run in the context of a specific entity. The executable code can be run locally, written in a language of your choosing, or remotely, as a iTDS transform. Transform output is used to add and/or modify entities in the given graph and comes in the form of XML formatted data.

The Product

I chose to develop a local transform written in Python which I have called, rather uncreatively, MaltegoNessusParser. Python is perfect for simple development tasks and contains an extensive set of built in libraries. The transform parses the XML tree of the Nessus scans and collects information on each unique host as well as the plugin output associated with it. This information is then consolidated and formatted into the XML format that Maltego expects. It also contains some small GUI based elements that prompt the user for the input file and plugin filtering options. The GUI components were written using the Tkinter python library.

Parsing Nessus Scans

Parsing Nessus scan files is pretty straight forward. The files are structured in an XML format with the bulk of interesting data being in the Report element. The Report element contains ReportHost elements, which in turn contain ReportItems. Currently the transform tries to combine similar services into a single entity, and when a service type cannot be identified, it uses the port number. Any miscellaneous outcome data is stored in the Notes property of the Maltego entity.


To use the transform, right click on the NessusScan entity. Select the “To IP Address [Using Scan Results]” transform which will populate the Maltego graph with IPv4Address entities for all unique hosts in the scan files. The new entities will also contain custom properties including the operating system, hostname, and device type if available.

The following prompts for file paths and Nessus plugin filtering settings will appear if the entity does not have them set prior to execution.

The next step is to run the “To Nessus Scan Data” transform. This will populate the Maltego graph with service, port, and Nessus plugin entities.

The number of specifically handled Nessus plugin types is limited, but the generic handler will create a custom Nessus Plugin entity for holding all the output data.

To date, this transform has been tested against Nessus scan files up to 300MBs in size. It is not particularly fast, but it will create maps containing thousands of entities. The resulting graph is easily searchable using Maltego’s search feature and can be shared between multiple users. I set up a local jabber server according to Paterva’s instruction and was able to provide my team with a unified space to work from during our assessments. It was not the most elegant solution, but it got the job done.

The transform still needs lots of work and would benefit from some optimization. Feel free to check it out on our Github and submit any feedback or pull requests.