As part of a growth hacking project, I needed to list the sub-domains of a specific site.
dig
The first idea that came to me was dig
(Domain Information Groper). It’s a command-line tool that lets you retrieve DNS information directly by querying name servers.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| $ dig prestashop-project.org
; <<>> DiG 9.18.30-0ubuntu0.22.04.2-Ubuntu <<>> prestashop-project.org
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 42051
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;prestashop-project.org. IN A
;; ANSWER SECTION:
prestashop-project.org. 300 IN A 104.18.16.231
prestashop-project.org. 300 IN A 104.18.17.231
;; Query time: 64 msec
;; SERVER: 127.0.0.1#53(127.0.0.1) (UDP)
;; WHEN: Mon May 19 06:55:17 CEST 2025
;; MSG SIZE rcvd: 83
|
Unfortunately, we can see that it doesn’t list the sub-domains as we’d like, but just the information for the main domain.
crt.sh
Second solution: Use certificates linked to domains.
Certificate Transparency (CT) is a project under which a Certification Authority (CA) must publish every SSL/TLS certificate it issues in a public log. An SSL/TLS certificate usually contains domain names, sub-domain names and e-mail addresses.
One of the best-known search engines on this subject is crt.sh
, which has one big advantage: it can be queried directly in SQL.
First, you need to install the dependencies you’ll need to connect to the PostgreSQL database:
1
| sudo apt install postgresql-client-common postgresql-client-14
|
We then connect to the public database:
1
| psql -h crt.sh -p 5432 -U guest certwatch
|
At this point, we can ask him:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| WITH ci AS (
SELECT min(sub.CERTIFICATE_ID) ID,
min(sub.ISSUER_CA_ID) ISSUER_CA_ID,
array_agg(DISTINCT sub.NAME_VALUE) NAME_VALUES,
x509_commonName(sub.CERTIFICATE) COMMON_NAME,
x509_notBefore(sub.CERTIFICATE) NOT_BEFORE,
x509_notAfter(sub.CERTIFICATE) NOT_AFTER,
encode(x509_serialNumber(sub.CERTIFICATE), 'hex') SERIAL_NUMBER
FROM (SELECT *
FROM certificate_and_identities cai
WHERE plainto_tsquery('certwatch', 'prestashop-project.org') @@ identities(cai.CERTIFICATE)
AND cai.NAME_VALUE ILIKE ('%%' || 'prestashop-project.org' || '%%')
) sub
GROUP BY sub.CERTIFICATE
)
SELECT array_to_string(ci.NAME_VALUES, chr(10)) NAME_VALUE
FROM ci
LEFT JOIN LATERAL (
SELECT min(ctle.ENTRY_TIMESTAMP) ENTRY_TIMESTAMP
FROM ct_log_entry ctle
WHERE ctle.CERTIFICATE_ID = ci.ID
) le ON TRUE,
ca
WHERE ci.ISSUER_CA_ID = ca.ID
GROUP BY NAME_VALUE
ORDER BY NAME_VALUE ASC;
|
Note: Use \q
to exit the PostgreSQL terminal.
And it works:
1
2
3
4
5
6
7
8
9
10
11
12
| name_value
-----------------------------------------
contributors.prestashop-project.org
docs.prestashop-project.org
help.prestashop-project.org
integration-help.prestashop-project.org
preprod-help.prestashop-project.org
prestashop-project.org
*.prestashop-project.org +
prestashop-project.org
www.prestashop-project.org
(8 rows)
|
Unfortunately, I found something to complain about: what if the sub-domain we were looking for didn’t use SSL certificates?
amass
Third solution: use another database.
The OWASP Amass suite of tools allows you to obtain sub-domain names by scraping different data sources, using recursive brute force, browsing web archives, swapping/altering names and performing a reverse DNS scan. And it’s all available from the command line.
Let’s start with the installation:
1
| sudo snap install amass
|
Then we run the following command line:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| $ amass enum --passive -d prestashop-project.org
integration-help.prestashop-project.org
api-nightly.prestashop-project.org
docs.prestashop-project.org
preprod-help.prestashop-project.org
www.prestashop-project.org
nightly.prestashop-project.org
build.prestashop-project.org
prestashop-project.org
api.prestashop-project.org
devdocs.prestashop-project.org
contributors.prestashop-project.org
i18n.prestashop-project.org
The enumeration has finished
Discoveries are being migrated into the local database
|
By adding the -o output.txt
option, this sends the contents of the analysis to a text file.
As can be seen, this returned more domains than via crt.sh
, which is logical as amass
uses several data sources including Certificate Transparency.
Conclusion
In the end, I recommend amass
for listing sub-domains. Using multiple databases allows you to get a fairly complete view of sub-domains via different techniques.