FlaskrTestCase.test_parse_rule()   B
last analyzed

Complexity

Conditions 1

Size

Total Lines 35

Duplication

Lines 0
Ratio 0 %

Importance

Changes 6
Bugs 0 Features 0
Metric Value
cc 1
c 6
b 0
f 0
dl 0
loc 35
rs 8.8571
1
from time import strftime, localtime
2
import re
3
4
from spike.model import db
5
from spike.model.naxsi_rules import NaxsiRules
6
7
from tests import TestsThatNeedsRules
8
9
try:
10
    from urlparse import urlparse
11
except ImportError:  # python3
12
    from urllib.parse import urlparse
13
14
15
class FlaskrTestCase(TestsThatNeedsRules):
16
    def test_index(self):
17
        rv = self.app.get('/', follow_redirects=True)
18
        self.assertEqual(rv.status_code, 200)
19
        self.assertIn('<title>SPIKE! - WAF Rules Builder</title>', str(rv.data))
20
        self.assertTrue(re.search(r'<h2>Naxsi - Rules \( \d+ \)</h2>', str(rv.data)) is not None)
21
22
    def test_view(self):
23
        _rule = NaxsiRules.query.order_by(NaxsiRules.sid.desc()).first()
0 ignored issues
show
Bug introduced by
The Class NaxsiRules does not seem to have a member named query.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
24
        rv = self.app.get('/rules/view/%d' % _rule.sid)
25
        self.assertEqual(rv.status_code, 200)
26
27
        _sid = _rule.sid + 1
28
        rv = self.app.get('/rules/view/%d' % _sid)
29
        self.assertEqual(urlparse(rv.location).path, '/rules/')
30
31
    def test_new_rule(self):
32
        rv = self.app.get('/rules/new')
33
        self.assertEqual(rv.status_code, 200)
34
35
        data = {
36
            'msg': 'this is a test message',
37
            'detection': 'str:DETECTION',
38
            'mz': 'BODY',
39
            'custom_mz_val': '',
40
            'negative': 'checked',
41
            'score_$SQL': 8,
42
            'score': '$SQL',
43
            'rmks': 'this is a test remark',
44
            'ruleset': 'WEB_APPS'
45
        }
46
        self.app.post('/rules/new', data=data, follow_redirects=True)
47
48
        _rule = NaxsiRules.query.order_by(NaxsiRules.sid.desc()).first()
0 ignored issues
show
Bug introduced by
The Class NaxsiRules does not seem to have a member named query.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
49
50
        self.assertEqual(_rule.msg, data['msg'])
51
        self.assertEqual(_rule.detection, data['detection'])
52
        self.assertEqual(_rule.mz, data['mz'])
53
        self.assertEqual(_rule.score, data['score'] + ':' + str(data['score_$SQL']))
54
        self.assertEqual(_rule.rmks, data['rmks'])
55
        self.assertEqual(_rule.ruleset, data['ruleset'])
56
        db.session.delete(_rule)
57
        db.session.commit()
58
59
        # Try to insert an invalid rule
60
        _sid = NaxsiRules.query.order_by(NaxsiRules.sid.desc()).first().sid
0 ignored issues
show
Bug introduced by
The Class NaxsiRules does not seem to have a member named query.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
61
        data['detection'] = 'this string does not start with "str:" or "rx:", sorry'
62
        rv = self.app.post('/rules/new', data=data)
63
        self.assertEqual(rv.status_code, 302)
64
        self.assertEqual(_sid, NaxsiRules.query.order_by(NaxsiRules.sid.desc()).first().sid)
0 ignored issues
show
Bug introduced by
The Class NaxsiRules does not seem to have a member named query.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
65
66
    def test_save_rule(self):
67
        rv = self.app.get('/rules/save')
68
        self.assertEqual(rv.status_code, 404)
69
70
        data = {
71
            'msg': 'POUET',
72
            'detection': 'str:test',
73
            'mz': 'BODY',
74
            'custom_mz_val': '',
75
            'negative': 'checked',
76
            'score_$SQL': 8,
77
            'score': '$SQL',
78
            'rmks': 'f hqewifueiwf hueiwhf uiewh fiewh fhw',
79
            'ruleset': 'WEB_APPS'
80
        }
81
        _rule = NaxsiRules.query.order_by(NaxsiRules.sid.desc()).first()
0 ignored issues
show
Bug introduced by
The Class NaxsiRules does not seem to have a member named query.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
82
        rv = self.app.post('/rules/save/{0}'.format(_rule.sid), data=data, follow_redirects=True)
83
84
        self.assertIn(data['msg'], str(rv.data))
85
        self.assertIn(data['detection'], str(rv.data))
86
        self.assertIn(data['mz'], str(rv.data))
87
        self.assertIn(data['score'], str(rv.data))
88
        self.assertIn(data['rmks'], str(rv.data))
89
        self.assertIn(data['ruleset'], str(rv.data))
90
91
        _rule = NaxsiRules.query.order_by(NaxsiRules.sid.desc()).first()
0 ignored issues
show
Bug introduced by
The Class NaxsiRules does not seem to have a member named query.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
92
        data['detection'] = 'rx:^lol$'
93
        rv = self.app.post('/rules/save/{0}'.format(_rule.sid), data=data, follow_redirects=True)
94
        self.assertIn(data['detection'], str(rv.data))
95
96
        _rule = NaxsiRules.query.order_by(NaxsiRules.sid.desc()).first()
0 ignored issues
show
Bug introduced by
The Class NaxsiRules does not seem to have a member named query.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
97
        data['detection'] = 'not str: nor rx:'
98
        rv = self.app.post('/rules/save/{0}'.format(_rule.sid), data=data)
99
        self.assertEqual(rv.status_code, 302)
100
        self.assertEqual(urlparse(rv.location).path, '/rules/edit/{}'.format(_rule.sid))
101
102
        _rule = NaxsiRules.query.order_by(NaxsiRules.sid.desc()).first()
0 ignored issues
show
Bug introduced by
The Class NaxsiRules does not seem to have a member named query.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
103
        db.session.delete(_rule)
104
        db.session.commit()
105
106
    def test_del_rule(self):
107
        _rule = NaxsiRules.query.order_by(NaxsiRules.sid.desc()).first()
0 ignored issues
show
Bug introduced by
The Class NaxsiRules does not seem to have a member named query.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
108
109
        db.session.add(NaxsiRules(u'PIF', 'str:test', u'BODY', u'$SQL:8', _rule.sid + 1, u'WEB_APPS',
110
                                  u'f hqewifueiwf hueiwhf uiewh fiewh fhw', '1', True, 1457101045))
111
        _sid = _rule.sid + 1
112
        rv = self.app.get('/rules/del/%d' % _sid)
113
        self.assertEqual(rv.status_code, 302)
114
115
        _rule = NaxsiRules.query.order_by(NaxsiRules.sid.desc()).first()
0 ignored issues
show
Bug introduced by
The Class NaxsiRules does not seem to have a member named query.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
116
        self.assertEqual(_rule.sid, _rule.sid)
117
118
    def test_plain_rule(self):
119
        _rule = NaxsiRules.query.order_by(NaxsiRules.sid.desc()).first()
0 ignored issues
show
Bug introduced by
The Class NaxsiRules does not seem to have a member named query.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
120
        rv = self.app.get('/rules/plain/%d' % _rule.sid)
121
        self.assertEqual(rv.status_code, 200)
122
        rdate = strftime("%F - %H:%M", localtime(float(str(_rule.timestamp))))
123
        rmks = "# ".join(_rule.rmks.strip().split("\n"))
124
        expected = """#
125
# sid: {0} | date: {1}
126
#
127
# {2}
128
#
129
{3}""".format(_rule.sid, rdate, rmks, str(_rule))
130
        self.assertEqual(expected.encode(), rv.data)
131
132
    def test_deact_rule(self):
133
        last_insert = NaxsiRules.query.order_by(NaxsiRules.sid.desc()).first().sid
0 ignored issues
show
Bug introduced by
The Class NaxsiRules does not seem to have a member named query.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
134
135
        rv = self.app.get('/rules/deact/%d' % last_insert)  # deactivate
136
        self.assertEqual(rv.status_code, 200)
137
        _rule = NaxsiRules.query.filter(NaxsiRules.sid == last_insert).first()
0 ignored issues
show
Bug introduced by
The Class NaxsiRules does not seem to have a member named query.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
138
        self.assertEqual(_rule.active, 0)
139
140
        rv = self.app.get('/rules/deact/%d' % last_insert)  # activate
141
        self.assertEqual(rv.status_code, 200)
142
        _rule = NaxsiRules.query.filter(NaxsiRules.sid == last_insert).first()
0 ignored issues
show
Bug introduced by
The Class NaxsiRules does not seem to have a member named query.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
143
        self.assertEqual(_rule.active, 1)
144
145
        non_existent_sid = last_insert + 1
146
        rv = self.app.get('/rules/deact/%d' % non_existent_sid)
147
        self.assertEqual(rv.status_code, 302)
148
149
        rv = self.app.get('/rules/deact/')
150
        self.assertEqual(rv.status_code, 404)
151
152
    def test_search_rule(self):
153
        rv = self.app.get('/rules/search/')
154
        self.assertEqual(rv.status_code, 302)
155
156
        rv = self.app.get('/rules/search/?s=a')
157
        self.assertEqual(rv.status_code, 302)
158
159
        rv = self.app.get('/rules/search/?s="OR 1=1;--')
160
        self.assertEqual(rv.status_code, 200)
161
        self.assertIn('value="&#34;OR 1=1;--"', str(rv.data))
162
        self.assertIn('<p><strong>Search: OR 11--</strong></p>', str(rv.data))  # filtered data
163
164
        rv = self.app.get('/rules/search/?s=1337')  # get rule by id
165
        self.assertEqual(rv.status_code, 200)
166
167
        rv = self.app.get('/rules/search/?s=cve:2015-1234')  # get rule by id
168
        self.assertEqual(rv.status_code, 200)
169
170
    def test_edit_rule(self):
171
        non_existent_sid = NaxsiRules.query.order_by(NaxsiRules.sid.desc()).first().sid + 1
0 ignored issues
show
Bug introduced by
The Class NaxsiRules does not seem to have a member named query.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
172
        rv = self.app.get('/rules/edit/%d' % non_existent_sid)
173
        self.assertEqual(rv.status_code, 302)
174
175
    def test_parse_rule(self):
176
        rule_parser = NaxsiRules()
177
178
        errors, warnings, ret = rule_parser.parse_rule('MainRule "rx:select|union|update|delete|insert|table|from|ascii|hex|unhex|drop"'
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (136/120).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
Unused Code introduced by
The variable ret seems to be unused.
Loading history...
179
                                    '"msg:sql keywords" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1000;')
180
        self.assertEqual(warnings,
181
                         ['Cookie in $HEADERS_VAR:Cookie is not lowercase. naxsi is case-insensitive',
182
                          'rule IDs below 10k are reserved (1000)'])
183
184
        errors, warnings, ret = rule_parser.parse_rule('BasicRule "rx:^ratata$" "mz:$URL:/foobar" '
185
                                    'id:4200001 "s:$SQL:8";')
186
        self.assertIn('$URL', str(errors))
187
        self.assertIn("The rule/whitelist doesn\'t target any zone.", str(errors))
188
        self.assertIn("Parsing of element \'mz:$URL:/foobar\' failed.", str(errors))
189
190
        errors, warnings, ret = rule_parser.parse_rule('"rx:^ratata$" "mz:$URL:/foobar|$BODY_VAR_X:^tutu$"'
191
                                    'id:4200001 "s:$SQL:8";')
192
        self.assertIn('No mainrule/basicrule keyword.', str(errors))
193
194
        errors, warnings, ret = rule_parser.parse_rule('MainRule BasicRule "rx:select"'
195
                                    '"msg:sql keywords" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1000;')
196
        self.assertEqual(['Both BasicRule and MainRule are present.'], errors)
197
198
        errors, warnings, ret = rule_parser.parse_rule('MainRule "rx:select"'
199
                                    '"msg:sql keywords" "mz:BODY" "s:$SQL:4" id:1000 "wrong:LOL";')
200
        self.assertIn("'wrong:LOL' is an invalid element and thus can not be parsed.", str(errors))
201
202
        errors, warnings, ret = rule_parser.parse_rule('MainRule "rx:select"'
203
                                    '"msg:sql keywords" "mz:BODY" "s:$SQL:4" "id:non_numeric";')
204
        self.assertEqual(['id:non_numeric is not numeric', "Parsing of element 'id:non_numeric' failed."],
205
                         errors)
206
207
        errors, warnings, ret = rule_parser.parse_rule('MainRule "rx:select" "mz:wrong" "msg:sql keywords" "s:$SQL:4" "id:10000";')
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (131/120).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
208
        self.assertIn("'wrong' is not a known sub-part of mz : ", str(errors))
209
        self.assertIn("Parsing of element 'mz:wrong' failed.", str(errors))
210