axiom——一款基于云的分布式网络安全扫描工具

发布时间 2023-04-14 16:40:19作者: tech_lee

分布式信息收集扫描工具,一键创建云上多实例分布式扫描。
github:https://github.com/pry0cc/axiom/

安装

官网上提供了四种方式,分别是Docker、Easy Install、Using Git Clone、Manual

我喜欢使用Git CLone的方式(可以在本地搭建也可以在VPS上搭建):

  1. Ensure that ~/.axiom/ does not exist

    rm -rf ~/.axiom/
    
  2. Clone the axiom repository

    git clone https://github.com/pry0cc/axiom ~/.axiom/
    
  3. Run configure script

    $HOME/.axiom/interact/axiom-configure
    

执行axiom-configure会自动安装依赖,需要填入云平台的key(这里支持多个云平台,我选择的AWS)

填入key和secret后再选择region,填写需要创建的镜像类型(如果是结合reconftw使用,就选择reconftw,常规保持默认default)

We currently offer three different base provisioner files, and 2 custom provisioner file to build images.

  • Default is our latest iteration of axiom provisioners. It comes with all tools installed and has been optimized for readability. Recommended for axiom-fleet.
  • ReconFTW provisioner includes all tools in ReconFTW and works with most modules. Recommended for ReconFTW.
  • Barebones is our decently secure base install, comes with Docker, Go-lang, Interlace and nmap installed. Recommended for templating.

Custom Images:

  • Classic provisioner works with most modules and was the first iteration of axiom provisioner files.
  • Light provisioner comes with zsh and a few other minor adjustments over the barebones provisioner.

之后就会自动在你所在的云平台创建image(之后分布式任务都是基于该image镜像,从image创建多个实例然后分布式的跑任务)

在安装成功后,基本如下这样:

Your build completed successfully in xx minutes! You should run axiom-update && axiom-build weekly to get the latest and greatest updates! 
To initialize an instance, run axiom-init
You may need to restart your shell: /usr/bin/bash

然后重启下shell,尝试axiom-init创建一个实例,如果可以成功创建,会出现以下回显:

Initializing 'gates22' at 'us-west-2' with image 'axiom-default-1681197876'
INITIALIZING IN 5 SECONDS, CTRL+C to quit... 
Initialized instance 'gates22' at '54.202.75.136'!
To connect, run 'axiom-ssh gates22' or 'axiom-connect'

然后就可以使用axiom-ssh gates22 or axiom-connect进行ssh连接:

ubuntu@ip-172-26-12-147:~/.axiom$ axiom-connect 
The authenticity of host '[54.202.75.136]:2266 ([54.202.75.136]:2266)' can't be established.
ECDSA key fingerprint is SHA256:7Jwl55zMmk0RVuTaFpVkcXh0avGNSvUpK1J8zEc/GXo.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '[54.202.75.136]:2266' (ECDSA) to the list of known hosts.

 ▄▄▄      ▒██   ██▒ ██▓ ▒█████   ███▄ ▄███▓
▒████▄    ▒▒ █ █ ▒░▓██▒▒██▒  ██▒▓██▒▀█▀ ██▒
▒██  ▀█▄  ░░  █   ░▒██▒▒██░  ██▒▓██    ▓██░
░██▄▄▄▄██  ░ █ █ ▒ ░██░▒██   ██░▒██    ▒██
 ▓█   ▓██▒▒██▒ ▒██▒░██░░ ████▓▒░▒██▒   ░██▒
 ▒▒   ▓▒█░▒▒ ░ ░▓ ░░▓  ░ ▒░▒░▒░ ░ ▒░   ░  ░
  ▒   ▒▒ ░░░   ░▒ ░ ▒ ░  ░ ▒ ▒░ ░  ░      ░

Public IP: 54.202.75.136 - Instance: ip-172-31-22-71

这样就表示已经安装好了。

基本使用

axiom-images

管理镜像、快照

axiom-images ls # List available images
axiom-images use <image name> # Replace image used for axiom-init/axiom-fleet with user provided image name 
axiom-images rm <image name> # Delete image by name

axiom-init

初始化一个实例

axiom-init <name> # Init
axiom-init <name> --deploy <profile> --restore <box> # Init & deploy & restore 
#Note: profile argument is file name is without .json

axiom-ls

列出当前运行的实例

axiom-ls

axiom-exec

在实例上运行命令

  axiom-exec id # Execute command id across all instances currently selected.conf (located in ~/.axiom/selected.conf)
  axiom-exec ifconfig --fleet testy # Execute ifconfig on testy fleet. Automatically select all instances in fleet testy
  axiom-exec sleep "$(($RANDOM % 10))" "&& id &&" echo $HOSTNAME --fleet stok # Evaluate complex one-liners on fleet stok
  axiom-exec 'sudo apt dist-upgrade -y' -q --cache --fleet OtherFleet --tmux MySession01 # Quietly execute command(s) inside a detacted tmux session on the remote instances with custom session name
  axiom-exec whoami -q --cache --sshconfig ~/.axiom/log/exec/axiom-exec+1234567890/sshconfig --fleet oldfleet --tmux # Specify the axiom SSH config to use (default is ~/.axiom/.sshconfig)

axiom-ssh

通过ssh连接到实例

axiom-connect #automatically connects to list initialized instance
axiom-connect <name>
axiom-ssh <name> <ssh args>
axiom-ssh <name> --tmux # 使用该参数,结合ctrl+a d 可以实现退出ssh窗口但会话依然运行
axiom-ssh <name> -m -t <tmux session> # Connect with mosh and attach to tmux session
axiom-ssh <name> -m -t main-15
axiom-ssh <name> -L 8080:127.0.0.1:8080 -D 4040 # All additional SSH args are passed to SSH
axiom-ssh <name> --cache # Don't generate ssh config, just connect with cache
axiom-ssh --just-generate # Generate an SSH config at ~/.axiom/.sshconfig

axiom-backup

将一个初始化的实例备份到云端

axiom-rm

删除一个或多个实例

axiom-rm <name> # Delete box by specifying the name
axiom-rm <name> -f # Forcibly delete box by specifying the
axiom-rm <name>\* # Delete all instances that start with <name>. You must escape the asterisk.  
axiom-rm <name>\* -f # Forcibly delete all instances that start with <name>. You must escape the asterisk.  
axiom-rm '\*' # Delete all instances on the account. Must be wrapped in single quote and escape the asterisk. 
axiom-rm '\*' -f # Forcibly delete all instances on the account. Must be wrapped in single quote and escape the asterisk. 

axiom-power

实例/集群 开启/关闭/重启

axiom-power on 'rez\*' # Power on all instances in fleet named rez
axiom-power off 'rez\*' # Power off rez fleet
axiom-power reboot 'rez\*' # Reboot rez fleet

axiom-boxes

列出所有备份box

axiom-boxes ls # List boxes
axiom-boxes ls --archive # List archived boxes
axiom-boxes new <box> # Create a blank box backup
axiom-boxes rm <box> # Delete a box backup 
axiom-boxes archive <box>  # Archive a box (tarball & gpg -e)
axiom-boxes unarchive <box> # Unarchive (from ~/.axiom/archives/), gpg decrypts
axiom-boxes get pry0cc/lazy # Get a box from  github, username/repo

axiom-region

切换到新的region

axiom-region ls # lists regions
axiom-region select <region> # select region

axiom-region select ams2

axiom-account

设置新账号和切换账号

axiom-account-setup # Setup a new account
axiom-account # No args, list available accounts
axiom-account <account> # Select/Switch to the specified account

axiom-scp

双向复制文件

  1. 从集群所有实例中复制文件到本地($name必须使用单引号)
    axiom-scp 'myfleet*':/home/op/myfile.txt '~/local/folder/$name.txt'
    
  2. 从集群所有实例中复制文件到本地文件夹($name必须使用单引号)
    axiom-scp 'myfleet*':/home/op/myfile/ '~/local/folder/$name'
    
  3. 从实例中复制文件到本地
    axiom-scp myfleet05:/home/op/myfile-from-myfleet05.txt '~/local/folder/myfile-from-myfleet05.txt'
    
  4. 从本地复制文件到集群
    axiom-scp myfile.txt 'myfleet*':/home/op/myfile.txt
    
  5. 从本地复制文件夹到集群
    axiom-scp mytemplates/ 'myfleet*':/home/op/custom-templates 
    

axiom-select

  1. 部署一个profile
    axiom-select '<instance>'
    axiom-select 'testy*'  # Testy is an example of a fleet
    axiom-deploy openvpn '<instance>' # Install openvpn against host or fleet
    axiom-deploy covenant '<instance>' # Install covenant
    
  2. 连接到远程的axom实例Docker(通过ssh),实际测试会报错Permission denied publickey
    axiom-select <instance>
    . axiom-docker # Not a typo, the . means source
    docker ps
    

axiom-vpn

连接到在axiom部署的openVPN

axiom-vpn <instance>

axiom-proxy

使用ssh隧道搭建socks代理,本地端口5000-50100之间,会在当前目录生成一个proxychains.conf配置文件。

axiom-proxy '<fleet>*'
axiom-proxy '<instance>'
axiom-proxy 'testy*'
proxychains4 curl -s ipinfo.io

axiom-dns

仅支持Digital Ocean VPS,创建一个DNS A记录

axiom-dns ls # List domains
axiom-dns ls <domain> # List records for domain
axiom-dns add <subdomain> <domain> <ip address>
axiom-dns add cisco navisec.xyz 167.71.89.136 # Example, this will create a record cisco.navisec.xyz pointing to 167.71.89.136 

axiom-fleet

初始化一个集群

axiom-fleet -i 13 # Initialize a fleet, name it randomly
axiom-fleet testy -i 8 # Initialize a fleet named 'testy', instances will be named, testy01, test02 etc
axiom-fleet testy -i 10 --regions nyc1,lon1,ams3,fra1 # Initialize a fleet using round-robin region distribution  

axiom-scan

集群扫描

axiom-select 'fleet*' # fleets should be already selected, but just in case, select can be a good idea

# Format
axiom-scan <input> -m <module> -o <text outfile> <any other args>

# Examples
axiom-scan subs.txt -m httpx -o http.txt # httpx module
axiom-scan http.txt -m nuclei -o nuclei.txt # nuclei module, find vulns
axiom-scan http.txt -m gowitness -o screenshots # gowitness, take screenshots
axiom-scan subs.txt -m dnsprobe -o dns.txt # Run dnsprobe

axiom-scan ips.txt -m nmap -oG portscan.txt # nmap
axiom-scan ips.txt -m nmap -oX portscan # Will create both portscan.xml & portscan.html
axiom-scan ips.txt -m nmap -oX full -p- -T5 -sV --script=vulners # Will create full.xml, will pass all args to nmap command

axiom-scan ips.txt -m masscan -oG masscan.txt # Run masscan

集群

Description:
  Spin up fleets of axiom instances in one or multiple regions.
  Specify the name of your fleet (fleet prefix) or have axiom choose for you.
Examples:
  axiom-fleet # Spin up three instances, let axiom decide on the fleet prefix
  axiom-fleet javis -i 10 # Spin up 10 instances with fleet prefix javis from javis01 to javis10
  axiom-fleet jerry -i 25 --regions nyc1,lon1,ams3,fra1 # Spin up 25 instances using Round-robin region distribution
Usage:
  -i/--instances <integer>
    The number of instances to spin up
  -r/--regions <regions> (optional)
    Supply comma-separated regions to cycle through (default is region in ~/.axiom/axiom.json)
  --help (optional)
    Display this help menu

一对多vs多对一

一对多:一个包含多个目标的文件被拆分到集群各个实例中进行工作。
多对一:集群多个实例对同一目标进行分布式工作(将字典拆分后同时进行)

一对多

举例说明:
puredns-bruteforce模块如下:

[{
    "command":"/home/op/go/bin/puredns bruteforce /home/op/lists/seclist/Discovery/DNS/dns-Jhaddix.txt --domains input --resolvers /home/op/lists/resolvers.txt | tee output",
    "ext":"txt"
}]

这里targets.txt就会进行拆分和上传到各个实例,并在命令中替代到input位置

axiom-scan targets.txt -m puredns-bruteforce -o result.txt

多对一

puredns-bruteforce模块如下:

[{
    "command":"/home/op/go/bin/puredns bruteforce input tesla.com --resolvers /home/op/lists/resolvers.txt | tee output",
    "ext":"txt"
}]

可见相比之前对module进行了修改,input位置是字典文件,目标则硬编码到module中。

axiom-scan bitquark-subdomains-top100000.txt -m puredns-single -o my-horizontal-results

也可以不将目标硬编码到module,如下:

[{
    "command":"/home/op/go/bin/puredns bruteforce input --resolvers /home/op/lists/resolvers.txt | tee output",
    "ext":"txt"
}]
axiom-scan bitquark-subdomains-top100000.txt -m puredns-single tesla.com -o myoutput.txt

这里,tesla.com目标作为额外参数,传入命令中了。

分布式扫描

axiom-scan

help

              _
  ____ __  __(_)___  ____ ___        ______________ _____                                                                                                                                                                                   
 / __ `/ |/_/ / __ \/ __ `__ \______/ ___/ ___/ __ `/ __ \                                                                                                                                                                                  
/ /_/ />  </ / /_/ / / / / / /_____(__  ) /__/ /_/ / / / /                                                                                                                                                                                  
\__,_/_/|_/_/\____/_/ /_/ /_/     /____/\___/\__,_/_/ /_/                                                                                                                                                                                   
                                                                                                                                                                                                                                            
                                    @pry0cc                                                                                                                                                                                                 
                                 & @0xtavian                                                                                                                                                                                                
                                                                                                                                                                                                                                            
axiom-scan provides easy distribution of arbitrary binaries and scripts.
axiom-scan splits user-provided input files (target lists), wordlists and configuration files and uploads them to a unique scan working directory on the remote instance.
axiom-scan combines user-provided command-line arguments with commands in the module and executes the final command on the remote instance.
axiom-scan downloads and merges scan output in a variety of differnet formats, specified by the extention in the module (dir, txt, csv, xml).
individual scanning operations are executed from a detacted tmux session (\$module+\$timestamp) inside a unique scan working directory (/home/op/scan/\$module+\$timestamp) on the remote instances.
Usage:
   axiom-scan inputfile.txt -m ffuf -w /home/op/wordlist-on-remote-instance
   axiom-scan inputfile.txt -m ffuf -wL /home/localuser/local-wordlist-to-upload
   axiom-scan inputfile.txt -m ffuf -wD /home/localuser/local-wordlist-to-split-and-upload
   axiom-scan inputfile.txt -m nuclei -w /home/op/nuclei-templates -o outputfile.txt
   axiom-scan inputfile.txt -m nuclei --nuclei-templates /home/localuser/local-custom-nuclei-template-folder/ -anew outputfile.txt
   axiom-scan inputfile.txt -m gowitness --spinup 10 -oD gowitness-screenshots
   axiom-scan inputfile.txt -m nmapx -p- -sV -T4 -v --open -oA nampx-scan
Flags:
INPUT:
   string[]              required positional first argument must always be an input file, this can be a list of URLs, IPs, hostnames, etc
   --dont-split          do not split input file, upload entire input file to every instance (default is to split the input file)
   --dont-shuffle        do not randomize input file before uploading (default is to randomize)
MODULE:
   -m string[]           the axiom-scan module to use with the scan
   --list                print all available modules
WORDLIST:
   -w string[]                           replace _wordlist_ in module with user-provided wordlist (must be a path to a remote wordlist)
   -wL string[]                          replace _wordlist_ in module with user-provided local wordlist ( must be a path to a local wordlist)
   -wD,--distribute-wordlist string[]    replace _wordlist_ in module with user-provided local wordlist to split and upload (default does not split the wordlist)
   --nuclei-templates string[]           replace _wordlist_ in module with user-provided local folder
CONFIGURATIONS:
   --config string[]           replace _config_ in module with user-provided configuration file (must be a configuration file on the remote instances)
   --local-config string[]     replace _config_ in module with user-provided local configuration file to upload ( must be a local configuration file)
OPTIMIZATIONS:
   --skip-preflight            do not automatically remove instances that cant be reached (default removes instances from the queue that cant be reached)
   --preflight-timeout int[]   specifies the timeout (in seconds) used when connecting to the SSH server, instead of using the default 10 seconds
   --max-runtime DURATION[]    kill scan if still running after DURATION. DURATION is a floating point number with an optional suffix: 's' for seconds (the default), 'm' for minutes, 'h' for hours or 'd' for days.
   --disable-oneshot           by default, if a module contains the string _target_ it is executed as a one-shot module. Use this flag to force disable
OUTPUT:
   -o string[]          output as default (the first ext mentioned in the module) 
   -oD/-oA string[]     output as directory (must also be supplied in the module using "ext":"dir" or "ext":"")
   -oX string[]         output as XML/HTML (supported for nmap and masscan)(must also be supplied in the module using "ext":"xml")
   -oG string[]         output as greppable, merge and sort unique (must also be supplied in the module using "ext":"oG")
   -csv string []       output as csv, extract csv header, merge and sort unique (must also be supplied in the module using "ext":"csv")
   -anew string[]       pipe the output to anew before creating the final output file
   --quiet              do not display findings to terminal
   --rm-logs            delete remote and local logs after scan completes
FLEET:
   --fleet string[]            supply fleet prefix to use (default uses instances in $HOME/.axiom/selected.conf)
   --spinup int[]              number of instances to spin up prior to scanning (default uses instances in $HOME/.axiom/selected.conf)
   --rm-when-done              delete the selected instances after the scan completes
   --shutdown-when-done        shutdown the selected instance after the scan completes
   -F string[]                 path to custom SSH config file (default is located at $HOME/.axiom/.sshconfig)
   --cache                     do not regenerate SSH config prior to scan, instead use cached config (located at $HOME/.axiom/.sshconfig)
DEBUG:
   --debug              run with set -xv, warning: very verbose
EXTRA ARGS:
   string[]             supply additional arguments to be passed to the module

工作流举例

# 获取子域名
axiom-scan roots.txt -m subfinder -o subs.txt --threads 3
# 通过子域名解析IP
axiom-scan subs.txt -m dnsx -resp -o dns.txt 
# 提取IP
cat dns.txt | awk '{ print $2 }' | anew ips.txt
# 去除掉CloudFlare的IP
cat ips.txt | cf-check > ips.txt
# 端口扫描
axiom-scan ips.txt -m masscan -oX masscan.xml -rate=100000
axiom-scan ips.txt -m nmap -oG nmap.txt -T4 -p- -sV
axiom-scan ips.txt -m nmap -oX nmap.xml -T4 -p- -sV
# 解析nmap.xml,输出为ip:host
ports.py nmap.xml | anew hosts.txt
# httpx发送http请求测试存活
axiom-scan hosts.txt -m httpx -o http.txt
# web截图
axiom-scan http.txt -m gowitness -o screenshots
# 扫目录
axiom-scan http.txt -m ffuf -o content.csv --threads 2

使用masscan扫描

axiom-scan ips.txt -m masscan -p80,443 -o masscan.txt

提供给axom-scan的任何参数都会自动传递给底层命令,比如:

axiom-scan ips.txt -m masscan -p80,443,8080 --rate=100000 --banners -o masscan-banners-fast.txt

一旦你有了一个集群,并且选择了它(axiom-select),你就可以使用axiom-scan。axiom-scan是一个工具,允许你在你的集群中执行类似扫描的操作。它至少需要一个参数,这个参数应该是一个可以在本地目录下访问的输入文件,其中有一个目标列表。

你的输入文件中的内容取决于你要运行的扫描的类型。您可以通过使用不同的axom-scan模块来修改扫描行为,这些模块位于~/.axom/modules/,是详细说明扫描行为的简单JSON文件。

Modules

你可以使用-m <module>标志来使用axiom-scan。让我们演示一下针对一个域的列表运行subfinder:

axiom-scan domains.txt -m subfinder -o subf.txt --threads 1

假设你的域名列表大于你的集群中的实例数量,它将把域名拆开,无论你在一个集群中有多少个实例。如果你有3个实例,它将把你的infile拆成3个并全部上传。

一旦上传,它将运行你的模块代码,下载输出,然后分类并将输出合并到一个单一的输出文件。

axiom-scan subsf.txt -m httpx -o http.txt

使用上述命令,我们可以对我们的子域运行httpx,并得到一个URLS的列表。