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