snort-rule 1.2.0 → 1.3.0

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: 983c58cf46f3b4d8c65327fa4bedcc2e1edebe93
4
- data.tar.gz: 45fbd8510d45346efd45603d3b350b1034b556e3
3
+ metadata.gz: 29dd2030dcab15c7a79fe409f387f365833d6ef9
4
+ data.tar.gz: c000e78ab850620360e3cf169a6675081b43f067
5
5
  SHA512:
6
- metadata.gz: dca88327fc2206fe1f8067665815b535d9d2624ddcee0e4a4a4c6e03ffc276a0cc93a1a0b6177c8c73209abe099177abfe4aa888742345302391368fc3f34927
7
- data.tar.gz: c6eb769c685cddc3c6195fb27f9b1d40d7cb547083e0d5932c9179986216a90c9bc8d91a642f38d07d79f0fa2f69799c356a3951c5d63ad727afee125e7920ef
6
+ metadata.gz: 719fa4d1026c38c683d06364c16c930be551c3dca3fe4b67493e23d6f33d52125a5d74bd9e05cb0b2528469792cac3e3cdcd70dcd0a29eb38b15d566879b5d27
7
+ data.tar.gz: 9158d07dc87858e5179bb6355f8b3e285645db5c65e14bf2e8f1ec6bf82a46ce669abe9c38cc59f7ddcc1f7a125bbe282b10f788d1ecb50f11ba38c905910f81
data/README.md CHANGED
@@ -19,9 +19,9 @@ Or install it yourself as:
19
19
  ## Usage
20
20
 
21
21
  require 'snort/rule'
22
- 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
+ rule = Snort::Rule.new({:enabled => true, :action => 'pass', :proto => 'udp', :src => '192.168.0.1', :sport => 'any', :dir => '<>', :dst => 'any', :dport => 53, :options => {'sid' => 48, 'threshold' => 'type limit,track by_src,count 1,seconds 3600' }})
23
23
 
24
- 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
+ rule.to_s # => "pass udp 192.168.0.1 any <> any 53 ( sid:48; threshold:type limit,track by_src,count 1,seconds 3600; )"
25
25
 
26
26
  rule = Snort::Rule.new
27
27
  rule.enabled = false
@@ -30,21 +30,22 @@ Or install it yourself as:
30
30
  rule.src = '192.168.0.1'
31
31
  rule.dir = '<>'
32
32
  rule.dport = 53
33
- rule.options << Snort::RuleOption.new('sid', 48)
34
- rule.options << Snort::RuleOption.new('threshold', 'type limit,track by_src,count 1,seconds 3600')
35
- rule.options << Snort::RuleOption.new('ref', 'ref1')
36
- rule.options << Snort::RuleOption.new('ref', 'ref2')
33
+ rule.add_option(Snort::RuleOption.new('sid', 48))
34
+ rule.add_option(Snort::RuleOption.new('threshold', 'type limit,track by_src,count 1,seconds 3600'))
35
+ rule.add_option(Snort::RuleOption.new('ref', 'ref1'))
36
+ rule.add_option(Snort::RuleOption.new('ref', ['ref2', 'nocase']))
37
37
  rule.options.each do |opt|
38
38
  puts opt
39
39
  end
40
- rule.options_hash["sid"] == 48
41
- rule.options_hash["ref"] == "ref2"
40
+ rule.options_hash["sid"][0].arguments[0] # => 48
41
+ rule.options_hash["ref"][1].arguments[0] # => "ref2"
42
+ rule.options_hash["ref"][1].arguments[1] # => "nocase"
42
43
 
43
44
  # if the rule is disabled, then it will begin with a #
44
- rule.to_s => "#pass udp 192.168.0.1 any <> any 53 ( sid:48; threshold:type limit,track by_src,count 1,seconds 3600; )"
45
+ rule.to_s # => #pass udp 192.168.0.1 any <> any 53 (sid:48; threshold:type limit,track by_src,count 1,seconds 3600; sid:48; threshold:type limit,track by_src,count 1,seconds 3600; ref:ref1; ref:ref2; nocase;)"
45
46
 
46
- 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; )")
47
- rule.to_s => "pass udp 192.168.0.1 any <> any 53 ( sid:48; threshold:type limit,track by_src,count 1,seconds 3600; )"
47
+ 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; ref:ref1; ref:ref2;)")
48
+ rule.to_s # => "pass udp 192.168.0.1 any <> any 53 (sid:48; threshold:type limit,track by_src,count 1,seconds 3600; ref:ref1; ref:ref2;)"
48
49
 
49
50
  ## Contributing
50
51
 
@@ -5,6 +5,7 @@ require "snort/rule/option"
5
5
  # Authors:: Chris Lee (mailto:rubygems@chrislee.dhs.org),
6
6
  # Will Green (will[ at ]hotgazpacho[ dot ]org),
7
7
  # Justin Knox (jknox[ at ]indexzero[ dot ]org)
8
+ # Ryan Barnett (rbarnett[ at ]modsecurity[ dot ]org)
8
9
  # Copyright:: Copyright (c) 2011 Chris Lee
9
10
  # License:: Distributes under the same terms as Ruby
10
11
  module Snort
@@ -13,7 +14,7 @@ module Snort
13
14
  class Rule
14
15
  attr_accessor :enabled, :action, :proto, :src, :sport, :dir, :dst, :dport, :options_hash
15
16
  attr_reader :options
16
-
17
+
17
18
  # Initializes the Rule
18
19
  # @param [Hash] kwargs The options to initialize the Rule with
19
20
  # @option kwargs [String] :enabled true or false
@@ -38,8 +39,13 @@ module Snort
38
39
  @dir = kwargs[:dir] || '->'
39
40
  @dst = kwargs[:dst] || 'any'
40
41
  @dport = kwargs[:dport] || 'any'
41
- @options = kwargs[:options] || []
42
- @options_hash = Hash[@options.map {|x| [x.keyword, x.arguments]}]
42
+ @options = []
43
+ @options_hash = {}
44
+ if kwargs[:options]
45
+ kwargs[:options].each do |opt|
46
+ add_option(opt)
47
+ end
48
+ end
43
49
  end
44
50
 
45
51
  # Output the current object into a snort rule
@@ -58,13 +64,21 @@ module Snort
58
64
  end
59
65
 
60
66
  def add_option(option)
67
+ if option.class == Array
68
+ option = Snort::RuleOption.new(option[0], option[1,100])
69
+ end
61
70
  @options << option
62
- @options_hash = Hash[@options.map {|x| [x.keyword, x.arguments]}]
71
+ unless @options_hash[option.keyword]
72
+ @options_hash[option.keyword] = []
73
+ end
74
+ @options_hash[option.keyword] << option
63
75
  end
64
76
 
65
77
  def del_option(option)
66
78
  @options.delete(option)
67
- @options_hash = Hash[@options.map {|x| [x.keyword, x.arguments]}]
79
+ if @options_hash[option.keyword]
80
+ @options_hash[option.keyword].delete(option)
81
+ end
68
82
  end
69
83
 
70
84
  def clear_options()
@@ -89,12 +103,17 @@ module Snort
89
103
  end
90
104
  optspart.gsub(/;\s*\).*$/,'').split(/\s*;\s*/).each do |x|
91
105
  if x =~ /(.*?):(.*)/
92
- rule.options << Snort::RuleOption.new(*x.split(/:/,2))
106
+ k, v = x.split(/:/, 2)
107
+ opt = Snort::RuleOption.new(k, v)
108
+ rule.options << opt
109
+ unless rule.options_hash[k]
110
+ rule.options_hash[k] = []
111
+ end
112
+ rule.options_hash[k] << opt
93
113
  else
94
- rule.options << Snort::RuleOption.new(x)
114
+ rule.options.last.arguments << x
95
115
  end
96
116
  end if optspart
97
- rule.options_hash = Hash[rule.options.map {|x| [x.keyword, x.arguments]}]
98
117
  rule
99
118
  end
100
119
  end
@@ -7,12 +7,24 @@ module Snort
7
7
  # @param [String] arguments
8
8
  def initialize(keyword, arguments=nil)
9
9
  @keyword = keyword.to_s
10
- @arguments = arguments.to_s
10
+ if arguments == nil
11
+ @arguments = []
12
+ elsif arguments.class == String or arguments.class == Fixnum
13
+ @arguments = [arguments]
14
+ elsif arguments.class == Array
15
+ @arguments = arguments
16
+ else
17
+ raise "I don't know what to do with an argument of class #{arguments.class}"
18
+ end
19
+ end
20
+
21
+ def add_argument(argument)
22
+ @arguments << argument
11
23
  end
12
24
 
13
25
  def to_s
14
- return "#{@keyword};" if @arguments.empty?
15
- "#{@keyword}:#{@arguments};"
26
+ return "#{@keyword};" if @arguments.length == 0
27
+ "#{@keyword}:#{@arguments.join("; ")};"
16
28
  end
17
29
 
18
30
  def ==(other)
@@ -1,5 +1,5 @@
1
1
  module Snort
2
2
  class Rule
3
- VERSION = "1.2.0"
3
+ VERSION = "1.3.0"
4
4
  end
5
5
  end
@@ -38,15 +38,24 @@ class TestSnortRuleOption < Minitest::Test
38
38
  end
39
39
 
40
40
  def test_options_hash
41
- strule = 'alert tcp $EXTERNAL_NET any -> $HTTP_SERVERS $HTTP_PORTS (msg:"test"; flow:to_server, established; content:"GET"; http_method; content:"/private.php?"; nocase; http_uri; content:"id="; nocase; http_uri; content:"UNITED"; nocase; http_uri; content:"SELECTED"; nocase; http_uri; pcre:"/UNITED.+SELECTED/Ui"; reference:ref1; reference:ref2; reference:ref3; classtype:test-attack; sid:1234; rev:442;)'
41
+ strule = 'alert tcp $EXTERNAL_NET any -> $HTTP_SERVERS $HTTP_PORTS (msg:"test"; ' +
42
+ 'flow:to_server, established; '+
43
+ 'content:"GET"; http_method; ' +
44
+ 'content:"/private.php?"; nocase; http_uri; ' +
45
+ 'content:"id="; nocase; http_uri; ' +
46
+ 'content:"UNITED"; nocase; http_uri; ' +
47
+ 'content:"SELECTED"; nocase; http_uri; ' +
48
+ 'pcre:"/UNITED.+SELECTED/Ui"; ' +
49
+ 'reference:ref1; reference:ref2; reference:ref3; ' +
50
+ 'classtype:test-attack; sid:1234; rev:442;)'
42
51
  rule = Snort::Rule.parse(strule)
43
- assert_equal "\"test\"", rule.options_hash["msg"]
44
- assert_equal "to_server, established", rule.options_hash["flow"]
45
- assert rule.options_hash["http_method"]
46
- assert rule.options_hash["http_method"].empty?
47
- assert_equal "ref3", rule.options_hash["reference"]
48
- assert rule.options_hash["nocase"]
49
- assert rule.options_hash["nocase"].empty?
52
+ assert_equal ["\"test\""], rule.options_hash["msg"][0].arguments
53
+ assert_equal ["to_server, established"], rule.options_hash["flow"][0].arguments
54
+ assert rule.options_hash["content"]
55
+ assert_equal 5, rule.options_hash["content"].length
56
+ assert_equal ['"/private.php?"', 'nocase', 'http_uri'], rule.options_hash["content"][1].arguments
57
+ assert_equal 3, rule.options_hash["reference"].length
58
+ assert_equal ["ref3"], rule.options_hash["reference"][2].arguments
50
59
  assert_nil rule.options_hash["xxxx"]
51
60
  end
52
61
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: snort-rule
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - chrislee35
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-10-25 00:00:00.000000000 Z
11
+ date: 2014-11-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler