zetalytics 0.1.0
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.
- checksums.yaml +7 -0
- data/lib/zetalytics.rb +329 -0
- data/lib/zetalytics/version.rb +3 -0
- metadata +59 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 5eb435aa697cffee0167ace95aef3e9953d9b151f321d33b3b949ab73c1c9e55
|
|
4
|
+
data.tar.gz: d83c85a2e1074384913c5ab34d600dbb107490e0f669c9a5380798bbfb21d98c
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: d4a3932746591b602452824a33048acbe95e95065d62e4fe44f5c2ab9d0cb296b23432febd1672d98e326161b4c07801058230715b9e6f33d48997a839170e8b
|
|
7
|
+
data.tar.gz: 02b89aae7706788152218b71545a1e65b7eb498a90a368fb2ed2a1f5b1566e7215dda6e346d098c4b22f6f3cda3bfe74d833765af6a3c142da69590d5a5188cc
|
data/lib/zetalytics.rb
ADDED
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
require_relative 'zetalytics/version'
|
|
2
|
+
require 'rest-client'
|
|
3
|
+
require 'json'
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
module Zetalytics
|
|
7
|
+
class Api
|
|
8
|
+
|
|
9
|
+
def initialize(api_key=nil, options={})
|
|
10
|
+
@base_uri = "https://zonecruncher.com/api/v2"
|
|
11
|
+
@api_key = api_key
|
|
12
|
+
|
|
13
|
+
# if we weren't passed a config
|
|
14
|
+
unless @api_key
|
|
15
|
+
# check to see if a config file exists
|
|
16
|
+
config_file_path = "#{File.dirname(__FILE__)}/../config/config.json"
|
|
17
|
+
if File.exist? config_file_path
|
|
18
|
+
config = JSON.parse(File.open(config_file_path,"r").read)
|
|
19
|
+
@api_key = config["api_key"]
|
|
20
|
+
else
|
|
21
|
+
raise "Unable to continue... no api key!"
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def search_cname2qname (cname)
|
|
28
|
+
result = JSON.parse RestClient.get "#{@base_uri}/cname2qname?q=#{cname}&token=#{@api_key}"
|
|
29
|
+
if result["total"] > 0
|
|
30
|
+
return result
|
|
31
|
+
else
|
|
32
|
+
return
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
## Search zonefile changes by domain for DNAME record.
|
|
37
|
+
## A DNAME record creates an alias for an entire subtree of the domain name tree
|
|
38
|
+
def search_domain_dname_records (domain)
|
|
39
|
+
domain_name = domain.split('.')[0]
|
|
40
|
+
result = JSON.parse RestClient.get "#{@base_uri}/domain-zone-activity?q=#{domain}&token=#{@api_key}"
|
|
41
|
+
if result["total"] > 0
|
|
42
|
+
return result
|
|
43
|
+
else
|
|
44
|
+
return
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
## Search passive dns by domain for AAAA (IPv6) records
|
|
49
|
+
def search_domain_for_ipv6_records (domain)
|
|
50
|
+
result = JSON.parse RestClient.get "#{@base_uri}/domain2aaaa?q=#{domain}&token=#{@api_key}"
|
|
51
|
+
if result["total"] > 0
|
|
52
|
+
return result
|
|
53
|
+
else
|
|
54
|
+
return
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
## Search passive dns by domain for CNAME records
|
|
59
|
+
def search_domain2cname (domain)
|
|
60
|
+
result = JSON.parse RestClient.get "#{@base_uri}/domain2cname?q=#{domain}&token=#{@api_key}"
|
|
61
|
+
if result["total"] > 0
|
|
62
|
+
return result
|
|
63
|
+
else
|
|
64
|
+
return
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
## Search historical d8s records and/or live d8s
|
|
69
|
+
def search_historical_live_dnsrecords (domain)
|
|
70
|
+
result = JSON.parse RestClient.get "#{@base_uri}/domain2d8s?q=#{domain}&token=#{@api_key}"
|
|
71
|
+
if result["total"] > 0
|
|
72
|
+
return result
|
|
73
|
+
else
|
|
74
|
+
return
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
## Search passive dns by domain for A (IPv4) records
|
|
80
|
+
def search_domain2ip (domain)
|
|
81
|
+
result = JSON.parse RestClient.get "#{@base_uri}/domain2ip?q=#{domain}&token=#{@api_key}"
|
|
82
|
+
if result["total"] > 0
|
|
83
|
+
return result
|
|
84
|
+
else
|
|
85
|
+
return
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
## Search malware dns by domain (some of the results are obsolete)
|
|
90
|
+
def search_domain2malwaredns (domain)
|
|
91
|
+
result = JSON.parse RestClient.get "#{@base_uri}/domain2malwaredns?q=#{domain}&token=#{@api_key}"
|
|
92
|
+
if result["total"] > 0
|
|
93
|
+
return result
|
|
94
|
+
else
|
|
95
|
+
return
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
## Search malware http by domain (some of the results are obsolete)
|
|
100
|
+
def search_domain2malwarehttp (domain)
|
|
101
|
+
result = JSON.parse RestClient.get "#{@base_uri}/domain2malwarehttp?q=#{domain}&token=#{@api_key}"
|
|
102
|
+
if result["total"] > 0
|
|
103
|
+
return result
|
|
104
|
+
else
|
|
105
|
+
return
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
## Search passive dns by domain for MX records
|
|
110
|
+
def search_domain2mx (domain)
|
|
111
|
+
result = JSON.parse RestClient.get "#{@base_uri}/domain2mx?q=#{domain}&token=#{@api_key}"
|
|
112
|
+
if result["total"] > 0
|
|
113
|
+
return result
|
|
114
|
+
else
|
|
115
|
+
return
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
## Search passive dns by domain for NS records
|
|
120
|
+
def search_domain2ns (domain)
|
|
121
|
+
result = JSON.parse RestClient.get "#{@base_uri}/domain2ns?q=#{domain}&token=#{@api_key}"
|
|
122
|
+
if result["total"] > 0
|
|
123
|
+
return result
|
|
124
|
+
else
|
|
125
|
+
return
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
## Search name server glue (IP) records by domain name.
|
|
130
|
+
## NOTE: these are only the glue records found in gTLD zone files and NOT all IP records
|
|
131
|
+
## for every name server domain.
|
|
132
|
+
## what is dns glue record? => https://ns1.com/blog/glue-records-and-dedicated-dns#:~:text=What%20is%20a%20Glue%20Record,ns2.example.net%E2%80%9D.
|
|
133
|
+
def search_domain2nsglue (domain)
|
|
134
|
+
result = JSON.parse RestClient.get "#{@base_uri}/domain2nsglue?q=#{domain}&token=#{@api_key}"
|
|
135
|
+
if result["total"] > 0
|
|
136
|
+
return result
|
|
137
|
+
else
|
|
138
|
+
return
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
## Search passive dns by domain for PTR records
|
|
143
|
+
def search_domain2ptr (domain)
|
|
144
|
+
result = JSON.parse RestClient.get "#{@base_uri}/domain2ptr?q=#{domain}&token=#{@api_key}"
|
|
145
|
+
if result["total"] > 0
|
|
146
|
+
return result
|
|
147
|
+
else
|
|
148
|
+
return
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
## Search passive dns by domain for PTR records
|
|
153
|
+
def search_domain2ptr (domain)
|
|
154
|
+
result = JSON.parse RestClient.get "#{@base_uri}/domain2ptr?q=#{domain}&token=#{@api_key}"
|
|
155
|
+
if result["total"] > 0
|
|
156
|
+
return result
|
|
157
|
+
else
|
|
158
|
+
return
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
## Search passive dns by domain for TXT records
|
|
163
|
+
def search_domain2txt (domain)
|
|
164
|
+
result = JSON.parse RestClient.get "#{@base_uri}/domain2txt?q=#{domain}&token=#{@api_key}"
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
if result["total"] > 0
|
|
168
|
+
return result
|
|
169
|
+
else
|
|
170
|
+
return
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
## Search historical whois records
|
|
175
|
+
def search_domain2whois (domain)
|
|
176
|
+
result = JSON.parse RestClient.get "#{@base_uri}/domain2whois?q=#{domain}&token=#{@api_key}"
|
|
177
|
+
if result["total"] > 0
|
|
178
|
+
return result
|
|
179
|
+
else
|
|
180
|
+
return
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
## Search for domains sharing a registration email address or SOA email from passive
|
|
185
|
+
def search_email_address (domain)
|
|
186
|
+
# using "a*@" is for identifying a large number of domains since the majority of DNS recorded contains else the administrator contact or abuse contact
|
|
187
|
+
email = "a*@"+ domain
|
|
188
|
+
result = JSON.parse RestClient.get "#{@base_uri}/email_address?q=#{email}&token=#{@api_key}"
|
|
189
|
+
if result["total"] > 0
|
|
190
|
+
return result
|
|
191
|
+
else
|
|
192
|
+
return
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
## Search for domains sharing a registration email address domain
|
|
197
|
+
def search_email_domain (domain)
|
|
198
|
+
result = JSON.parse RestClient.get "#{@base_uri}/email_domain?q=#{domain}&token=#{@api_key}"
|
|
199
|
+
if result["total"] > 0
|
|
200
|
+
return result
|
|
201
|
+
else
|
|
202
|
+
return
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
## Search malware dns by md5 hash
|
|
207
|
+
def search_hash2malwaredns (hash)
|
|
208
|
+
result = JSON.parse RestClient.get "#{@base_uri}/hash2malwaredns?q=#{hash}&token=#{@api_key}"
|
|
209
|
+
if result["total"] > 0
|
|
210
|
+
return result
|
|
211
|
+
else
|
|
212
|
+
return
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
## Search malware http by md5 hash
|
|
217
|
+
def search_hash2malwaredns (hash)
|
|
218
|
+
result = JSON.parse RestClient.get "#{@base_uri}/hash2malwarehttp?q=#{hash}&token=#{@api_key}"
|
|
219
|
+
if result["total"] > 0
|
|
220
|
+
return result
|
|
221
|
+
else
|
|
222
|
+
return
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
## Search passive dns by hostname for mixed resource record types
|
|
227
|
+
def search_by_hostname (domain)
|
|
228
|
+
result = JSON.parse RestClient.get "#{@base_uri}/hostname?q=#{domain}&token=#{@api_key}"
|
|
229
|
+
if result["total"] > 0
|
|
230
|
+
return result
|
|
231
|
+
else
|
|
232
|
+
return
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
## Search passive dns by IP, CIDR, or Range (v6 compatible)
|
|
237
|
+
def search_by_ip (ip)
|
|
238
|
+
result = JSON.parse RestClient.get "#{@base_uri}/ip?q=#{ip}&token=#{@api_key}"
|
|
239
|
+
if result["total"] > 0
|
|
240
|
+
return result
|
|
241
|
+
else
|
|
242
|
+
return
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
## Search malware dns by IP
|
|
247
|
+
def search_ip2malwaredns(ip)
|
|
248
|
+
result = JSON.parse RestClient.get "#{@base_uri}/ip2malwaredns?q=#{ip}&token=#{@api_key}"
|
|
249
|
+
if result["total"] > 0
|
|
250
|
+
return result
|
|
251
|
+
else
|
|
252
|
+
return
|
|
253
|
+
end
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
## Search malware http by IP/CIDR for http://x.x.x.x/ (not the IP a hostname resolved to).
|
|
257
|
+
## These results would not appear in the malware dns result since they do not require a DNS lookup.
|
|
258
|
+
def search_ip2malwarehttp(ip)
|
|
259
|
+
result = JSON.parse RestClient.get "#{@base_uri}/ip2malwarehttp?q=#{ip}&token=#{@api_key}"
|
|
260
|
+
if result["total"] > 0
|
|
261
|
+
return result
|
|
262
|
+
else
|
|
263
|
+
return
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
## Search name server glue (IP) records by IP, CIDR, or Range (v6 compatible)
|
|
268
|
+
## what is dns glue record? => https://ns1.com/blog/glue-records-and-dedicated-dns#:~:text=What%20is%20a%20Glue%20Record,ns2.example.net%E2%80%9D.
|
|
269
|
+
def search_ip2nsglue(ip)
|
|
270
|
+
result = JSON.parse RestClient.get "#{@base_uri}/ip2nsglue?q=#{ip}&token=#{@api_key}"
|
|
271
|
+
if result["total"] > 0
|
|
272
|
+
return result
|
|
273
|
+
else
|
|
274
|
+
return
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
## Perform a live DNS lookup for a domain
|
|
279
|
+
def search_livedns(domain)
|
|
280
|
+
result = JSON.parse RestClient.get "#{@base_uri}/liveDNS?q=#{domain}&token=#{@api_key}"
|
|
281
|
+
if result["total"] > 0
|
|
282
|
+
return result
|
|
283
|
+
else
|
|
284
|
+
return
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
## Search zonefile changes by nameserver
|
|
289
|
+
def search_nszoneactivity(nameserver)
|
|
290
|
+
result = JSON.parse RestClient.get "#{@base_uri}/ns-zone-activity?q=#{nameserver}&token=#{@api_key}"
|
|
291
|
+
if result["total"] > 0
|
|
292
|
+
return result
|
|
293
|
+
else
|
|
294
|
+
return
|
|
295
|
+
end
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
## Search current zone files and passive DNS for domains served by nameserver.
|
|
299
|
+
def search_ns2domain(nameserver)
|
|
300
|
+
result = JSON.parse RestClient.get "#{@base_uri}/mx2domain?q=#{nameserver}&token=#{@api_key}"
|
|
301
|
+
if result["total"] > 0
|
|
302
|
+
return result
|
|
303
|
+
else
|
|
304
|
+
return
|
|
305
|
+
end
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
## Search current zone files and passive DNS for domains served by nameserver.
|
|
309
|
+
def search_ns2domain(nameserver)
|
|
310
|
+
result = JSON.parse RestClient.get"#{@base_uri}/mx2domain?q=#{nameserver}&token=#{@api_key}"
|
|
311
|
+
if result["total"] > 0
|
|
312
|
+
return result
|
|
313
|
+
else
|
|
314
|
+
return
|
|
315
|
+
end
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
## Search passive dns by domain for a list of subdomains from any record type.
|
|
319
|
+
def search_subdomains(domain)
|
|
320
|
+
result = JSON.parse RestClient.get "#{@base_uri}/subdomains?q=#{domain}&token=#{@api_key}"
|
|
321
|
+
if result["total"] > 0
|
|
322
|
+
return result
|
|
323
|
+
else
|
|
324
|
+
return
|
|
325
|
+
end
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
end
|
|
329
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: zetalytics
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Anas Ben Salah
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2020-12-04 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: json
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '0'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '0'
|
|
27
|
+
description: API client for the Zetalytics API
|
|
28
|
+
email:
|
|
29
|
+
- anas@intrigue.io
|
|
30
|
+
executables: []
|
|
31
|
+
extensions: []
|
|
32
|
+
extra_rdoc_files: []
|
|
33
|
+
files:
|
|
34
|
+
- lib/zetalytics.rb
|
|
35
|
+
- lib/zetalytics/version.rb
|
|
36
|
+
homepage:
|
|
37
|
+
licenses:
|
|
38
|
+
- MIT
|
|
39
|
+
metadata: {}
|
|
40
|
+
post_install_message:
|
|
41
|
+
rdoc_options: []
|
|
42
|
+
require_paths:
|
|
43
|
+
- lib
|
|
44
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
45
|
+
requirements:
|
|
46
|
+
- - ">="
|
|
47
|
+
- !ruby/object:Gem::Version
|
|
48
|
+
version: '0'
|
|
49
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - ">="
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '0'
|
|
54
|
+
requirements: []
|
|
55
|
+
rubygems_version: 3.1.4
|
|
56
|
+
signing_key:
|
|
57
|
+
specification_version: 4
|
|
58
|
+
summary: API client for the Zetalytics API
|
|
59
|
+
test_files: []
|