tcell_agent 0.2.2

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.
Files changed (84) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +4 -0
  3. data/README.md +43 -0
  4. data/Rakefile +7 -0
  5. data/bin/tcell_agent +171 -0
  6. data/config/initializers/authlogic_auth.rb +51 -0
  7. data/config/initializers/devise_auth.rb +167 -0
  8. data/config/initializers/init.rb +8 -0
  9. data/lib/tcell_agent.rb +33 -0
  10. data/lib/tcell_agent/agent.rb +79 -0
  11. data/lib/tcell_agent/agent/event_processor.rb +133 -0
  12. data/lib/tcell_agent/agent/policy_manager.rb +138 -0
  13. data/lib/tcell_agent/agent/policy_types.rb +42 -0
  14. data/lib/tcell_agent/agent/static_agent.rb +22 -0
  15. data/lib/tcell_agent/api.rb +101 -0
  16. data/lib/tcell_agent/appsensor.rb +42 -0
  17. data/lib/tcell_agent/appsensor/cmdi.rb +32 -0
  18. data/lib/tcell_agent/appsensor/path_traversal.rb +33 -0
  19. data/lib/tcell_agent/appsensor/sqli.rb +55 -0
  20. data/lib/tcell_agent/appsensor/xss.rb +40 -0
  21. data/lib/tcell_agent/authlogic.rb +26 -0
  22. data/lib/tcell_agent/configuration.rb +148 -0
  23. data/lib/tcell_agent/dataloss.rb +0 -0
  24. data/lib/tcell_agent/devise.rb +83 -0
  25. data/lib/tcell_agent/instrumentation.rb +44 -0
  26. data/lib/tcell_agent/logger.rb +46 -0
  27. data/lib/tcell_agent/policies/add_script_tag_policy.rb +47 -0
  28. data/lib/tcell_agent/policies/appsensor_policy.rb +76 -0
  29. data/lib/tcell_agent/policies/clickjacking_policy.rb +113 -0
  30. data/lib/tcell_agent/policies/content_security_policy.rb +119 -0
  31. data/lib/tcell_agent/policies/dataloss_policy.rb +175 -0
  32. data/lib/tcell_agent/policies/honeytokens_policy.rb +67 -0
  33. data/lib/tcell_agent/policies/http_redirect_policy.rb +84 -0
  34. data/lib/tcell_agent/policies/http_tx_policy.rb +60 -0
  35. data/lib/tcell_agent/policies/login_fraud_policy.rb +42 -0
  36. data/lib/tcell_agent/policies/secure_headers_policy.rb +64 -0
  37. data/lib/tcell_agent/rails.rb +146 -0
  38. data/lib/tcell_agent/rails/devise.rb +0 -0
  39. data/lib/tcell_agent/rails/dlp.rb +204 -0
  40. data/lib/tcell_agent/rails/middleware/body_filter_middleware.rb +69 -0
  41. data/lib/tcell_agent/rails/middleware/context_middleware.rb +50 -0
  42. data/lib/tcell_agent/rails/middleware/global_middleware.rb +53 -0
  43. data/lib/tcell_agent/rails/middleware/headers_middleware.rb +176 -0
  44. data/lib/tcell_agent/rails/routes.rb +130 -0
  45. data/lib/tcell_agent/rails/settings_reporter.rb +40 -0
  46. data/lib/tcell_agent/sensor_events/app_config.rb +16 -0
  47. data/lib/tcell_agent/sensor_events/app_sensor.rb +240 -0
  48. data/lib/tcell_agent/sensor_events/dlp.rb +58 -0
  49. data/lib/tcell_agent/sensor_events/honeytokens.rb +16 -0
  50. data/lib/tcell_agent/sensor_events/login_fraud.rb +43 -0
  51. data/lib/tcell_agent/sensor_events/metrics.rb +24 -0
  52. data/lib/tcell_agent/sensor_events/sensor.rb +85 -0
  53. data/lib/tcell_agent/sensor_events/server_agent.rb +101 -0
  54. data/lib/tcell_agent/sensor_events/util/redirect_utils.rb +22 -0
  55. data/lib/tcell_agent/sensor_events/util/sanitizer_utilities.rb +153 -0
  56. data/lib/tcell_agent/sensor_events/util/utils.rb +21 -0
  57. data/lib/tcell_agent/sinatra.rb +41 -0
  58. data/lib/tcell_agent/start_background_thread.rb +63 -0
  59. data/lib/tcell_agent/userinfo.rb +8 -0
  60. data/lib/tcell_agent/utils/queue_with_timeout.rb +60 -0
  61. data/lib/tcell_agent/version.rb +5 -0
  62. data/spec/controllers/application_controller.rb +12 -0
  63. data/spec/lib/tcell_agent/api/api_spec.rb +36 -0
  64. data/spec/lib/tcell_agent/appsensor_spec.rb +66 -0
  65. data/spec/lib/tcell_agent/policies/add_script_tag_policy_spec.rb +37 -0
  66. data/spec/lib/tcell_agent/policies/appsensor_policy_spec.rb +40 -0
  67. data/spec/lib/tcell_agent/policies/clickjacking_policy_spec.rb +71 -0
  68. data/spec/lib/tcell_agent/policies/content_security_policy_spec.rb +71 -0
  69. data/spec/lib/tcell_agent/policies/dataloss_policy_spec.rb +88 -0
  70. data/spec/lib/tcell_agent/policies/honeytokens_policy_spec.rb +22 -0
  71. data/spec/lib/tcell_agent/policies/http_redirect_policy_spec.rb +62 -0
  72. data/spec/lib/tcell_agent/policies/http_tx_policy_spec.rb +22 -0
  73. data/spec/lib/tcell_agent/policies/login_policy_spec.rb +42 -0
  74. data/spec/lib/tcell_agent/policies/secure_headers_policy_spec.rb +67 -0
  75. data/spec/lib/tcell_agent/rails/middleware/global_middleware_spec.rb +187 -0
  76. data/spec/lib/tcell_agent/rails_spec.rb +57 -0
  77. data/spec/lib/tcell_agent/sensor_events/dlp_spec.rb +14 -0
  78. data/spec/lib/tcell_agent/sensor_events/util/redirect_utils_spec.rb +25 -0
  79. data/spec/lib/tcell_agent/sensor_events/util/sanitizer_utilities_spec.rb +57 -0
  80. data/spec/lib/tcell_agent_spec.rb +22 -0
  81. data/spec/resources/normal_config.json +13 -0
  82. data/spec/spec_helper.rb +4 -0
  83. data/tcell_agent.gemspec +29 -0
  84. 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