Add a new tool scanner class
As a first step to integrate a new scanner, answer the below questions:
- Which module will this scanner be a part of?
- Amass is used for subdomain discovery and hence will be part of the disovery module
- Is this scanner a command line tool or API?
- Amass is a command line tool
- What will the tool output?
- Amass will output a list of subdomains
- What is the report output format we are expecting to parse?
- Though Amass supports a number of output formats, lets go with .txt
- What is the command that you need to execute?
- amass enum -passive -d {input_domain} -o {output_file_path}
- What is the input that the tool takes, meaning, TLDs, subdomains, IPs etc.?
- Amass takes TLDs as an input
Now that we have a clear understanding of the expected input and output from the tool, let's begin the process of creating the scanner class. As previously indicated here, we are required to implement three functions:
- base_get_commands() or get_commands()
- parse_report()
- db_operations()
Creating the Tool Class
Please Note - The name of the tool class should be the same as defined in the config file
Create a new file under /mantis/mantis/modules/discovery/
and name it Amass.py
Implementing get_commands()
This function needs to return a list of tool commands for every asset.
def get_commands(self, assets):
self.org = args.org
self.base_command = 'amass enum -passive -d {input_domain} -o {output_file_path}'
self.outfile_extension = ".txt"
self.assets = await get_assets_grouped_by_type(args, ASSET_TYPE_TLD)
return super().base_get_commands(self.assets)
- self.base_command represents the command to be executed
- self.outfile_extension indicates the output file extension
- self.assets exclusively extract TLDs from the database, which are then supplied as input to Amass
Infoπ‘- As mentioned here, Mantis incorporates a range of pre-existing utility functions to facilitate the seamless integration of new tools
Implementing parse_report()
This function is required to parse what the scanner outputs and insert it into the database. In this context, a list of subdomains need to be extrated and inserted into the database.
Infoπ‘- To understand the DB schema, click here
def parse_report(self, outfile):
output_dict_list = []
amass_output = open(outfile).readlines()
for domain in amass_output:
domain_dict = {}
domain_dict['asset'] = domain.rstrip('\n')
domain_dict['asset_type'] = ASSET_TYPE_SUBDOMAIN
domain_dict['org'] = self.org
output_dict_list.append(domain_dict)
return output_dict_list
You dont have to worry about where the output file is stored etc. The outfile parameter is the path to the output file generated by the tool
- domain contains the subdomain
- asset_type is a parameter required for Mantis, the type of Asset, if its a TLD, subdomain or IP
- org is the organisation to which the asset belongs to, fetched from args
Implementing db_operations()
The final step is to insert the data into mongoDB
async def db_operations(self, tool_output_dict, asset=None):
await CrudUtils.insert_assets(tool_output_dict)
This is straight forward, call the corresponding util function to insert the data into mongoDB.
Infoπ‘- Depending on whether you are inserting an asset, or updating an asset for recon information, or adding a new finding, you can use the corresponding util functions as described here
βοΈ In a similar fashion let's try to add a new API scanner.