metasploit_data_models 0.16.4-java → 0.16.5-java
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.
@@ -3,20 +3,98 @@
|
|
3
3
|
class EnforceAddressUniquenessInWorkspaceInHosts < ActiveRecord::Migration
|
4
4
|
TABLE_NAME = :hosts
|
5
5
|
|
6
|
+
# maps Table -> Association Column for models that "belong to" a Host
|
7
|
+
HOST_ASSOCIATION_MAP = {
|
8
|
+
'clients' => 'host_id',
|
9
|
+
'events' => 'host_id',
|
10
|
+
'exploit_attempts' => 'host_id',
|
11
|
+
'exploited_hosts' => 'host_id',
|
12
|
+
'host_details' => 'host_id',
|
13
|
+
'hosts_tags' => 'host_id',
|
14
|
+
'loots' => 'host_id',
|
15
|
+
'notes' => 'host_id',
|
16
|
+
'sessions' => 'host_id',
|
17
|
+
'services' => 'host_id',
|
18
|
+
'vulns' => 'host_id'
|
19
|
+
}
|
20
|
+
|
21
|
+
# Historically there a few scenarios where a user could end up with Hosts
|
22
|
+
# in the same workspace with the same IP. Primarily, if you run a Nexpose Scan
|
23
|
+
# and a Discover scan simultaneously, AR does not know about these separate
|
24
|
+
# transactions, so the Hosts will be valid when added and the user will end up
|
25
|
+
# (when transaction completes) with two hosts with the same IP in the same workspace.
|
26
|
+
#
|
27
|
+
# Since we are adding a DB uniq constraint here, this migration could fail if the user
|
28
|
+
# has hit aforementioned scenarios. So we try to "merge" any hosts with the same
|
29
|
+
# address in the same workspace before adding the DB constraint, to prevent the
|
30
|
+
# migration from simply failing.
|
31
|
+
#
|
32
|
+
# Note: We can't rely on AR directly here (or in any migration), since we have no
|
33
|
+
# idea what version of the code the user has checked out. So we fall back to SQL :(
|
34
|
+
def find_and_merge_duplicate_hosts!
|
35
|
+
# find all duplicate addresses within the same workspace currently in the db
|
36
|
+
dupe_addresses_and_workspaces = ActiveRecord::Base.connection.execute(%Q{
|
37
|
+
SELECT workspace_id, address, count_addr
|
38
|
+
FROM (
|
39
|
+
SELECT workspace_id, address, COUNT(address) AS count_addr
|
40
|
+
FROM hosts
|
41
|
+
GROUP BY address, workspace_id
|
42
|
+
) X
|
43
|
+
WHERE count_addr > 1
|
44
|
+
})
|
45
|
+
|
46
|
+
if dupe_addresses_and_workspaces.present? and
|
47
|
+
not dupe_addresses_and_workspaces.num_tuples.zero?
|
48
|
+
puts "Duplicate hosts in workspace found. Merging host references."
|
49
|
+
# iterate through the duped IPs
|
50
|
+
dupe_addresses_and_workspaces.each do |result|
|
51
|
+
# so its come to this
|
52
|
+
address = ActiveRecord::Base.connection.quote(result['address'])
|
53
|
+
workspace_id = result['workspace_id'].to_i
|
54
|
+
# look up the duplicate Host table entries to find all IDs of the duped Hosts
|
55
|
+
hosts = ActiveRecord::Base.connection.execute(%Q|
|
56
|
+
SELECT id
|
57
|
+
FROM hosts
|
58
|
+
WHERE address=#{address} AND workspace_id=#{workspace_id}
|
59
|
+
ORDER BY id DESC
|
60
|
+
|)
|
61
|
+
# grab and quote the ID for each result row
|
62
|
+
hosts = hosts.map { |h| h["id"].to_i }
|
63
|
+
# grab every Host entry besides the first one
|
64
|
+
first_host_id = hosts.first
|
65
|
+
dupe_host_ids = hosts[1..-1]
|
66
|
+
# update associations to these duplicate Hosts
|
67
|
+
HOST_ASSOCIATION_MAP.each do |table, column|
|
68
|
+
ActiveRecord::Base.connection.execute(%Q|
|
69
|
+
UPDATE #{table} SET #{column}=#{first_host_id}
|
70
|
+
WHERE #{column} IN (#{dupe_host_ids.join(',')})
|
71
|
+
|)
|
72
|
+
end
|
73
|
+
# destroy the duplicate host rows
|
74
|
+
ActiveRecord::Base.connection.execute(%Q|
|
75
|
+
DELETE FROM hosts WHERE id IN (#{dupe_host_ids.join(',')})
|
76
|
+
|)
|
77
|
+
end
|
78
|
+
|
79
|
+
# At this point all duped hosts in the same workspace should be merged.
|
80
|
+
# You could end up with duplicate services, but hey its better than just
|
81
|
+
# dropping all data about the old Host.
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
6
85
|
# Restores old index on address
|
7
86
|
def down
|
8
87
|
change_table TABLE_NAME do |t|
|
9
88
|
t.remove_index [:workspace_id, :address]
|
10
|
-
|
11
89
|
t.index :address
|
12
90
|
end
|
13
91
|
end
|
14
92
|
|
15
93
|
# Make index on address scope to workspace_id and be unique
|
16
94
|
def up
|
95
|
+
find_and_merge_duplicate_hosts!
|
17
96
|
change_table TABLE_NAME do |t|
|
18
97
|
t.remove_index :address
|
19
|
-
|
20
98
|
t.index [:workspace_id, :address], :unique => true
|
21
99
|
end
|
22
100
|
end
|
@@ -4,5 +4,5 @@ module MetasploitDataModels
|
|
4
4
|
# metasploit-framework/data/sql/migrate to db/migrate in this project, not all models have specs that verify the
|
5
5
|
# migrations (with have_db_column and have_db_index) and certain models may not be shared between metasploit-framework
|
6
6
|
# and pro, so models may be removed in the future. Because of the unstable API the version should remain below 1.0.0
|
7
|
-
VERSION = '0.16.
|
7
|
+
VERSION = '0.16.5'
|
8
8
|
end
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: metasploit_data_models
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.16.
|
5
|
+
version: 0.16.5
|
6
6
|
platform: java
|
7
7
|
authors:
|
8
8
|
- Samuel Huckins
|
@@ -12,7 +12,7 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date: 2013-07-
|
15
|
+
date: 2013-07-16 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: rake
|