ronin-db-activerecord 0.1.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.document +5 -0
- data/.github/workflows/ruby.yml +31 -0
- data/.gitignore +13 -0
- data/.rspec +1 -0
- data/.ruby-version +1 -0
- data/.yardopts +1 -0
- data/COPYING.txt +165 -0
- data/ChangeLog.md +39 -0
- data/Gemfile +27 -0
- data/README.md +143 -0
- data/Rakefile +72 -0
- data/db/migrate/0001_create_ronin_ip_address_mac_addresses_table.rb +43 -0
- data/db/migrate/0002_create_ronin_vulnerabilities_table.rb +61 -0
- data/db/migrate/0003_create_ronin_url_schemes_table.rb +32 -0
- data/db/migrate/0004_create_ronin_url_query_param_names_table.rb +32 -0
- data/db/migrate/0005_create_ronin_user_names_table.rb +33 -0
- data/db/migrate/0006_create_ronin_software_vendors_table.rb +32 -0
- data/db/migrate/0007_create_ronin_advisories_table.rb +42 -0
- data/db/migrate/0008_create_ronin_host_name_ip_addresses_table.rb +43 -0
- data/db/migrate/0009_create_ronin_host_names_table.rb +34 -0
- data/db/migrate/0010_create_ronin_arches_table.rb +37 -0
- data/db/migrate/0011_create_ronin_email_addresses_table.rb +44 -0
- data/db/migrate/0012_create_ronin_oses_table.rb +36 -0
- data/db/migrate/0013_create_ronin_organizations_table.rb +31 -0
- data/db/migrate/0014_create_ronin_ip_addresses_table.rb +35 -0
- data/db/migrate/0015_create_ronin_os_guesses_table.rb +40 -0
- data/db/migrate/0016_create_ronin_url_query_params_table.rb +42 -0
- data/db/migrate/0017_create_ronin_passwords_table.rb +32 -0
- data/db/migrate/0018_create_ronin_open_ports_table.rb +46 -0
- data/db/migrate/0019_create_ronin_urls_table.rb +50 -0
- data/db/migrate/0020_create_ronin_softwares_table.rb +39 -0
- data/db/migrate/0021_create_ronin_mac_addresses_table.rb +33 -0
- data/db/migrate/0022_create_ronin_countries_table.rb +34 -0
- data/db/migrate/0023_create_ronin_services_table.rb +32 -0
- data/db/migrate/0024_create_ronin_credentials_table.rb +44 -0
- data/db/migrate/0025_create_ronin_ports_table.rb +33 -0
- data/db/migrate/0026_create_ronin_asns_table.rb +44 -0
- data/db/migrate/0027_create_ronin_http_query_param_names_table.rb +32 -0
- data/db/migrate/0028_create_ronin_http_query_params_table.rb +42 -0
- data/db/migrate/0029_create_ronin_http_header_names_table.rb +31 -0
- data/db/migrate/0030_create_ronin_http_request_headers_table.rb +41 -0
- data/db/migrate/0031_create_ronin_http_response_headers_table.rb +41 -0
- data/db/migrate/0032_create_ronin_http_requests_table.rb +41 -0
- data/db/migrate/0033_create_ronin_http_responses_table.rb +36 -0
- data/db/migrate/0034_create_ronin_service_credentials_table.rb +41 -0
- data/db/migrate/0035_create_ronin_web_credentials_table.rb +41 -0
- data/gemspec.yml +28 -0
- data/lib/ronin/db/address.rb +105 -0
- data/lib/ronin/db/advisory.rb +169 -0
- data/lib/ronin/db/arch.rb +160 -0
- data/lib/ronin/db/asn.rb +212 -0
- data/lib/ronin/db/credential.rb +248 -0
- data/lib/ronin/db/email_address.rb +225 -0
- data/lib/ronin/db/host_name.rb +224 -0
- data/lib/ronin/db/host_name_ip_address.rb +65 -0
- data/lib/ronin/db/http_header_name.rb +75 -0
- data/lib/ronin/db/http_query_param.rb +79 -0
- data/lib/ronin/db/http_query_param_name.rb +76 -0
- data/lib/ronin/db/http_request.rb +120 -0
- data/lib/ronin/db/http_request_header.rb +78 -0
- data/lib/ronin/db/http_response.rb +91 -0
- data/lib/ronin/db/http_response_header.rb +78 -0
- data/lib/ronin/db/ip_address.rb +351 -0
- data/lib/ronin/db/ip_address_mac_address.rb +62 -0
- data/lib/ronin/db/mac_address.rb +91 -0
- data/lib/ronin/db/migrations.rb +137 -0
- data/lib/ronin/db/model/has_name.rb +102 -0
- data/lib/ronin/db/model/has_unique_name.rb +82 -0
- data/lib/ronin/db/model/importable.rb +85 -0
- data/lib/ronin/db/model/last_scanned_at.rb +48 -0
- data/lib/ronin/db/model.rb +37 -0
- data/lib/ronin/db/models.rb +108 -0
- data/lib/ronin/db/open_port.rb +148 -0
- data/lib/ronin/db/organization.rb +50 -0
- data/lib/ronin/db/os.rb +183 -0
- data/lib/ronin/db/os_guess.rb +67 -0
- data/lib/ronin/db/password.rb +167 -0
- data/lib/ronin/db/port.rb +123 -0
- data/lib/ronin/db/root.rb +28 -0
- data/lib/ronin/db/schema_migration.rb +34 -0
- data/lib/ronin/db/service.rb +48 -0
- data/lib/ronin/db/service_credential.rb +66 -0
- data/lib/ronin/db/software.rb +85 -0
- data/lib/ronin/db/software_vendor.rb +42 -0
- data/lib/ronin/db/url.rb +497 -0
- data/lib/ronin/db/url_query_param.rb +79 -0
- data/lib/ronin/db/url_query_param_name.rb +76 -0
- data/lib/ronin/db/url_scheme.rb +80 -0
- data/lib/ronin/db/user_name.rb +96 -0
- data/lib/ronin/db/vulnerability.rb +81 -0
- data/lib/ronin/db/web_credential.rb +69 -0
- data/ronin-db-activerecord.gemspec +61 -0
- data/spec/advisory_spec.rb +277 -0
- data/spec/arch_spec.rb +228 -0
- data/spec/asn_spec.rb +504 -0
- data/spec/credential_spec.rb +362 -0
- data/spec/email_address_spec.rb +372 -0
- data/spec/host_name_ip_address_spec.rb +8 -0
- data/spec/host_name_spec.rb +207 -0
- data/spec/http_header_name_spec.rb +25 -0
- data/spec/http_query_param_name_spec.rb +25 -0
- data/spec/http_query_param_spec.rb +104 -0
- data/spec/http_request_header_spec.rb +72 -0
- data/spec/http_request_spec.rb +168 -0
- data/spec/http_response_header_spec.rb +74 -0
- data/spec/http_response_spec.rb +103 -0
- data/spec/ip_address_mac_addresses_spec.rb +8 -0
- data/spec/ip_address_spec.rb +386 -0
- data/spec/mac_address_spec.rb +67 -0
- data/spec/migrations_spec.rb +122 -0
- data/spec/model/has_name_spec.rb +65 -0
- data/spec/model/has_unique_name_spec.rb +61 -0
- data/spec/model/importable_spec.rb +105 -0
- data/spec/models_spec.rb +60 -0
- data/spec/open_port_spec.rb +87 -0
- data/spec/organization_spec.rb +10 -0
- data/spec/os_guess_spec.rb +43 -0
- data/spec/os_spec.rb +114 -0
- data/spec/password_spec.rb +81 -0
- data/spec/port_spec.rb +102 -0
- data/spec/schema_migration_spec.rb +8 -0
- data/spec/service_credential_spec.rb +43 -0
- data/spec/service_spec.rb +39 -0
- data/spec/software_spec.rb +76 -0
- data/spec/software_vendor_spec.rb +33 -0
- data/spec/spec_helper.rb +13 -0
- data/spec/url_query_param_name_spec.rb +25 -0
- data/spec/url_query_param_spec.rb +110 -0
- data/spec/url_scheme_spec.rb +39 -0
- data/spec/url_spec.rb +951 -0
- data/spec/user_name_spec.rb +54 -0
- data/spec/vulnerability_spec.rb +8 -0
- data/spec/web_credential_spec.rb +72 -0
- metadata +266 -0
@@ -0,0 +1,105 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-db-activerecord - ActiveRecord backend for the Ronin Database.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
6
|
+
#
|
7
|
+
# ronin-db-activerecord is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Lesser General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# ronin-db-activerecord is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Lesser General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Lesser General Public License
|
18
|
+
# along with ronin-db-activerecord. If not, see <https://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'ronin/db/model'
|
22
|
+
require 'ronin/db/model/importable'
|
23
|
+
require 'ronin/db/model/last_scanned_at'
|
24
|
+
|
25
|
+
require 'active_record'
|
26
|
+
|
27
|
+
module Ronin
|
28
|
+
module DB
|
29
|
+
#
|
30
|
+
# A base model which represents an Internet Address, such as:
|
31
|
+
#
|
32
|
+
# * {MACAddress}
|
33
|
+
# * {IPAddress}
|
34
|
+
# * {HostName}
|
35
|
+
#
|
36
|
+
class Address < ActiveRecord::Base
|
37
|
+
|
38
|
+
include Model
|
39
|
+
include Model::Importable
|
40
|
+
include Model::LastScannedAt
|
41
|
+
|
42
|
+
self.abstract_class = true
|
43
|
+
|
44
|
+
# @!attribute [rw] id
|
45
|
+
# The primary key of the Address
|
46
|
+
#
|
47
|
+
# @return [Integer]
|
48
|
+
attribute :id, :integer
|
49
|
+
|
50
|
+
# @!attribute [rw] address
|
51
|
+
# The Address
|
52
|
+
#
|
53
|
+
# @return [String]
|
54
|
+
attribute :address, :string
|
55
|
+
validates :address, presence: true, uniqueness: true
|
56
|
+
|
57
|
+
# @!attribute [rw] created_at
|
58
|
+
# Tracks when the IP Address was first created
|
59
|
+
#
|
60
|
+
# @return [Time]
|
61
|
+
attribute :created_at, :time
|
62
|
+
|
63
|
+
#
|
64
|
+
# Looks up the address.
|
65
|
+
#
|
66
|
+
# @param [String] address
|
67
|
+
# The address to query.
|
68
|
+
#
|
69
|
+
# @return [Address, nil]
|
70
|
+
# The found address.
|
71
|
+
#
|
72
|
+
def self.lookup(address)
|
73
|
+
find_by(address: address)
|
74
|
+
end
|
75
|
+
|
76
|
+
#
|
77
|
+
# Imports an address.
|
78
|
+
#
|
79
|
+
# @param [String] address
|
80
|
+
# The address to parse.
|
81
|
+
#
|
82
|
+
# @return [Address]
|
83
|
+
# The parsed address.
|
84
|
+
#
|
85
|
+
# @api public
|
86
|
+
#
|
87
|
+
def self.import(address)
|
88
|
+
create(address: address)
|
89
|
+
end
|
90
|
+
|
91
|
+
#
|
92
|
+
# Converts the address into a string.
|
93
|
+
#
|
94
|
+
# @return [String]
|
95
|
+
# The address.
|
96
|
+
#
|
97
|
+
# @api public
|
98
|
+
#
|
99
|
+
def to_s
|
100
|
+
self.address.to_s
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,169 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-db-activerecord - ActiveRecord backend for the Ronin Database.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
6
|
+
#
|
7
|
+
# ronin-db-activerecord is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Lesser General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# ronin-db-activerecord is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Lesser General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Lesser General Public License
|
18
|
+
# along with ronin-db-activerecord. If not, see <https://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'ronin/db/model'
|
22
|
+
require 'ronin/db/model/importable'
|
23
|
+
|
24
|
+
require 'active_record'
|
25
|
+
|
26
|
+
module Ronin
|
27
|
+
module DB
|
28
|
+
#
|
29
|
+
# Represents a vulnerability Advisory, with a Publisher, Number and
|
30
|
+
# URL.
|
31
|
+
#
|
32
|
+
class Advisory < ActiveRecord::Base
|
33
|
+
|
34
|
+
include Model
|
35
|
+
include Model::Importable
|
36
|
+
|
37
|
+
self.primary_key = :id
|
38
|
+
|
39
|
+
# @!attribute [rw] id
|
40
|
+
# Primary key of the advisory.
|
41
|
+
#
|
42
|
+
# @return [String]
|
43
|
+
attribute :id, :string
|
44
|
+
|
45
|
+
# @!attribute [rw] prefix
|
46
|
+
# The ID prefix (ex: `CVE` or `GHSA`).
|
47
|
+
#
|
48
|
+
# @return [String]
|
49
|
+
attribute :prefix, :string
|
50
|
+
validates :prefix, presence: true
|
51
|
+
|
52
|
+
# @!attribute [rw] year
|
53
|
+
# The year the advisory was published in.
|
54
|
+
#
|
55
|
+
# @return [Integer]
|
56
|
+
attribute :year, :integer
|
57
|
+
validates :year, allow_nil: true,
|
58
|
+
comparison: {
|
59
|
+
greater_than: 1990,
|
60
|
+
less_than_or_equal_to: Date.today.year
|
61
|
+
}
|
62
|
+
|
63
|
+
# @!attribute [rw] identifier
|
64
|
+
# The advisory identifier
|
65
|
+
#
|
66
|
+
# @return [String]
|
67
|
+
attribute :identifier, :string
|
68
|
+
validates :identifier, presence: true
|
69
|
+
|
70
|
+
#
|
71
|
+
# @api private
|
72
|
+
#
|
73
|
+
module ID
|
74
|
+
#
|
75
|
+
# Parses a security avdisory ID.
|
76
|
+
#
|
77
|
+
# @param [String] string
|
78
|
+
# The security advisory ID String to split.
|
79
|
+
#
|
80
|
+
# @return [Hash{Symbol => Object}]
|
81
|
+
# The parsed security advisory ID.
|
82
|
+
#
|
83
|
+
# @raise [ArgumentError]
|
84
|
+
# The ID does not appear to be a valid security ID.
|
85
|
+
#
|
86
|
+
def self.parse(string)
|
87
|
+
if (match = string.match(/\A([A-Z]+)-(\d{4})[:-]([0-9][0-9-]+)\z/))
|
88
|
+
{
|
89
|
+
id: match[0],
|
90
|
+
prefix: match[1],
|
91
|
+
year: match[2].to_i,
|
92
|
+
identifier: match[3]
|
93
|
+
}
|
94
|
+
elsif (match = string.match(/\AMS(\d{2})-(\d{3,})\z/))
|
95
|
+
{
|
96
|
+
id: match[0],
|
97
|
+
prefix: 'MS',
|
98
|
+
year: 2000 + match[1].to_i,
|
99
|
+
identifier: match[2]
|
100
|
+
}
|
101
|
+
elsif (match = string.match(/\A([A-Z]+)-(.+)\z/))
|
102
|
+
{
|
103
|
+
id: match[0],
|
104
|
+
prefix: match[1],
|
105
|
+
identifier: match[2]
|
106
|
+
}
|
107
|
+
else
|
108
|
+
raise(ArgumentError,"id does not appear to be a valid security advisory ID: #{string.inspect}")
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
#
|
114
|
+
# Looks up the advisory.
|
115
|
+
#
|
116
|
+
# @param [String] id
|
117
|
+
#
|
118
|
+
# @return [Advisory, nil]
|
119
|
+
#
|
120
|
+
def self.lookup(id)
|
121
|
+
find_by(id: id)
|
122
|
+
end
|
123
|
+
|
124
|
+
#
|
125
|
+
# Parses an Advisory ID String.
|
126
|
+
#
|
127
|
+
# @param [String] id
|
128
|
+
# The ID String for the advisory.
|
129
|
+
#
|
130
|
+
# @return [Advisory]
|
131
|
+
# The new advisory.
|
132
|
+
#
|
133
|
+
# @api public
|
134
|
+
#
|
135
|
+
def self.import(id)
|
136
|
+
create(**ID.parse(id))
|
137
|
+
end
|
138
|
+
|
139
|
+
#
|
140
|
+
# Generates a URL for the advisory.
|
141
|
+
#
|
142
|
+
# @return [String, nil]
|
143
|
+
# The URL for the advisory.
|
144
|
+
#
|
145
|
+
# @api public
|
146
|
+
#
|
147
|
+
def url
|
148
|
+
case prefix
|
149
|
+
when 'CVE' then "https://nvd.nist.gov/vuln/detail/#{id}"
|
150
|
+
when 'RHSA' then "https://access.redhat.com/errata/#{id}"
|
151
|
+
when 'GHSA' then "https://github.com/advisories/#{id}"
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
#
|
156
|
+
# Converts the advisory to a String.
|
157
|
+
#
|
158
|
+
# @return [String]
|
159
|
+
# The advisory ID string.
|
160
|
+
#
|
161
|
+
# @api public
|
162
|
+
#
|
163
|
+
def to_s
|
164
|
+
self.id
|
165
|
+
end
|
166
|
+
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
@@ -0,0 +1,160 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-db-activerecord - ActiveRecord backend for the Ronin Database.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
6
|
+
#
|
7
|
+
# ronin-db-activerecord is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Lesser General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# ronin-db-activerecord is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Lesser General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Lesser General Public License
|
18
|
+
# along with ronin-db-activerecord. If not, see <https://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'ronin/db/model'
|
22
|
+
require 'ronin/db/model/has_unique_name'
|
23
|
+
|
24
|
+
require 'active_record'
|
25
|
+
|
26
|
+
module Ronin
|
27
|
+
module DB
|
28
|
+
#
|
29
|
+
# Represents a Computer Architecture and predefines many other common
|
30
|
+
# architectures ({x86}, {x86_64}, {ppc}, {ppc64}, {mips}, {mips_le},
|
31
|
+
# {mips_be}, {arm}, {arm_le}, and {arm_be}).
|
32
|
+
#
|
33
|
+
class Arch < ActiveRecord::Base
|
34
|
+
|
35
|
+
include Model
|
36
|
+
include Model::HasUniqueName
|
37
|
+
|
38
|
+
# @!attribute [rw] id
|
39
|
+
# The primary key of the arch.
|
40
|
+
#
|
41
|
+
# @return [Integer]
|
42
|
+
attribute :id, :integer
|
43
|
+
|
44
|
+
# @!attribute [rw] endian
|
45
|
+
# Endianness of the architecture.
|
46
|
+
#
|
47
|
+
# @return [:little, :big]
|
48
|
+
enum :endian, {little: 'little', big: 'big'}
|
49
|
+
validates :endian, presence: true
|
50
|
+
|
51
|
+
# @!attribute [rw] word_size
|
52
|
+
# Address length of the architecture.
|
53
|
+
#
|
54
|
+
# @return [Integer]
|
55
|
+
attribute :word_size, :integer
|
56
|
+
validates :word_size, presence: true,
|
57
|
+
inclusion: {in: [4, 8]}
|
58
|
+
|
59
|
+
#
|
60
|
+
# The x86 Architecture
|
61
|
+
#
|
62
|
+
# @return [Arch]
|
63
|
+
#
|
64
|
+
def self.x86
|
65
|
+
find_or_create_by(name: 'x86')
|
66
|
+
end
|
67
|
+
|
68
|
+
#
|
69
|
+
# The i686 Architecture
|
70
|
+
#
|
71
|
+
# @return [Arch]
|
72
|
+
#
|
73
|
+
def self.i686
|
74
|
+
find_or_create_by(name: 'i686')
|
75
|
+
end
|
76
|
+
|
77
|
+
#
|
78
|
+
# The x86_64 Architecture
|
79
|
+
#
|
80
|
+
# @return [Arch]
|
81
|
+
#
|
82
|
+
def self.x86_64
|
83
|
+
find_or_create_by(name: 'x86-64')
|
84
|
+
end
|
85
|
+
|
86
|
+
#
|
87
|
+
# The 32-bit PowerPC Architecture
|
88
|
+
#
|
89
|
+
# @return [Arch]
|
90
|
+
#
|
91
|
+
def self.ppc
|
92
|
+
find_or_create_by(name: 'PPC')
|
93
|
+
end
|
94
|
+
|
95
|
+
#
|
96
|
+
# The 64-bit PowerPC Architecture
|
97
|
+
#
|
98
|
+
# @return [Arch]
|
99
|
+
#
|
100
|
+
def self.ppc64
|
101
|
+
find_or_create_by(name: 'PPC64')
|
102
|
+
end
|
103
|
+
|
104
|
+
#
|
105
|
+
# The MIPS Architecture
|
106
|
+
#
|
107
|
+
# @return [Arch]
|
108
|
+
#
|
109
|
+
def self.mips
|
110
|
+
find_or_create_by(name: 'MIPS')
|
111
|
+
end
|
112
|
+
|
113
|
+
#
|
114
|
+
# The MIPS (little endian) Architecture
|
115
|
+
#
|
116
|
+
# @return [Arch]
|
117
|
+
#
|
118
|
+
def self.mips_le
|
119
|
+
find_or_create_by(name: 'MIPS (Little-Endian)')
|
120
|
+
end
|
121
|
+
|
122
|
+
#
|
123
|
+
# The MIPS (big endian) Architecture
|
124
|
+
#
|
125
|
+
# @return [Arch]
|
126
|
+
#
|
127
|
+
def self.mips_be
|
128
|
+
find_or_create_by(name: 'MIPS (Big-Endian)')
|
129
|
+
end
|
130
|
+
|
131
|
+
#
|
132
|
+
# The ARM Architecture
|
133
|
+
#
|
134
|
+
# @return [Arch]
|
135
|
+
#
|
136
|
+
def self.arm
|
137
|
+
find_or_create_by(name: 'ARM')
|
138
|
+
end
|
139
|
+
|
140
|
+
#
|
141
|
+
# The ARM (little endian) Architecture
|
142
|
+
#
|
143
|
+
# @return [Arch]
|
144
|
+
#
|
145
|
+
def self.arm_le
|
146
|
+
find_or_create_by(name: 'ARM (Little-Endian)')
|
147
|
+
end
|
148
|
+
|
149
|
+
#
|
150
|
+
# The ARM (big endian) Architecture
|
151
|
+
#
|
152
|
+
# @return [Arch]
|
153
|
+
#
|
154
|
+
def self.arm_be
|
155
|
+
find_or_create_by(name: 'ARM (Big-Endian)')
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
data/lib/ronin/db/asn.rb
ADDED
@@ -0,0 +1,212 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# ronin-db-activerecord - ActiveRecord backend for the Ronin Database.
|
4
|
+
#
|
5
|
+
# Copyright (c) 2022 Hal Brodigan (postmodern.mod3 at gmail.com)
|
6
|
+
#
|
7
|
+
# ronin-db-activerecord is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Lesser General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# ronin-db-activerecord is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Lesser General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Lesser General Public License
|
18
|
+
# along with ronin-db-activerecord. If not, see <https://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
|
+
|
21
|
+
require 'ronin/db/model'
|
22
|
+
|
23
|
+
module Ronin
|
24
|
+
module DB
|
25
|
+
#
|
26
|
+
# Represents an ASN range.
|
27
|
+
#
|
28
|
+
class ASN < ActiveRecord::Base
|
29
|
+
|
30
|
+
include Model
|
31
|
+
|
32
|
+
# @!attribute [rw] id
|
33
|
+
# The primary key of the ASN range.
|
34
|
+
#
|
35
|
+
# @return [Integer]
|
36
|
+
attribute :id, :integer
|
37
|
+
|
38
|
+
# @!attribute [rw] version
|
39
|
+
# Whether the ASN range represents an IPv4 or IPv6 range.
|
40
|
+
#
|
41
|
+
# @return [Integer]
|
42
|
+
attribute :version, :integer
|
43
|
+
validates :version, presence: true,
|
44
|
+
inclusion: {in: [4, 6]}
|
45
|
+
|
46
|
+
# @!attribute [rw] range_start
|
47
|
+
# The starting IP address of the ASN range.
|
48
|
+
#
|
49
|
+
# @return [String]
|
50
|
+
attribute :range_start, :string
|
51
|
+
validates :range_start, presence: true
|
52
|
+
|
53
|
+
# @!attribute [rw] range_end
|
54
|
+
# The ending IP address of the ASN range.
|
55
|
+
#
|
56
|
+
# @return [String]
|
57
|
+
attribute :range_end, :string
|
58
|
+
validates :range_end, presence: true
|
59
|
+
|
60
|
+
# @!attribute [r] range_start_hton
|
61
|
+
# The starting IP address of the ASN range, but in network byte-order.
|
62
|
+
#
|
63
|
+
# @return [String]
|
64
|
+
attribute :range_start_hton, :binary
|
65
|
+
|
66
|
+
# @!attribute [r] range_end_hton
|
67
|
+
# The ending IP address of the ASN range, but in network byte-order.
|
68
|
+
#
|
69
|
+
# @return [String]
|
70
|
+
attribute :range_end_hton, :binary
|
71
|
+
|
72
|
+
before_save :set_hton
|
73
|
+
|
74
|
+
# @!attribute [rw] number
|
75
|
+
# The ASN number.
|
76
|
+
#
|
77
|
+
# @return [Integer]
|
78
|
+
attribute :number, :integer
|
79
|
+
validates :number, presence: true,
|
80
|
+
uniqueness: {scope: [:range_start, :range_end]}
|
81
|
+
|
82
|
+
# @!attribute [rw] country_code
|
83
|
+
# The country code of the ASN.
|
84
|
+
#
|
85
|
+
# @return [String]
|
86
|
+
attribute :country_code, :string
|
87
|
+
|
88
|
+
# @!attribute [rw] name
|
89
|
+
# The organization the ASN is currently assigned to.
|
90
|
+
#
|
91
|
+
# @return [String]
|
92
|
+
attribute :name, :string
|
93
|
+
|
94
|
+
#
|
95
|
+
# Searches for all IPv4 ASNs.
|
96
|
+
#
|
97
|
+
# @return [Array<ASN>]
|
98
|
+
# The IPv4 ASNs.
|
99
|
+
#
|
100
|
+
# @api public
|
101
|
+
#
|
102
|
+
def self.v4
|
103
|
+
where(version: 4)
|
104
|
+
end
|
105
|
+
|
106
|
+
#
|
107
|
+
# Searches for all IPv6 ASNs.
|
108
|
+
#
|
109
|
+
# @return [Array<ASNs>]
|
110
|
+
# The IPv6 ASNs.
|
111
|
+
#
|
112
|
+
# @api public
|
113
|
+
#
|
114
|
+
def self.v6
|
115
|
+
where(version: 6)
|
116
|
+
end
|
117
|
+
|
118
|
+
#
|
119
|
+
# Searches for all ASNs with the matching AS number.
|
120
|
+
#
|
121
|
+
# @param [Integer] number
|
122
|
+
# The AS number to search for.
|
123
|
+
#
|
124
|
+
# @return [Array<ASN>]
|
125
|
+
#
|
126
|
+
def self.with_number(number)
|
127
|
+
where(number: number)
|
128
|
+
end
|
129
|
+
|
130
|
+
#
|
131
|
+
# Searches for all ASNs with the matching country code.
|
132
|
+
#
|
133
|
+
# @param [String] country_code
|
134
|
+
# The two letter country code to search for.
|
135
|
+
#
|
136
|
+
# @return [Array<ASN>]
|
137
|
+
#
|
138
|
+
def self.with_country_code(country_code)
|
139
|
+
where(country_code: country_code)
|
140
|
+
end
|
141
|
+
|
142
|
+
#
|
143
|
+
# Searches for all ASNs with the matching name.
|
144
|
+
#
|
145
|
+
# @param [String] name
|
146
|
+
# The name to search for.
|
147
|
+
#
|
148
|
+
# @return [Array<ASN>]
|
149
|
+
#
|
150
|
+
def self.with_name(name)
|
151
|
+
where(name: name)
|
152
|
+
end
|
153
|
+
|
154
|
+
#
|
155
|
+
# Queries the ASN that contains the given IP address.
|
156
|
+
#
|
157
|
+
# @param [IPAddr, String] ip
|
158
|
+
#
|
159
|
+
# @return [ASN, nil]
|
160
|
+
#
|
161
|
+
def self.containing_ip(ip)
|
162
|
+
ip = IPAddr.new(ip) unless ip.kind_of?(IPAddr)
|
163
|
+
ip_hton = ip.hton
|
164
|
+
|
165
|
+
range_start_hton = self.arel_table[:range_start_hton]
|
166
|
+
range_end_hton = self.arel_table[:range_end_hton]
|
167
|
+
|
168
|
+
where(range_start_hton.lteq(ip_hton).and(range_end_hton.gteq(ip_hton))).first
|
169
|
+
end
|
170
|
+
|
171
|
+
#
|
172
|
+
# @return [IPAddr, nil]
|
173
|
+
#
|
174
|
+
def range_start_ipaddr
|
175
|
+
@range_start_ipaddr ||= if self.range_start
|
176
|
+
IPAddr.new(self.range_start)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
#
|
181
|
+
# @return [IPAddr, nil]
|
182
|
+
#
|
183
|
+
def range_end_ipaddr
|
184
|
+
@range_end_ipaddr ||= if self.range_end
|
185
|
+
IPAddr.new(self.range_end)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
#
|
190
|
+
# Queries all IP addresses within the ASN IP range.
|
191
|
+
#
|
192
|
+
# @return [Array<IPAddress>]
|
193
|
+
#
|
194
|
+
def ip_addresses
|
195
|
+
IPAddress.between(range_start,range_end)
|
196
|
+
end
|
197
|
+
|
198
|
+
private
|
199
|
+
|
200
|
+
#
|
201
|
+
# Sets the `range_start_hton` and `range_end_hton` attributes.
|
202
|
+
#
|
203
|
+
def set_hton
|
204
|
+
self.range_start_hton = range_start_ipaddr.hton
|
205
|
+
self.range_end_hton = range_end_ipaddr.hton
|
206
|
+
end
|
207
|
+
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
require 'ronin/db/ip_address'
|