Axiom: It Kinda Feels Like Cheating
10 min read

Axiom: It Kinda Feels Like Cheating

Axiom allows you to drastically scale up your bug bounty recon-game for pennies on the dollar.

Hack the Planet, with a little help from a friend.

Axiom is early in development and some of the syntax is not yet finalized. As the tooling changes, I'll make an effort to keep this post updated.

@pry0cc (Ben Bidmead)'s axiom project turns you into a recon rockstar. If you run a lot of modern recon tools you will most certainly benefit from leveraging axiom to speed things up. Axiom takes synchronous recon tools as we know them, and enables us to quickly scale them up by splitting up the input data and running multiple processes across a fleet of virtual machines!  It abstracts all of the complexity away from configuring and deploying virtual machines that are ready to go.

Axiom allows you to drastically scale up your recon-game for pennies on the dollar.

Have I... created a monster?

DigitalOcean is the first cloud provider that axiom integrated with, but IBM and Google Cloud are in the works as well. You can play around with these today!

I'm going to braindump a bit about my axiom workflow and how to get started. If you want to follow along, make sure you have a Digital Ocean account. I encourage you to use pry's referral link for $100 in credit you can play around with. (Note that DO limits new accounts to a droplet limit of 3. This is more than enough to get a fleet going, but you may want to deposit some $ into your account and request a limit increase.)

Finally, I'll say that I'm pretty new to the bug bounty game. What I discuss here are sure to be basic, entry-level thoughts and ideas. I would love if you could expand on how you use axiom either in the comments below, or by hitting me up on twitter at @adamsvoboda. Share the knowledge!

Getting started with axiom

There's already a great guide on the GitHub page complete with images, so I won't re-invent the wheel here. Refer to that link if you need a little nudge.

Toss this into the terminal of your choice, on macOS/Linux:

bash <(curl -s https://raw.githubusercontent.com/pry0cc/axiom/master/interact/axiom-configure)

While it runs, give yourself a pat on the back. You just took the first step towards cheating at recon. It's okay to feel a little dirty about it. Most people shower after their first fleet.

As this script runs, head on over to the DigitalOcean API key settings and generate a new key. You'll need this at the end of the installation. Once complete, continue on...

One bug bounty program I like to hack on is the Department of Defense VDP program on HackerOne. It has a massive scope and is a great target for axiom's superpowers. Because of this, in the examples below I'll be using the army.mil domain.

Let's spin up a fleet named "army.mil" with 3 droplets and an expiration time of 2 hours:

axiom-fleet army.mil -i=3 -t=2

Note: You may want to use a fleet name without a period inside of it. I learned later that these may mess up the grep matching for other commands.

While we wait for this, get acquainted with Interact Modules in the next section. You can always list available fleets with axiom-ls

Interact Modules

Axiom contains interact modules, which are rulesets for running tools, defined in JSON. These tell axiom how to execute the command of your choice across the fleet. It includes a few "complete" modules and the rest are seemingly templates for you to expand upon yourself.

Here is an example of the first custom interact module I created. I'm a heavy user of httprobe by tomnomnom for passing over my list of discovered domains to find live websites.

~/.axiom/interact/modules/httprobe.json

{
	"command":"cat $infile | /home/op/go/bin/httprobe -c 200 -t 10000 > $outfile",
	"box_infile":"httprobe_input",
	"box_outfile":"httprobe_output",
	"output_format":"txt",
	"output_ext":"txt",
	"output_dirs":"false",
	"default_ports":"",
	"default_args":""
}

The ruleset is pretty simple. It passes an input file into httprobe and runs it with 200 concurrent requests: -c 200. I also change the default timeout value to 10 seconds per host using -t 10000.

Here's a general rule of thumb for creating a custom module.

  • Specify a custom box_infile and box_outfile for each module. This can help with debugging modules and also makes sure that file names don't overlap.
  • Edit the command parameter to reflect a verison of the local command you would typically run. If it doesn't already, you should have it output the stdout to a local file (to assist in debugging). There's been a few times when writing custom interact modules that I've had to axiom-ssh into a box and check these files.

You can start to quickly scaffold interact modules for all of the recon commands you use. Here's another example with waybackurls by tomnomnom.

~/.axiom/interact/modules/waybackurls.json

{
	"command":"cat $infile | /home/op/go/bin/waybackurls > $outfile",
	"box_infile":"waybackurls_input",
	"box_outfile":"waybackurls_output",
	"output_format":"txt",
	"output_ext":"txt",
	"output_dirs":"false",
	"default_ports":"",
	"default_args":""
}

Once the interact modules are created, you can execute them using axiom-scan (on the selected fleet), like so:

axiom-select "army.mil*"

axiom-scan army.mil.domains -m=httprobe -o=army.mil.httprobe

  • The first argument is the input file, which is a list of army.mil domains. (This used to be specified using the -iL= parameter but it's optional now.
  • -m tells axiom-scan which module ruleset to use.
  • -o is the output file, the compiled output we receive from the distributed httprobe command across all of our fleet vms.

Starting to make sense? Check out some of the modules included in the GitHub repository and see how you can build and expand on them. Add the cli agruments you frequently use to the tools and play around with creating your own rulesets.

Continuing our tutorial, let's kick off a distributed dnsprobe command using the built-in dnsprobe interact module. If you need an example copy of army.mil.domains you can download an incomplete list (from assetfinder) here.

Axiom recently made some changes to the scan syntax. Before running axiom-scan we now need to run axiom-select to select which fleet we want to run the scan on. axiom-select actually stores the selected fleet at $AXIOM_PATH/selected.conf and makes it easier to have axiom manage and spin up multiple fleets and assign them seperate tasks. It's a good step in the right direction to improving the flexibility of axiom!

axiom-select "army.mil*"

axiom-select updated the selected.conf file with the machines to target commands for.

axiom-scan army.mil.domains -m=dnsprobe -o=army.mil.dnsprobe

This will take the source file of domains army.mil.domains and split them up into as many pieces as droplets are in your fleet. In our case, 3 pieces. Each piece is sent to one of the fleet droplets for processing. When all droplets in the fleet are finished, the results are returned, concatenated together, and saved to the army.mil.dnsprobe file.

When the scan command completes, check the army.mil.dnsprobe file. You should see a series of domains and IP addresses on the same line if they resolved successfully.

Here we can see the distributed dnsprobe module reduced our actual resolvable domains down from 7,760 to 67!

Think about the time savings (as a factor of droplets in your fleet) for a lot of the more time-consuming recon tools!

How can you chain several axiom-scan commands together and end up with something really useful at the end? This idea should be at the core of your recon automation workflow.

When you're finished with your fleet, don't forget to remove it. If you do, it will just expire after the initial time you passed in the fleet creation command, but you'll be billed for any time you don't use.

You can see a list of droplets in your fleet by doing axiom-ls, and you can remove them by running axiom-rm "army".

NOTE: Be careful with the axiom-rm command if you have other droplets in your Digital Ocean account. If you don't specify a specific string with wildcard you could risk deleting VMs you care about. You do get the option to confirm each deletion so just pay attention and you'll be alright.

How axiom fits into my recon automation workflow

Right now I'm having a lot of fun compartmentalizing the different components of my modular recon workflow, and moving a lot of the more time-consuming tasks to axiom, where they complete in a fraction of the time.

This is a very basic recon automation workflow, that takes a lot of suggestions from The Bug Hunter's Methodology v4: Recon Edition by Jason Haddix as well as Mechanizing the Methodology by Daniel Miessler. I highly suggest you watch these videos! You'll pick up a thing or two that can be done to improve your recon workflows.

Soon, I'll be open-sourcing these components on my GitHub. I'll create another blog post discussing them and make sure you guys won't miss it.

My general one-script-fits-all recon automation works as follows:

  1. A root domain is provided, ASN lookups are performed, and information about the root domain and IP address are saved to asn.txt
  2. An axiom fleet is started and we give it time to spin up in the background.
  3. A folder is automatically created for the project files root.domain/
  4. assetfinder (by tomnomnom) is ran to quickly give us a list of domains to start with. These may or may not be live, valid domains. We filter those out later. Since assetfinder is SO FAST, I just run it locally instead of on an axiom fleet.
  5. amass is used to enumerate domains. I only use passive scanning here. This is the slowest process that's not offloaded to an axiom fleet for processing. It's harder to offload domain enumeration tools on root domains since theres no easy way to segment the work.
  6. subfinder is used to catch any domains we might've missed
  7. A list of results from assetfinder, amass & subfinder are combined into one massive "source domains" list. Duplicates are removed.
  8. Our axiom fleet is ready to rock by now. We kick things off with an axiom-scan command using the dnsprobe module. The goal here is to have axiom execute a distributed instance of dnsprobe to get rid of all the domains in our list that do not resolve. axiom-scan $DOMAIN.filtered -m=dnsprobe -o=$DOMAIN.livedns
  9. We extract all of the IP addresses from the results and send them to axiom again, this time using the masscan module. The goal here is to check these IPs for HTTP services on a variety of common ports. axiom-scan $DOMAIN.ips --rate=10000 -p80,443,8000,8080,8043,8443,4443 --banners  -o=$DOMAIN.masscan
  10. Recently I've gone back and forth between masscan and a combination of httprobe and aquatone.  axiom-scan $DOMAIN.livehosts -m=httprobe -o=$DOMAIN.httprobe
  11. After this, I defer to axiom-scan using a custom meg module. I also have a ffuf  modue that is coming along nicely. I plan to talk more about this in the future.
  12. Finally, my recon automation will run waybackurls (outside of axiom since it's pretty fast), followed by aquatone to generate me interesting HTML reports. This is great for large scopes like the Department of Defense VDP program.
  13. At this point I have a good set of files to use for other toolsets, as well as a great HTML report generated by Aquatone to identify any low-hanging fruit or interesting webpages.

This automation workflow was a big bottleneck for me prior to using axiom. What took 3-4 hours on my machine completes in under 15 minutes. I can scan 300k domains using multiple tools in well under 1 hour.

Using this workflow enabled me to discover three vulnerabilities (two critical) in the DoD in under 4 days of looking!

Insane return on investment!

I'm still impressed by how cheap this is to run. I didn't fully realize how cost-effective the public cloud was for concurrent tasks until I spent some time with multiple axiom fleets.

Digital Ocean charges you for a minimum of one-hour per droplet you create. That means that if you used axiom to spin up a fleet of 10 droplets and only used them for 15 minutes, you'd be billed for 10 hours. Fortunately, axiom does a great job estimating your billing cost by taking into account the -t (time to expire) parameter when you launch a fleet.

In my first week with axiom, I was billed for 76 hours worth of droplets. That's 76 seperate droplet instances all working together. It cost me less than $1.

My bill after a week of axiom usage.

How can I get involved?

  • Try axiom out yourself!
  • Report issues or feature requests on GitHub.
  • Sponsor pry on GitHub.
  • Tell your friends!
  • Contribute to the project on GitHub.

Thank you for your time!

More posts on axiom and my recon automation journey are on the way.