tcell_agent 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +4 -0
- data/README.md +43 -0
- data/Rakefile +7 -0
- data/bin/tcell_agent +171 -0
- data/config/initializers/authlogic_auth.rb +51 -0
- data/config/initializers/devise_auth.rb +167 -0
- data/config/initializers/init.rb +8 -0
- data/lib/tcell_agent.rb +33 -0
- data/lib/tcell_agent/agent.rb +79 -0
- data/lib/tcell_agent/agent/event_processor.rb +133 -0
- data/lib/tcell_agent/agent/policy_manager.rb +138 -0
- data/lib/tcell_agent/agent/policy_types.rb +42 -0
- data/lib/tcell_agent/agent/static_agent.rb +22 -0
- data/lib/tcell_agent/api.rb +101 -0
- data/lib/tcell_agent/appsensor.rb +42 -0
- data/lib/tcell_agent/appsensor/cmdi.rb +32 -0
- data/lib/tcell_agent/appsensor/path_traversal.rb +33 -0
- data/lib/tcell_agent/appsensor/sqli.rb +55 -0
- data/lib/tcell_agent/appsensor/xss.rb +40 -0
- data/lib/tcell_agent/authlogic.rb +26 -0
- data/lib/tcell_agent/configuration.rb +148 -0
- data/lib/tcell_agent/dataloss.rb +0 -0
- data/lib/tcell_agent/devise.rb +83 -0
- data/lib/tcell_agent/instrumentation.rb +44 -0
- data/lib/tcell_agent/logger.rb +46 -0
- data/lib/tcell_agent/policies/add_script_tag_policy.rb +47 -0
- data/lib/tcell_agent/policies/appsensor_policy.rb +76 -0
- data/lib/tcell_agent/policies/clickjacking_policy.rb +113 -0
- data/lib/tcell_agent/policies/content_security_policy.rb +119 -0
- data/lib/tcell_agent/policies/dataloss_policy.rb +175 -0
- data/lib/tcell_agent/policies/honeytokens_policy.rb +67 -0
- data/lib/tcell_agent/policies/http_redirect_policy.rb +84 -0
- data/lib/tcell_agent/policies/http_tx_policy.rb +60 -0
- data/lib/tcell_agent/policies/login_fraud_policy.rb +42 -0
- data/lib/tcell_agent/policies/secure_headers_policy.rb +64 -0
- data/lib/tcell_agent/rails.rb +146 -0
- data/lib/tcell_agent/rails/devise.rb +0 -0
- data/lib/tcell_agent/rails/dlp.rb +204 -0
- data/lib/tcell_agent/rails/middleware/body_filter_middleware.rb +69 -0
- data/lib/tcell_agent/rails/middleware/context_middleware.rb +50 -0
- data/lib/tcell_agent/rails/middleware/global_middleware.rb +53 -0
- data/lib/tcell_agent/rails/middleware/headers_middleware.rb +176 -0
- data/lib/tcell_agent/rails/routes.rb +130 -0
- data/lib/tcell_agent/rails/settings_reporter.rb +40 -0
- data/lib/tcell_agent/sensor_events/app_config.rb +16 -0
- data/lib/tcell_agent/sensor_events/app_sensor.rb +240 -0
- data/lib/tcell_agent/sensor_events/dlp.rb +58 -0
- data/lib/tcell_agent/sensor_events/honeytokens.rb +16 -0
- data/lib/tcell_agent/sensor_events/login_fraud.rb +43 -0
- data/lib/tcell_agent/sensor_events/metrics.rb +24 -0
- data/lib/tcell_agent/sensor_events/sensor.rb +85 -0
- data/lib/tcell_agent/sensor_events/server_agent.rb +101 -0
- data/lib/tcell_agent/sensor_events/util/redirect_utils.rb +22 -0
- data/lib/tcell_agent/sensor_events/util/sanitizer_utilities.rb +153 -0
- data/lib/tcell_agent/sensor_events/util/utils.rb +21 -0
- data/lib/tcell_agent/sinatra.rb +41 -0
- data/lib/tcell_agent/start_background_thread.rb +63 -0
- data/lib/tcell_agent/userinfo.rb +8 -0
- data/lib/tcell_agent/utils/queue_with_timeout.rb +60 -0
- data/lib/tcell_agent/version.rb +5 -0
- data/spec/controllers/application_controller.rb +12 -0
- data/spec/lib/tcell_agent/api/api_spec.rb +36 -0
- data/spec/lib/tcell_agent/appsensor_spec.rb +66 -0
- data/spec/lib/tcell_agent/policies/add_script_tag_policy_spec.rb +37 -0
- data/spec/lib/tcell_agent/policies/appsensor_policy_spec.rb +40 -0
- data/spec/lib/tcell_agent/policies/clickjacking_policy_spec.rb +71 -0
- data/spec/lib/tcell_agent/policies/content_security_policy_spec.rb +71 -0
- data/spec/lib/tcell_agent/policies/dataloss_policy_spec.rb +88 -0
- data/spec/lib/tcell_agent/policies/honeytokens_policy_spec.rb +22 -0
- data/spec/lib/tcell_agent/policies/http_redirect_policy_spec.rb +62 -0
- data/spec/lib/tcell_agent/policies/http_tx_policy_spec.rb +22 -0
- data/spec/lib/tcell_agent/policies/login_policy_spec.rb +42 -0
- data/spec/lib/tcell_agent/policies/secure_headers_policy_spec.rb +67 -0
- data/spec/lib/tcell_agent/rails/middleware/global_middleware_spec.rb +187 -0
- data/spec/lib/tcell_agent/rails_spec.rb +57 -0
- data/spec/lib/tcell_agent/sensor_events/dlp_spec.rb +14 -0
- data/spec/lib/tcell_agent/sensor_events/util/redirect_utils_spec.rb +25 -0
- data/spec/lib/tcell_agent/sensor_events/util/sanitizer_utilities_spec.rb +57 -0
- data/spec/lib/tcell_agent_spec.rb +22 -0
- data/spec/resources/normal_config.json +13 -0
- data/spec/spec_helper.rb +4 -0
- data/tcell_agent.gemspec +29 -0
- metadata +249 -0
@@ -0,0 +1,101 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# See the file "LICENSE" for the full license governing this code.
|
3
|
+
require 'rest-client'
|
4
|
+
require 'tcell_agent/logger'
|
5
|
+
require 'tcell_agent/configuration'
|
6
|
+
require 'tcell_agent/version'
|
7
|
+
require 'date'
|
8
|
+
|
9
|
+
module TCellAgent
|
10
|
+
class TCellApi
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
end
|
14
|
+
|
15
|
+
def pollAPI(last_timestamp=nil)
|
16
|
+
if !TCellAgent.configuration || !TCellAgent.configuration.tcell_api_url || !TCellAgent.configuration.app_id
|
17
|
+
raise "Config Information Not Found, can't poll tCell service"
|
18
|
+
end
|
19
|
+
full_url = TCellAgent.configuration.tcell_api_url + "/app/" + TCellAgent.configuration.app_id + "/update"
|
20
|
+
if (last_timestamp && last_timestamp != "")
|
21
|
+
full_url = full_url + "?last_timestamp=" + last_timestamp.to_s
|
22
|
+
end
|
23
|
+
TCellAgent.logger.debug "tCell.io API Request: " + full_url
|
24
|
+
request_headers = {
|
25
|
+
:Authorization => 'Bearer ' + TCellAgent.configuration.api_key
|
26
|
+
}
|
27
|
+
begin
|
28
|
+
request_headers[:TCellAgent] = "RubyAgent " + TCellAgent::VERSION
|
29
|
+
rescue Exception => e
|
30
|
+
TCellAgent.logger.debug("tCell.io Could not add agent string: " + e.message)
|
31
|
+
end
|
32
|
+
response = RestClient.get full_url,request_headers
|
33
|
+
new_timestamp = last_timestamp
|
34
|
+
TCellAgent.logger.debug "tCell.io API Response: " + response
|
35
|
+
response_json = JSON.parse(response)
|
36
|
+
if (response_json && response_json.has_key?("result"))
|
37
|
+
return response_json["result"]
|
38
|
+
end
|
39
|
+
# else result was null and no new information exists...
|
40
|
+
return nil
|
41
|
+
end
|
42
|
+
|
43
|
+
def pollOldAPI(last_timestamp=nil)
|
44
|
+
if !TCellAgent.configuration || !TCellAgent.configuration.tcell_api_url || !TCellAgent.configuration.app_id
|
45
|
+
raise "Config Information Not Found, can't poll tCell service"
|
46
|
+
end
|
47
|
+
full_url = TCellAgent.configuration.tcell_api_url + "/api/" + TCellAgent.configuration.app_id + "/csp/poll"
|
48
|
+
TCellAgent.logger.debug "tCell.io API Request: " + full_url
|
49
|
+
full_url = full_url + "/" + TCellAgent.configuration.api_key
|
50
|
+
if (last_timestamp && last_timestamp != "")
|
51
|
+
full_url = full_url + "?last_timestamp=" + last_timestamp.to_s
|
52
|
+
end
|
53
|
+
TCellAgent.logger.debug("tCell.io Old API Request: " + full_url)
|
54
|
+
response = RestClient.get full_url
|
55
|
+
TCellAgent.logger.debug "tCell.io API Response: " + response
|
56
|
+
response_json = JSON.parse(response)
|
57
|
+
if (response_json && response_json.has_key?("result"))
|
58
|
+
return response_json["result"]
|
59
|
+
end
|
60
|
+
# else result was null and no new information exists...
|
61
|
+
return nil
|
62
|
+
end
|
63
|
+
|
64
|
+
def sendEventSet(events)
|
65
|
+
if !TCellAgent.configuration || !TCellAgent.configuration.tcell_input_url || !TCellAgent.configuration.app_id
|
66
|
+
raise "Config Information Not Found, can't send events"
|
67
|
+
end
|
68
|
+
current_time = DateTime.now.to_time.to_i
|
69
|
+
if (events)
|
70
|
+
events.each { |event| event.calculateOffset(current_time) }
|
71
|
+
else
|
72
|
+
events = []
|
73
|
+
end
|
74
|
+
eventset = { "uuid"=>TCellAgent.configuration.uuid,
|
75
|
+
"hostname"=>TCellAgent.configuration.host_identifier,
|
76
|
+
"events"=>events }
|
77
|
+
TCellAgent.logger.debug("Sending #{eventset.to_json}")
|
78
|
+
full_url = TCellAgent.configuration.tcell_input_url + "/app/" + TCellAgent.configuration.app_id + "/server_agent"
|
79
|
+
|
80
|
+
TCellAgent.logger.debug("tCell.io SendEvents API Request: " + full_url)
|
81
|
+
request_headers = {
|
82
|
+
:Authorization => 'Bearer ' + TCellAgent.configuration.api_key,
|
83
|
+
:content_type => :json,
|
84
|
+
:accept => :json,
|
85
|
+
}
|
86
|
+
begin
|
87
|
+
request_headers[:TCellAgent] = "RubyAgent " + TCellAgent::VERSION
|
88
|
+
rescue Exception => e
|
89
|
+
TCellAgent.logger.debug("tCell.io Could not add agent string: " + e.message)
|
90
|
+
end
|
91
|
+
response = RestClient.post full_url, eventset.to_json, request_headers
|
92
|
+
TCellAgent.logger.debug("tCell.io SendEvents API Response: " + response.code.to_s)
|
93
|
+
return response.code == 200
|
94
|
+
end
|
95
|
+
|
96
|
+
def valid_header?(str)
|
97
|
+
return true if (/^[\p{L}\w\d\-_ :\/,;.'\"%?@#=$]*$/).match(str)
|
98
|
+
return false
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# See the file "LICENSE" for the full license governing this code.
|
3
|
+
|
4
|
+
require 'tcell_agent/appsensor/xss'
|
5
|
+
require 'tcell_agent/appsensor/sqli'
|
6
|
+
require 'tcell_agent/appsensor/cmdi'
|
7
|
+
require 'tcell_agent/appsensor/path_traversal'
|
8
|
+
|
9
|
+
module TCellAgent
|
10
|
+
class AppSensor
|
11
|
+
|
12
|
+
GENERALLY_SAFE_REGEX = /^[a-zA-Z0-9_\s\r\n\t]*$/
|
13
|
+
NULL_CHARS_REGEX=/\0/
|
14
|
+
RETURN_CHARS_REGEX=/(\n|\r)/
|
15
|
+
|
16
|
+
def self.generallySafe(value)
|
17
|
+
if !value.instance_of? String
|
18
|
+
return false
|
19
|
+
end
|
20
|
+
return (value.match(AppSensor::GENERALLY_SAFE_REGEX)!=nil)
|
21
|
+
end
|
22
|
+
def self.containsNull(value)
|
23
|
+
if !value.instance_of? String
|
24
|
+
return false
|
25
|
+
end
|
26
|
+
if value.match(AppSensor::NULL_CHARS_REGEX)
|
27
|
+
return true
|
28
|
+
end
|
29
|
+
return false
|
30
|
+
end
|
31
|
+
def self.containsReturnChars(value)
|
32
|
+
if !value.instance_of? String
|
33
|
+
return false
|
34
|
+
end
|
35
|
+
if value.match(AppSensor::RETURN_CHARS_REGEX)
|
36
|
+
return true
|
37
|
+
end
|
38
|
+
return false
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# See the file "LICENSE" for the full license governing this code.
|
3
|
+
|
4
|
+
require 'tcell_agent/sensor_events/util/sanitizer_utilities'
|
5
|
+
|
6
|
+
|
7
|
+
# Some Rules Originate from ModSecurity
|
8
|
+
# ModSecurity for Apache 2.x, http://www.modsecurity.org/
|
9
|
+
# Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
10
|
+
|
11
|
+
module TCellAgent
|
12
|
+
class AppSensor
|
13
|
+
CMDI_PATTERNS = [
|
14
|
+
/(?i:(?:[\;\|\`]\W*?\bcc|\b(wget|curl))\b|\/cc(?:[\'\"\|\;\`\-\s]|$))/,
|
15
|
+
/(?:\b(?:(?:n(?:et(?:\b\W+?\blocalgroup|\.exe)|(?:map|c)\.exe)|t(?:racer(?:oute|t)|elnet\.exe|clsh8?|ftp)|(?:w(?:guest|sh)|rcmd|ftp)\.exe|echo\b\W*?\by+)\b|c(?:md(?:(?:\.exe|32)\b|\b\W*?\\\/c)|d(?:\b\W*?[\\\/]|\W*?\.\.)|hmod.{0,40}?\+.{0,3}x))|[\;\|\`]\W*?\b(?:(?:c(?:h(?:grp|mod|own|sh)|md|pp)|p(?:asswd|ython|erl|ing|s)|n(?:asm|map|c)|f(?:inger|tp)|(?:kil|mai)l|(?:xte)?rm|ls(?:of)?|telnet|uname|echo|id)\b|g(?:\+\+|cc\b)))/
|
16
|
+
]
|
17
|
+
def self.isCmdi(value)
|
18
|
+
if !value.instance_of? String
|
19
|
+
return false
|
20
|
+
end
|
21
|
+
if generallySafe(value)
|
22
|
+
return false
|
23
|
+
end
|
24
|
+
CMDI_PATTERNS.each do |cmdi_pattern|
|
25
|
+
if value.match(cmdi_pattern)
|
26
|
+
return true
|
27
|
+
end
|
28
|
+
end
|
29
|
+
false
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# See the file "LICENSE" for the full license governing this code.
|
3
|
+
|
4
|
+
require 'tcell_agent/sensor_events/util/sanitizer_utilities'
|
5
|
+
|
6
|
+
|
7
|
+
# Some Rules Originate from ModSecurity
|
8
|
+
# ModSecurity for Apache 2.x, http://www.modsecurity.org/
|
9
|
+
# Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
10
|
+
|
11
|
+
module TCellAgent
|
12
|
+
class AppSensor
|
13
|
+
PATH_TRAVERSAL_REGEXES = [
|
14
|
+
Regexp.new("(?:(?:\\\/|\\\\)?\\.+(\\\/|\\\\)(?:\\.+)?)|(?:\\w+\\.exe\\??\\s)|(?:;\\s*\\w+\\s*\\\/[\\w*-]+\\\/)|(?:\\d\\.\\dx\\|)|(?:%(?:c0\\.|af\\.|5c\\.))|(?:\\\/(?:%2e){2})"),
|
15
|
+
Regexp.new("(?:%c0%ae\\\/)|(?:(?:\\\/|\\\\)(home|conf|usr|etc|proc|opt|s?bin|local|dev|tmp|kern|[br]oot|sys|system|windows|winnt|program|%[a-z_-]{3,}%)(?:\\\/|\\\\))|(?:(?:\\\/|\\\\)inetpub|localstart\\.asp|boot\\.ini)"),
|
16
|
+
Regexp.new("(?:etc\\\/\\W*passwd)")
|
17
|
+
]
|
18
|
+
def self.isPathTraversal(value)
|
19
|
+
if !value.instance_of? String
|
20
|
+
return false
|
21
|
+
end
|
22
|
+
if generallySafe(value)
|
23
|
+
return false
|
24
|
+
end
|
25
|
+
PATH_TRAVERSAL_REGEXES.each do |pattern|
|
26
|
+
if value.match(pattern)
|
27
|
+
return true
|
28
|
+
end
|
29
|
+
end
|
30
|
+
false
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# See the file "LICENSE" for the full license governing this code.
|
3
|
+
|
4
|
+
require 'tcell_agent/sensor_events/util/sanitizer_utilities'
|
5
|
+
|
6
|
+
|
7
|
+
# Some Rules Originate from ModSecurity
|
8
|
+
# ModSecurity for Apache 2.x, http://www.modsecurity.org/
|
9
|
+
# Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
10
|
+
|
11
|
+
module TCellAgent
|
12
|
+
class AppSensor
|
13
|
+
SQLI_PATTERNS = [
|
14
|
+
/(?i:(?i:\d[\"'`´’‘]\s+[\"'`´’‘]\s+\d)|(?:^admin\s*?[\"'`´’‘]|(\/\*)+[\"'`´’‘]+\s?(?:--|#|\/\*|{)?)|(?:[\"'`´’‘]\s*?\b(x?or|div|like|between|and)\b\s*?[+<>=(),-]\s*?[\d\"'`´’‘])|(?:[\"'`´’‘]\s*?[^\w\s]?=\s*?[\"'`´’‘])|(?:[\"'`´’‘]\W*?[+=]+\W*?[\"'`´’‘])|(?:[\"'`´’‘]\s*?[!=|][\d\s!=+-]+.*?[\"'`´’‘(].*?$)|(?:[\"'`´’‘]\s*?[!=|][\d\s!=]+.*?\d+$)|(?:[\"'`´’‘]\s*?like\W+[\w\"'`´’‘(])|(?:\sis\s*?0\W)|(?:where\s[\s\w\.,-]+\s=)|(?:[\"'`´’‘][<>~]+[\"'`´’‘]))/,
|
15
|
+
#Hex Evasion (ModSecurity)
|
16
|
+
#/(?i:(?:\A|[^\d])0x[a-f\d]{3,}[a-f\d]*)+/,
|
17
|
+
#Order By (ModSecurity)
|
18
|
+
/\b(?i:having)\b\s+(\d{1,10}|'[^=]{1,10}')\s*?[=<>]|(?i:\bexecute(\s{1,5}[\w\.$]{1,5}\s{0,3})?\()|\bhaving\b ?(?:\d{1,10}|[\'\"][^=]{1,10}[\'\"]) ?[=<>]+|(?i:\bcreate\s+?table.{0,20}?\()|(?i:\blike\W*?char\W*?\()|(?i:(?:(select(.*?)case|from(.*?)limit|order\sby)))|exists\s(\sselect|select\Sif(null)?\s\(|select\Stop|select\Sconcat|system\s\(|\b(?i:having)\b\s+(\d{1,10})|'[^=]{1,10}')/,
|
19
|
+
# (ModSecurity)
|
20
|
+
#/(?i:([\s'\"`´’‘\(\)]*?)\b([\d\w]++)([\s'\"`´’‘\(\)]*?)(?:(?:=|<=>|r?like|sounds\s+like|regexp)([\s'\"`´’‘\(\)]*?)\2\b|(?:!=|<=|>=|<>|<|>|\^|is\s+not|not\s+like|not\s+regexp)([\s'\"`´’‘\(\)]*?)(?!\2)([\d\w]+)\b))/,
|
21
|
+
# Tautaulogy (ModSecurity)
|
22
|
+
/([';]--|--[\s\r\n\v\f]|(?:--[^-]*?-)|([^\-&])#.*?[\s\r\n\v\f]|;?\\x00)/,
|
23
|
+
/(?i:(?:@.+=\s*?\(\s*?select)|(?:\d+\s*?(x?or|div|like|between|and)\s*?\d+\s*?[\-+])|(?:\/\w+;?\s+(?:having|and|x?or|div|like|between|and|select)\W)|(?:\d\s+group\s+by.+\()|(?:(?:;|#|--)\s*?(?:drop|alter))|(?:(?:;|#|--)\s*?(?:update|insert)\s*?\w{2,})|(?:[^\w]SET\s*?@\w+)|(?:(?:n?and|x?x?or|div|like|between|and|not |\|\||\&\&)[\s(]+\w+[\s)]*?[!=+]+[\s\d]*?[\"'`´’‘=()]))/,
|
24
|
+
/(?i:(?:in\s*?\(+\s*?select)|(?:(?:n?and|x?x?or|div|like|between|and|not |\|\||\&\&)\s+[\s\w+]+(?:regexp\s*?\(|sounds\s+like\s*?[\"'`´’‘]|[=\d]+x))|([\"'`´’‘]\s*?\d\s*?(?:--|#))|(?:[\"'`´’‘][\%&<>^=]+\d\s*?(=|x?or|div|like|between|and))|(?:[\"'`´’‘]\W+[\w+-]+\s*?=\s*?\d\W+[\"'`´’‘])|(?:[\"'`´’‘]\s*?is\s*?\d.+[\"'`´’‘]?\w)|(?:[\"'`´’‘]\|?[\w-]{3,}[^\w\s.,]+[\"'`´’‘])|(?:[\"'`´’‘]\s*?is\s*?[\d.]+\s*?\W.*?[\"'`´’‘]))/,
|
25
|
+
/(?i:(?:[\"'`´’‘]\s*?\*.+(?:x?or|div|like|between|and|id)\W*?[\"'`´’‘]\d)|(?:\^[\"'`´’‘])|(?:^[\w\s\"'`´’‘-]+(?<=and\s)(?<=or|xor|div|like|between|and\s)(?<=xor\s)(?<=nand\s)(?<=not\s)(?<=\|\|)(?<=\&\&)\w+\()|(?:[\"'`´’‘][\s\d]*?[^\w\s]+\W*?\d\W*?.*?[\"'`´’‘\d])|(?:[\"'`´’‘]\s*?[^\w\s?]+\s*?[^\w\s]+\s*?[\"'`´’‘])|(?:[\"'`´’‘]\s*?[^\w\s]+\s*?[\W\d].*?(?:#|--))|(?:[\"'`´’‘].*?\*\s*?\d)|(?:[\"'`´’‘]\s*?(x?or|div|like|between|and)\s[^\d]+[\w-]+.*?\d)|(?:[()\*<>%+-][\w-]+[^\w\s]+[\"'`´’‘][^,]))/,
|
26
|
+
#Probing (ModSecurity)
|
27
|
+
#/(^[\"'`´’‘;]+|[\"'`´’‘;]+$)/,
|
28
|
+
#SQL Ops (ModSecurity)
|
29
|
+
#/(?i:(\!\=|\&\&|\|\||>>|<<|>=|<=|<>|<=>|xor|rlike|regexp|isnull)|(?:not\s+between\s+0\s+and)|(?:is\s+null)|(like\s+null)|(?:(?:^|\W)in[+\s]*\([\s\d\"]+[^()]*\))|(?:xor|<>|rlike(?:\s+binary)?)|(?:regexp\s+binary))/,
|
30
|
+
#Database strings (ModSecurity)
|
31
|
+
#/(?i:(?:m(?:s(?:ysaccessobjects|ysaces|ysobjects|ysqueries|ysrelationships|ysaccessstorage|ysaccessxml|ysmodules|ysmodules2|db)|aster\.\.sysdatabases|ysql\.db)|s(?:ys(?:\.database_name|aux)|chema(?:\W*\(|_name)|qlite(_temp)?_master)|d(?:atabas|b_nam)e\W*\(|information_schema|pg_(catalog|toast)|northwind|tempdb))/,
|
32
|
+
#Blind (ModSecurity)
|
33
|
+
#/(?i:(?:\b(?:(?:s(?:ys\.(?:user_(?:(?:t(?:ab(?:_column|le)|rigger)|object|view)s|c(?:onstraints|atalog))|all_tables|tab)|elect\b.{0,40}\b(?:substring|users?|ascii))|m(?:sys(?:(?:queri|ac)e|relationship|column|object)s|ysql\.(db|user))|c(?:onstraint_type|harindex)|waitfor\b\W*?\bdelay|attnotnull)\b|(?:locate|instr)\W+\()|\@\@spid\b)|\b(?:(?:s(?:ys(?:(?:(?:process|tabl)e|filegroup|object)s|c(?:o(?:nstraint|lumn)s|at)|dba|ibm)|ubstr(?:ing)?)|user_(?:(?:(?:constrain|objec)t|tab(?:_column|le)|ind_column|user)s|password|group)|a(?:tt(?:rel|typ)id|ll_objects)|object_(?:(?:nam|typ)e|id)|pg_(?:attribute|class)|column_(?:name|id)|xtype\W+\bchar|mb_users|rownum)\b|t(?:able_name\b|extpos\W+\()))/,
|
34
|
+
# (ModSecurity)
|
35
|
+
/(?i:(?i:\d[\"'`´’‘]\s+[\"'`´’‘]\s+\d)|(?:^admin\s*?[\"'`´’‘]|(\/\*)+[\"'`´’‘]+\s?(?:--|#|\/\*|{)?)|(?:[\"'`´’‘]\s*?\b(x?or|div|like|between|and)\b\s*?[+<>=(),-]\s*?[\d\"'`´’‘])|(?:[\"'`´’‘]\s*?[^\w\s]?=\s*?[\"'`´’‘])|(?:[\"'`´’‘]\W*?[+=]+\W*?[\"'`´’‘])|(?:[\"'`´’‘]\s*?[!=|][\d\s!=+-]+.*?[\"'`´’‘(].*?$)|(?:[\"'`´’‘]\s*?[!=|][\d\s!=]+.*?\d+$)|(?:[\"'`´’‘]\s*?like\W+[\w\"'`´’‘(])|(?:\sis\s*?0\W)|(?:where\s[\s\w\.,-]+\s=)|(?:[\"'`´’‘][<>~]+[\"'`´’‘]))/
|
36
|
+
# (ModSecurity)
|
37
|
+
#/(?i:(?:\sexec\s+xp_cmdshell)|(?:[\"'`´’‘]\s*?!\s*?[\"'`´’‘\w])|(?:from\W+information_schema\W)|(?:(?:(?:current_)?user|database|schema|connection_id)\s*?\([^\)]*?)|(?:[\"'`´’‘];?\s*?(?:select|union|having)\s*?[^\s])|(?:\wiif\s*?\()|(?:exec\s+master\.)|(?:union select @)|(?:union[\w(\s]*?select)|(?:select.*?\w?user\()|(?:into[\s+]+(?:dump|out)file\s*?[\"'`´’‘]))/
|
38
|
+
]
|
39
|
+
def self.isSqli(value)
|
40
|
+
if !value.instance_of? String
|
41
|
+
return false
|
42
|
+
end
|
43
|
+
if generallySafe(value)
|
44
|
+
return false
|
45
|
+
end
|
46
|
+
SQLI_PATTERNS.each do |sqli_pattern|
|
47
|
+
if value.match(sqli_pattern)
|
48
|
+
return true
|
49
|
+
end
|
50
|
+
end
|
51
|
+
false
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# See the file "LICENSE" for the full license governing this code.
|
3
|
+
|
4
|
+
require 'tcell_agent/sensor_events/util/sanitizer_utilities'
|
5
|
+
|
6
|
+
|
7
|
+
# Some Rules Originate from ModSecurity
|
8
|
+
# ModSecurity for Apache 2.x, http://www.modsecurity.org/
|
9
|
+
# Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
10
|
+
|
11
|
+
module TCellAgent
|
12
|
+
class AppSensor
|
13
|
+
XSS_PATTERNS = [
|
14
|
+
Regexp.new("<(script|iframe|embed|frame|frameset|object|img|applet|body|html|style|layer|link|ilayer|meta|bgsound)"),
|
15
|
+
Regexp.new("(alert|on\\w+|function\\s+\\w+)\\s*\\(\\s*(['+\\d\\w](,?\\s*['+\\d\\w]*)*)*\\s*\\)"),
|
16
|
+
Regexp.new("(?:\"[^\"]*[^-]?>)|(?:[^\\w\\s]\\s*\\/>)|(?:>\")"),
|
17
|
+
Regexp.new("(?:\"+.*[<=]\\s*\"[^\"]+\")|(?:\"\\s*\\w+\\s*=)|(?:>\\w=\\/)|(?:#.+\\)[\"\\s]*>)|(?:\"\\s*(?:src|style|on\\w+)\\s*=\\s*\")|(?:[^\"]?\"[,;\\s]+\\w*[\\[\\(])"),
|
18
|
+
Regexp.new("(?:^>[\\w\\s]*<\\/?\\w{2,}>)"),
|
19
|
+
Regexp.new("(?:with\\s*\\(\\s*.+\\s*\\)\\s*\\w+\\s*\\()|(?:(?:do|while|for)\\s*\\([^)]*\\)\\s*\\{)|(?:\\/[\\w\\s]*\\[\\W*\\w)"),
|
20
|
+
Regexp.new("(?:[=(].+\\?.+:)|(?:with\\([^)]*\\)\\))|(?:\\.\\s*source\\W)"),
|
21
|
+
Regexp.new("(?:[\".]script\\s*\\()|(?:\\$\\$?\\s*\\(\\s*[\\w\"])|(?:\\/[\\w\\s]+\\/\\.)|(?:=\\s*\\/\\w+\\/\\s*\\.)|(?:(?:this|window|top|parent|frames|self|content)\\[\\s*[(,\"]*\\s*[\\w\\$])|(?:,\\s*new\\s+\\w+\\s*[,;)])"),
|
22
|
+
Regexp.new("(?:=\\s*\\w+\\s*\\+\\s*\")|(?:\\+=\\s*\\(\\s\")|(?:!+\\s*[\\d.,]+\\w?\\d*\\s*\\?)|(?:=\\s*\\[s*\\])|(?:\"\\s*\\+\\s*\")|(?:[^\\s]\\[\\s*\\d+\\s*\\]\\s*[;+])|(?:\"\\s*[&|]+\\s*\")|(?:\\/\\s*\\?\\s*\")|(?:\\/\\s*\\)\\s*\\[)|(?:\\d\\?.+:\\d)|(?:\\]\\s*\\[\\W*\\w)|(?:[^\\s]\\s*=\\s*\\/)"),
|
23
|
+
Regexp.new("<iframe.*")
|
24
|
+
]
|
25
|
+
def self.isXss(value)
|
26
|
+
if !value.instance_of? String
|
27
|
+
return false
|
28
|
+
end
|
29
|
+
if generallySafe(value)
|
30
|
+
return false
|
31
|
+
end
|
32
|
+
XSS_PATTERNS.each do |xss_pattern|
|
33
|
+
if value.match(xss_pattern)
|
34
|
+
return true
|
35
|
+
end
|
36
|
+
end
|
37
|
+
false
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# See the file "LICENSE" for the full license governing this code.
|
2
|
+
|
3
|
+
require 'tcell_agent/userinfo'
|
4
|
+
require 'tcell_agent/logger'
|
5
|
+
require 'tcell_agent/sensor_events/honeytokens'
|
6
|
+
|
7
|
+
module TCellAgent
|
8
|
+
if defined?(Authlogic)
|
9
|
+
TCellAgent::UserInformation.class_eval do
|
10
|
+
class << self
|
11
|
+
alias_method :original_getUserFromRequest, :getUserFromRequest
|
12
|
+
def getUserFromRequest(request)
|
13
|
+
orig_user_id = original_getUserFromRequest(request)
|
14
|
+
begin
|
15
|
+
if request.session and request.session.has_key?("user_credentials_id")
|
16
|
+
return request.session["user_credentials_id"].to_s
|
17
|
+
end
|
18
|
+
rescue Exception => e
|
19
|
+
return orig_user_id
|
20
|
+
end
|
21
|
+
return orig_user_id
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,148 @@
|
|
1
|
+
# See the file "LICENSE" for the full license governing this code.
|
2
|
+
require 'fileutils'
|
3
|
+
require 'json'
|
4
|
+
require 'socket'
|
5
|
+
require 'securerandom'
|
6
|
+
|
7
|
+
module TCellAgent
|
8
|
+
class << self
|
9
|
+
attr_accessor :configuration
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.configure
|
13
|
+
self.configuration ||= Configuration.new
|
14
|
+
yield(configuration)
|
15
|
+
end
|
16
|
+
|
17
|
+
class Configuration
|
18
|
+
attr_accessor :version, :app_id, :api_key, :hmac_key,
|
19
|
+
:tcell_api_url, :tcell_input_url,
|
20
|
+
:enabled, :logging_options,
|
21
|
+
:fetch_policies_from_tcell, :instrument_for_events,
|
22
|
+
:preload_policy_filename,
|
23
|
+
:proxy_host, :proxy_port, :proxy_username, :proxy_password,
|
24
|
+
:use_websockets, :host_identifier, :session_cookie_names,
|
25
|
+
:uuid,
|
26
|
+
:company,
|
27
|
+
:event_batch_size_limit, :event_time_limit_seconds,
|
28
|
+
:default_log_filename,
|
29
|
+
:base_dir,
|
30
|
+
:cache_filename,
|
31
|
+
:js_agent_api_base_url,
|
32
|
+
:js_agent_url
|
33
|
+
|
34
|
+
attr_accessor :exp_config_settings
|
35
|
+
|
36
|
+
|
37
|
+
def initialize(filename="config/tcell_agent.config", useapp=nil)
|
38
|
+
@version = 0
|
39
|
+
@exp_config_settings = true
|
40
|
+
|
41
|
+
|
42
|
+
@fetch_policies_from_tcell = true
|
43
|
+
@instrument_for_events = true
|
44
|
+
@enabled = true
|
45
|
+
@cache_filename = "tcell/tcell_agent.cache"
|
46
|
+
@default_log_filename = "tcell/tcell_agent.log"
|
47
|
+
read_config_using_env
|
48
|
+
read_config_from_file(filename)
|
49
|
+
|
50
|
+
@tcell_api_url ||= "https://api.tcell.io/api/v1"
|
51
|
+
@tcell_input_url ||= "https://input.tcell.io/api/v1"
|
52
|
+
@js_agent_api_base_url ||= nil
|
53
|
+
@js_agent_url ||= "https://api.tcell.io/tcellagent.min.js"
|
54
|
+
@event_batch_size_limit = 25
|
55
|
+
@event_time_limit_seconds = 30
|
56
|
+
|
57
|
+
begin
|
58
|
+
@host_identifier = (Socket.gethostname() || "localhost")
|
59
|
+
rescue Exception => e
|
60
|
+
@host_identifier = "host_identifier_not_found"
|
61
|
+
end
|
62
|
+
@uuid = SecureRandom.uuid
|
63
|
+
|
64
|
+
FileUtils::mkdir_p File.dirname(@cache_filename)
|
65
|
+
if @logging_options and @logging_options["filename"]
|
66
|
+
FileUtils::mkdir_p File.dirname(@logging_options["filename"])
|
67
|
+
else
|
68
|
+
FileUtils::mkdir_p File.dirname(@default_log_filename)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
def read_config_using_env
|
72
|
+
@app_id = ENV["TCELL_APP_ID"]
|
73
|
+
@api_key = ENV["TCELL_API_KEY"]
|
74
|
+
@hmac_key = ENV["TCELL_HMAC_KEY"]
|
75
|
+
@tcell_api_url = ENV["TCELL_API_URL"]
|
76
|
+
@tcell_input_url = ENV["TCELL_INPUT_URL"]
|
77
|
+
end
|
78
|
+
def read_config_from_file(filename)
|
79
|
+
if File.file?(filename)
|
80
|
+
#puts "tCell.io: Loading from file"
|
81
|
+
begin
|
82
|
+
config_text = open(filename).read
|
83
|
+
config = JSON.parse(config_text)
|
84
|
+
if (config["version"] == 1)
|
85
|
+
# Required
|
86
|
+
app_data = config["applications"][0] #Default
|
87
|
+
@version = 1
|
88
|
+
@app_id ||= app_data["app_id"]
|
89
|
+
@app_id ||= app_data["name"]
|
90
|
+
@api_key ||= app_data["api_key"]
|
91
|
+
|
92
|
+
# Optional
|
93
|
+
@enabled = app_data.fetch("enabled", true)
|
94
|
+
@preload_policy_filename = app_data.fetch("preload_policy_filename", nil)
|
95
|
+
@fetch_policies_from_tcell = app_data.fetch("fetch_policies_from_tcell", @fetch_policies_from_tcell)
|
96
|
+
@instrument_for_events = app_data.fetch("instrument_for_events", @instrument_for_events)
|
97
|
+
|
98
|
+
@logging_options = app_data.fetch("logging_options", {})
|
99
|
+
|
100
|
+
@tcell_api_url = app_data.fetch("tcell_api_url", @tcell_api_url)
|
101
|
+
@tcell_input_url = app_data.fetch("tcell_input_url", @tcell_input_url)
|
102
|
+
|
103
|
+
@proxy_host = app_data["proxy_host"]
|
104
|
+
@proxy_port = app_data["proxy_port"]
|
105
|
+
@proxy_username = app_data["proxy_username"]
|
106
|
+
@proxy_password = app_data["proxy_password"]
|
107
|
+
|
108
|
+
@use_websockets = app_data["use_websockets"]
|
109
|
+
@host_identifier = app_data["host_identifier"]
|
110
|
+
if (@host_identifier == nil)
|
111
|
+
@host_identifier = (Socket.gethostname() || "localhost")
|
112
|
+
end
|
113
|
+
@hmac_key ||= app_data["hmac_key"] # if not already set
|
114
|
+
@session_cookie_names = app_data["session_cookie_names"]
|
115
|
+
@uuid = SecureRandom.uuid
|
116
|
+
if (@uuid == nil)
|
117
|
+
@uuid = "secure-random-failed"
|
118
|
+
end
|
119
|
+
|
120
|
+
if app_data.key?("js_agent_api_base_url")
|
121
|
+
@js_agent_api_base_url = app_data["js_agent_api_base_url"]
|
122
|
+
end
|
123
|
+
if app_data.key?("js_agent_url")
|
124
|
+
@js_agent_url = app_data["js_agent_url"]
|
125
|
+
end
|
126
|
+
|
127
|
+
# Causes old event url to be used
|
128
|
+
@company = app_data["company"]
|
129
|
+
|
130
|
+
|
131
|
+
else
|
132
|
+
puts " ********* ********* ********* *********"
|
133
|
+
puts "* tCell.io *"
|
134
|
+
puts "* Unsupported config file version *"
|
135
|
+
puts " ********* ********* ********* *********"
|
136
|
+
end
|
137
|
+
rescue Exception => e
|
138
|
+
puts " ********* ********* ********* *********"
|
139
|
+
puts "* tCell.io *"
|
140
|
+
puts "* Could not load config file *"
|
141
|
+
puts " ********* ********* ********* *********"
|
142
|
+
puts e
|
143
|
+
end #begin
|
144
|
+
end # filename exist
|
145
|
+
end #def read
|
146
|
+
end # class
|
147
|
+
TCellAgent.configuration ||= TCellAgent::Configuration.new
|
148
|
+
end
|