thm 0.1.8
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.
- checksums.yaml +7 -0
- data/README.1ST +38 -0
- data/README.md +59 -0
- data/bin/thm-consumer +89 -0
- data/bin/thm-pcap +67 -0
- data/bin/thm-producer +102 -0
- data/bin/thm-session +319 -0
- data/bin/thm-useradmin +75 -0
- data/config.rb +30 -0
- data/datalayerlight.rb +143 -0
- data/js/JSXTransformer.js +15919 -0
- data/js/chartkick.js +829 -0
- data/js/files/authenticate.jsx +30 -0
- data/js/jquery.min.js +5 -0
- data/js/marked.min.js +6 -0
- data/js/react.js +19602 -0
- data/lib/thm.rb +49 -0
- data/lib/thm/consumer.rb +228 -0
- data/lib/thm/dataservices.rb +73 -0
- data/lib/thm/localmachine.rb +170 -0
- data/lib/thm/producer.rb +198 -0
- data/lib/thm/version.rb +14 -0
- data/service_definitions.csv +6366 -0
- data/sql/geoipdata-monetdb.sql +111 -0
- data/sql/threatmonitor-monetdb.sql +174 -0
- data/sql/threatmonitor-mysql.sql +156 -0
- data/stylesheets/screen.css +150 -0
- data/thm-authentication.rb +65 -0
- data/thm-authorization.rb +173 -0
- data/thm-privileges.rb +97 -0
- data/views/authenticate.slim +18 -0
- data/views/dashboard.erb +69 -0
- data/views/logout.slim +10 -0
- metadata +237 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 91428c60a9b74ea883550ea758c66868d9dff5df
|
4
|
+
data.tar.gz: 78114801f27854edd1133d5b9d1852594040fe01
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4669fd20a613c0ebd2434671d1abc5f1eaa8f8177edc0bfd17f572fd014feba1d0d2d0714589117a1054fb9154152b41cdbe11ce02a2503cdd6776eb4b7c4660
|
7
|
+
data.tar.gz: c976aa7fa719c269906e22fdbb2008c4f634e379e13549792c08190592eaa6573e4cd53219b42eddd9294665b1b4b949e1c2fdd17cc4d0155dd719e09f74a769
|
data/README.1ST
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
Threatmonitor Overview
|
2
|
+
======================
|
3
|
+
|
4
|
+
|
5
|
+
Sending data to a RabbitMQ queue so you can grab the data later.
|
6
|
+
|
7
|
+
Please note that the queue prefix -q the queue will end up named wifi_iptables etc ...
|
8
|
+
|
9
|
+
ruby thm-producer.rb -m capture -q wifi
|
10
|
+
|
11
|
+
Loading your data into a database.
|
12
|
+
|
13
|
+
You can change the queue it reads from / databases tables it loads into in the code just make sure you've created the database tables.
|
14
|
+
|
15
|
+
obj = Thm::Consumer.new
|
16
|
+
obj.queueprefix = "wifi"
|
17
|
+
obj.tblname_ippacket = "wifi_ippacket"
|
18
|
+
obj.tblname_tcppacket = "wifi_tcppacket"
|
19
|
+
obj.tblname_udppacket = "wifi_udppacket"
|
20
|
+
|
21
|
+
ruby thm-consumer.rb
|
22
|
+
|
23
|
+
How to load a pcap file.
|
24
|
+
|
25
|
+
obj = Thm::Localmachine.new
|
26
|
+
obj.tblname_ippacket = "wifi_ippacket"
|
27
|
+
obj.tblname_tcppacket = "wifi_tcppacket"
|
28
|
+
obj.tblname_udppacket = "wifi_udppacket"
|
29
|
+
obj.dbconnect
|
30
|
+
|
31
|
+
ruby thm-pcap.rb -f Example2.pcap
|
32
|
+
|
33
|
+
Thats really all the is to it.
|
34
|
+
|
35
|
+
Enjoy!
|
36
|
+
|
37
|
+
Brian Hood
|
38
|
+
|
data/README.md
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
|
2
|
+
Threatmonitor - Packet Analysis suite with MonetDB / MySQL - RabbitMQ & PCap integration
|
3
|
+
|
4
|
+

|
5
|
+
|
6
|
+
Getting Started
|
7
|
+
|
8
|
+
Things you need
|
9
|
+
|
10
|
+
RabbitMQ
|
11
|
+
|
12
|
+
MonetDB or MySQL
|
13
|
+
|
14
|
+
Ruby
|
15
|
+
|
16
|
+
Pcaplet - https://github.com/ahobson/ruby-pcap
|
17
|
+
|
18
|
+
PCAPRUB - https://github.com/puppetpies/pcaprub - For Interface Realtime capture / dumping to disk
|
19
|
+
|
20
|
+

|
21
|
+
|
22
|
+
To build:
|
23
|
+
|
24
|
+
You'll need PCAP / Development Header files
|
25
|
+
|
26
|
+
gem build pcap.gemspec
|
27
|
+
gem install pcap-0.7.7.gem
|
28
|
+
|
29
|
+
GEMS: AMQP, Bunny, Eventmachine, guid, MonetDB, mysql, pcaplet
|
30
|
+
|
31
|
+
This is all experimental but i believe it works well so far.
|
32
|
+
|
33
|
+
Features ability to push pcap data to Message Queue.
|
34
|
+
|
35
|
+
Read data from disk into message queue
|
36
|
+
|
37
|
+
Write data from message queue to disk.
|
38
|
+
|
39
|
+
Allows you to easily move IP / TCP / UDP data with ease and analyze else where
|
40
|
+
|
41
|
+
Creating your database once you've installed MonetDB
|
42
|
+
|
43
|
+
monetdbd create /path/to/dbfarm
|
44
|
+
|
45
|
+
monetdbd start /path/to/dbfarm
|
46
|
+
|
47
|
+
monetdb create threatmonitor
|
48
|
+
|
49
|
+
monetdb release threatmonitor
|
50
|
+
|
51
|
+
monetdb start threatmonitor
|
52
|
+
|
53
|
+
Import the schema from the SQL provided now moved to sql/
|
54
|
+
|
55
|
+
I've now included MySQL Database support also however if your going to create big data sets i think i would use MonetDB
|
56
|
+
|
57
|
+

|
58
|
+
|
59
|
+
Have fun !
|
data/bin/thm-consumer
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
########################################################################
|
3
|
+
#
|
4
|
+
# Author: Brian Hood
|
5
|
+
#
|
6
|
+
# Description: Threatmonitor Consumer
|
7
|
+
#
|
8
|
+
# Producer - Save data from queue to Database
|
9
|
+
#
|
10
|
+
########################################################################
|
11
|
+
#puts Dir.getwd
|
12
|
+
require 'getoptlong'
|
13
|
+
require File.expand_path(File.join(
|
14
|
+
File.dirname(__FILE__),
|
15
|
+
"../lib/thm.rb", "../../config.rb"))
|
16
|
+
|
17
|
+
include Thm::Defaults
|
18
|
+
|
19
|
+
ARGV[0] = "--help" if ARGV[0] == nil
|
20
|
+
|
21
|
+
banner = "\e[1;34mWelcome to Threatmonitor Consumer \e[0m\ \n"
|
22
|
+
banner << "\e[1;34m=================================\e[0m\ \n"
|
23
|
+
|
24
|
+
opts = GetoptLong.new(
|
25
|
+
[ '--help', '-h', GetoptLong::NO_ARGUMENT ],
|
26
|
+
[ '--infinite', '-i', GetoptLong::NO_ARGUMENT ],
|
27
|
+
[ '--passes', '-p', GetoptLong::REQUIRED_ARGUMENT ],
|
28
|
+
[ '--runonce', '-r', GetoptLong::NO_ARGUMENT ]
|
29
|
+
)
|
30
|
+
|
31
|
+
opts.each do |opt, arg|
|
32
|
+
case opt
|
33
|
+
when '--help'
|
34
|
+
helper = %q[
|
35
|
+
-h, --help:
|
36
|
+
show help
|
37
|
+
|
38
|
+
-i, --infinite [ For consuming live captures ]
|
39
|
+
|
40
|
+
-p, --passes number of passes [ For medium / larger queues ]
|
41
|
+
|
42
|
+
-r, --runonce [ Just as it says ]
|
43
|
+
|
44
|
+
NOTES:
|
45
|
+
|
46
|
+
Press CTRL+C to exit Reactor thread at anytime to move on to next queue.
|
47
|
+
There are currently 3 queues ippacket, tcppacket, udppacket
|
48
|
+
|
49
|
+
]
|
50
|
+
puts banner
|
51
|
+
puts helper
|
52
|
+
exit
|
53
|
+
when '--infinite'
|
54
|
+
@infinite = arg
|
55
|
+
when '--passes'
|
56
|
+
@passes = arg
|
57
|
+
when '--runonce'
|
58
|
+
@runonce = arg
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
puts banner
|
63
|
+
# See thmmq.rb for list for variables
|
64
|
+
obj = Thm::Consumer.new
|
65
|
+
obj.datastore = DATASTORE
|
66
|
+
obj.mqhost = MQHOST
|
67
|
+
obj.mquser = MQUSER
|
68
|
+
obj.mqpass = MQPASS
|
69
|
+
obj.mqvhost = MQVHOST
|
70
|
+
obj.dbhost = DBHOST
|
71
|
+
obj.dbuser = DBUSER
|
72
|
+
obj.dbpass = DBPASS
|
73
|
+
obj.dbname = DBNAME
|
74
|
+
obj.queueprefix = QUEUEPREFIX
|
75
|
+
obj.tblname_ippacket = TBLNAME_IPPACKET
|
76
|
+
obj.tblname_tcppacket = TBLNAME_TCPPACKET
|
77
|
+
obj.tblname_udppacket = TBLNAME_UDPPACKET
|
78
|
+
obj.mqconnect
|
79
|
+
obj.dbconnect
|
80
|
+
# Send data to database from queue
|
81
|
+
if @infinite.nil? == false
|
82
|
+
obj.infinite
|
83
|
+
elsif @passes.nil? == false
|
84
|
+
obj.passes(@passes.to_i)
|
85
|
+
elsif @runonce.nil? == false
|
86
|
+
obj.from_mq_to_db
|
87
|
+
end
|
88
|
+
obj.mqclose
|
89
|
+
|
data/bin/thm-pcap
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
########################################################################
|
3
|
+
#
|
4
|
+
# Author: Brian Hood
|
5
|
+
#
|
6
|
+
# Description: Threatmonitor Pcap
|
7
|
+
#
|
8
|
+
# Producer - Save data from Pcap file(s) to Database
|
9
|
+
#
|
10
|
+
########################################################################
|
11
|
+
|
12
|
+
require 'getoptlong'
|
13
|
+
require File.expand_path(File.join(
|
14
|
+
File.dirname(__FILE__),
|
15
|
+
"../lib/thm.rb", "../../config.rb"))
|
16
|
+
|
17
|
+
include Thm::Defaults
|
18
|
+
|
19
|
+
ARGV[0] = "--help" if ARGV[0] == nil
|
20
|
+
|
21
|
+
banner = "\e[1;34mWelcome to Threatmonitor PCap Loader \e[0m\ \n"
|
22
|
+
banner << "\e[1;34m===================================\e[0m\ \n"
|
23
|
+
|
24
|
+
opts = GetoptLong.new(
|
25
|
+
[ '--help', '-h', GetoptLong::NO_ARGUMENT ],
|
26
|
+
[ '--pcapfile', '-f', GetoptLong::OPTIONAL_ARGUMENT ]
|
27
|
+
)
|
28
|
+
|
29
|
+
opts.each do |opt, arg|
|
30
|
+
case opt
|
31
|
+
when '--help'
|
32
|
+
helper = %q[
|
33
|
+
-h, --help:
|
34
|
+
show help
|
35
|
+
|
36
|
+
-f, --pcapfile [ REQUIRED ]
|
37
|
+
]
|
38
|
+
puts banner
|
39
|
+
puts helper
|
40
|
+
exit
|
41
|
+
when '--pcapfile'
|
42
|
+
@pcapfile = arg
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
puts banner
|
47
|
+
# See thmmq.rb for list for variables
|
48
|
+
obj = Thm::Localmachine.new
|
49
|
+
obj.datastore = DATASTORE
|
50
|
+
obj.mqhost = MQHOST
|
51
|
+
obj.mquser = MQUSER
|
52
|
+
obj.mqpass = MQPASS
|
53
|
+
obj.mqvhost = MQVHOST
|
54
|
+
obj.dbhost = DBHOST
|
55
|
+
obj.dbuser = DBUSER
|
56
|
+
obj.dbpass = DBPASS
|
57
|
+
obj.dbname = DBNAME
|
58
|
+
obj.queueprefix = QUEUEPREFIX
|
59
|
+
obj.tblname_ippacket = TBLNAME_IPPACKET
|
60
|
+
obj.tblname_tcppacket = TBLNAME_TCPPACKET
|
61
|
+
obj.tblname_udppacket = TBLNAME_UDPPACKET
|
62
|
+
obj.dbconnect
|
63
|
+
# Send data to database from queue
|
64
|
+
if @pcapfile.nil? == false
|
65
|
+
obj.from_pcap_db("#{@pcapfile}")
|
66
|
+
end
|
67
|
+
|
data/bin/thm-producer
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
########################################################################
|
3
|
+
#
|
4
|
+
# Author: Brian Hood
|
5
|
+
#
|
6
|
+
# Description: Threatmonitor Producer
|
7
|
+
#
|
8
|
+
# Producer - Load data Database to RabbitMQ for distrubition or Packet
|
9
|
+
# Trace live data and send to RabbitMQ
|
10
|
+
########################################################################
|
11
|
+
|
12
|
+
require 'getoptlong'
|
13
|
+
require File.expand_path(File.join(
|
14
|
+
File.dirname(__FILE__),
|
15
|
+
"../lib/thm.rb", "../../config.rb"))
|
16
|
+
|
17
|
+
include Thm::Defaults
|
18
|
+
|
19
|
+
ARGV[0] = "--help" if ARGV[0] == nil
|
20
|
+
|
21
|
+
opts = GetoptLong.new(
|
22
|
+
[ '--help', '-h', GetoptLong::NO_ARGUMENT ],
|
23
|
+
[ '--mode', '-m', GetoptLong::REQUIRED_ARGUMENT ],
|
24
|
+
[ '--queueprefix', '-q', GetoptLong::OPTIONAL_ARGUMENT ],
|
25
|
+
[ '--interface', '-i', GetoptLong::REQUIRED_ARGUMENT ],
|
26
|
+
[ '--filter', '-f', GetoptLong::REQUIRED_ARGUMENT ]
|
27
|
+
)
|
28
|
+
|
29
|
+
banner = "\e[1;34mWelcome to Threatmonitor Producer \e[0m\ \n"
|
30
|
+
banner << "\e[1;34m=================================\e[0m\ \n"
|
31
|
+
|
32
|
+
opts.each do |opt, arg|
|
33
|
+
case opt
|
34
|
+
when '--help'
|
35
|
+
helper = %q[
|
36
|
+
-h, --help:
|
37
|
+
show help
|
38
|
+
|
39
|
+
-m, --mode database / capture [ REQUIRED ]
|
40
|
+
|
41
|
+
-q, --queueprefix queue name [ OPTIONAL ] [ Uses config.rb ]
|
42
|
+
|
43
|
+
-i --interface network interface [ REQUIRED ]
|
44
|
+
|
45
|
+
-f --filter your pcap / tcpdump style filter [ OPTIONAL ]
|
46
|
+
]
|
47
|
+
puts banner
|
48
|
+
puts helper
|
49
|
+
exit
|
50
|
+
when '--mode'
|
51
|
+
@modeparam = arg
|
52
|
+
when '--queueprefix'
|
53
|
+
@queueprefix = arg
|
54
|
+
when '--interface'
|
55
|
+
@interface = arg
|
56
|
+
when '--filter'
|
57
|
+
@filter = arg
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
puts banner
|
62
|
+
# See thmmq.rb for list for variables
|
63
|
+
obj = Thm::Producer.new
|
64
|
+
obj.datastore = DATASTORE
|
65
|
+
obj.mqhost = MQHOST
|
66
|
+
obj.mquser = MQUSER
|
67
|
+
obj.mqpass = MQPASS
|
68
|
+
obj.mqvhost = MQVHOST
|
69
|
+
obj.dbhost = DBHOST
|
70
|
+
obj.dbuser = DBUSER
|
71
|
+
obj.dbpass = DBPASS
|
72
|
+
obj.dbname = DBNAME
|
73
|
+
if !defined? @queueprefix
|
74
|
+
obj.queueprefix = QUEUEPREFIX
|
75
|
+
else
|
76
|
+
obj.queueprefix = @queueprefix
|
77
|
+
end
|
78
|
+
obj.tblname_ippacket = TBLNAME_IPPACKET
|
79
|
+
obj.tblname_tcppacket = TBLNAME_TCPPACKET
|
80
|
+
obj.tblname_udppacket = TBLNAME_UDPPACKET
|
81
|
+
obj.mqconnect
|
82
|
+
obj.dbconnect unless @modeparam == "capture"
|
83
|
+
mode = @modeparam
|
84
|
+
|
85
|
+
if mode == "database"
|
86
|
+
# Send data from Database to RabbitMQ for Fanout etc
|
87
|
+
ippacketsql = "SELECT * FROM \"threatmonitor\".#{obj.tblname_ippacket} LIMIT 300 OFFSET 400000"
|
88
|
+
obj.from_db_to_mq(ippacketsql)
|
89
|
+
|
90
|
+
elsif mode == "capture"
|
91
|
+
# From Pcap to RabbitMQ for Fanout etc.
|
92
|
+
#
|
93
|
+
# Standard Pcap / Wireshark filters
|
94
|
+
# 'tcp port not 22 and not arp and udp port not 53 and udp portrange not 67-69 and tcp port not 8443 and host not 78.47.223.130'
|
95
|
+
if %x{id -u}.strip != "0"
|
96
|
+
puts "Require superuser privileges"
|
97
|
+
exit
|
98
|
+
end
|
99
|
+
obj.from_interface_to_mq("#{@interface}", "#{@filter}")
|
100
|
+
#obj.from_pcap_to_mq("wlo1", "tcp port not 22")
|
101
|
+
obj.mqclose
|
102
|
+
end
|
data/bin/thm-session
ADDED
@@ -0,0 +1,319 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
########################################################################
|
3
|
+
#
|
4
|
+
# Author: Brian Hood
|
5
|
+
#
|
6
|
+
# Description: Threatmonitor User Administration / Dashboard
|
7
|
+
# Codename: Deedrah
|
8
|
+
#
|
9
|
+
# Extends the functionality of the Thm module adding Authorization
|
10
|
+
# Adding Session Login / Sinatra / Web Interface functionality
|
11
|
+
#
|
12
|
+
########################################################################
|
13
|
+
|
14
|
+
require 'rubygems' if RUBY_VERSION < "1.9"
|
15
|
+
require 'chartkick'
|
16
|
+
require 'sinatra/base'
|
17
|
+
require 'slim'
|
18
|
+
require 'colorize'
|
19
|
+
|
20
|
+
require File.expand_path(File.join(
|
21
|
+
File.dirname(__FILE__),
|
22
|
+
"../thm-authentication.rb"))
|
23
|
+
|
24
|
+
RELEASE = "Deedrah"
|
25
|
+
|
26
|
+
class Sinatra::Base
|
27
|
+
|
28
|
+
class << self
|
29
|
+
|
30
|
+
def getpost(path, opts={}, &block)
|
31
|
+
get(path, opts, &block)
|
32
|
+
post(path, opts, &block)
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
class Geocounter
|
41
|
+
|
42
|
+
# Create / Add to instance variable
|
43
|
+
def geocount(country)
|
44
|
+
country.gsub!(" ", "_") # no spaces or case
|
45
|
+
if !instance_variable_get("@#{country}")
|
46
|
+
instance_variable_set("@#{country}", 1)
|
47
|
+
else
|
48
|
+
instance_variable_set("@#{country}", instance_variable_get("@#{country}") + 1)
|
49
|
+
end
|
50
|
+
puts "Country: #{country} Value: "+instance_variable_get("@#{country}").to_s
|
51
|
+
end
|
52
|
+
|
53
|
+
# Read a single country
|
54
|
+
def geocount_reader(country)
|
55
|
+
country.gsub!(" ", "_") # no spaces or case
|
56
|
+
valnum = instance_variable_get("@#{country}")
|
57
|
+
return valnum
|
58
|
+
end
|
59
|
+
|
60
|
+
# Compile in array with the totals of all instance variables
|
61
|
+
def geocount_compile
|
62
|
+
countrycounts = Array.new
|
63
|
+
instance_variables.each {|n|
|
64
|
+
t = n.to_s.gsub("@", "")
|
65
|
+
countrycounts << ["#{t}", instance_variable_get("#{n}")]
|
66
|
+
}
|
67
|
+
return countrycounts
|
68
|
+
countrycounts
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
module ThmUI extend self
|
74
|
+
|
75
|
+
class Deedrah < Sinatra::Base
|
76
|
+
|
77
|
+
attr_reader :thmsession
|
78
|
+
|
79
|
+
include Chartkick::Helper
|
80
|
+
|
81
|
+
set :server, :puma
|
82
|
+
set :logging, :true
|
83
|
+
set :app_file, __FILE__
|
84
|
+
|
85
|
+
configure do
|
86
|
+
enable :session
|
87
|
+
end
|
88
|
+
|
89
|
+
before do
|
90
|
+
content_type :html
|
91
|
+
end
|
92
|
+
|
93
|
+
set :title, "Threatmonitor - Packet Analysis Suite #{RELEASE}"
|
94
|
+
set :port, 4567
|
95
|
+
set :bind, "0.0.0.0"
|
96
|
+
# Global helpers
|
97
|
+
#helpers ApplicationHelper
|
98
|
+
|
99
|
+
# Set folders for template to
|
100
|
+
set :root, File.expand_path(File.join(File.dirname(__FILE__), '../'))
|
101
|
+
puts root.green
|
102
|
+
|
103
|
+
templateroot = File.expand_path(File.join(File.dirname(__FILE__), '../views'))
|
104
|
+
set :sessions,
|
105
|
+
:httponly => true,
|
106
|
+
:secure => production?,
|
107
|
+
:expire_after => 3600, # 1 hour
|
108
|
+
#:views => File.expand_path(File.expand_path('../../views/', __FILE__)),
|
109
|
+
:views => Proc.new { File.join(root, "views") },
|
110
|
+
#:layout_engine => :slim,
|
111
|
+
:public_folder => File.dirname(__FILE__) + '/bin'
|
112
|
+
|
113
|
+
enable :method_override
|
114
|
+
|
115
|
+
puts "TemplateRoot: #{templateroot}".to_s
|
116
|
+
def objstart!
|
117
|
+
@sessobj = Thm::Authorization::Authentication.new
|
118
|
+
@sessobj.datastore = "monetdb"
|
119
|
+
@sessobj.dbconnect
|
120
|
+
end
|
121
|
+
|
122
|
+
# NOTE: Monkey patch Sinatra initialize
|
123
|
+
# If you go to /dashboard without logging in @sessobj it won't have been created
|
124
|
+
# So if you create it objstart! in the Sinatra's initialize your sorted.
|
125
|
+
# Page requests will come in a @sessobj will always exist and be the same one no headaches
|
126
|
+
def initialize(app = nil)
|
127
|
+
super()
|
128
|
+
objstart! # Little trick here patch so i can get objstart! out of the box!
|
129
|
+
@app = app
|
130
|
+
@template_cache = Tilt::Cache.new
|
131
|
+
yield self if block_given?
|
132
|
+
end
|
133
|
+
|
134
|
+
def login_session?
|
135
|
+
if @sessobj.login_session? == false
|
136
|
+
puts "Not logged in"
|
137
|
+
else
|
138
|
+
return true
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def get_session_info?
|
143
|
+
puts "Sinatra: #{Sinatra::VERSION} / Thmsession: #{@sessobj.thmsession}"
|
144
|
+
end
|
145
|
+
|
146
|
+
def login(username, password)
|
147
|
+
@sessobj.login("#{username}", "#{password}")
|
148
|
+
if login_session?
|
149
|
+
puts "\e[1;32m\Welcome to Threatmonitor \e[0m\ "
|
150
|
+
puts "Thm Session: #{@sessobj.thmsession}"
|
151
|
+
return true
|
152
|
+
else
|
153
|
+
return false
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def logout
|
158
|
+
@sessobj.thmsesslock = "DEADBEEF"
|
159
|
+
end
|
160
|
+
|
161
|
+
def login_lock?
|
162
|
+
if @sessobj.thmsesslock != "OK"
|
163
|
+
puts "Session doesn't exist redirecting to Login..."
|
164
|
+
redirect '/'
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
# Sinatra routings
|
169
|
+
|
170
|
+
getpost '/' do
|
171
|
+
if params[:submit] != nil
|
172
|
+
@sessthm = login(params[:username], params[:password])
|
173
|
+
end
|
174
|
+
if @sessobj.thmsesslock == "OK"
|
175
|
+
puts "Session created redirecting to Dashboard ..."
|
176
|
+
redirect '/dashboard'
|
177
|
+
end
|
178
|
+
slim :authenticate
|
179
|
+
end
|
180
|
+
|
181
|
+
def geoiplookup(ip)
|
182
|
+
query = "SELECT continent_name, country_name FROM geoipdata_ipv4blocks_country a JOIN geoipdata_locations_country b ON (a.geoname_id = b.geoname_id) WHERE network LIKE '#{ip.split(".")[0]}.#{ip.split(".")[1]}.%' GROUP BY b.continent_name, b.country_name LIMIT 1;"
|
183
|
+
resusrcnt = @sessobj.query("#{query}")
|
184
|
+
while row = resusrcnt.fetch_hash do
|
185
|
+
continent_name = row["continent_name"].to_s
|
186
|
+
country_name = row["country_name"].to_s
|
187
|
+
#if continent_name == ""
|
188
|
+
cname = "(#{country_name})"
|
189
|
+
#else
|
190
|
+
# cname = "(#{continent_name})"
|
191
|
+
#end
|
192
|
+
end
|
193
|
+
# geoipcount(
|
194
|
+
return cname
|
195
|
+
end
|
196
|
+
|
197
|
+
def packetcounts(proto)
|
198
|
+
# Retrieve
|
199
|
+
query = "select count(*) as num2, ip_dst from wifi_ippacket a JOIN wifi_#{proto}packet b on (a.guid = b.guid) JOIN service_definitions s on (s.num = b.#{proto}_dport) where #{proto}_dport > 0 and #{proto}_dport < 10000 and s.protocol = '#{proto.upcase}' and ip_dst not in ('255.255.255.255') group by b.#{proto}_dport, a.ip_dst;"
|
200
|
+
resusrcnt = @sessobj.query("#{query}")
|
201
|
+
rowusrcnt = Array.new
|
202
|
+
@gcnt = Geocounter.new
|
203
|
+
while row = resusrcnt.fetch_hash do
|
204
|
+
num2 = row["num2"].to_s
|
205
|
+
ip_dst = row["ip_dst"].to_s
|
206
|
+
location = geoiplookup(ip_dst)
|
207
|
+
locfix = location.to_s.gsub("(", "").gsub(")", "") # Yawn
|
208
|
+
if location != nil or location == ""
|
209
|
+
@gcnt.geocount("#{locfix}")
|
210
|
+
end
|
211
|
+
rowusrcnt << ["#{ip_dst} #{location}", "#{num2}"]
|
212
|
+
end
|
213
|
+
return rowusrcnt
|
214
|
+
end
|
215
|
+
|
216
|
+
def servicecounts(proto)
|
217
|
+
query = "select num, description, count(*) as num2 from wifi_ippacket a JOIN wifi_#{proto}packet b on (a.guid = b.guid) JOIN service_definitions s on (s.num = b.#{proto}_dport) where #{proto}_dport > 0 and #{proto}_dport < 10000 and s.protocol = '#{proto.upcase}' and ip_dst not in ('255.255.255.255') group by b.#{proto}_dport, a.ip_dst, s.description, s.num;"
|
218
|
+
resusrcnt = @sessobj.query("#{query}")
|
219
|
+
rowusrcnt = Array.new
|
220
|
+
while row = resusrcnt.fetch_hash do
|
221
|
+
num = row["num"].to_s
|
222
|
+
desc = row["description"].to_s
|
223
|
+
count = row["num2"].to_s
|
224
|
+
rowusrcnt << ["#{desc} (#{num})", "#{count}"]
|
225
|
+
end
|
226
|
+
return rowusrcnt
|
227
|
+
end
|
228
|
+
|
229
|
+
def toptalkers(proto)
|
230
|
+
query = "select count(*) as num2, #{proto}_dport, ip_dst from wifi_ippacket a JOIN wifi_#{proto}packet b on (a.guid = b.guid) JOIN service_definitions s on (s.num = b.#{proto}_dport) where #{proto}_dport > 0 and #{proto}_dport < 10000 and s.protocol = '#{proto.upcase}' and ip_dst not in ('255.255.255.255') group by b.#{proto}_dport, a.ip_dst order by num2 desc;"
|
231
|
+
resusrcnt = @sessobj.query("#{query}")
|
232
|
+
rowusrcnt = Array.new
|
233
|
+
while row = resusrcnt.fetch_hash do
|
234
|
+
ip_dst = row["ip_dst"].to_s
|
235
|
+
num = row["#{proto}_dport"].to_s
|
236
|
+
count = row["num2"].to_s
|
237
|
+
location = geoiplookup(ip_dst)
|
238
|
+
rowusrcnt << ["#{ip_dst} #{location} (#{num})", "#{count}"]
|
239
|
+
end
|
240
|
+
return rowusrcnt
|
241
|
+
end
|
242
|
+
|
243
|
+
getpost '/dashboard' do
|
244
|
+
login_lock?
|
245
|
+
# UDP
|
246
|
+
@rowusrcnt = packetcounts("udp")
|
247
|
+
# TCP
|
248
|
+
@rowusrcnt2 = packetcounts("tcp")
|
249
|
+
# Service chart UDP
|
250
|
+
@rowusrcnt3 = servicecounts("udp")
|
251
|
+
# Service chart TCP
|
252
|
+
@rowusrcnt4 = servicecounts("tcp")
|
253
|
+
# Top TCP/IP Talkers
|
254
|
+
@rowusrcnt5 = toptalkers("udp")
|
255
|
+
# Top UDP/IP Talkers
|
256
|
+
@rowusrcnt6 = toptalkers("tcp")
|
257
|
+
@rowgeocount = @gcnt.geocount_compile
|
258
|
+
puts "Geo Data:"
|
259
|
+
@rowgeocount.each {|n, x|
|
260
|
+
puts "#{n} #{x}"
|
261
|
+
}
|
262
|
+
erb :dashboard
|
263
|
+
end
|
264
|
+
|
265
|
+
get '/status' do
|
266
|
+
# Informational / Debug
|
267
|
+
get_session_info?
|
268
|
+
end
|
269
|
+
|
270
|
+
get '/logout' do
|
271
|
+
# Logout and remove thmsesslock
|
272
|
+
if @sessobj.thmsesslock == "OK"
|
273
|
+
logout
|
274
|
+
redirect '/'
|
275
|
+
end
|
276
|
+
slim :logout
|
277
|
+
end
|
278
|
+
|
279
|
+
get '/stylesheets/screen.css' do
|
280
|
+
send_file 'stylesheets/screen.css', :type => :css
|
281
|
+
end
|
282
|
+
|
283
|
+
get '/js/chartkick.js' do
|
284
|
+
send_file 'js/chartkick.js', :type => :js
|
285
|
+
end
|
286
|
+
|
287
|
+
get '/js/jquery.min.js' do
|
288
|
+
send_file 'js/jquery.min.js', :type => :js
|
289
|
+
end
|
290
|
+
|
291
|
+
get '/js/JSXTransformer.js' do
|
292
|
+
send_file 'js/JSXTransformer.js', :type => :js
|
293
|
+
end
|
294
|
+
|
295
|
+
get '/js/marked.min.js' do
|
296
|
+
send_file 'js/marked.min.js', :type => :js
|
297
|
+
end
|
298
|
+
|
299
|
+
get '/js/react.js' do
|
300
|
+
send_file 'js/react.js', :type => :js
|
301
|
+
end
|
302
|
+
|
303
|
+
get '/js/files/authenticate.jsx' do
|
304
|
+
send_file 'js/files/authenticate.jsx', :type => :js
|
305
|
+
end
|
306
|
+
|
307
|
+
get '/js/jsapi.js' do
|
308
|
+
send_file 'js/jsapi.js', :type => :js
|
309
|
+
end
|
310
|
+
|
311
|
+
run!
|
312
|
+
|
313
|
+
end
|
314
|
+
|
315
|
+
end
|
316
|
+
|
317
|
+
# Start Dashboard Release
|
318
|
+
|
319
|
+
Deedrah.new
|