fidius-evasiondb 0.0.1
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.
- data/.gitignore +9 -0
- data/.yardopts +6 -0
- data/Gemfile +5 -0
- data/LICENSE +57 -0
- data/README.md +180 -0
- data/Rakefile +33 -0
- data/bin/fidius-evasiondb +111 -0
- data/evasion-db.gemspec +37 -0
- data/lib/db/db-install.rb +103 -0
- data/lib/db/migrations/001_create_packets.rb +18 -0
- data/lib/db/migrations/002_create_idmef_events.rb +23 -0
- data/lib/db/migrations/003_create_attack_modules.rb +14 -0
- data/lib/db/migrations/004_create_attack_options.rb +14 -0
- data/lib/db/migrations/005_create_attack_payloads.rb +13 -0
- data/lib/evasion-db/base.rb +80 -0
- data/lib/evasion-db/idmef-fetchers/fetchers.rb +67 -0
- data/lib/evasion-db/idmef-fetchers/prelude-db/fetcher.rb +8 -0
- data/lib/evasion-db/idmef-fetchers/prelude-db/lib/models/additional_data.rb +16 -0
- data/lib/evasion-db/idmef-fetchers/prelude-db/lib/models/address.rb +8 -0
- data/lib/evasion-db/idmef-fetchers/prelude-db/lib/models/alert.rb +46 -0
- data/lib/evasion-db/idmef-fetchers/prelude-db/lib/models/analyzer.rb +18 -0
- data/lib/evasion-db/idmef-fetchers/prelude-db/lib/models/classification.rb +10 -0
- data/lib/evasion-db/idmef-fetchers/prelude-db/lib/models/connection.rb +10 -0
- data/lib/evasion-db/idmef-fetchers/prelude-db/lib/models/detect_time.rb +10 -0
- data/lib/evasion-db/idmef-fetchers/prelude-db/lib/models/impact.rb +19 -0
- data/lib/evasion-db/idmef-fetchers/prelude-db/lib/models/prelude_event.rb +120 -0
- data/lib/evasion-db/idmef-fetchers/prelude-db/lib/models/service.rb +10 -0
- data/lib/evasion-db/idmef-fetchers/prelude-db/lib/patches/postgres_patch.rb +12 -0
- data/lib/evasion-db/idmef-fetchers/prelude-db/lib/prelude_event_fetcher.rb +67 -0
- data/lib/evasion-db/idmef-fetchers/test-fetcher/fetcher.rb +6 -0
- data/lib/evasion-db/idmef-fetchers/test-fetcher/lib/test_fetcher.rb +19 -0
- data/lib/evasion-db/knowledge/attack_module.rb +41 -0
- data/lib/evasion-db/knowledge/attack_option.rb +12 -0
- data/lib/evasion-db/knowledge/attack_payload.rb +13 -0
- data/lib/evasion-db/knowledge/connection.rb +7 -0
- data/lib/evasion-db/knowledge/idmef_event.rb +21 -0
- data/lib/evasion-db/knowledge/packet.rb +17 -0
- data/lib/evasion-db/knowledge.rb +128 -0
- data/lib/evasion-db/log_matches_helper.rb +43 -0
- data/lib/evasion-db/recorders/msf-recorder/lib/msf-recorder.rb +78 -0
- data/lib/evasion-db/recorders/msf-recorder/recorder.rb +6 -0
- data/lib/evasion-db/recorders/recorders.rb +61 -0
- data/lib/evasion-db/version.rb +5 -0
- data/lib/fidius-evasiondb.rb +27 -0
- data/lib/msf-plugins/database.yml.example +24 -0
- data/lib/msf-plugins/evasiondb.rb +378 -0
- data/test/config/database.yml +11 -0
- data/test/config/prelude.sql +439 -0
- data/test/helper.rb +50 -0
- data/test/preludedb_helper.rb +70 -0
- data/test/test_fetchers.rb +34 -0
- data/test/test_knowledge.rb +102 -0
- data/test/test_preludedb.rb +41 -0
- data/test/test_recorders.rb +115 -0
- metadata +238 -0
@@ -0,0 +1,128 @@
|
|
1
|
+
module FIDIUS
|
2
|
+
module EvasionDB
|
3
|
+
# This module provides active-record classes for the knowledge database.
|
4
|
+
# Some handy query methods are also available.
|
5
|
+
module Knowledge
|
6
|
+
# used in find_events_for_exploit
|
7
|
+
# to indicate that the exploit with minimal events should be searched
|
8
|
+
MIN_EVENTS = 1
|
9
|
+
# used in find_events_for_exploit
|
10
|
+
# to indicate that the exploit with maximal events should be searched
|
11
|
+
MAX_EVENTS = 2
|
12
|
+
|
13
|
+
autoload :AttackModule, 'evasion-db/knowledge/attack_module'
|
14
|
+
autoload :AttackOption, 'evasion-db/knowledge/attack_option'
|
15
|
+
autoload :AttackPayload, 'evasion-db/knowledge/attack_payload'
|
16
|
+
autoload :Connection, 'evasion-db/knowledge/connection'
|
17
|
+
autoload :IdmefEvent, 'evasion-db/knowledge/idmef_event'
|
18
|
+
autoload :Packet, 'evasion-db/knowledge/packet'
|
19
|
+
|
20
|
+
# returns all modules(exploits) in knowledge database
|
21
|
+
def self.get_exploits
|
22
|
+
AttackModule.all
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.get_exploit(id)
|
26
|
+
AttackModule.find(id)
|
27
|
+
end
|
28
|
+
|
29
|
+
# finds a packet within an id
|
30
|
+
#
|
31
|
+
#@param [integer] packet id
|
32
|
+
def self.get_packet(id)
|
33
|
+
Packet.find(id)
|
34
|
+
end
|
35
|
+
|
36
|
+
# returns all idmef-events
|
37
|
+
def self.get_events
|
38
|
+
IdmefEvent.all
|
39
|
+
end
|
40
|
+
|
41
|
+
# return an certain event
|
42
|
+
#
|
43
|
+
#@param [integer] event id
|
44
|
+
def self.get_event(event_id)
|
45
|
+
IdmefEvent.find(event_id)
|
46
|
+
end
|
47
|
+
|
48
|
+
# returns a certain packet
|
49
|
+
#
|
50
|
+
#@param [integer] packet id
|
51
|
+
def self.get_packet(pid)
|
52
|
+
Packet.find(pid)
|
53
|
+
end
|
54
|
+
|
55
|
+
# returns all exploits for the given service
|
56
|
+
#
|
57
|
+
#@param [integer] port
|
58
|
+
def self.find_exploits_for_service(port)
|
59
|
+
option_set = AttackOption.where(:option_key => "RPORT",
|
60
|
+
:option_value => port)
|
61
|
+
exploits = []
|
62
|
+
option_set.each { |opt| exploits << opt.attack_module }
|
63
|
+
exploits
|
64
|
+
end
|
65
|
+
|
66
|
+
# returns the packets which might be responsible for the given event
|
67
|
+
#
|
68
|
+
# @param [integer] event id
|
69
|
+
def self.get_packet_for_event(event_id)
|
70
|
+
event = IdmefEvent.find(event_id)
|
71
|
+
FIDIUS::EvasionDB::LogMatchesHelper.find_packets_for_event(event,Packet.all)
|
72
|
+
end
|
73
|
+
|
74
|
+
# find out the events raised by the given payload
|
75
|
+
#
|
76
|
+
#@param [string] payload
|
77
|
+
def self.get_events_for_payload(payload)
|
78
|
+
#TODO: Search all packets which belong to this event
|
79
|
+
events = []
|
80
|
+
search_payload = FIDIUS::EvasionDB::LogMatchesHelper.to_hex(payload)
|
81
|
+
IdmefEvent.find_each do |event|
|
82
|
+
event_payload = FIDIUS::EvasionDB::LogMatchesHelper.to_hex(event.payload)
|
83
|
+
events << event if event_payload.include?(search_payload)
|
84
|
+
end
|
85
|
+
|
86
|
+
events
|
87
|
+
end
|
88
|
+
|
89
|
+
# find events for an module(exploit). you can restrict your results by setting options
|
90
|
+
# which sould be used by the exploit. You can even determine if minimal or maximal size of
|
91
|
+
# events should be returned
|
92
|
+
#
|
93
|
+
#@param [string] exploit/module name
|
94
|
+
#@param [hash] options which should be used
|
95
|
+
#@param [integer] MIN_EVENTS||MAX_EVENTS
|
96
|
+
def self.find_events_for_exploit(name,options={},result = MIN_EVENTS)
|
97
|
+
attacks = AttackModule.find_all_by_name(name).delete_if do |attack|
|
98
|
+
!attack.has_options(options)
|
99
|
+
end
|
100
|
+
|
101
|
+
if attacks.size > 0
|
102
|
+
res = nil
|
103
|
+
if result == MIN_EVENTS
|
104
|
+
min_cnt = 1073741823 #max value
|
105
|
+
attacks.each do |attack|
|
106
|
+
events_cnt = attack.idmef_events.size
|
107
|
+
if events_cnt < min_cnt
|
108
|
+
min_cnt = events_cnt
|
109
|
+
res = attack
|
110
|
+
end
|
111
|
+
end
|
112
|
+
elsif result == MAX_EVENTS
|
113
|
+
min_cnt = 0 #min value
|
114
|
+
attacks.each do |attack|
|
115
|
+
events_cnt = attack.idmef_events.size
|
116
|
+
if events_cnt > min_cnt
|
117
|
+
min_cnt = events_cnt
|
118
|
+
res = attack
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
return res.idmef_events if result
|
123
|
+
end
|
124
|
+
nil
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module FIDIUS
|
2
|
+
module EvasionDB
|
3
|
+
# This helper is indented to find matches between logged packets and idmef-events
|
4
|
+
# by comparing their payload.
|
5
|
+
module LogMatchesHelper
|
6
|
+
|
7
|
+
# this method is from Rex::Text of metasploit
|
8
|
+
def self.to_hex(str, prefix = "\\x", count = 1)
|
9
|
+
raise ::RuntimeError, "unable to chunk into #{count} byte chunks" if ((str.length % count) > 0)
|
10
|
+
|
11
|
+
# XXX: Regexp.new is used here since using /.{#{count}}/o would compile
|
12
|
+
# the regex the first time it is used and never check again. Since we
|
13
|
+
# want to know how many to capture on every instance, we do it this
|
14
|
+
# way.
|
15
|
+
return str.unpack('H*')[0].gsub(Regexp.new(".{#{count * 2}}", nil, 'n')) { |s| prefix + s }
|
16
|
+
end
|
17
|
+
|
18
|
+
# tries to find the packet which generated the given event
|
19
|
+
#
|
20
|
+
#@param [IdmefEvent] a certain idmef event
|
21
|
+
#@param [Array] Array of Packet
|
22
|
+
#@return [hash] {:packet=>:index,:length} index and length are indicating where the match between both payloads is.
|
23
|
+
def self.find_packets_for_event(event,packets)
|
24
|
+
event_payload = nil
|
25
|
+
return unless event.payload
|
26
|
+
if event.payload.size > 0
|
27
|
+
event_payload = self.to_hex(event.payload).gsub("\\x","")
|
28
|
+
end
|
29
|
+
return unless event_payload
|
30
|
+
|
31
|
+
packets.each do |packet|
|
32
|
+
str = nil
|
33
|
+
# lets find the payload of the prelude event
|
34
|
+
# in one of the logged payloads
|
35
|
+
packet_payload = self.to_hex(packet.payload).gsub("\\x","")
|
36
|
+
str = packet_payload[event_payload]
|
37
|
+
return {:packet=>packet,:index=>packet.payload.index(event.payload),:length=>event.payload.size} if str != nil
|
38
|
+
end
|
39
|
+
nil
|
40
|
+
end
|
41
|
+
end#module LogMatchesHelper
|
42
|
+
end#module EvasionDB
|
43
|
+
end#module FIDIUS
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module FIDIUS
|
2
|
+
module EvasionDB
|
3
|
+
# This recorder provides an interface for the metasploit console
|
4
|
+
# it is used to have callbacks when modules are executed.
|
5
|
+
#
|
6
|
+
# @see {file:msf-plugins/evasiondb.rb}
|
7
|
+
module MsfRecorder
|
8
|
+
def module_started(module_instance)
|
9
|
+
@@current_exploit = FIDIUS::EvasionDB::Knowledge::AttackModule.find_or_create_by_name_and_options(module_instance.fullname,module_instance.datastore)
|
10
|
+
FIDIUS::EvasionDB.current_fetcher.begin_record
|
11
|
+
end
|
12
|
+
|
13
|
+
def module_completed(module_instance)
|
14
|
+
begin
|
15
|
+
# TODO: refactor this
|
16
|
+
if module_instance.datastore["RHOST"]
|
17
|
+
FIDIUS::EvasionDB.current_fetcher.local_ip = FIDIUS::Common.get_my_ip(module_instance.datastore["RHOST"])
|
18
|
+
end
|
19
|
+
if module_instance.datastore["RHOSTS"]
|
20
|
+
FIDIUS::EvasionDB.current_fetcher.local_ip = FIDIUS::Common.get_my_ip(module_instance.datastore["RHOSTS"])
|
21
|
+
end
|
22
|
+
unless @@current_exploit.finished
|
23
|
+
$logger.debug("module #{module_instance} finished")
|
24
|
+
idmef_events = FIDIUS::EvasionDB.current_fetcher.fetch_events(module_instance)
|
25
|
+
$logger.debug("found #{idmef_events.size} events")
|
26
|
+
idmef_events.each do |idmef_event|
|
27
|
+
if module_instance && module_instance.respond_to?("fullname")
|
28
|
+
$logger.debug "idmef_events << #{idmef_event}"
|
29
|
+
@@current_exploit.idmef_events << idmef_event
|
30
|
+
# meterpreter is not a module and does not respond to fullname
|
31
|
+
# we handle this seperatly
|
32
|
+
elsif module_instance == "Meterpreter"
|
33
|
+
$logger.debug "attack_payload.idmef_events << #{idmef_event}"
|
34
|
+
@@current_exploit.attack_payload.idmef_events << idmef_event
|
35
|
+
end
|
36
|
+
end
|
37
|
+
@@current_exploit.finished = true
|
38
|
+
@@current_exploit.save
|
39
|
+
end
|
40
|
+
rescue
|
41
|
+
$logger.error $!.message+":"+$!.backtrace.to_s
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def module_error(module_instance,exception)
|
46
|
+
module_completed(module_instance)
|
47
|
+
end
|
48
|
+
|
49
|
+
def log_packet(module_instance,data,socket)
|
50
|
+
begin
|
51
|
+
# set local ip, if there is no
|
52
|
+
#FIDIUS::EvasionDB.current_fetcher.local_ip = FIDIUS::Common.get_my_ip(socket.peerhost)
|
53
|
+
$logger.debug "logged module_instance: #{module_instance} with #{data.size} bytes payload"
|
54
|
+
# TODO: what shall we do with meterpreter?
|
55
|
+
# it has not options and no fullname, logger assigns only the string "meterpreter"
|
56
|
+
if module_instance.respond_to?("fullname")
|
57
|
+
unless @@current_exploit.finished
|
58
|
+
@@current_exploit.packets << FIDIUS::EvasionDB::Knowledge::Packet.create(:payload=>data,:src_addr=>socket.localhost,:src_port=>socket.localport,:dest_addr=>socket.peerhost,:dest_port=>socket.peerport)
|
59
|
+
@@current_exploit.save
|
60
|
+
end
|
61
|
+
# meterpreter is not a module and does not respond to fullname
|
62
|
+
# we handle this seperatly
|
63
|
+
elsif module_instance == "Meterpreter"
|
64
|
+
$logger.debug "module_instance is meterpreter"
|
65
|
+
$logger.debug "putting package to attack_payload"
|
66
|
+
@@current_exploit.attack_payload.packets << FIDIUS::EvasionDB::Knowledge::Packet.create(:payload=>data,:src_addr=>socket.localhost,:src_port=>socket.localport,:dest_addr=>socket.peerhost,:dest_port=>socket.peerport)
|
67
|
+
@@current_exploit.save
|
68
|
+
end
|
69
|
+
$logger.debug "LOG: #{module_instance} #{data.size} Bytes on #{socket}"
|
70
|
+
rescue ActiveRecord::StatementInvalid
|
71
|
+
$logger.error "StatementInvalid"
|
72
|
+
rescue
|
73
|
+
$logger.error "error:" # "#{$!.message}" ##{$!.inspect}:#{$!.backtrace}"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module FIDIUS
|
2
|
+
module EvasionDB
|
3
|
+
def self.recorder(name,&block)
|
4
|
+
FIDIUS::EvasionDB::Recorder.new(name,&block)
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.install_recorders
|
8
|
+
$logger.debug "installing recoders"
|
9
|
+
FIDIUS::EvasionDB::Recorder.all.each do |recorder|
|
10
|
+
recorder.run_install
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# A Recorder us used to log packets for an executed attack
|
15
|
+
class Recorder
|
16
|
+
@@recorders = []
|
17
|
+
attr_accessor :name
|
18
|
+
|
19
|
+
def initialize(name,&block)
|
20
|
+
self.instance_eval(&block)
|
21
|
+
@name = name
|
22
|
+
@@recorders << self
|
23
|
+
end
|
24
|
+
|
25
|
+
def install(&block)
|
26
|
+
$logger.debug "setting installblock"
|
27
|
+
@install = block
|
28
|
+
end
|
29
|
+
|
30
|
+
def run_install
|
31
|
+
raise "no install block given" unless @install
|
32
|
+
$logger.debug "run install of #{@name}"
|
33
|
+
@install.call
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.all
|
37
|
+
@@recorders
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.by_name(name)
|
41
|
+
self.all.each do |recorder|
|
42
|
+
return recorder if recorder.name == name
|
43
|
+
end
|
44
|
+
nil
|
45
|
+
end
|
46
|
+
|
47
|
+
def start
|
48
|
+
raise "overwrite this"
|
49
|
+
end
|
50
|
+
|
51
|
+
def log_packet
|
52
|
+
raise "overwrite this"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
Dir[File.join(File.dirname(__FILE__), "*/recorder.rb")].each{|fetch_require|
|
59
|
+
$logger.debug "load #{fetch_require}"
|
60
|
+
require fetch_require
|
61
|
+
}
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'logger'
|
4
|
+
require 'fidius-common'
|
5
|
+
require 'active_record'
|
6
|
+
require 'evasion-db/base'
|
7
|
+
|
8
|
+
module FIDIUS
|
9
|
+
module EvasionDB
|
10
|
+
$logger = Logger.new(STDOUT)
|
11
|
+
$logger.level = Logger::ERROR
|
12
|
+
GEM_BASE = File.expand_path('..', __FILE__)
|
13
|
+
$logger.debug "GEM_BASE ist: #{GEM_BASE}"
|
14
|
+
|
15
|
+
autoload :VERSION, 'evasion-db/version'
|
16
|
+
autoload :LogMatchesHelper, 'evasion-db/log_matches_helper'
|
17
|
+
autoload :Knowledge, 'evasion-db/knowledge'
|
18
|
+
|
19
|
+
# install fetchers
|
20
|
+
require File.join(GEM_BASE, 'evasion-db', 'idmef-fetchers', 'fetchers.rb')
|
21
|
+
FIDIUS::EvasionDB.install_fetchers
|
22
|
+
|
23
|
+
# install recorders
|
24
|
+
require File.join(GEM_BASE, 'evasion-db', 'recorders', 'recorders.rb')
|
25
|
+
FIDIUS::EvasionDB.install_recorders
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
ids_db:
|
2
|
+
adapter: postgresql
|
3
|
+
host: 10.10.10.253
|
4
|
+
port: 5432
|
5
|
+
encoding: utf8
|
6
|
+
database: preludemanager
|
7
|
+
username: preludemanager
|
8
|
+
password: fidius09
|
9
|
+
read_timeout: 1
|
10
|
+
write_timeout: 1
|
11
|
+
wait_timeout: 1
|
12
|
+
timeout: 1
|
13
|
+
pool: 1
|
14
|
+
retry: 3
|
15
|
+
|
16
|
+
evasion_db:
|
17
|
+
adapter: mysql2
|
18
|
+
host: localhost
|
19
|
+
port: 3306
|
20
|
+
encoding: utf8
|
21
|
+
database: evasion_db
|
22
|
+
username: root
|
23
|
+
password:
|
24
|
+
socket: /opt/lampp/var/mysql/mysql.sock
|