Class: MigrateCredData

Inherits:
ActiveRecord::Migration
  • Object
show all
Defined in:
db/migrate/20100819123300_migrate_cred_data.rb

Class Method Summary collapse

Class Method Details

.downObject

Raises:

  • (ActiveRecord::IrreversibleMigration)


149
150
151
# File 'db/migrate/20100819123300_migrate_cred_data.rb', line 149

def self.down
	raise ActiveRecord::IrreversibleMigration
end

.upObject



3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'db/migrate/20100819123300_migrate_cred_data.rb', line 3

def self.up
	begin # Wrap the whole thing in a giant rescue.
	skipped_notes = []
	new_creds = []
	Mdm::Note.find(:all).each do |note|
		next unless note.ntype[/^auth\.(.*)/]
		service_name = $1
		if !service_name
			skipped_notes << note
			next
		end
		if note.host and note.host.respond_to?(:address)
			if note.service
				svc_id = note.service.id
			else
				candidate_services = []
				note.host.services.each do |service|
					if service.name == service_name
						candidate_services << service
					end
				end
				# Use the default port, or the first port that matches the protocol name.
				default_port = case service_name.downcase
					when 'ftp'; 21
					when /^smb/; 445
					when /^imap/; 143
					when 'telnet'; 23
					when 'pop3'; 110
					when 'http','domino','axis','wordpress','tomcat'; 80
					when 'tns'; 1521
					when 'snmp'; 161
					when 'mssql'; 1433
					when 'ssh'; 22
					when 'https'; 443
					when 'mysql'; 3306
					when 'db2'; 50000
					when 'postgres'; 5432
					else nil
				end
				if !default_port
					skipped_notes << note
					next
				end
				if candidate_services.size == 1
					svc_id = candidate_services.first.id
				elsif candidate_services.empty?
					Mdm::Service.new do |svc|
						svc.host_id = note.host.id
						svc.port = default_port
						svc.proto = 'tcp'
						svc.state = 'open'
						svc.name = service_name.downcase
						svc.save!
						svc_id = svc.id
					end
				elsif candidate_services.size > 1
					svc_ports = candidate_services.map{|s| s.port}
					if svc_ports.index(default_port)
						svc_id = candidate_services[svc_ports.index(default_port)].id
					else
						svc_id = candidate_services.first.id
					end
				end
			end
		else
			skipped_notes << note
			next
		end
		if note.data[:hash]
			ptype = 'smb_hash'
			pass = note.data[:hash]
		elsif note.data[:ssh_key]
			ptype = 'ssh_key'
			pass = note.data[:extra]
		else
			ptype = 'password'
			pass = note.data[:pass]
		end
		# Format domains and databases into the usernames.
		if note.ntype == "auth.smb_challenge"
			domain = note.data[:extra].match(/DOMAIN=([^\s]+)/)[1]
			if domain
				user = [domain, note.data[:user]].join("/")
			else
				user = note.data[:user]
			end
		elsif note.ntype =~ /auth\.(postgres|db2)/
			if note.data[:database]
				user = [note.data[:database], note.data[:user]].join("/")
			else
				user = note.data[:user]
			end
		else
			user = note.data[:user]
		end
		# Not actually a credentials, convert to migrated notes
		if service_name == 'smb' && note.data[:token]
			skipped_notes << note
			next
		end
		if service_name == 'tns' && note.data[:type] == "bruteforced_sid"
			skipped_notes << note
			next
		end
		# Special case for the bizarre reporting for aux/admin/oracle/oracle_login
		if service_name == 'tns' && note.data[:type] == "bruteforced_account"
			note.data[:data] =~ /([^\x2f]+)\x2f([^\s]+).*with sid (.*)/
			user = "#{$3}/#{$1}"
			pass = $2
		end
		new_creds << [svc_id, ptype, user, pass]
	end

	say "Migrating #{new_creds.size} credentials."
	new_creds.uniq.each do |note|
		Mdm::Cred.new do |cred|
			cred.service_id = note[0]
			cred.user = note[2]
			cred.pass = note[3]
			cred.ptype = note[1]
			cred.save!
		end
	end

	say "Migrating #{skipped_notes.size} notes."
	skipped_notes.uniq.each do |note|
		Mdm::Note.new do |new_note|
			new_note.host_id = note.host_id
			new_note.ntype = "migrated_auth"
			new_note.data = note.data.merge(:migrated_auth_type => note.ntype)
			new_note.save!
		end
	end

	say "Deleting migrated auth notes."
	Mdm::Note.find(:all).each do |note|
		next unless note.ntype[/^auth\.(.*)/]
		note.delete
	end
	rescue 
		say "There was a problem migrating auth credentials. Skipping."
		return true # Never fail!
	end
end