snort-rule 1.3.0 → 1.4.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: 29dd2030dcab15c7a79fe409f387f365833d6ef9
4
- data.tar.gz: c000e78ab850620360e3cf169a6675081b43f067
3
+ metadata.gz: e2eabb911b41cd33e776dd69cc3f50ba807ccaf8
4
+ data.tar.gz: 7bfa5b2a310dc398d362991c6cecd7b1c72fb022
5
5
  SHA512:
6
- metadata.gz: 719fa4d1026c38c683d06364c16c930be551c3dca3fe4b67493e23d6f33d52125a5d74bd9e05cb0b2528469792cac3e3cdcd70dcd0a29eb38b15d566879b5d27
7
- data.tar.gz: 9158d07dc87858e5179bb6355f8b3e285645db5c65e14bf2e8f1ec6bf82a46ce669abe9c38cc59f7ddcc1f7a125bbe282b10f788d1ecb50f11ba38c905910f81
6
+ metadata.gz: dc95c1a7217f9d624cb887e53a7a1f8bcc0d710a617863f1d484259edec11423033005e4082547e823489bcd0fe4eb8d999dfce13236c6e566b59ca3d639095e
7
+ data.tar.gz: fb1d93af758a6485bf2ae7a39509f4c117325c0b15c7820d891301450dd9c23223f325437993fd6a1d49c4b2c1098ea8b1c3ec38bfab466f249da99a4ca0c036
data/.gitignore CHANGED
@@ -14,4 +14,5 @@ rdoc
14
14
  spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
+ test/community-rules
17
18
  tmp
@@ -1,5 +1,6 @@
1
1
  require "snort/rule/version"
2
2
  require "snort/rule/option"
3
+ require 'pp'
3
4
  # Generates and parses snort rules
4
5
  #
5
6
  # Authors:: Chris Lee (mailto:rubygems@chrislee.dhs.org),
@@ -85,17 +86,51 @@ module Snort
85
86
  @options = []
86
87
  @options_hash = {}
87
88
  end
89
+
90
+ def get_option(option_name)
91
+ if @options_hash[option_name]
92
+ if @options_hash[option_name].length == 1
93
+ if @options_hash[option_name][0].arguments.length == 1
94
+ return @options_hash[option_name][0].arguments[0]
95
+ end
96
+ end
97
+ end
98
+ nil
99
+ end
100
+
101
+ def get_option_first(option_name)
102
+ if @options_hash[option_name]
103
+ if @options_hash[option_name].length > 0
104
+ if @options_hash[option_name][0].arguments.length > 0
105
+ return @options_hash[option_name][0].arguments[0]
106
+ end
107
+ end
108
+ end
109
+ nil
110
+ end
111
+
112
+ def get_option_last(option_name)
113
+ if @options_hash[option_name]
114
+ if @options_hash[option_name].length > 0
115
+ if @options_hash[option_name].last.arguments.length > 0
116
+ return @options_hash[option_name].last.arguments[0]
117
+ end
118
+ end
119
+ end
120
+ nil
121
+ end
88
122
 
89
123
  # Parse a snort rule to generate an object
90
124
  def Rule::parse(string)
91
125
  rule = Snort::Rule.new
126
+ rulestr = string.strip
92
127
  # If the string begins with /^#+\s*/, then the rule is disabled.
93
128
  # If disabled, let's scrub the disabling substring from the string.
94
- if string.index(/^#+\s+/)
129
+ if rulestr.index(/^#/)
95
130
  rule.enabled = false
96
- string.gsub!(/^#+\s*/,'')
131
+ rulestr.gsub!(/^#+\s*/,'')
97
132
  end
98
- rulepart, optspart = string.split(/\s*\(\s*/,2)
133
+ rulepart, optspart = rulestr.split(/\s*\(\s*/,2)
99
134
  rule.action, rule.proto, rule.src, rule.sport, rule.dir, rule.dst, rule.dport = rulepart.split(/\s+/)
100
135
  if not ['<>', '<-', '->'].index(rule.dir)
101
136
  # most likely, I have a parse error, maybe it's just a random comment
@@ -1,5 +1,5 @@
1
1
  module Snort
2
2
  class Rule
3
- VERSION = "1.3.0"
3
+ VERSION = "1.4.1"
4
4
  end
5
5
  end
@@ -0,0 +1,64 @@
1
+ unless Kernel.respond_to?(:require_relative)
2
+ module Kernel
3
+ def require_relative(path)
4
+ require File.join(File.dirname(caller[0]), path.to_str)
5
+ end
6
+ end
7
+ end
8
+
9
+ require_relative 'helper'
10
+
11
+ class TestSnortCommunityRules < Minitest::Test
12
+ def setup
13
+ destination = "test"
14
+ if not File.exist?("#{destination}/community-rules/community.rules")
15
+ require 'open-uri'
16
+ require 'zlib'
17
+ require 'rubygems/package'
18
+ require 'fileutils'
19
+
20
+ url = "https://www.snort.org/downloads/community/community-rules.tar.gz"
21
+ puts "downloading #{url} to #{destination}/community-rules/community.rules"
22
+ tarfile = open(url)
23
+
24
+ # un-gzips the given IO, returning the
25
+ # decompressed version as a StringIO
26
+ z = Zlib::GzipReader.new(tarfile)
27
+ unzipped = StringIO.new(z.read)
28
+ z.close
29
+ tarfile.close
30
+ Gem::Package::TarReader.new unzipped do |tar|
31
+ tar.each do |tarfile|
32
+ destination_file = File.join destination, tarfile.full_name
33
+ if tarfile.directory?
34
+ FileUtils.mkdir_p destination_file
35
+ else
36
+ destination_directory = File.dirname(destination_file)
37
+ FileUtils.mkdir_p destination_directory unless File.directory?(destination_directory)
38
+ File.open destination_file, "wb" do |f|
39
+ f.print tarfile.read
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+ def test_complete_rules_file
48
+ rules = []
49
+ File.open("test/community-rules/community.rules").each_line do |line|
50
+ next unless line =~ /alert/
51
+ begin
52
+ rule = Snort::Rule.parse(line)
53
+ if rule
54
+ rules << rule
55
+ end
56
+ rescue ArgumentError => e
57
+ rescue NoMethodError => e
58
+ end
59
+ end
60
+ assert_equal 3127, rules.length
61
+ assert_equal 2522, rules.count{|r| ! r.enabled}
62
+ assert_equal 605, rules.count{|r| r.enabled}
63
+ end
64
+ end
@@ -25,8 +25,8 @@ class TestSnortRule < Minitest::Test
25
25
  rule.src = '192.168.0.1'
26
26
  rule.dir = '<>'
27
27
  rule.dport = 53
28
- rule.options << Snort::RuleOption.new('sid', 48)
29
- rule.options << Snort::RuleOption.new('threshold', 'type limit,track by_src,count 1,seconds 3600')
28
+ rule.add_option(Snort::RuleOption.new('sid', 48))
29
+ rule.add_option(Snort::RuleOption.new('threshold', 'type limit,track by_src,count 1,seconds 3600'))
30
30
  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;)"
31
31
  end
32
32
 
@@ -39,18 +39,14 @@ class TestSnortRule < Minitest::Test
39
39
  rule.dir = '->'
40
40
  rule.dst = '$EXTERNAL_NET'
41
41
  rule.dport = '$HTTP_PORTS'
42
- rule.options << Snort::RuleOption.new('msg', '"HTTP Host www.baddomain.com"')
43
- rule.options << Snort::RuleOption.new('content', '"Host|3a|"')
44
- rule.options << Snort::RuleOption.new('nocase')
45
- rule.options << Snort::RuleOption.new('http_header')
46
- rule.options << Snort::RuleOption.new('content', '"www.baddomain.com"')
47
- rule.options << Snort::RuleOption.new('nocase')
48
- rule.options << Snort::RuleOption.new('http_header')
49
- rule.options << Snort::RuleOption.new('pcre', '"/^Host\\x3a(.*\\.|\\s*)www\\.baddomain\\.com\\s*$/mi"')
50
- rule.options << Snort::RuleOption.new('flow', 'to_server,established')
51
- rule.options << Snort::RuleOption.new('threshold', 'type limit, track by_src, count 1, seconds 300')
52
- rule.options << Snort::RuleOption.new('classtype', 'bad-unknown')
53
- rule.options << Snort::RuleOption.new('sid', '100000000')
42
+ rule.add_option(Snort::RuleOption.new('msg', '"HTTP Host www.baddomain.com"'))
43
+ rule.add_option(Snort::RuleOption.new('content', ['"Host|3a|"', 'nocase', 'http_header']))
44
+ rule.add_option(Snort::RuleOption.new('content', ['"www.baddomain.com"', 'nocase', 'http_header']))
45
+ rule.add_option(Snort::RuleOption.new('pcre', '"/^Host\\x3a(.*\\.|\\s*)www\\.baddomain\\.com\\s*$/mi"'))
46
+ rule.add_option(Snort::RuleOption.new('flow', 'to_server,established'))
47
+ rule.add_option(Snort::RuleOption.new('threshold', 'type limit, track by_src, count 1, seconds 300'))
48
+ rule.add_option(Snort::RuleOption.new('classtype', 'bad-unknown'))
49
+ rule.add_option(Snort::RuleOption.new('sid', '100000000'))
54
50
  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
55
51
  end
56
52
 
@@ -63,33 +59,33 @@ class TestSnortRule < Minitest::Test
63
59
  rule.dir = '->'
64
60
  rule.dst = '$EXTERNAL_NET'
65
61
  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')
62
+ rule.add_option(Snort::RuleOption.new('msg', '"HTTP Host www.baddomain.com"'))
63
+ rule.add_option(Snort::RuleOption.new('content', ['"Host|3a|"', 'nocase', 'http_header']))
64
+ rule.add_option(Snort::RuleOption.new('content', ['"www.baddomain.com"', 'nocase', 'http_header']))
65
+ rule.add_option(Snort::RuleOption.new('pcre', '"/^Host\\x3a(.*\\.|\\s*)www\\.baddomain\\.com\\s*$/mi"'))
66
+ rule.add_option(Snort::RuleOption.new('flow', 'to_server,established'))
67
+ rule.add_option(Snort::RuleOption.new('threshold', 'type limit, track by_src, count 1, seconds 300'))
68
+ rule.add_option(Snort::RuleOption.new('classtype', 'bad-unknown'))
69
+ rule.add_option(Snort::RuleOption.new('sid', '100000000'))
78
70
  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
71
+ assert_equal '100000000', rule.get_option('sid')
72
+ assert_nil rule.get_option('content')
73
+ assert_equal '"Host|3a|"', rule.get_option_first('content')
74
+ assert_equal '"www.baddomain.com"', rule.get_option_last('content')
79
75
  end
80
76
 
81
77
  def test_parse_an_existing_rule_and_generate_the_same_rule
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; )")
78
+ 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; )")
83
79
  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;)"
84
80
  end
85
81
 
86
82
  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; )")
83
+ 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
84
  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
85
  end
90
86
 
91
87
  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; )")
88
+ 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
89
  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
90
  end
95
91
 
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.3.0
4
+ version: 1.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - chrislee35
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-11-05 00:00:00.000000000 Z
11
+ date: 2014-11-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -86,6 +86,7 @@ files:
86
86
  - lib/snort/rule/version.rb
87
87
  - snort-rule.gemspec
88
88
  - test/helper.rb
89
+ - test/test_snort-community-rules.rb
89
90
  - test/test_snort-rule.rb
90
91
  - test/test_snort_rule_option.rb
91
92
  homepage: http://github.com/chrislee35/snort-rule
@@ -114,5 +115,6 @@ specification_version: 4
114
115
  summary: Class for parsing and generating Snort Rules
115
116
  test_files:
116
117
  - test/helper.rb
118
+ - test/test_snort-community-rules.rb
117
119
  - test/test_snort-rule.rb
118
120
  - test/test_snort_rule_option.rb