Files
sn0int/modules/dev/ctlogs.lua
2019-04-24 13:42:54 +02:00

102 lines
2.5 KiB
Lua

-- Description: Query certificate transparency logs to discover subdomains
-- Version: 0.5.0
-- Source: domains
-- License: GPL-3.0
function each_name(name)
local domain_id, psl_domain
if seen[name] == 1 then
return
end
seen[name] = 1
debug(name)
if name:find('*.') == 1 then
-- ignore wildcard domains
return
end
-- the cert might be valid for subdomains that do not belong to the
-- domain we started with
psl_domain = psl_domain_from_dns_name(name)
domain_id = domains[psl_domain]
if domain_id == nil then
if any_domain then
-- unknown domains should be added to database
domain_id = db_add('domain', {
value=psl_domain,
})
else
-- only use domains that are already in scope
domain_id = db_select('domain', psl_domain)
end
-- if we didn't get a valid id, skip
if domain_id == nil then
return
end
domains[psl_domain] = domain_id
end
db_add('subdomain', {
domain_id=domain_id,
value=name,
})
end
function run(arg)
full = getopt('full') ~= nil
any_domain = getopt('any-domain') ~= nil
domains = {}
domains[arg['value']] = arg['id']
session = http_mksession()
req = http_request(session, 'GET', 'https://crt.sh/', {
query={
q='%.' .. arg['value'],
output='json'
}
})
resp = http_send(req)
if last_err() then return end
if resp['status'] ~= 200 then return 'http error: ' .. resp['status'] end
certs = json_decode(resp['text'])
if last_err() then return end
seen = {}
for i=1, #certs do
c = certs[i]
debug(c)
if full then
-- fetch certificate
id = c['min_cert_id']
req = http_request(session, 'GET', 'https://crt.sh/', {
query={
d=id .. '', -- TODO: find nicer way for tostring
}
})
resp = http_send(req)
if last_err() then return end
if resp['status'] ~= 200 then return 'http error: ' .. resp['status'] end
-- iterate over all valid names
crt = x509_parse_pem(resp['text'])
if last_err() then return end
names = crt['valid_names']
for j=1, #names do
each_name(names[j])
end
else
each_name(c['name_value'])
end
end
end