snort-rule 1.0.2 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 814357ce2643e9bde5663248cb35dbd708c4616e
4
- data.tar.gz: ff24fe59ef9d47ff9bb6ff82daa4a4da497ed871
3
+ metadata.gz: 5769406b39c3f4e4d6f69f7e93dedb7480569ede
4
+ data.tar.gz: 87099f070762d3fe352aa9394dc9ee7faf366265
5
5
  SHA512:
6
- metadata.gz: b9f683cfb2fc3cfce9530091d43d5cead649e95d8aae5304f4c64adaa938f14ed369a5c4d8c43dc4f7e4466b01ccda720f0288d7ade910777f3fa76dda010466
7
- data.tar.gz: d3d8f96ae04a7b3276e2b7be1344c902bbe1e6f13067cd4903f8508bab110768336c7bf35a489a5468efae4de56c7da70b39d3a0941e6e8c213e7a7b9b4acd71
6
+ metadata.gz: 9985ac508c0dd80e357e6b7885537b9682f0a7ea0d1b7cacf5d3b3730c22f243d3cf861f36dd6194571e1dd8b78c3e1e798ebb4df0e22410affd2ba6fb2cc773
7
+ data.tar.gz: 588b14c3522b7283b13c1c481133c83c7fc50510abf73c74f0d87c2f8ae6d7cf995f3b023c8a066d0a19e75b974b948c211f251df13913ddf7f8f6d44d10ced2
data/README.md CHANGED
@@ -18,11 +18,12 @@ Or install it yourself as:
18
18
 
19
19
  ## Usage
20
20
 
21
- rule = Snort::Rule.new({:action => 'pass', :proto => 'udp', :src => '192.168.0.1', :sport => 'any', :dir => '<>', :dst => 'any', :dport => 53, :opts => {'sid' => 48, 'threshold' => 'type limit,track by_src,count 1,seconds 3600' }})
22
-
21
+ rule = Snort::Rule.new({:enabled => true, :action => 'pass', :proto => 'udp', :src => '192.168.0.1', :sport => 'any', :dir => '<>', :dst => 'any', :dport => 53, :opts => {'sid' => 48, 'threshold' => 'type limit,track by_src,count 1,seconds 3600' }})
22
+
23
23
  rule.to_s => "pass udp 192.168.0.1 any <> any 53 ( sid:48; threshold:type limit,track by_src,count 1,seconds 3600; )"
24
24
 
25
25
  rule = Snort::Rule.new
26
+ rule.enabled = false
26
27
  rule.action = 'pass'
27
28
  rule.proto = 'udp'
28
29
  rule.src = '192.168.0.1'
@@ -30,8 +31,9 @@ Or install it yourself as:
30
31
  rule.dport = 53
31
32
  rule.opts['sid'] = 48
32
33
  rule.opts['threshold'] = 'type limit,track by_src,count 1,seconds 3600'
33
-
34
- rule.to_s => "pass udp 192.168.0.1 any <> any 53 ( sid:48; threshold:type limit,track by_src,count 1,seconds 3600; )"
34
+
35
+ # if the rule is disabled, then it will begin with a #
36
+ rule.to_s => "#pass udp 192.168.0.1 any <> any 53 ( sid:48; threshold:type limit,track by_src,count 1,seconds 3600; )"
35
37
 
36
38
  rule = Snort::Rule.parse("pass udp 192.168.0.1 any <> any 53 ( sid:48; threshold:type limit,track by_src,count 1,seconds 3600; )")
37
39
  rule.to_s => "pass udp 192.168.0.1 any <> any 53 ( sid:48; threshold:type limit,track by_src,count 1,seconds 3600; )"
@@ -43,3 +45,5 @@ Or install it yourself as:
43
45
  3. Commit your changes (`git commit -am 'Add some feature'`)
44
46
  4. Push to the branch (`git push origin my-new-feature`)
45
47
  5. Create new Pull Request
48
+
49
+ Thanks so much for those who have already contributed.
data/bin/snortrule CHANGED
@@ -4,8 +4,9 @@ require 'getoptlong'
4
4
  require 'snort/rule'
5
5
 
6
6
  def usage
7
- puts "Usage: #{$0} [-h] [-a <action>] [-p <protocol>] [-s <srcip>] [-x <srcport>] [-w <direction>] [-d <dstip>] [-c <dstport>] [-o <key:value>] [-o <key:value> ...]"
7
+ puts "Usage: #{$0} [-hE] [-a <action>] [-p <protocol>] [-s <srcip>] [-x <srcport>] [-w <direction>] [-d <dstip>] [-c <dstport>] [-o <key:value>] [-o <key:value> ...]"
8
8
  puts "-h This text."
9
+ puts "-E Not enabled. i.e., commented out"
9
10
  puts "-a <action> alert, log, pass, ... : alert"
10
11
  puts "-p <protocol> ip, udp, tcp, ... : ip"
11
12
  puts "-s <srcip> dotted quad IP address : any"
@@ -19,6 +20,8 @@ end
19
20
 
20
21
  opts = GetoptLong.new(
21
22
  [ '--help', '-h', GetoptLong::NO_ARGUMENT ],
23
+ [ '--disabled', '-E', GetoptLong::NO_ARGUMENT ],
24
+ [ '--rule', '-r', GetoptLong::REQUIRED_ARGUMENT ],
22
25
  [ '--action', '-a', GetoptLong::REQUIRED_ARGUMENT ],
23
26
  [ '--proto', '-p', GetoptLong::REQUIRED_ARGUMENT ],
24
27
  [ '--src', '-s', GetoptLong::REQUIRED_ARGUMENT ],
@@ -34,6 +37,11 @@ opts.each do |opt, arg|
34
37
  case opt
35
38
  when '--help'
36
39
  usage
40
+ when '--disabled'
41
+ rule.enabled = false
42
+ when '--rule'
43
+ # TODO: regex sanity check here? better to fail gracefully.
44
+ rule = Snort::Rule.parse(arg)
37
45
  when '--action'
38
46
  rule.action = arg
39
47
  when '--proto'
@@ -1,5 +1,5 @@
1
1
  module Snort
2
2
  class Rule
3
- VERSION = "1.0.2"
3
+ VERSION = "1.1.1"
4
4
  end
5
5
  end
data/lib/snort/rule.rb CHANGED
@@ -2,18 +2,21 @@ require "snort/rule/version"
2
2
  require "snort/rule/option"
3
3
  # Generates and parses snort rules
4
4
  #
5
- # Authors:: Chris Lee (mailto:rubygems@chrislee.dhs.org), Will Green (will[ at ]hotgazpacho[ dot ]org)
5
+ # Authors:: Chris Lee (mailto:rubygems@chrislee.dhs.org),
6
+ # Will Green (will[ at ]hotgazpacho[ dot ]org),
7
+ # Justin Knox (jknox[ at ]indexzero[ dot ]org)
6
8
  # Copyright:: Copyright (c) 2011 Chris Lee
7
9
  # License:: Distributes under the same terms as Ruby
8
10
  module Snort
9
11
 
10
12
  # This class stores and generates the features of a snort rule
11
13
  class Rule
12
- attr_accessor :action, :proto, :src, :sport, :dir, :dst, :dport
14
+ attr_accessor :enabled, :action, :proto, :src, :sport, :dir, :dst, :dport
13
15
  attr_reader :options
14
16
 
15
17
  # Initializes the Rule
16
18
  # @param [Hash] kwargs The options to initialize the Rule with
19
+ # @option kwargs [String] :enabled true or false
17
20
  # @option kwargs [String] :action The action
18
21
  # @option kwargs [String] :proto The protocol
19
22
  # @option kwargs [String] :src The source IP
@@ -24,6 +27,10 @@ module Snort
24
27
  # @option kwargs[Array<Snort::RuleOption>] :options The better way of passing in options, using
25
28
  # option objects that know how to represent themselves as a string properly
26
29
  def initialize(kwargs={})
30
+ @enabled = true
31
+ if kwargs.has_key?(:enabled) and (not kwargs[:enabled] or ['false', 'no', 'off'].index(kwargs[:enabled].to_s.downcase))
32
+ @enabled = false
33
+ end
27
34
  @action = kwargs[:action] || 'alert'
28
35
  @proto = kwargs[:proto] || 'IP'
29
36
  @src = kwargs[:src] || 'any'
@@ -37,7 +44,10 @@ module Snort
37
44
  # Output the current object into a snort rule
38
45
  def to_s(options_only=false)
39
46
  rule = ""
40
- rule = [@action, @proto, @src, @sport, @dir, @dst, @dport].join(" ") unless options_only
47
+ if not @enabled
48
+ rule = "#"
49
+ end
50
+ rule += [@action, @proto, @src, @sport, @dir, @dst, @dport].join(" ") unless options_only
41
51
  if options.any?
42
52
  rule += " (" unless options_only
43
53
  rule += options.join(' ')
@@ -49,8 +59,18 @@ module Snort
49
59
  # Parse a snort rule to generate an object
50
60
  def Rule::parse(string)
51
61
  rule = Snort::Rule.new
62
+ # If the string begins with /^#+\s*/, then the rule is disabled.
63
+ # If disabled, let's scrub the disabling substring from the string.
64
+ if string.index(/^#+\s+/)
65
+ rule.enabled = false
66
+ string.gsub!(/^#+\s*/,'')
67
+ end
52
68
  rulepart, optspart = string.split(/\s*\(\s*/,2)
53
69
  rule.action, rule.proto, rule.src, rule.sport, rule.dir, rule.dst, rule.dport = rulepart.split(/\s+/)
70
+ if not ['<>', '<-', '->'].index(rule.dir)
71
+ # most likely, I have a parse error, maybe it's just a random comment
72
+ raise ArgumentError.new("Unable to parse rule, #{rulepart}")
73
+ end
54
74
  optspart.gsub(/;\s*\).*$/,'').split(/\s*;\s*/).each do |x|
55
75
  if x =~ /(.*?):(.*)/
56
76
  rule.options << Snort::RuleOption.new(*x.split(/:/,2))
data/snort-rule.gemspec CHANGED
@@ -23,6 +23,6 @@ Gem::Specification.new do |spec|
23
23
  spec.add_development_dependency "minitest"
24
24
  spec.add_development_dependency "guard-minitest"
25
25
 
26
- spec.signing_key = "#{File.dirname(__FILE__)}/../gem-private_key.pem"
27
- spec.cert_chain = ["#{File.dirname(__FILE__)}/../gem-public_cert.pem"]
26
+ #spec.signing_key = "#{File.dirname(__FILE__)}/../gem-private_key.pem"
27
+ #spec.cert_chain = ["#{File.dirname(__FILE__)}/../gem-public_cert.pem"]
28
28
  end
data/test/helper.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  require 'minitest/autorun'
2
2
  require 'minitest/pride'
3
- require File.expand_path('../../lib/snort/rule.rb', __FILE__)
3
+ require File.expand_path('../../lib/snort/rule.rb', __FILE__)
@@ -10,8 +10,8 @@ require_relative 'helper'
10
10
 
11
11
  class TestSnortRule < Minitest::Test
12
12
  def test_constructor_should_set_all_the_parameters_and_generate_the_correct_rule
13
- rule = Snort::Rule.new({:action => 'pass', :proto => 'udp', :src => '192.168.0.1', :sport => 'any', :dir => '<>',
14
- :dst => 'any', :dport => 53,
13
+ rule = Snort::Rule.new({:enabled => true, :action => 'pass', :proto => 'udp', :src => '192.168.0.1', :sport => 'any', :dir => '<>',
14
+ :dst => 'any', :dport => 53,
15
15
  :options => [Snort::RuleOption.new('sid', 48), Snort::RuleOption.new('threshold', 'type limit,track by_src,count 1,seconds 3600')]
16
16
  })
17
17
  assert_equal rule.to_s, "pass udp 192.168.0.1 any <> any 53 (sid:48; threshold:type limit,track by_src,count 1,seconds 3600;)"
@@ -19,6 +19,7 @@ class TestSnortRule < Minitest::Test
19
19
 
20
20
  def test_construct_a_default_rule_and_update_each_member_to_generate_the_correct_rule
21
21
  rule = Snort::Rule.new
22
+ rule.enabled = true
22
23
  rule.action = 'pass'
23
24
  rule.proto = 'udp'
24
25
  rule.src = '192.168.0.1'
@@ -31,6 +32,7 @@ class TestSnortRule < Minitest::Test
31
32
 
32
33
  def test_construct_a_default_rule_with_many_options_having_the_same_keyword
33
34
  rule = Snort::Rule.new
35
+ rule.enabled = true
34
36
  rule.action = 'alert'
35
37
  rule.proto = 'tcp'
36
38
  rule.src = '$HOME_NET'
@@ -52,8 +54,49 @@ class TestSnortRule < Minitest::Test
52
54
  assert_equal 'alert tcp $HOME_NET any -> $EXTERNAL_NET $HTTP_PORTS (msg:"HTTP Host www.baddomain.com"; content:"Host|3a|"; nocase; http_header; content:"www.baddomain.com"; nocase; http_header; pcre:"/^Host\x3a(.*\.|\s*)www\.baddomain\.com\s*$/mi"; flow:to_server,established; threshold:type limit, track by_src, count 1, seconds 300; classtype:bad-unknown; sid:100000000;)', rule.to_s
53
55
  end
54
56
 
57
+ def test_construct_a_disabled_default_rule_with_many_options_having_the_same_keyword
58
+ rule = Snort::Rule.new
59
+ rule.enabled = false
60
+ rule.action = 'alert'
61
+ rule.proto = 'tcp'
62
+ rule.src = '$HOME_NET'
63
+ rule.dir = '->'
64
+ rule.dst = '$EXTERNAL_NET'
65
+ rule.dport = '$HTTP_PORTS'
66
+ rule.options << Snort::RuleOption.new('msg', '"HTTP Host www.baddomain.com"')
67
+ rule.options << Snort::RuleOption.new('content', '"Host|3a|"')
68
+ rule.options << Snort::RuleOption.new('nocase')
69
+ rule.options << Snort::RuleOption.new('http_header')
70
+ rule.options << Snort::RuleOption.new('content', '"www.baddomain.com"')
71
+ rule.options << Snort::RuleOption.new('nocase')
72
+ rule.options << Snort::RuleOption.new('http_header')
73
+ rule.options << Snort::RuleOption.new('pcre', '"/^Host\\x3a(.*\\.|\\s*)www\\.baddomain\\.com\\s*$/mi"')
74
+ rule.options << Snort::RuleOption.new('flow', 'to_server,established')
75
+ rule.options << Snort::RuleOption.new('threshold', 'type limit, track by_src, count 1, seconds 300')
76
+ rule.options << Snort::RuleOption.new('classtype', 'bad-unknown')
77
+ rule.options << Snort::RuleOption.new('sid', '100000000')
78
+ assert_equal '#alert tcp $HOME_NET any -> $EXTERNAL_NET $HTTP_PORTS (msg:"HTTP Host www.baddomain.com"; content:"Host|3a|"; nocase; http_header; content:"www.baddomain.com"; nocase; http_header; pcre:"/^Host\x3a(.*\.|\s*)www\.baddomain\.com\s*$/mi"; flow:to_server,established; threshold:type limit, track by_src, count 1, seconds 300; classtype:bad-unknown; sid:100000000;)', rule.to_s
79
+ end
80
+
55
81
  def test_parse_an_existing_rule_and_generate_the_same_rule
56
82
  rule = Snort::Rule.parse("pass udp 192.168.0.1 any <> any 53 ( sid:48; threshold:type limit,track by_src,count 1,seconds 3600; )")
57
83
  assert_equal rule.to_s, "pass udp 192.168.0.1 any <> any 53 (sid:48; threshold:type limit,track by_src,count 1,seconds 3600;)"
58
84
  end
85
+
86
+ def test_parse_an_existing_disabled_rule_and_generate_the_same_rule
87
+ rule = Snort::Rule.parse("#pass udp 192.168.0.1 any <> any 53 ( sid:48; threshold:type limit,track by_src,count 1,seconds 3600; )")
88
+ assert_equal rule.to_s, "#pass udp 192.168.0.1 any <> any 53 (sid:48; threshold:type limit,track by_src,count 1,seconds 3600;)"
89
+ end
90
+
91
+ def test_parse_a_disabled_rule_and_generate_the_normalized_disabled_rule
92
+ rule = Snort::Rule.parse("### pass udp 192.168.0.1 any <> any 53 ( sid:48; threshold:type limit,track by_src,count 1,seconds 3600; )")
93
+ assert_equal rule.to_s, "#pass udp 192.168.0.1 any <> any 53 (sid:48; threshold:type limit,track by_src,count 1,seconds 3600;)"
94
+ end
95
+
96
+ def test_parse_a_garbled_rule_and_throws_an_exception
97
+ assert_raises ArgumentError do
98
+ Snort::Rule.parse("pass udp 192.168.0.1 bla bla bla 53 ( sid:48; threshold:type limit,track by_src,count 1,seconds 3600; )")
99
+ end
100
+ end
101
+
59
102
  end
@@ -37,4 +37,4 @@ class TestSnortRuleOption < Minitest::Test
37
37
  assert_equal option1.hash, option2.hash
38
38
  end
39
39
 
40
- end
40
+ end
metadata CHANGED
@@ -1,91 +1,69 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: snort-rule
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - chrislee35
8
8
  autorequire:
9
9
  bindir: bin
10
- cert_chain:
11
- - |
12
- -----BEGIN CERTIFICATE-----
13
- MIIDYjCCAkqgAwIBAgIBADANBgkqhkiG9w0BAQUFADBXMREwDwYDVQQDDAhydWJ5
14
- Z2VtczEYMBYGCgmSJomT8ixkARkWCGNocmlzbGVlMRMwEQYKCZImiZPyLGQBGRYD
15
- ZGhzMRMwEQYKCZImiZPyLGQBGRYDb3JnMB4XDTEzMDUyMjEyNTk0N1oXDTE0MDUy
16
- MjEyNTk0N1owVzERMA8GA1UEAwwIcnVieWdlbXMxGDAWBgoJkiaJk/IsZAEZFghj
17
- aHJpc2xlZTETMBEGCgmSJomT8ixkARkWA2RoczETMBEGCgmSJomT8ixkARkWA29y
18
- ZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANcPrx8BZiWIR9xWWG8I
19
- tqR538tS1t+UJ4FZFl+1vrtU9TiuWX3Vj37TwUpa2fFkziK0n5KupVThyEhcem5m
20
- OGRjvgrRFbWQJSSscIKOpwqURHVKRpV9gVz/Hnzk8S+xotUR1Buo3Ugr+I1jHewD
21
- Cgr+y+zgZbtjtHsJtsuujkOcPhEjjUinj68L9Fz9BdeJQt+IacjwAzULix6jWCht
22
- Uc+g+0z8Esryca2G6I1GsrgX6WHw8dykyQDT9dCtS2flCOwSC1R0K5T/xHW54f+5
23
- wcw8mm53KLNe+tmgVC6ZHyME+qJsBnP6uxF0aTEnGA/jDBQDhQNTF0ZP/abzyTsL
24
- zjUCAwEAAaM5MDcwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFO8w
25
- +aeP7T6kVJblCg6eusOII9DfMA0GCSqGSIb3DQEBBQUAA4IBAQBCQyRJLXsBo2Fy
26
- 8W6e/W4RemQRrlAw9DK5O6U71JtedVob2oq+Ob+zmS+PifE2+L+3RiJ2H6VTlOzi
27
- x+A061MUXhGraqVq4J2FC8kt4EQywAD0P0Ta5GU24CGSF08Y3GkJy1Sa4XqTC2YC
28
- o51s7JP+tkCCtpVYSdzJhTllieRAWBpGV1dtaoeUKE6tYPMBkosxSRcVGczk/Sc3
29
- 7eQCpexYy9JlUBI9u3BqIY9E+l+MSn8ihXSPmyK0DgrhaCu+voaSFVOX6Y+B5qbo
30
- jLXMQu2ZgISYwXNjNbGVHehut82U7U9oiHoWcrOGazaRUmGO9TXP+aJLH0gw2dcK
31
- AfMglXPi
32
- -----END CERTIFICATE-----
33
- date: 2014-05-02 00:00:00.000000000 Z
10
+ cert_chain: []
11
+ date: 2014-10-05 00:00:00.000000000 Z
34
12
  dependencies:
35
13
  - !ruby/object:Gem::Dependency
36
14
  name: bundler
37
15
  requirement: !ruby/object:Gem::Requirement
38
16
  requirements:
39
- - - ~>
17
+ - - "~>"
40
18
  - !ruby/object:Gem::Version
41
19
  version: '1.3'
42
20
  type: :development
43
21
  prerelease: false
44
22
  version_requirements: !ruby/object:Gem::Requirement
45
23
  requirements:
46
- - - ~>
24
+ - - "~>"
47
25
  - !ruby/object:Gem::Version
48
26
  version: '1.3'
49
27
  - !ruby/object:Gem::Dependency
50
28
  name: rake
51
29
  requirement: !ruby/object:Gem::Requirement
52
30
  requirements:
53
- - - '>='
31
+ - - ">="
54
32
  - !ruby/object:Gem::Version
55
33
  version: '0'
56
34
  type: :development
57
35
  prerelease: false
58
36
  version_requirements: !ruby/object:Gem::Requirement
59
37
  requirements:
60
- - - '>='
38
+ - - ">="
61
39
  - !ruby/object:Gem::Version
62
40
  version: '0'
63
41
  - !ruby/object:Gem::Dependency
64
42
  name: minitest
65
43
  requirement: !ruby/object:Gem::Requirement
66
44
  requirements:
67
- - - '>='
45
+ - - ">="
68
46
  - !ruby/object:Gem::Version
69
47
  version: '0'
70
48
  type: :development
71
49
  prerelease: false
72
50
  version_requirements: !ruby/object:Gem::Requirement
73
51
  requirements:
74
- - - '>='
52
+ - - ">="
75
53
  - !ruby/object:Gem::Version
76
54
  version: '0'
77
55
  - !ruby/object:Gem::Dependency
78
56
  name: guard-minitest
79
57
  requirement: !ruby/object:Gem::Requirement
80
58
  requirements:
81
- - - '>='
59
+ - - ">="
82
60
  - !ruby/object:Gem::Version
83
61
  version: '0'
84
62
  type: :development
85
63
  prerelease: false
86
64
  version_requirements: !ruby/object:Gem::Requirement
87
65
  requirements:
88
- - - '>='
66
+ - - ">="
89
67
  - !ruby/object:Gem::Version
90
68
  version: '0'
91
69
  description: Parses and generates Snort rules similar to PERL's Snort::Rule
@@ -96,7 +74,7 @@ executables:
96
74
  extensions: []
97
75
  extra_rdoc_files: []
98
76
  files:
99
- - .gitignore
77
+ - ".gitignore"
100
78
  - Gemfile
101
79
  - Guardfile
102
80
  - LICENSE.txt
@@ -120,17 +98,17 @@ require_paths:
120
98
  - lib
121
99
  required_ruby_version: !ruby/object:Gem::Requirement
122
100
  requirements:
123
- - - '>='
101
+ - - ">="
124
102
  - !ruby/object:Gem::Version
125
103
  version: '0'
126
104
  required_rubygems_version: !ruby/object:Gem::Requirement
127
105
  requirements:
128
- - - '>='
106
+ - - ">="
129
107
  - !ruby/object:Gem::Version
130
108
  version: '0'
131
109
  requirements: []
132
110
  rubyforge_project:
133
- rubygems_version: 2.1.11
111
+ rubygems_version: 2.2.2
134
112
  signing_key:
135
113
  specification_version: 4
136
114
  summary: Class for parsing and generating Snort Rules
checksums.yaml.gz.sig DELETED
Binary file
data.tar.gz.sig DELETED
Binary file
metadata.gz.sig DELETED
@@ -1,3 +0,0 @@
1
- �����<R@���%��������n�W��pWx��
2
- �ڏH
3
- s�`����if&Z@��������l�����9ʥky��:�����G�UA�6�@B��ck�ىs���W��� �����9��b�гˢ�J9|"ߑ�-� 8}�z˝���<��Y���̿��k�� �s�A��j`
4
- 0u� ��Ar,�%<���,C�