sqreen 0.1.0.pre → 0.7.01461158029

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/CODE_OF_CONDUCT.md +22 -0
  3. data/README.md +77 -0
  4. data/Rakefile +40 -0
  5. data/lib/sqreen.rb +67 -0
  6. data/lib/sqreen/binding_accessor.rb +184 -0
  7. data/lib/sqreen/ca.crt +72 -0
  8. data/lib/sqreen/callback_tree.rb +78 -0
  9. data/lib/sqreen/callbacks.rb +120 -0
  10. data/lib/sqreen/capped_queue.rb +23 -0
  11. data/lib/sqreen/condition_evaluator.rb +169 -0
  12. data/lib/sqreen/conditionable.rb +50 -0
  13. data/lib/sqreen/configuration.rb +151 -0
  14. data/lib/sqreen/context.rb +22 -0
  15. data/lib/sqreen/deliveries/batch.rb +80 -0
  16. data/lib/sqreen/deliveries/simple.rb +36 -0
  17. data/lib/sqreen/detect.rb +14 -0
  18. data/lib/sqreen/detect/shell_injection.rb +61 -0
  19. data/lib/sqreen/detect/sql_injection.rb +115 -0
  20. data/lib/sqreen/event.rb +16 -0
  21. data/lib/sqreen/events/attack.rb +60 -0
  22. data/lib/sqreen/events/remote_exception.rb +53 -0
  23. data/lib/sqreen/exception.rb +31 -0
  24. data/lib/sqreen/frameworks.rb +40 -0
  25. data/lib/sqreen/frameworks/generic.rb +243 -0
  26. data/lib/sqreen/frameworks/rails.rb +155 -0
  27. data/lib/sqreen/frameworks/rails3.rb +36 -0
  28. data/lib/sqreen/frameworks/sinatra.rb +34 -0
  29. data/lib/sqreen/frameworks/sqreen_test.rb +26 -0
  30. data/lib/sqreen/instrumentation.rb +504 -0
  31. data/lib/sqreen/log.rb +116 -0
  32. data/lib/sqreen/metrics.rb +6 -0
  33. data/lib/sqreen/metrics/average.rb +39 -0
  34. data/lib/sqreen/metrics/base.rb +41 -0
  35. data/lib/sqreen/metrics/collect.rb +22 -0
  36. data/lib/sqreen/metrics/sum.rb +20 -0
  37. data/lib/sqreen/metrics_store.rb +94 -0
  38. data/lib/sqreen/parsers/sql.rb +98 -0
  39. data/lib/sqreen/parsers/sql_tokenizer.rb +266 -0
  40. data/lib/sqreen/parsers/unix.rb +110 -0
  41. data/lib/sqreen/payload_creator.rb +132 -0
  42. data/lib/sqreen/performance_notifications.rb +86 -0
  43. data/lib/sqreen/performance_notifications/log.rb +36 -0
  44. data/lib/sqreen/performance_notifications/metrics.rb +36 -0
  45. data/lib/sqreen/performance_notifications/newrelic.rb +36 -0
  46. data/lib/sqreen/remote_command.rb +82 -0
  47. data/lib/sqreen/rule_attributes.rb +25 -0
  48. data/lib/sqreen/rule_callback.rb +97 -0
  49. data/lib/sqreen/rules.rb +116 -0
  50. data/lib/sqreen/rules_callbacks.rb +29 -0
  51. data/lib/sqreen/rules_callbacks/binding_accessor_metrics.rb +79 -0
  52. data/lib/sqreen/rules_callbacks/count_http_codes.rb +18 -0
  53. data/lib/sqreen/rules_callbacks/crawler_user_agent_matches.rb +24 -0
  54. data/lib/sqreen/rules_callbacks/crawler_user_agent_matches_metrics.rb +25 -0
  55. data/lib/sqreen/rules_callbacks/execjs.rb +136 -0
  56. data/lib/sqreen/rules_callbacks/headers_insert.rb +20 -0
  57. data/lib/sqreen/rules_callbacks/inspect_rule.rb +20 -0
  58. data/lib/sqreen/rules_callbacks/matcher_rule.rb +103 -0
  59. data/lib/sqreen/rules_callbacks/rails_parameters.rb +14 -0
  60. data/lib/sqreen/rules_callbacks/record_request_context.rb +23 -0
  61. data/lib/sqreen/rules_callbacks/reflected_xss.rb +40 -0
  62. data/lib/sqreen/rules_callbacks/regexp_rule.rb +36 -0
  63. data/lib/sqreen/rules_callbacks/shell.rb +33 -0
  64. data/lib/sqreen/rules_callbacks/shell_env.rb +32 -0
  65. data/lib/sqreen/rules_callbacks/sql.rb +41 -0
  66. data/lib/sqreen/rules_callbacks/system_shell.rb +25 -0
  67. data/lib/sqreen/rules_callbacks/url_matches.rb +25 -0
  68. data/lib/sqreen/rules_callbacks/user_agent_matches.rb +22 -0
  69. data/lib/sqreen/rules_signature.rb +142 -0
  70. data/lib/sqreen/runner.rb +312 -0
  71. data/lib/sqreen/runtime_infos.rb +127 -0
  72. data/lib/sqreen/session.rb +340 -0
  73. data/lib/sqreen/stats.rb +18 -0
  74. data/lib/sqreen/version.rb +6 -0
  75. metadata +95 -34
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3ac827297f3a7ea104931830b85a9725b70b32de
4
- data.tar.gz: 78253b20d5386ab58c3cddbe881aa2d85126e5c5
3
+ metadata.gz: 41eb1593f1c0f104fd9dac3323979b08c926d6b5
4
+ data.tar.gz: 0c8824d5cc42fa088e3ef2245eebbc407aba6d7f
5
5
  SHA512:
6
- metadata.gz: 7f9bdf5c8ce0767298b00cd517818fdace114c82b19d7026f9f1d1cff0b3ce1fc74b43ce6cb1b6b281f76a94a35b99d848a2a817d4bc00453be2092704b4b8da
7
- data.tar.gz: cf71144b30f5e2ceaf59a43bd8e385e49d25fe9aebef92db2db629aa14488ad2ddcbe285ca2d2d0f22d46af0dbf31041d4cc0cfd5504998e665e3e7f6fd62710
6
+ metadata.gz: 76d5df1af7328773782bd01e4e0fab909e6097551fb7595c915c16e5bd326fa349c41a7c4bb5a5ed1d2817f61bcf4519fd6bbdcb57cf2e059b1f6e880a6a9099
7
+ data.tar.gz: d6eeb65b51bd7c0f1913420ced42f29e73ba3daf09381da2524f7c53ff0a44d7f82417b83bc188668cf28aaa3f9110f91c1209df58a0d489126dc0094a362898
@@ -0,0 +1,22 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
4
+
5
+ We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality.
6
+
7
+ Examples of unacceptable behavior by participants include:
8
+
9
+ * The use of sexualized language or imagery
10
+ * Personal attacks
11
+ * Trolling or insulting/derogatory comments
12
+ * Public or private harassment
13
+ * Publishing other's private information, such as physical or electronic addresses, without explicit permission
14
+ * Other unethical or unprofessional conduct.
15
+
16
+ Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team.
17
+
18
+ This code of conduct applies both within project spaces and in public spaces when an individual is representing the project or its community.
19
+
20
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
21
+
22
+ This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.2.0, available at [http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/)
data/README.md ADDED
@@ -0,0 +1,77 @@
1
+ # Sqreen
2
+
3
+ Auto protection for you application.
4
+
5
+ Copyright (c) 2015 Sqreen. All Rights Reserved.
6
+ Please refer to our terms for more information: https://www.sqreen.io/terms.html
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ ```ruby
13
+ gem 'sqreen'
14
+ ```
15
+
16
+ And then execute:
17
+
18
+ $ bundle
19
+
20
+ Or install it yourself as:
21
+
22
+ $ gem install sqreen
23
+
24
+ ## Configuration
25
+
26
+ The only required parameter is your application's `token`.
27
+
28
+ ### By file
29
+ - for Rails:
30
+ ```shell
31
+ $ echo token: your_token > /path/to/RailsApp/config/sqreen.yml
32
+ ```
33
+ - for anything else:
34
+ ```shell
35
+ $ echo token: your_token > ~/sqreen.yml
36
+ ```
37
+
38
+ ### By environment:
39
+ ```shell
40
+ $ export SQREEN_TOKEN=your_token
41
+ ```
42
+
43
+ The following can be set:
44
+
45
+ *file* | *environment*
46
+ ------------|-------------
47
+ token | SQREEN_TOKEN
48
+ url | SQREEN_URL
49
+ verbosity | SQREEN_VERBOSITY
50
+ local_rules | SQREEN_RULES
51
+
52
+ SQREEN_RULES allows the agent to use rules that do not come from the server, but
53
+ from a local file.
54
+
55
+ ## Usage
56
+
57
+ TODO: Write usage instructions here
58
+
59
+ ## Development
60
+
61
+ ```shell
62
+ $ gem install bundler
63
+ $ bundle
64
+ ```
65
+
66
+ Check that everything is all right:
67
+ ```shell
68
+ $ bundle exec rake test
69
+ ```
70
+
71
+ Use `bin/console` for an interactive prompt that will allow you to experiment.
72
+
73
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
74
+
75
+ ## Contributing
76
+
77
+ Bug reports and pull requests are welcome on GitHub at https://github.com/sqreen/RubyAgent. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct.
data/Rakefile ADDED
@@ -0,0 +1,40 @@
1
+ # Copyright (c) 2015 Sqreen. All Rights Reserved.
2
+ # Please refer to our terms for more information: https://www.sqreen.io/terms.html
3
+
4
+ require 'bundler/gem_tasks'
5
+ require 'rake/testtask'
6
+
7
+ if RUBY_VERSION >= '1.9.3'
8
+ require 'ci/reporter/rake/minitest'
9
+ task :testunit => 'ci:setup:minitest'
10
+ else
11
+ task :testunit => :test
12
+ end
13
+
14
+ Rake::TestTask.new do |t|
15
+ t.pattern = 'test/**/*.rb'
16
+ t.libs << 'test'
17
+ end
18
+
19
+ desc 'Run tests'
20
+ task :default => :test
21
+
22
+ task :pre_build do
23
+ version = Bundler::GemHelper.new.send(:version)
24
+ template = <<-EOF.gsub(/^\s{0,3}/m, '')
25
+ # Copyright (c) 2015 Sqreen. All Rights Reserved.
26
+ # Please refer to our terms for more information: https://www.sqreen.io/terms.html
27
+ # Warning This file is auto generated! DO NOT edit.
28
+
29
+ module Sqreen
30
+ VERSION = #{version.to_s.inspect}.freeze
31
+ end
32
+ EOF
33
+ fname = File.join(File.dirname(__FILE__), 'lib', 'sqreen', 'version.rb')
34
+ File.open(fname, 'w') do |f|
35
+ f.puts template
36
+ end
37
+ end
38
+
39
+ default_build = Rake::Task['build']
40
+ default_build.prerequisites.push(Rake::Task['pre_build'])
data/lib/sqreen.rb ADDED
@@ -0,0 +1,67 @@
1
+ # Copyright (c) 2015 Sqreen. All Rights Reserved.
2
+ # Please refer to our terms for more information: https://www.sqreen.io/terms.html
3
+
4
+ require 'sqreen/instrumentation'
5
+ require 'sqreen/session'
6
+ require 'sqreen/runner'
7
+ require 'sqreen/callbacks'
8
+ require 'sqreen/version'
9
+ require 'sqreen/log'
10
+ require 'sqreen/stats'
11
+ require 'sqreen/exception'
12
+ require 'sqreen/configuration'
13
+ require 'sqreen/events/attack'
14
+
15
+ require 'thread'
16
+
17
+ # Auto start the instrumentation.
18
+
19
+ Sqreen.framework.on_start do |framework|
20
+ Thread.new do
21
+ begin
22
+ runner = nil
23
+ configuration = Sqreen.config_init(framework)
24
+ Sqreen.log.debug("Starting Sqreen #{Sqreen::VERSION}")
25
+ framework.sqreen_configuration = configuration
26
+ prevent_startup = Sqreen.framework.prevent_startup
27
+ if !prevent_startup
28
+ runner = Sqreen::Runner.new(configuration, framework)
29
+ runner.do_heartbeat
30
+ runner.run_watcher
31
+ else
32
+ Sqreen.log.debug("#{prevent_startup} prevented Sqreen startup")
33
+ end
34
+ rescue Sqreen::TokenNotFoundException
35
+ Sqreen.log.error "Sorry but we couldn't find your Sqreen token.\nYour application is NOT currently protected by Sqreen.\n\nHave you filled your config/sqreen.yml?\n\n"
36
+ rescue Sqreen::TokenInvalidException
37
+ Sqreen.log.error "Sorry but your Sqreen token appears to be invalid.\nYour application is NOT currently protected by Sqreen.\n\nHave you correctly filled your config/sqreen.yml?\n\n"
38
+ rescue Exception => e
39
+ Sqreen.log.error e.inspect
40
+ Sqreen.log.info e.backtrace.join("\n")
41
+ if runner
42
+ # immediately post exception
43
+ runner.session.post_sqreen_exception(Sqreen::RemoteException.new(e))
44
+ Sqreen.log.debug("runner = #{runner.inspect}")
45
+ begin
46
+ runner.remove_instrumentation
47
+ rescue => remove_exception
48
+ Sqreen.log.error(remove_exception.inspect)
49
+ # We did not managed to remove instrumentation, state is unclear:
50
+ # terminate thread
51
+ return nil
52
+ end
53
+ begin
54
+ runner.logout(false)
55
+ rescue => logout_exception
56
+ Sqreen.log.error(logout_exception.inspect)
57
+ nil
58
+ end
59
+ end
60
+ # Wait a few seconds before retrying
61
+ delay = rand(120)
62
+ Sqreen.log.debug("Sleeping #{delay} seconds before retry")
63
+ sleep(delay)
64
+ retry
65
+ end
66
+ end
67
+ end unless ENV['SQREEN_DISABLE'].to_i == 1
@@ -0,0 +1,184 @@
1
+ # Copyright (c) 2015 Sqreen. All Rights Reserved.
2
+ # Please refer to our terms for more information: https://www.sqreen.io/terms.html
3
+
4
+ require 'strscan'
5
+
6
+ # the value located at the given binding
7
+ class BindingAccessor
8
+ attr_reader :path, :expression, :convert
9
+
10
+ # Expression to be accessed
11
+ # @param expression [String] expression to read
12
+ # @param convert [Boolean] wheter to convert objects to simpler types (Array, Hash, String...)
13
+ def initialize(expression, convert = false)
14
+ @expression = expression
15
+ @path = []
16
+ @convert = convert
17
+ parse(expression)
18
+ end
19
+
20
+ # Resolve this expression for the give binding
21
+ def resolve(binding, framework = nil, instance = nil, arguments = nil, cbdata = nil, last_return = nil)
22
+ env = [framework, instance, arguments, cbdata, last_return]
23
+ value = nil
24
+ @path.each do |component|
25
+ value = resolve_component(value, component, binding, env)
26
+ end
27
+ return convert(value) if @convert
28
+ value
29
+ end
30
+
31
+ protected
32
+
33
+ if binding.respond_to?(:local_variable_get)
34
+ def get_local(name, bind)
35
+ bind.local_variable_get(name)
36
+ end
37
+ else
38
+ def get_local(name, bind)
39
+ eval(name, bind)
40
+ end
41
+ end
42
+
43
+ def resolve_component(current_value, component, binding, env)
44
+ case component[:kind]
45
+ when 'string', 'symbol', 'integer'
46
+ component[:value]
47
+ when 'local-variable'
48
+ get_local(component[:name], binding)
49
+ when 'instance-variable'
50
+ current_value.instance_variable_get("@#{component[:name]}")
51
+ when 'class-variable'
52
+ current_value.class.class_variable_get("@@#{component[:name]}")
53
+ when 'global-variable'
54
+ instance_eval("$#{component[:name]}")
55
+ when 'constant'
56
+ if current_value
57
+ current_value.const_get(component[:name].to_s)
58
+ else
59
+ Object.const_get(component[:name].to_s)
60
+ end
61
+ when 'method'
62
+ current_value.send(component[:name])
63
+ when 'index'
64
+ current_value[component[:index]]
65
+ when 'sqreen-variable'
66
+ resolve_sqreen_variable(component[:name], *env)
67
+ else
68
+ raise "Do not know how to handle this component #{component.inspect}"
69
+ end
70
+ end
71
+
72
+ def resolve_sqreen_variable(what, framework, instance, args, cbdata, rv)
73
+ case what
74
+ when 'data'
75
+ cbdata
76
+ when 'rv'
77
+ rv
78
+ when 'args'
79
+ args
80
+ when 'inst'
81
+ instance
82
+ else
83
+ framework.send(what)
84
+ end
85
+ end
86
+
87
+ def parse(expression)
88
+ @scan = StringScanner.new(expression)
89
+ until @scan.eos?
90
+ pos = @scan.pos
91
+ scalar = scan_scalar
92
+ if scalar
93
+ @path.push scalar
94
+ return
95
+ end
96
+ if @path.size == 0
97
+ scan_push_variable
98
+ else
99
+ scan_push_method
100
+ end
101
+ scan_push_indexes
102
+ scan_push_more_constant if @scan.scan(/\./).nil?
103
+ raise error_state('Scan stuck') if @scan.pos == pos
104
+ end
105
+ end
106
+
107
+ def scan_scalar
108
+ case
109
+ when @scan.scan(/\d+/)
110
+ return { :value => @scan[0].to_i, :kind => 'integer' }
111
+ when @scan.scan(/:(\w+)/)
112
+ return { :value => @scan[1].to_sym, :kind => 'symbol' }
113
+ when @scan.scan(/'((?:\\.|[^\\'])*)'/)
114
+ return { :value => @scan[1], :kind => 'string' }
115
+ end
116
+ end
117
+
118
+ RUBY_IDENTIFIER_CHAR = if ''.respond_to? :encoding
119
+ '[\w\u0080-\u{10ffff}]'
120
+ else
121
+ '[\w\x80-\xFF]'
122
+ end
123
+
124
+ def scan_push_constant
125
+ return unless @scan.scan(/([A-Z]#{RUBY_IDENTIFIER_CHAR}+)/)
126
+ @path << { :name => @scan[1], :kind => 'constant' }
127
+ end
128
+
129
+ def scan_push_more_constant
130
+ while @scan.scan(/::/)
131
+ raise error_state('No more constant') unless scan_push_constant
132
+ end
133
+ end
134
+
135
+ def scan_push_variable
136
+ case
137
+ when @scan.scan(/\$(#{RUBY_IDENTIFIER_CHAR}+)/)
138
+ return @path << { :name => @scan[1], :kind => 'global-variable' }
139
+ when @scan.scan(/@@(#{RUBY_IDENTIFIER_CHAR}+)/)
140
+ return @path << { :name => @scan[1], :kind => 'class-variable' }
141
+ when @scan.scan(/@(#{RUBY_IDENTIFIER_CHAR}+)/)
142
+ return @path << { :name => @scan[1], :kind => 'instance-variable' }
143
+ when @scan.scan(/#\.(\w+)/)
144
+ return @path << { :name => @scan[1], :kind => 'sqreen-variable' }
145
+ when scan_push_constant
146
+ return
147
+ when @scan.scan(/(#{RUBY_IDENTIFIER_CHAR}+)/u)
148
+ return @path << { :name => @scan[1], :kind => 'local-variable' }
149
+ end
150
+ end
151
+
152
+ def scan_push_method
153
+ case
154
+ when @scan.scan(/@@(#{RUBY_IDENTIFIER_CHAR}+)/)
155
+ return @path << { :name => @scan[1], :kind => 'class-variable' }
156
+ when @scan.scan(/@(#{RUBY_IDENTIFIER_CHAR}+)/)
157
+ return @path << { :name => @scan[1], :kind => 'instance-variable' }
158
+ when @scan.scan(/(#{RUBY_IDENTIFIER_CHAR}+)/)
159
+ return @path << { :name => @scan[1], :kind => 'method' }
160
+ end
161
+ end
162
+
163
+ def scan_push_indexes
164
+ while @scan.scan(/\[/)
165
+ scalar = scan_scalar
166
+ raise error_state('Invalid index') unless scalar
167
+ raise error_state('Unfinished index') unless @scan.scan(/\]/)
168
+ @path << { :kind => 'index', :index => scalar[:value] }
169
+ end
170
+ end
171
+
172
+ def error_state(msg)
173
+ "#{msg} at #{@scan.pos} after #{@scan.string[0...@scan.pos]} (#{@scan.string})"
174
+ end
175
+
176
+ def convert(value)
177
+ case value
178
+ when Exception
179
+ return { 'message' => value.message, 'backtrace' => value.backtrace }
180
+ else
181
+ return value
182
+ end
183
+ end
184
+ end
data/lib/sqreen/ca.crt ADDED
@@ -0,0 +1,72 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
3
+ MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
4
+ d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
5
+ ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL
6
+ MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
7
+ LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
8
+ RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm
9
+ +9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW
10
+ PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM
11
+ xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB
12
+ Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3
13
+ hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg
14
+ EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF
15
+ MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA
16
+ FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec
17
+ nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z
18
+ eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF
19
+ hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2
20
+ Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
21
+ vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
22
+ +OkuE6N36B9K
23
+ -----END CERTIFICATE-----
24
+ -----BEGIN CERTIFICATE-----
25
+ MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBY
26
+ MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMo
27
+ R2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEx
28
+ MjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgxCzAJBgNVBAYTAlVTMRYwFAYDVQQK
29
+ Ew1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQcmltYXJ5IENlcnRp
30
+ ZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
31
+ AQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9
32
+ AWbK7hWNb6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjA
33
+ ZIVcFU2Ix7e64HXprQU9nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE0
34
+ 7e9GceBrAqg1cmuXm2bgyxx5X9gaBGgeRwLmnWDiNpcB3841kt++Z8dtd1k7j53W
35
+ kBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGttm/81w7a4DSwDRp35+MI
36
+ mO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G
37
+ A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJ
38
+ KoZIhvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ1
39
+ 6CePbJC/kRYkRj5KTs4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl
40
+ 4b7UVXGYNTq+k+qurUKykG/g/CFNNWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6K
41
+ oKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHaFloxt/m0cYASSJlyc1pZU8Fj
42
+ UjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG1riR/aYNKxoU
43
+ AT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk=
44
+ -----END CERTIFICATE-----
45
+ -----BEGIN CERTIFICATE-----
46
+ MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB
47
+ yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
48
+ ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp
49
+ U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW
50
+ ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0
51
+ aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL
52
+ MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW
53
+ ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln
54
+ biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp
55
+ U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y
56
+ aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1
57
+ nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex
58
+ t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz
59
+ SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG
60
+ BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+
61
+ rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/
62
+ NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E
63
+ BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH
64
+ BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy
65
+ aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv
66
+ MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE
67
+ p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y
68
+ 5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK
69
+ WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ
70
+ 4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N
71
+ hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq
72
+ -----END CERTIFICATE-----