Amass
Installation
Macos
brew tap caffix/amass
brew install amass
Linux
sudo snap install amass
Subcommands (modes)
Name | description | command (e.g) |
---|---|---|
intel | Discover targets for enumerations | amass intel -active -addr 192.168.2.1-64 -p 80,443,8080 |
enum | Perform enumerations and network mapping | amass enum -d google.com |
viz | Visualize enumeration results | amass viz -d3 -d google.com |
track | Track differences between enumerations | amass track -d google.com |
db | Manipulate the Amass graph database | amass db -show |
dns | Resolve DNS names at high performance | amass dns -d google.com |
Go-to Commands
amass enum -config ~/.config/amass/conf.ini -d "domain1,domain2" -brute -o domains
Snippets
PostgreSQL for OWASP Amass
Create to database
psql postgres://username:password@localhost:5432/ -c "CREATE DATABASE amass"
psql postgres://username:password@localhost:5432/ -c "ALTER DATABASE amass SET TIMEZONE to 'UTC'"
Amass config file
options:
database: "postgres://username:password@localhost:5432/amass?testing=works"
ASE (Amass Scripting Engine)
Amass는 자체적으로 scripting engine을 내장하고 있습니다. 이는 nmap의 scripting engine인 NSE와 비슷하며 동일하게 Lua로 작성할 수 있습니다.
Using scripts
Amass의 enum 명령 중 -scripts 플래그를 사용하여 로드할 스크립트 경로나 디렉토리를 명시할 수 있습니다.
amass enum --help
....
-scripts string
Path to a directory containing ADS scripts
...
e.g
amass enum -d hahwul.com -scripts ./subfinder.ads
amass enum -d hahwul.com --scripts .
in sub finder
phoenix.hahwul.com
hahwul.com
Struct of ads
스크립트는 name과 type 필드를 필수로 구성한 후 Amass event에 대한 callback function을 구현하는 형태로 만들어야 합니다.
- name: 스크립트의 이름입니다.
- type: 스크립트의 타입입니다. 어떤 역할을 하는지 명시할 수 있습니다.
- callback: 스크립트의 동작을 위한 callback 들입니다. event listener 처럼 구현합니다.
- function: 간편한 스크립팅을 위해 미리 정의된 함수들입니다.
Type field
타입은 미리 정의되어 있어서 아래 표를 참고하여 목적에 맞는 type으로 작성해주시면 됩니다.
Valid Value | Category |
---|---|
“dns” | DNS Queries |
“axfr” | DNS Zone Transfers |
“scrape” | Web Scraping |
“crawl” | Web Crawling |
“api” | Various APIs |
“cert” | TLS Certificates |
“archive” | Web Archives |
“brute” | Brute Forcing |
“alt” | Name Alterations |
“guess” | Name Guessing |
“rir” | Regional Internet Registry |
“ext” | External Program / Data Source |
Callbacks
Amass의 event에 따라 동작한 callback에 로직은 구현해야 합니다. Amass가 event를 전달하는 callback은 아래와 같습니다.
start callback
start는 amass가 시작할 떄 호출할 callback입니다.
function start()
set_rate_limit(1)
end
stop callback
stop은 amass가 종료될 때 호출할 callback입니다.
function stop()
-- Cleanup code, etc.
end
vertical callback
vertical은 amass가 동작할 때 호출할 callback입니다. -d 옵션으로 전달받은 domain을 2번째 인자값으로 넘겨줍니다. 이후 로직을 처리한 후 subdomain 정보를 리턴해야 합니다. 이 때 new_name()을 통해 전달할 수 있습니다.
function vertical(ctx, domain)
-- Send back discovered subdomain names
new_name(ctx, name)
end
이를 통해서 subfinder, assetfinder, findomain 등 외부 서브 도메인 스캐닝 도구를 사용하여 스캔하고, 결과를 amass 결과에 포함시킬 수 있습니다.
horizontal callback
horizontal도 amass가 동작할 때 호출할 callback입니다. -d 옵션으로 전달받은 domain을 2번째 인자값으로 넘겨줍니다. 다만 horizontal은 amass가 다시 스캔할 domain의 이름을 리턴해야 합니다.
function horizontal(ctx, domain)
-- Send back an associated domain name
associated(ctx, domain, assoc)
end
이 기능은 서브도메인 보단, 연관 도메인을 lua script를 통해 확인하고, 이를 기반으로 다시 amass에 넘겨주어 스캔하도록 구성하기 위해 사용하는 callback입니다.
revolved callback
resolved는 dns query를 조회할 때 호출할 callback입니다.
function resolved(ctx, name, domain, records)
crawl(ctx, "https://" .. name, 0)
end
subdomain callback
subdomain은 DNS Query를 통해 resolving이 성공했을 떄 호출할 callback입니다. 여기의 인자값으로 전달되는 도메인은 dns resolv가 성공한 도메인입니다.
function subdomain(ctx, name, domain, times)
if times == 1 then
crawl(ctx, "https://" .. name, 0)
end
end
address callback
address는 IP address에 대해 프로바이드 됬을 때 호출할 callback입니다. IP를 두번째 인자값으로 넘겨줍니다.
function address(ctx, addr)
-- Send back a related subdomain name
new_name(ctx, name)
-- Send back a related IP address
new_addr(ctx, ipaddr, domain)
end
asn callback
asn은 ASN을 조회했을 때 호출할 callback입니다. 이를 통해 스캔 대상의 asn을 인자값으로 얻어올 수 있습니다.
function asn(ctx, addr, asn)
-- Send back the related AS information
new_asn(ctx, {
['addr']=addr,
['asn']=tonumber(asn),
['desc']=desc,
prefix=cidr,
cc="US",
registry="ARIN",
netblocks={cidr},
})
end
Functions
Scripting에는 미리 정의된 함수도 존재합니다. 이를 이용하면 Amass의 다른 기능들을 lua script에서 불러와서 사용할 수 있습니다. 몇가지 중요한 function만 소개해볼게요.
log()
log() 함수는 말그대로 로그를 찍는 함수입니다. 실제 정보 전달이 목적이던, 디버깅이 목적이던 기본적인 프린팅 함수는 중요합니다.
function sendmsg(ctx, msg)
log(ctx, msg)
end
request()
request() 함수는 웹 요청을 전송하는 함수입니다. 물론 lua script에서 직접 구현해도 되지만, 이미 잘 만들어져 있어서 가져다 쓰는것이 좋을 것 같네요.
function vertical(ctx, domain)
local url = "https://" .. domain
local resp, err = request(ctx, {
method="POST",
data=body,
['url']=url,
headers={['Content-Type']="application/json"},
id=api["key"],
pass=api["secret"],
})
if (err ~= nil and err ~= "") then
return
end
-- Utilize the content provided in the response
end
scrape()
scrape() 함수는 HTTP Client를 이용하여 웹 스크래핑을 진행해주는 함수입니다. 때때로 스캔한 도메인에 대해 스크래핑이 필요할 수 있는데, 미리 정의된 함수로 쉽게 구현할 수 있습니다.
function vertical(ctx, domain)
local url = "https://" .. domain
local ok = scrape(ctx, {
['url']=url,
headers={['Accept']="text/*, text/html, text/html;level=1, */*"},
id=api["username"],
pass=api["password"],
})
end
brute_wordlist()
brute scan에서 사용할 wordlist를 array 형태로 리턴하는 함수입니다.
function vertical(ctx, domain)
local wordlist = brute_wordlist(ctx)
for i, word in pairs(wordlist) do
print(word)
end
end
alt_wordlist()
alterations scan에서 사용할 wordlist를 array 형태로 리턴하는 함수입니다.
function vertical(ctx, domain)
local wordlist = alt_wordlist(ctx)
for i, word in pairs(wordlist) do
print(word)
end
end
More
이외에도 엄청 많으니.. 아래 링크를 참고해주세요!
https://github.com/OWASP/Amass/blob/master/doc/scripting.md#config-function
Examples
gist에 공개된 코드 중 괜찮은게 있어서 몇개 가져왔습니다. scan with assetfinder
name = "assetfinder"
type = "ext"
function vertical(ctx, domain)
print("in asset finder")
local cmd = outputdir(ctx) .. "assetfinder --subs-only " .. domain
local data = assert(io.popen(cmd))
for line in data:lines() do
newname(ctx, line)
end
data:close()
end
scan with subfinder
name = "subfinder"
type = "ext"
function vertical(ctx, domain)
print("in sub finder")
local cmd = outputdir(ctx) .. "subfinder -d " .. domain
local data = assert(io.popen(cmd))
for line in data:lines() do
newname(ctx, line)
end
data:close()
end