oneforall-kjl 0.1.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- OneForAll/__init__.py +15 -0
- OneForAll/brute.py +503 -0
- OneForAll/common/check.py +41 -0
- OneForAll/common/crawl.py +10 -0
- OneForAll/common/database.py +277 -0
- OneForAll/common/domain.py +63 -0
- OneForAll/common/ipasn.py +42 -0
- OneForAll/common/ipreg.py +139 -0
- OneForAll/common/lookup.py +28 -0
- OneForAll/common/module.py +369 -0
- OneForAll/common/query.py +9 -0
- OneForAll/common/records.py +363 -0
- OneForAll/common/request.py +264 -0
- OneForAll/common/resolve.py +173 -0
- OneForAll/common/search.py +78 -0
- OneForAll/common/similarity.py +138 -0
- OneForAll/common/tablib/__init__.py +0 -0
- OneForAll/common/tablib/format.py +89 -0
- OneForAll/common/tablib/tablib.py +360 -0
- OneForAll/common/tldextract.py +240 -0
- OneForAll/common/utils.py +789 -0
- OneForAll/config/__init__.py +17 -0
- OneForAll/config/api.py +94 -0
- OneForAll/config/default.py +255 -0
- OneForAll/config/log.py +38 -0
- OneForAll/config/setting.py +108 -0
- OneForAll/export.py +72 -0
- OneForAll/modules/altdns.py +216 -0
- OneForAll/modules/autotake/github.py +105 -0
- OneForAll/modules/certificates/censys_api.py +73 -0
- OneForAll/modules/certificates/certspotter.py +48 -0
- OneForAll/modules/certificates/crtsh.py +84 -0
- OneForAll/modules/certificates/google.py +48 -0
- OneForAll/modules/certificates/myssl.py +46 -0
- OneForAll/modules/certificates/racent.py +49 -0
- OneForAll/modules/check/axfr.py +97 -0
- OneForAll/modules/check/cdx.py +44 -0
- OneForAll/modules/check/cert.py +58 -0
- OneForAll/modules/check/csp.py +94 -0
- OneForAll/modules/check/nsec.py +58 -0
- OneForAll/modules/check/robots.py +44 -0
- OneForAll/modules/check/sitemap.py +44 -0
- OneForAll/modules/collect.py +70 -0
- OneForAll/modules/crawl/archivecrawl.py +59 -0
- OneForAll/modules/crawl/commoncrawl.py +59 -0
- OneForAll/modules/datasets/anubis.py +45 -0
- OneForAll/modules/datasets/bevigil.py +50 -0
- OneForAll/modules/datasets/binaryedge_api.py +50 -0
- OneForAll/modules/datasets/cebaidu.py +45 -0
- OneForAll/modules/datasets/chinaz.py +45 -0
- OneForAll/modules/datasets/chinaz_api.py +49 -0
- OneForAll/modules/datasets/circl_api.py +49 -0
- OneForAll/modules/datasets/cloudflare_api.py +130 -0
- OneForAll/modules/datasets/dnsdb_api.py +51 -0
- OneForAll/modules/datasets/dnsdumpster.py +52 -0
- OneForAll/modules/datasets/dnsgrep.py +44 -0
- OneForAll/modules/datasets/fullhunt.py +48 -0
- OneForAll/modules/datasets/hackertarget.py +45 -0
- OneForAll/modules/datasets/ip138.py +45 -0
- OneForAll/modules/datasets/ipv4info_api.py +73 -0
- OneForAll/modules/datasets/netcraft.py +66 -0
- OneForAll/modules/datasets/passivedns_api.py +51 -0
- OneForAll/modules/datasets/qianxun.py +61 -0
- OneForAll/modules/datasets/rapiddns.py +45 -0
- OneForAll/modules/datasets/riddler.py +45 -0
- OneForAll/modules/datasets/robtex.py +58 -0
- OneForAll/modules/datasets/securitytrails_api.py +56 -0
- OneForAll/modules/datasets/sitedossier.py +57 -0
- OneForAll/modules/datasets/spyse_api.py +62 -0
- OneForAll/modules/datasets/sublist3r.py +45 -0
- OneForAll/modules/datasets/urlscan.py +45 -0
- OneForAll/modules/datasets/windvane.py +92 -0
- OneForAll/modules/dnsquery/mx.py +35 -0
- OneForAll/modules/dnsquery/ns.py +35 -0
- OneForAll/modules/dnsquery/soa.py +35 -0
- OneForAll/modules/dnsquery/spf.py +35 -0
- OneForAll/modules/dnsquery/txt.py +35 -0
- OneForAll/modules/enrich.py +72 -0
- OneForAll/modules/finder.py +206 -0
- OneForAll/modules/intelligence/alienvault.py +50 -0
- OneForAll/modules/intelligence/riskiq_api.py +58 -0
- OneForAll/modules/intelligence/threatbook_api.py +50 -0
- OneForAll/modules/intelligence/threatminer.py +45 -0
- OneForAll/modules/intelligence/virustotal.py +60 -0
- OneForAll/modules/intelligence/virustotal_api.py +59 -0
- OneForAll/modules/iscdn.py +86 -0
- OneForAll/modules/search/ask.py +69 -0
- OneForAll/modules/search/baidu.py +96 -0
- OneForAll/modules/search/bing.py +79 -0
- OneForAll/modules/search/bing_api.py +78 -0
- OneForAll/modules/search/fofa_api.py +74 -0
- OneForAll/modules/search/gitee.py +71 -0
- OneForAll/modules/search/github_api.py +86 -0
- OneForAll/modules/search/google.py +83 -0
- OneForAll/modules/search/google_api.py +77 -0
- OneForAll/modules/search/hunter_api.py +72 -0
- OneForAll/modules/search/quake_api.py +72 -0
- OneForAll/modules/search/shodan_api.py +53 -0
- OneForAll/modules/search/so.py +75 -0
- OneForAll/modules/search/sogou.py +72 -0
- OneForAll/modules/search/wzsearch.py +68 -0
- OneForAll/modules/search/yahoo.py +81 -0
- OneForAll/modules/search/yandex.py +80 -0
- OneForAll/modules/search/zoomeye_api.py +73 -0
- OneForAll/modules/srv.py +75 -0
- OneForAll/modules/wildcard.py +319 -0
- OneForAll/oneforall.py +275 -0
- OneForAll/takeover.py +168 -0
- OneForAll/test.py +23 -0
- oneforall_kjl-0.1.1.dist-info/METADATA +18 -0
- oneforall_kjl-0.1.1.dist-info/RECORD +114 -0
- oneforall_kjl-0.1.1.dist-info/WHEEL +5 -0
- oneforall_kjl-0.1.1.dist-info/entry_points.txt +2 -0
- oneforall_kjl-0.1.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,216 @@
|
|
1
|
+
"""
|
2
|
+
Reference: https://github.com/ProjectAnte/dnsgen
|
3
|
+
"""
|
4
|
+
import re
|
5
|
+
import time
|
6
|
+
import itertools
|
7
|
+
|
8
|
+
from config import settings
|
9
|
+
|
10
|
+
from modules import wildcard
|
11
|
+
from common import utils
|
12
|
+
from common import resolve
|
13
|
+
from common import request
|
14
|
+
from common.domain import Domain
|
15
|
+
from common.module import Module
|
16
|
+
from config.log import logger
|
17
|
+
|
18
|
+
|
19
|
+
def split_domain(domain):
|
20
|
+
"""
|
21
|
+
Split domain base on subdomain levels
|
22
|
+
Root+TLD is taken as one part, regardless of its levels
|
23
|
+
"""
|
24
|
+
|
25
|
+
# test.1.foo.example.com -> [test, 1, foo, example.com]
|
26
|
+
# test.2.foo.example.com.cn -> [test, 2, foo, example.com.cn]
|
27
|
+
# test.example.co.uk -> [test, example.co.uk]
|
28
|
+
|
29
|
+
ext = Domain(domain).extract()
|
30
|
+
subname = ext.subdomain
|
31
|
+
parts = ext.subdomain.split('.') + [ext.registered_domain]
|
32
|
+
return subname, parts
|
33
|
+
|
34
|
+
|
35
|
+
class Altdns(Module):
|
36
|
+
def __init__(self, domain):
|
37
|
+
Module.__init__(self)
|
38
|
+
self.module = 'Altdns'
|
39
|
+
self.source = 'Altdns'
|
40
|
+
self.start = time.time()
|
41
|
+
self.domain = domain
|
42
|
+
self.words = set()
|
43
|
+
self.now_subdomains = set()
|
44
|
+
self.new_subdomains = set()
|
45
|
+
self.wordlen = 6 # Min length of custom words extracted from domains
|
46
|
+
self.num_count = 3
|
47
|
+
|
48
|
+
def get_words(self):
|
49
|
+
path = settings.data_storage_dir.joinpath('altdns_wordlist.txt')
|
50
|
+
with open(path) as fd:
|
51
|
+
for line in fd:
|
52
|
+
word = line.lower().strip()
|
53
|
+
if word:
|
54
|
+
self.words.add(word)
|
55
|
+
|
56
|
+
def extract_words(self):
|
57
|
+
"""
|
58
|
+
Extend the dictionary based on target's domain naming conventions
|
59
|
+
"""
|
60
|
+
|
61
|
+
for subdomain in self.now_subdomains:
|
62
|
+
_, parts = split_domain(subdomain)
|
63
|
+
tokens = set(itertools.chain(*[word.lower().split('-') for word in parts]))
|
64
|
+
tokens = tokens.union({word.lower() for word in parts})
|
65
|
+
for token in tokens:
|
66
|
+
if len(token) >= self.wordlen:
|
67
|
+
self.words.add(token)
|
68
|
+
|
69
|
+
def increase_num(self, subname):
|
70
|
+
"""
|
71
|
+
If number is found in existing subdomain,
|
72
|
+
increase this number without any other alteration.
|
73
|
+
"""
|
74
|
+
|
75
|
+
# test.1.foo.example.com -> test.2.foo.example.com, test.3.foo.example.com, ...
|
76
|
+
# test1.example.com -> test2.example.com, test3.example.com, ...
|
77
|
+
# test01.example.com -> test02.example.com, test03.example.com, ...
|
78
|
+
|
79
|
+
count = 0
|
80
|
+
digits = re.findall(r'\d{1,3}', subname)
|
81
|
+
for d in digits:
|
82
|
+
for m in range(self.num_count):
|
83
|
+
replacement = str(int(d) + 1 + m).zfill(len(d))
|
84
|
+
tmp_domain = subname.replace(d, replacement)
|
85
|
+
new_domain = f'{tmp_domain}.{self.domain}'
|
86
|
+
self.new_subdomains.add(new_domain)
|
87
|
+
count += 1
|
88
|
+
logger.log('DEBUG', f'The increase_num generated {count} subdomains')
|
89
|
+
|
90
|
+
def decrease_num(self, subname):
|
91
|
+
"""
|
92
|
+
If number is found in existing subdomain,
|
93
|
+
decrease this number without any other alteration.
|
94
|
+
"""
|
95
|
+
|
96
|
+
# test.4.foo.example.com -> test.3.foo.example.com, test.2.foo.example.com, ...
|
97
|
+
# test4.example.com -> test3.example.com, test2.example.com, ...
|
98
|
+
# test04.example.com -> test03.example.com, test02.example.com, ...
|
99
|
+
|
100
|
+
count = 0
|
101
|
+
digits = re.findall(r'\d{1,3}', subname)
|
102
|
+
for d in digits:
|
103
|
+
for m in range(self.num_count):
|
104
|
+
new_digit = (int(d) - 1 - m)
|
105
|
+
if new_digit < 0:
|
106
|
+
break
|
107
|
+
|
108
|
+
replacement = str(new_digit).zfill(len(d))
|
109
|
+
tmp_domain = subname.replace(d, replacement)
|
110
|
+
new_domain = f'{tmp_domain}.{self.domain}'
|
111
|
+
self.new_subdomains.add(new_domain)
|
112
|
+
count += 1
|
113
|
+
logger.log('DEBUG', f'The decrease_num generated {count} subdomains')
|
114
|
+
|
115
|
+
def insert_word(self, parts):
|
116
|
+
"""
|
117
|
+
Create new subdomain levels by inserting the words between existing levels
|
118
|
+
"""
|
119
|
+
|
120
|
+
# test.1.foo.example.com -> WORD.test.1.foo.example.com,
|
121
|
+
# test.WORD.1.foo.example.com,
|
122
|
+
# test.1.WORD.foo.example.com,
|
123
|
+
# test.1.foo.WORD.example.com,
|
124
|
+
# ...
|
125
|
+
|
126
|
+
count = 0
|
127
|
+
for word in self.words:
|
128
|
+
for index in range(len(parts)):
|
129
|
+
tmp_parts = parts.copy()
|
130
|
+
tmp_parts.insert(index, word)
|
131
|
+
new_domain = '.'.join(tmp_parts)
|
132
|
+
self.new_subdomains.add(new_domain)
|
133
|
+
count += 1
|
134
|
+
logger.log('DEBUG', f'The insert_word generated {count} subdomains')
|
135
|
+
|
136
|
+
def add_word(self, subnames):
|
137
|
+
"""
|
138
|
+
On every subdomain level, prepend existing content with WORD-`,
|
139
|
+
append existing content with `-WORD`
|
140
|
+
"""
|
141
|
+
|
142
|
+
count = 0
|
143
|
+
for word in self.words:
|
144
|
+
for index, name in enumerate(subnames):
|
145
|
+
# Prepend with `-`
|
146
|
+
# test.1.foo.example.com -> WORD-test.1.foo.example.com
|
147
|
+
tmp_subnames = subnames.copy()
|
148
|
+
tmp_subnames[index] = f'{word}-{name}'
|
149
|
+
new_subname = '.'.join(tmp_subnames + [self.domain])
|
150
|
+
self.new_subdomains.add(new_subname)
|
151
|
+
|
152
|
+
# Prepend with `-`
|
153
|
+
# test.1.foo.example.com -> test-WORD.1.foo.example.com
|
154
|
+
tmp_subnames = subnames.copy()
|
155
|
+
tmp_subnames[index] = f'{name}-{word}'
|
156
|
+
new_subname = '.'.join(tmp_subnames + [self.domain])
|
157
|
+
self.new_subdomains.add(new_subname)
|
158
|
+
count += 1
|
159
|
+
logger.log('DEBUG', f'The add_word generated {count} subdomains')
|
160
|
+
|
161
|
+
def replace_word(self, subname):
|
162
|
+
"""
|
163
|
+
If word longer than 3 is found in existing subdomain,
|
164
|
+
replace it with other words from the dictionary
|
165
|
+
"""
|
166
|
+
|
167
|
+
# WORD1.1.foo.example.com -> WORD2.1.foo.example.com,
|
168
|
+
# WORD3.1.foo.example.com,
|
169
|
+
# WORD4.1.foo.example.com,
|
170
|
+
# ..
|
171
|
+
|
172
|
+
count = 0
|
173
|
+
for word in self.words:
|
174
|
+
if word not in subname:
|
175
|
+
continue
|
176
|
+
for word_alt in self.words:
|
177
|
+
if word == word_alt:
|
178
|
+
continue
|
179
|
+
new_subname = subname.replace(word, word_alt)
|
180
|
+
new_subdomain = f'{new_subname}.{self.domain}'
|
181
|
+
self.new_subdomains.add(new_subdomain)
|
182
|
+
count += 1
|
183
|
+
logger.log('DEBUG', f'The replace_word generated {count} subdomains')
|
184
|
+
|
185
|
+
def gen_new_subdomains(self):
|
186
|
+
for subdomain in self.now_subdomains:
|
187
|
+
subname, parts = split_domain(subdomain)
|
188
|
+
subnames = subname.split('.')
|
189
|
+
if settings.altdns_increase_num:
|
190
|
+
self.increase_num(subname)
|
191
|
+
if settings.altdns_decrease_num:
|
192
|
+
self.decrease_num(subname)
|
193
|
+
if settings.altdns_replace_word:
|
194
|
+
self.replace_word(subname)
|
195
|
+
if settings.altdns_insert_word:
|
196
|
+
self.insert_word(parts)
|
197
|
+
if settings.altdns_add_word:
|
198
|
+
self.add_word(subnames)
|
199
|
+
count = len(self.new_subdomains)
|
200
|
+
logger.log('DEBUG', f'The altdns module generated {count} subdomains')
|
201
|
+
|
202
|
+
def run(self, data, port):
|
203
|
+
logger.log('INFOR', f'Start altdns module')
|
204
|
+
self.now_subdomains = utils.get_subdomains(data)
|
205
|
+
self.get_words()
|
206
|
+
self.extract_words()
|
207
|
+
self.gen_new_subdomains()
|
208
|
+
self.subdomains = self.new_subdomains - self.now_subdomains
|
209
|
+
count = len(self.subdomains)
|
210
|
+
logger.log('INFOR', f'The altdns module generated {count} new subdomains')
|
211
|
+
self.end = time.time()
|
212
|
+
self.elapse = round(self.end - self.start, 1)
|
213
|
+
self.gen_result()
|
214
|
+
resolved_data = resolve.run_resolve(self.domain, self.results)
|
215
|
+
valid_data = wildcard.deal_wildcard(resolved_data) # 强制开启泛解析处理
|
216
|
+
request.run_request(self.domain, valid_data, port)
|
@@ -0,0 +1,105 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
# coding=utf-8
|
3
|
+
|
4
|
+
"""
|
5
|
+
github自动接管
|
6
|
+
"""
|
7
|
+
|
8
|
+
import json
|
9
|
+
import base64
|
10
|
+
import requests
|
11
|
+
from config import settings
|
12
|
+
|
13
|
+
HEADERS = {
|
14
|
+
"Accept": "application/json, text/javascript, */*; q=0.01",
|
15
|
+
"Accept-Language": "zh-CN,zh;q=0.9",
|
16
|
+
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) "
|
17
|
+
"AppleWebKit/537.36 (KHTML, like Gecko) "
|
18
|
+
"Chrome/63.0.3239.84 Safari/537.36",
|
19
|
+
}
|
20
|
+
|
21
|
+
|
22
|
+
def github_takeover(url):
|
23
|
+
# 读取config配置文件
|
24
|
+
repo_name = url
|
25
|
+
print('[*]正在读取配置文件')
|
26
|
+
user = settings.github_api_user
|
27
|
+
token = settings.github_api_token
|
28
|
+
headers = {
|
29
|
+
"Authorization": 'token ' + token,
|
30
|
+
"Accept": "application/vnd.github.switcheroo-preview+json"
|
31
|
+
}
|
32
|
+
repos_url = 'https://api.github.com/repos/' + user + '/' + repo_name
|
33
|
+
repos_r = requests.get(url=repos_url, headers=headers)
|
34
|
+
# 验证token是否正确
|
35
|
+
if 'message' in repos_r.json():
|
36
|
+
if repos_r.json()['message'] == 'Bad credentials':
|
37
|
+
print('[*]请检查Token是否正确')
|
38
|
+
elif repos_r.json()['message'] == 'Not Found':
|
39
|
+
print('[*]正在生成接管库') # 生成接管库
|
40
|
+
creat_repo_dict = {
|
41
|
+
"name": repo_name,
|
42
|
+
"description": "This is a subdomain takeover Repository",
|
43
|
+
}
|
44
|
+
creat_repo_url = 'https://api.github.com/user/repos'
|
45
|
+
creat_repo_r = requests.post(url=creat_repo_url,
|
46
|
+
headers=headers,
|
47
|
+
data=json.dumps(creat_repo_dict))
|
48
|
+
creat_repo_status = creat_repo_r.status_code
|
49
|
+
if creat_repo_status == 201:
|
50
|
+
print('[*]创建接管库' + repo_name + '成功,正在进行自动接管')
|
51
|
+
# 接管文件生成
|
52
|
+
# index.html文件
|
53
|
+
html = b'''
|
54
|
+
<html>
|
55
|
+
<p>Subdomain Takerover Test!</>
|
56
|
+
</html>
|
57
|
+
'''
|
58
|
+
html64 = base64.b64encode(html).decode('utf-8')
|
59
|
+
html_dict = {
|
60
|
+
"message": "my commit message",
|
61
|
+
"committer": {
|
62
|
+
"name": "user", # 提交id,非必改项
|
63
|
+
"email": "user@163.com" # 同上
|
64
|
+
},
|
65
|
+
"content": html64
|
66
|
+
}
|
67
|
+
# CNAME文件
|
68
|
+
cname_url = bytes(url, encoding='utf-8')
|
69
|
+
cname_url64 = base64.b64encode(cname_url).decode('utf-8')
|
70
|
+
url_dict = {
|
71
|
+
"message": "my commit message",
|
72
|
+
"committer": {
|
73
|
+
"name": "user",
|
74
|
+
"email": "user@163.com"
|
75
|
+
},
|
76
|
+
"content": cname_url64
|
77
|
+
}
|
78
|
+
base_url = 'https://api.github.com/repos/'
|
79
|
+
html_url = base_url + user + '/' + repo_name + '/contents/index.html'
|
80
|
+
url_url = base_url + user + '/' + repo_name + '/contents/CNAME'
|
81
|
+
html_r = requests.put(url=html_url, data=json.dumps(html_dict),
|
82
|
+
headers=headers) # 上传index.html
|
83
|
+
cname_r = requests.put(url=url_url, data=json.dumps(url_dict),
|
84
|
+
headers=headers) # 上传CNAME
|
85
|
+
rs = cname_r.status_code
|
86
|
+
if rs == 201:
|
87
|
+
print('[*]生成接管库成功,正在开启Github pages')
|
88
|
+
page_url = "https://api.github.com/repos/" + user + "/" + url + "/pages"
|
89
|
+
page_dict = {
|
90
|
+
"source": {
|
91
|
+
"branch": "master"
|
92
|
+
}
|
93
|
+
}
|
94
|
+
page_r = requests.post(url=page_url,
|
95
|
+
data=json.dumps(page_dict),
|
96
|
+
headers=headers) # 开启page
|
97
|
+
if page_r.status_code == 201:
|
98
|
+
print('[+]自动接管成功,请稍后访问http://' + str(url) + '查看结果')
|
99
|
+
else:
|
100
|
+
print('[+]开启Github pages失败,请检查网络或稍后重试')
|
101
|
+
else:
|
102
|
+
print('[+]生成接管库失败,请检查网络或稍后重试')
|
103
|
+
elif url in repos_r.json()['name']:
|
104
|
+
print('[*]生成接管库失败,请检查https://github.com/' + user +
|
105
|
+
'?tab=repositories是否存在同名接管库')
|
@@ -0,0 +1,73 @@
|
|
1
|
+
from config import settings
|
2
|
+
from common.query import Query
|
3
|
+
from config.log import logger
|
4
|
+
|
5
|
+
|
6
|
+
class CensysAPI(Query):
|
7
|
+
def __init__(self, domain):
|
8
|
+
Query.__init__(self)
|
9
|
+
self.domain = domain
|
10
|
+
self.module = 'Certificate'
|
11
|
+
self.source = "CensysAPIQuery"
|
12
|
+
self.addr = 'https://search.censys.io/api/v2/certificates/search'
|
13
|
+
self.id = settings.censys_api_id
|
14
|
+
self.secret = settings.censys_api_secret
|
15
|
+
self.delay = 3.0 # Censys 接口查询速率限制 最快2.5秒查1次
|
16
|
+
|
17
|
+
def query(self):
|
18
|
+
"""
|
19
|
+
向接口查询子域并做子域匹配
|
20
|
+
"""
|
21
|
+
self.header = self.get_header()
|
22
|
+
self.proxy = self.get_proxy(self.source)
|
23
|
+
params = {
|
24
|
+
'q': f'names: {self.domain}',
|
25
|
+
'per_page': 100,
|
26
|
+
}
|
27
|
+
resp = self.get(self.addr, params=params, auth=(self.id, self.secret))
|
28
|
+
if not resp:
|
29
|
+
return
|
30
|
+
json = resp.json()
|
31
|
+
status = json.get('status')
|
32
|
+
if status != 'OK':
|
33
|
+
logger.log('ALERT', f'{self.source} module {status}')
|
34
|
+
return
|
35
|
+
subdomains = self.match_subdomains(resp.text)
|
36
|
+
self.subdomains.update(subdomains)
|
37
|
+
next_cursor = json.get("result").get("links").get("next")
|
38
|
+
while next_cursor:
|
39
|
+
tmp_params = {
|
40
|
+
'q': f'names: {self.domain}',
|
41
|
+
'per_page': 100,
|
42
|
+
"cursor": next_cursor
|
43
|
+
}
|
44
|
+
tmp_resp = self.get(self.addr, params=tmp_params, auth=(self.id, self.secret))
|
45
|
+
self.subdomains = self.collect_subdomains(tmp_resp)
|
46
|
+
next_cursor = tmp_resp.json().get("result").get("links").get("next")
|
47
|
+
|
48
|
+
def run(self):
|
49
|
+
"""
|
50
|
+
类执行入口
|
51
|
+
"""
|
52
|
+
if not self.have_api(self.id, self.secret):
|
53
|
+
return
|
54
|
+
self.begin()
|
55
|
+
self.query()
|
56
|
+
self.finish()
|
57
|
+
self.save_json()
|
58
|
+
self.gen_result()
|
59
|
+
self.save_db()
|
60
|
+
|
61
|
+
|
62
|
+
def run(domain):
|
63
|
+
"""
|
64
|
+
类统一调用入口
|
65
|
+
|
66
|
+
:param str domain: 域名
|
67
|
+
"""
|
68
|
+
query = CensysAPI(domain)
|
69
|
+
query.run()
|
70
|
+
|
71
|
+
|
72
|
+
if __name__ == '__main__':
|
73
|
+
run('example.com')
|
@@ -0,0 +1,48 @@
|
|
1
|
+
from common.query import Query
|
2
|
+
|
3
|
+
|
4
|
+
class CertSpotter(Query):
|
5
|
+
def __init__(self, domain):
|
6
|
+
Query.__init__(self)
|
7
|
+
self.domain = domain
|
8
|
+
self.module = 'Certificate'
|
9
|
+
self.source = 'CertSpotterQuery'
|
10
|
+
self.addr = 'https://api.certspotter.com/v1/issuances'
|
11
|
+
|
12
|
+
def query(self):
|
13
|
+
"""
|
14
|
+
向接口查询子域并做子域匹配
|
15
|
+
"""
|
16
|
+
self.header = self.get_header()
|
17
|
+
self.proxy = self.get_proxy(self.source)
|
18
|
+
params = {'domain': self.domain,
|
19
|
+
'include_subdomains': 'true',
|
20
|
+
'expand': 'dns_names'}
|
21
|
+
resp = self.get(self.addr, params)
|
22
|
+
self.subdomains = self.collect_subdomains(resp)
|
23
|
+
|
24
|
+
def run(self):
|
25
|
+
"""
|
26
|
+
类执行入口
|
27
|
+
"""
|
28
|
+
self.begin()
|
29
|
+
self.query()
|
30
|
+
self.finish()
|
31
|
+
self.save_json()
|
32
|
+
self.gen_result()
|
33
|
+
self.save_db()
|
34
|
+
|
35
|
+
|
36
|
+
def run(domain):
|
37
|
+
"""
|
38
|
+
类统一调用入口
|
39
|
+
|
40
|
+
:param str domain: 域名
|
41
|
+
|
42
|
+
"""
|
43
|
+
query = CertSpotter(domain)
|
44
|
+
query.run()
|
45
|
+
|
46
|
+
|
47
|
+
if __name__ == '__main__':
|
48
|
+
run('example.com')
|
@@ -0,0 +1,84 @@
|
|
1
|
+
from common.query import Query
|
2
|
+
import json
|
3
|
+
import os
|
4
|
+
|
5
|
+
|
6
|
+
class Crtsh(Query):
|
7
|
+
def __init__(self, domain):
|
8
|
+
Query.__init__(self)
|
9
|
+
self.domain = domain
|
10
|
+
self.module = 'Certificate'
|
11
|
+
self.source = 'CrtshQuery'
|
12
|
+
self.addr = 'https://crt.sh/'
|
13
|
+
|
14
|
+
def query(self):
|
15
|
+
"""
|
16
|
+
向接口查询子域并做子域匹配
|
17
|
+
"""
|
18
|
+
self.header = self.get_header()
|
19
|
+
self.proxy = self.get_proxy(self.source)
|
20
|
+
self.timeout = 120
|
21
|
+
params = {'q': f'%.{self.domain}', 'output': 'json'}
|
22
|
+
resp = self.get(self.addr, params)
|
23
|
+
if not resp:
|
24
|
+
return
|
25
|
+
text = resp.text.replace(r'\n', ' ')
|
26
|
+
"""
|
27
|
+
* > altdns
|
28
|
+
"""
|
29
|
+
subDomains = set()
|
30
|
+
try:
|
31
|
+
jsonData = json.loads(text)
|
32
|
+
except Exception as e:
|
33
|
+
pass
|
34
|
+
for i in range(len(jsonData)):
|
35
|
+
try:
|
36
|
+
name_value = str(jsonData[i]['name_value'])
|
37
|
+
except Exception as e:
|
38
|
+
pass
|
39
|
+
if '*' in name_value:
|
40
|
+
try:
|
41
|
+
if 'certificates' in os.path.dirname(os.path.abspath(__file__)):
|
42
|
+
dictFile = open("../../data/altdns_wordlist.txt", "r", encoding='utf8')
|
43
|
+
else:
|
44
|
+
dictFile = open("./data/altdns_wordlist.txt", "r", encoding='utf8')
|
45
|
+
for line in dictFile.readlines():
|
46
|
+
altdns = line.strip()
|
47
|
+
result = name_value.replace('*', altdns)
|
48
|
+
if self.domain in result:
|
49
|
+
subDomains.add(result)
|
50
|
+
except Exception as e:
|
51
|
+
pass
|
52
|
+
if len(subDomains) > 0:
|
53
|
+
for x in subDomains:
|
54
|
+
text = text + ',' + x + ','
|
55
|
+
"""
|
56
|
+
* > altdns end
|
57
|
+
"""
|
58
|
+
subdomains = self.match_subdomains(text)
|
59
|
+
self.subdomains.update(subdomains)
|
60
|
+
|
61
|
+
def run(self):
|
62
|
+
"""
|
63
|
+
类执行入口
|
64
|
+
"""
|
65
|
+
self.begin()
|
66
|
+
self.query()
|
67
|
+
self.finish()
|
68
|
+
self.save_json()
|
69
|
+
self.gen_result()
|
70
|
+
self.save_db()
|
71
|
+
|
72
|
+
|
73
|
+
def run(domain):
|
74
|
+
"""
|
75
|
+
类统一调用入口
|
76
|
+
|
77
|
+
:param str domain: 域名
|
78
|
+
"""
|
79
|
+
query = Crtsh(domain)
|
80
|
+
query.run()
|
81
|
+
|
82
|
+
|
83
|
+
if __name__ == '__main__':
|
84
|
+
run('163.com')
|
@@ -0,0 +1,48 @@
|
|
1
|
+
from common.query import Query
|
2
|
+
|
3
|
+
|
4
|
+
class Google(Query):
|
5
|
+
def __init__(self, domain):
|
6
|
+
Query.__init__(self)
|
7
|
+
self.domain = domain
|
8
|
+
self.module = 'Certificate'
|
9
|
+
self.source = 'GoogleQuery'
|
10
|
+
self.addr = 'https://transparencyreport.google.com/' \
|
11
|
+
'transparencyreport/api/v3/httpsreport/ct/certsearch'
|
12
|
+
|
13
|
+
def query(self):
|
14
|
+
"""
|
15
|
+
向接口查询子域并做子域匹配
|
16
|
+
"""
|
17
|
+
self.header = self.get_header()
|
18
|
+
self.proxy = self.get_proxy(self.source)
|
19
|
+
params = {'include_expired': 'true',
|
20
|
+
'include_subdomains': 'true',
|
21
|
+
'domain': self.domain}
|
22
|
+
resp = self.get(self.addr, params)
|
23
|
+
self.subdomains = self.collect_subdomains(resp)
|
24
|
+
|
25
|
+
def run(self):
|
26
|
+
"""
|
27
|
+
类执行入口
|
28
|
+
"""
|
29
|
+
self.begin()
|
30
|
+
self.query()
|
31
|
+
self.finish()
|
32
|
+
self.save_json()
|
33
|
+
self.gen_result()
|
34
|
+
self.save_db()
|
35
|
+
|
36
|
+
|
37
|
+
def run(domain):
|
38
|
+
"""
|
39
|
+
类统一调用入口
|
40
|
+
|
41
|
+
:param str domain: 域名
|
42
|
+
"""
|
43
|
+
query = Google(domain)
|
44
|
+
query.run()
|
45
|
+
|
46
|
+
|
47
|
+
if __name__ == '__main__':
|
48
|
+
run('example.com')
|
@@ -0,0 +1,46 @@
|
|
1
|
+
from common.query import Query
|
2
|
+
|
3
|
+
|
4
|
+
class MySSL(Query):
|
5
|
+
def __init__(self, domain):
|
6
|
+
Query.__init__(self)
|
7
|
+
self.domain = domain
|
8
|
+
self.module = 'Certificate'
|
9
|
+
self.source = 'MySSLQuery'
|
10
|
+
self.addr = 'https://myssl.com/api/v1/discover_sub_domain'
|
11
|
+
|
12
|
+
def query(self):
|
13
|
+
"""
|
14
|
+
向接口查询子域并做子域匹配
|
15
|
+
"""
|
16
|
+
self.header = self.get_header()
|
17
|
+
self.proxy = self.get_proxy(self.source)
|
18
|
+
params = {'domain': self.domain}
|
19
|
+
resp = self.get(self.addr, params)
|
20
|
+
self.subdomains = self.collect_subdomains(resp)
|
21
|
+
|
22
|
+
def run(self):
|
23
|
+
"""
|
24
|
+
类执行入口
|
25
|
+
"""
|
26
|
+
self.begin()
|
27
|
+
self.query()
|
28
|
+
self.finish()
|
29
|
+
self.save_json()
|
30
|
+
self.gen_result()
|
31
|
+
self.save_db()
|
32
|
+
|
33
|
+
|
34
|
+
def run(domain):
|
35
|
+
"""
|
36
|
+
类统一调用入口
|
37
|
+
|
38
|
+
:param str domain: 域名
|
39
|
+
|
40
|
+
"""
|
41
|
+
query = MySSL(domain)
|
42
|
+
query.run()
|
43
|
+
|
44
|
+
|
45
|
+
if __name__ == '__main__':
|
46
|
+
run('freebuf.com')
|
@@ -0,0 +1,49 @@
|
|
1
|
+
from config import settings
|
2
|
+
from common.query import Query
|
3
|
+
|
4
|
+
|
5
|
+
class Racent(Query):
|
6
|
+
def __init__(self, domain):
|
7
|
+
Query.__init__(self)
|
8
|
+
self.domain = domain
|
9
|
+
self.module = 'Certificate'
|
10
|
+
self.source = 'RacentQuery'
|
11
|
+
self.addr = 'https://face.racent.com/tool/query_ctlog'
|
12
|
+
self.api = settings.racent_api_token
|
13
|
+
|
14
|
+
def query(self):
|
15
|
+
"""
|
16
|
+
向接口查询子域并做子域匹配
|
17
|
+
"""
|
18
|
+
self.header = self.get_header()
|
19
|
+
self.proxy = self.get_proxy(self.source)
|
20
|
+
params = {'token': self.api, 'keyword': self.domain}
|
21
|
+
resp = self.get(self.addr, params)
|
22
|
+
self.subdomains = self.collect_subdomains(resp)
|
23
|
+
|
24
|
+
def run(self):
|
25
|
+
"""
|
26
|
+
类执行入口
|
27
|
+
"""
|
28
|
+
if not self.have_api(self.api):
|
29
|
+
return
|
30
|
+
self.begin()
|
31
|
+
self.query()
|
32
|
+
self.finish()
|
33
|
+
self.save_json()
|
34
|
+
self.gen_result()
|
35
|
+
self.save_db()
|
36
|
+
|
37
|
+
|
38
|
+
def run(domain):
|
39
|
+
"""
|
40
|
+
类统一调用入口
|
41
|
+
|
42
|
+
:param str domain: 域名
|
43
|
+
"""
|
44
|
+
query = Racent(domain)
|
45
|
+
query.run()
|
46
|
+
|
47
|
+
|
48
|
+
if __name__ == '__main__':
|
49
|
+
run('example.com')
|