Practical amass – How I configure and use amass in my recon flow

Map of servers, clouds, and computers

If you’re into recon, you’ve probably heard of amass. It’s a powerful tool for mapping attack surfaces during bug bounty hunting or penetration testing. Here’s why I love it:

  • It’s close to an all-in-one recon tool.
  • It aggregates data from multiple resources (DNS, ASN, Whois, etc.).
  • Its capabilities can be extended with API keys.
  • It stores all data in a SQLite database, making information management and querying easier than relying on text files.

Instead of repeating what’s already in the official tutorial, I’ll take you through how I use Amass in my bug bounty recon workflow.

Global Configuration

Once you install amass, the first step is setting up its configuration files. For me, these live in:

~/.config/amass/

Then in here, I did the following:

1. Create the Required Files:

  1. datasources.yaml: Stores API keys.
  2. config.yaml: Default configuration file.

2. Set Up Datasources

Run the following to see which sources need configuring:

 amass enum -list

Any source marked with a star requires an API key. Register for as many free resources as possible to maximize Amass’s capabilities. For example, my datasources.yaml file contains:

datasources:
  - name: Shodan
    creds:
      account:
        apikey: "<key>"
  - name: VirusTotal
    creds:
      account:
        apikey: "<key>"
  - name: SecurityTrails
    creds:
      account:
        apikey: "<key>"
global_options:
  minimum_ttl: 1440

3. Link Datasources to the Configuration

Use config.yaml to reference your datasources file:

options:
  datasources: <PATH TO>/.config/amass/datasources.yaml

For a basic setup, this configuration is enough. You can explore more customization options in the OWASP Amass project.

Workspace Setup

Before I start working on a program, I create a directory for all of my program-specific work:

~/bounties/<program-name>/recon/amass

This is where I would store amass outputs, configuration files, and databases.

Project-Specific Configuration

In the amass directory, I maintain a separate config.yaml tailored to the specific program:

scope:
  domains:
    - example.com
    - example1.com
  ips:
    - 127.0.0.1
  asns:
    - 1234
  blacklist:
    - sensitive.example.com
options:
  timeout: 5

This keeps Amass focused on the program’s defined scope and prevents unnecessary noise. You can point amass to this project-specific configuration file with the -config flag.

Root Domain Discovery

If you’re starting with ASNs, IP ranges, or an organization’s name, the intel command helps find root domains to target:

amass intel -asn 16839 -dir amass -config recon/config.yaml

Or, if you already have a domain and want to expand the attack surface:

amass intel -whois -d example.com -dir amass -config recon/config.yaml

This performs a reverse whois lookup, gathering related domains.

Subdomain Discovery

Once you’ve identified root domains, it’s time to dig deeper with enum:

amass enum -d example.com -dir amass -config recon/config.yaml

This will map out subdomains for further analysis.

By default, amass enum runs passively, meaning it relies solely on 3rd parties for the information. You can use the active flag to tell it to directly interact with the target for (potentially) more results and increased accuracy:

amass enum -active -d example.com -dir amass -config recon/config.yaml

This will likely take longer to run than the passive option. I recommend starting with passive then circling back to active once you’ve exhausted your exploitation efforts.

It’s also worth noting that amass has capabilities for performing subdomain brute-forcing. One useful option being a hashcat-like masking option. I’ll leave that for you to explore in the official tutorial.

Parsing Gathered Domains

amass organizes all data in a SQLite database stored in the directory specified by the -dir flag. Using sqlite3, you can query and manage the data:

$ sqlite3 amass.sqlite
sqlite> .tables
assets           gorp_migrations  relations

The assets table is the most relevant, categorizing data into types like FQDN, IPAddress, ASN, and more.

An example query to extract recent IPv4 addresses:

SELECT content -> 'address'
FROM assets 
WHERE type = 'IPAddress' 
AND json_extract(content, '$.type') = 'IPv4' 
ORDER BY last_seen DESC 
LIMIT 10;

As you can see, using sqlite as the DBM makes it easy to pull exactly what you need and plug it into other tools.

Why SQLite Beats Legacy Features

Older versions of Amass supported amass db for queries and amass viz for visualization. While those features were neat, I prefer direct database queries. They give you more control and are easy to script for repeated workflows.

For example, you could write a script to export all gathered domains and IPs into separate files for further analysis.

Also, the viz feature doesn’t add much value in my opinion. For me, visualizing massive amounts of data would be more overwhelming than useful.

I’d much rather pull only what stands out to me and throw it in a mind-mapping tool (like xmind). That way, I can work in a less cluttered environment.

Conclusion

amass is a game-changer for recon workflows. While setting up API keys may cost some time (and occasionally money), it’s an investment that will give you an edge in bug bounty programs.

I highly encourage you to experiment with this tool, tweak configurations, and build scripts to fit your needs.

Happy hunting!