logstash-filter-decrypt 0.0.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1ffee5f64ee92e1cf2bff9126ec72e8029776015
4
+ data.tar.gz: d79a89fba3b9bc3a1f0c2c5915301d99418fc0ba
5
+ SHA512:
6
+ metadata.gz: fdfa04c5a811f139240bfe854e927085a5675b24c4d2f31fb19b2dfd7b1db4591f59c9c1827556a90d56830d101eddc6efe1458204dceac9e4e0c7ac179c8904
7
+ data.tar.gz: 49a860b321c74b53199d7e1cdb527844106b1777d67525d74695585ca8b4c4d83d6e8f6533393396ae3e3fc06cd541bf2d84696ce7ed293d7c6393e74640b8b8
@@ -0,0 +1,5 @@
1
+ ## 2.0.0
2
+ - Plugins were updated to follow the new shutdown semantic, this mainly allows Logstash to instruct input plugins to terminate gracefully,
3
+ instead of using Thread.raise on the plugins' threads. Ref: https://github.com/elastic/logstash/pull/3895
4
+ - Dependency on logstash-core update to 2.0
5
+
@@ -0,0 +1,11 @@
1
+ The following is a list of people who have contributed ideas, code, bug
2
+ reports, or in general have helped logstash along its way.
3
+
4
+ Contributors:
5
+ * Aaron Mildenstein (untergeek)
6
+ * Pier-Hugues Pellerin (ph)
7
+
8
+ Note: If you've sent us patches, bug reports, or otherwise contributed to
9
+ Logstash, and you aren't on the list above and want to be, please let us know
10
+ and we'll make sure you're here. Contributions from folks like you are what make
11
+ open source awesome.
@@ -0,0 +1,2 @@
1
+ # logstash-filter-example
2
+ Example filter plugin. This should help bootstrap your effort to write your own filter plugin!
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright (c) 2012–2016 Elasticsearch <http://www.elastic.co>
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
@@ -0,0 +1,5 @@
1
+ Elasticsearch
2
+ Copyright 2012-2015 Elasticsearch
3
+
4
+ This product includes software developed by The Apache Software
5
+ Foundation (http://www.apache.org/).
@@ -0,0 +1,3 @@
1
+ # Logstash Decrypt Filter
2
+
3
+ Simple Filter to Decrypt XOR and AES Payloads.
@@ -0,0 +1,16 @@
1
+ require 'openssl'
2
+ class Aes < Cipher
3
+
4
+ def decrypt(data,key)
5
+ aes = OpenSSL::Cipher.new('AES-128-CBC')
6
+ aes.decrypt
7
+ aes.key = key
8
+ return aes.update(data)
9
+ end
10
+
11
+ def aesdecrypt
12
+ return match(@payload,@prefix,@keys,@keywords)
13
+
14
+
15
+ end
16
+ end
@@ -0,0 +1,44 @@
1
+ # encoding: utf-8
2
+ require 'base64'
3
+ require 'uri'
4
+ class Cipher
5
+ def initialize(prefix,payload,keys,keywords)
6
+ @prefix=prefix
7
+ @payload=payload
8
+ @keys=keys
9
+ @keywords=keywords
10
+ end
11
+
12
+ #Extract according to prefix
13
+ def extract(payload)
14
+ return payload[@prefix.length..@payload.length]
15
+ end
16
+
17
+ #Decode Payload and unescape Characters
18
+ def decode(payload)
19
+ return Base64.decode64(URI.unescape(payload))
20
+ end
21
+
22
+ def match(payload,prefix,keys,keywords)
23
+ #Match, Payload
24
+ result = [false,'']
25
+ payload = decode(extract(payload))
26
+ keys.each do |key|
27
+ begin
28
+ payload = decrypt(payload, Base64.decode64(key))
29
+ keywords.each do |keyword|
30
+ if payload.include? keyword
31
+ result[0] = true
32
+ result[1] = payload.to_s
33
+ break
34
+ end
35
+ end
36
+ rescue
37
+ return result
38
+ end
39
+ end
40
+
41
+ return result
42
+ end
43
+
44
+ end
@@ -0,0 +1,116 @@
1
+ # encoding: utf-8
2
+ require "logstash/filters/base"
3
+ require "logstash/namespace"
4
+ require "logstash/json"
5
+ require "logstash/timestamp"
6
+ require "logstash/filters/cipher"
7
+ require "logstash/filters/xor"
8
+ require "logstash/filters/aes"
9
+ require 'thread'
10
+
11
+
12
+ class LogStash::Filters::Decrypt < LogStash::Filters::Base
13
+
14
+ # The field to perform filter
15
+ #
16
+ # Example, to use the @message field (default) :
17
+ # [source,ruby]
18
+ # filter { decrypt { source => "message" } }
19
+
20
+ #Config_name for the Logstash Config
21
+ config_name "decrypt"
22
+
23
+ # Replace the message with this value.
24
+ config :source, :validate => :string, :required => true
25
+
26
+
27
+ public
28
+ def register
29
+ # Add instance variables
30
+ @campaigns = Dir.glob("campaigns/*.json")
31
+ end # def register
32
+
33
+ public
34
+ def filter(event)
35
+
36
+ if @source
37
+ source = event.get(@source)
38
+ # Replace the event message with our message as configured in the
39
+ # config file.
40
+ parsed = LogStash::Json.load(source)
41
+
42
+ parsed_timestamp = parsed.delete(LogStash::Event::TIMESTAMP)
43
+ begin
44
+ timestamp = parsed_timestamp ? LogStash::Timestamp.coerce(parsed_timestamp) : nil
45
+ rescue LogStash::TimestampParserError => e
46
+ timestamp = nil
47
+ end
48
+
49
+ threads = []
50
+
51
+ @campaigns.each do |file|
52
+ file = File.read(file)
53
+ campaign = LogStash::Json.load(file)
54
+ @keywordstrategy = nil
55
+ @strategies = campaign['SearchStrategies']
56
+ @strategies.each do |strategy|
57
+ if strategy["type"].eql? "KeywordStrategy"
58
+ @logger.info("Found Keyword Strategy")
59
+ @keywordstrategy = strategy
60
+ end
61
+ end
62
+ if parsed["body"].nil? || parsed["body"].empty?
63
+ @logger.info("Empty Body -> Skip")
64
+ elsif @keywordstrategy.nil?
65
+ @logger.info("No Keyword Strategy found -> Skip")
66
+ elsif parsed["body"].include? @keywordstrategy["prefix"]
67
+ @logger.info("Decrypt Body")
68
+ threads << Thread.new {
69
+
70
+ if campaign["encryption"]["xor"].any?
71
+ xor=Xor.new(@keywordstrategy["prefix"],parsed["body"],campaign["encryption"]["xor"],@keywordstrategy["keywords"])
72
+ result = xor.xordecrypt
73
+ if result[0]
74
+ parsed["decrypted"] = result[1]
75
+ parsed["tags"] = [campaign["name"],"XOR"]
76
+ end
77
+ end
78
+
79
+ if campaign["encryption"]["aes"].any?
80
+ aes=Aes.new(@keywordstrategy["prefix"],parsed["body"],campaign["encryption"]["aes"],@keywordstrategy["keywords"])
81
+ result = aes.aesdecrypt
82
+ if result[0]
83
+ parsed["decrypted"] = result[1]
84
+ parsed["tags"] = [campaign["name"],"AES"]
85
+ end
86
+ end
87
+ }
88
+ else
89
+ @logger.info("Prefix not in Payload -> Skip")
90
+ end
91
+ end
92
+
93
+ threads.each { |thr| thr.join }
94
+
95
+ # using the event.set API
96
+ parsed.each{|k, v| event.set(k, v)}
97
+
98
+ if parsed_timestamp
99
+ if timestamp
100
+ event.timestamp = timestamp
101
+ else
102
+ event.timestamp = LogStash::Timestamp.new
103
+ @logger.warn("Unrecognized #{LogStash::Event::TIMESTAMP} value, setting current time to #{LogStash::Event::TIMESTAMP}, original in #{LogStash::Event::TIMESTAMP_FAILURE_FIELD} field", :value => parsed_timestamp.inspect)
104
+ event.tag(LogStash::Event::TIMESTAMP_FAILURE_TAG)
105
+ event.set(LogStash::Event::TIMESTAMP_FAILURE_FIELD, parsed_timestamp.to_s)
106
+ end
107
+ end
108
+ # correct debugging log statement for reference
109
+ # using the event.get API
110
+ @logger.info("Event after filter", :event => event)
111
+ end
112
+
113
+ # filter_matched should go in the last line of our successful code
114
+ filter_matched(event)
115
+ end # def filter
116
+ end # class LogStash::Filters::Example
@@ -0,0 +1,16 @@
1
+ # encoding: utf-8
2
+ class Xor < Cipher
3
+
4
+ def decrypt(data, key)
5
+ data.length.times { |e|
6
+ data[e] = (key[e % key.length].ord ^ data[e].ord).chr;
7
+ }
8
+ return data
9
+ end
10
+
11
+ #Decrypt Payload and match it against Keywords
12
+ def xordecrypt
13
+ return match(@payload,@prefix,@keys,@keywords)
14
+ end
15
+
16
+ end
@@ -0,0 +1,23 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'logstash-filter-decrypt'
3
+ s.version = '0.0.2'
4
+ s.licenses = ['Apache License (2.0)']
5
+ s.summary = "Decrypt Filter for XOR Trojan"
6
+ s.description = "This is a Logstash Filter to be installed on a logstash instance"
7
+ s.authors = ["Silvan Adrian, Fabian Binna"]
8
+ s.email = 'silvan.adrian@gmail.com'
9
+ s.homepage = ""
10
+ s.require_paths = ["lib"]
11
+
12
+ # Files
13
+ s.files = Dir['lib/**/*','spec/**/*','vendor/**/*','*.gemspec','*.md','CONTRIBUTORS','Gemfile','LICENSE','NOTICE.TXT']
14
+ # Tests
15
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
16
+
17
+ # Special flag to let us know this is actually a logstash plugin
18
+ s.metadata = { "logstash_plugin" => "true", "logstash_group" => "filter" }
19
+
20
+ # Gem dependencies
21
+ s.add_runtime_dependency "logstash-core-plugin-api", "~> 2.0"
22
+ s.add_development_dependency 'logstash-devutils' , '~> 0'
23
+ end
@@ -0,0 +1,20 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+ require "logstash/filters/decrypt"
4
+
5
+ describe LogStash::Filters::Decrypt do
6
+ describe "Set to Hello World" do
7
+ let(:config) do <<-CONFIG
8
+ filter {
9
+ decrypt {
10
+ message => "Hello World"
11
+ }
12
+ }
13
+ CONFIG
14
+ end
15
+
16
+ sample("message" => "some text") do
17
+ expect(subject.get("message")).to eq('Hello World')
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,2 @@
1
+ # encoding: utf-8
2
+ require "logstash/devutils/rspec/spec_helper"
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: logstash-filter-decrypt
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Silvan Adrian, Fabian Binna
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-03-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: logstash-core-plugin-api
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: logstash-devutils
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: This is a Logstash Filter to be installed on a logstash instance
42
+ email: silvan.adrian@gmail.com
43
+ executables: []
44
+ extensions: []
45
+ extra_rdoc_files: []
46
+ files:
47
+ - CHANGELOG.md
48
+ - CONTRIBUTORS
49
+ - DEVELOPER.md
50
+ - Gemfile
51
+ - LICENSE
52
+ - NOTICE.TXT
53
+ - README.md
54
+ - lib/logstash/filters/aes.rb
55
+ - lib/logstash/filters/cipher.rb
56
+ - lib/logstash/filters/decrypt.rb
57
+ - lib/logstash/filters/xor.rb
58
+ - logstash-filter-decrypt.gemspec
59
+ - spec/filters/decrypt_spec.rb
60
+ - spec/spec_helper.rb
61
+ homepage: ''
62
+ licenses:
63
+ - Apache License (2.0)
64
+ metadata:
65
+ logstash_plugin: 'true'
66
+ logstash_group: filter
67
+ post_install_message:
68
+ rdoc_options: []
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ requirements: []
82
+ rubyforge_project:
83
+ rubygems_version: 2.6.4
84
+ signing_key:
85
+ specification_version: 4
86
+ summary: Decrypt Filter for XOR Trojan
87
+ test_files:
88
+ - spec/filters/decrypt_spec.rb
89
+ - spec/spec_helper.rb