Completed
Push — master ( 18fabe...7154a7 )
by -
01:30
created

FlaskrTestCase.test_parse_rule()   B

Complexity

Conditions 1

Size

Total Lines 43

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 1
dl 0
loc 43
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
10
try:
11
    from urlparse import urlparse
12
except ImportError:  # python3
13
    from urllib.parse import urlparse
14
15
16
17
class FlaskrTestCase(TestsThatNeedsRules):
18
    def test_index(self):
19
        rv = self.app.get('/', follow_redirects=True)
20
        self.assertEqual(rv.status_code, 200)
21
        self.assertIn('<title>SPIKE! - WAF Rules Builder</title>', str(rv.data))
22
        self.assertTrue(re.search(r'<h2>Naxsi - Rules \( \d+ \)</h2>', str(rv.data)) is not None)
23
24
    def test_view(self):
25
        _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...
26
        rv = self.app.get('/rules/view/%d' % _rule.sid)
27
        self.assertEqual(rv.status_code, 200)
28
29
        _sid = _rule.sid + 1
30
        rv = self.app.get('/rules/view/%d' % _sid)
31
        self.assertEqual(urlparse(rv.location).path, '/rules/')
32
33
    def test_new_rule(self):
34
        rv = self.app.get('/rules/new')
35
        self.assertEqual(rv.status_code, 200)
36
37
        data = {
38
            'msg': 'this is a test message',
39
            'detection': 'str:DETECTION',
40
            'mz': 'BODY',
41
            'custom_mz_val': '',
42
            'negative': 'checked',
43
            'score_$SQL': 8,
44
            'score': '$SQL',
45
            'rmks': 'this is a test remark',
46
            'ruleset': 'WEB_APPS'
47
        }
48
        rv = self.app.post('/rules/new', data=data, follow_redirects=True)
49
50
        _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...
51
52
        self.assertIn(('<li> - OK: created %d : %s</li>' % (_rule.sid, _rule.msg)), str(rv.data))
53
        self.assertEqual(_rule.msg, data['msg'])
54
        self.assertEqual(_rule.detection, data['detection'])
55
        self.assertEqual(_rule.mz, data['mz'])
56
        self.assertEqual(_rule.score, data['score'] + ':' + str(data['score_$SQL']))
57
        self.assertEqual(_rule.rmks, data['rmks'])
58
        self.assertEqual(_rule.ruleset, data['ruleset'])
59
        db.session.delete(_rule)
60
        db.session.commit()
61
62
        # Try to insert an invalid rule
63
        _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...
64
        data['detection'] = 'this string does not start with "str:" or "rx:", sorry'
65
        rv = self.app.post('/rules/new', data=data)
66
        self.assertEqual(rv.status_code, 302)
67
        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...
68
69
    def test_save_rule(self):
70
        rv = self.app.get('/rules/save')
71
        self.assertEqual(rv.status_code, 404)
72
73
        data = {
74
            'msg': 'POUET',
75
            'detection': 'str:test',
76
            'mz': 'BODY',
77
            'custom_mz_val': '',
78
            'negative': 'checked',
79
            'score_$SQL': 8,
80
            'score': '$SQL',
81
            'rmks': 'f hqewifueiwf hueiwhf uiewh fiewh fhw',
82
            'ruleset': 'WEB_APPS'
83
        }
84
        _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...
85
        rv = self.app.post('/rules/save/{0}'.format(_rule.sid), data=data, follow_redirects=True)
86
87
        self.assertIn(data['msg'], str(rv.data))
88
        self.assertIn(data['detection'], str(rv.data))
89
        self.assertIn(data['mz'], str(rv.data))
90
        self.assertIn(data['score'], str(rv.data))
91
        self.assertIn(data['rmks'], str(rv.data))
92
        self.assertIn(data['ruleset'], str(rv.data))
93
94
        _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...
95
        data['detection'] = 'rx:^lol$'
96
        rv = self.app.post('/rules/save/{0}'.format(_rule.sid), data=data, follow_redirects=True)
97
        self.assertIn(data['detection'], str(rv.data))
98
99
        _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...
100
        data['detection'] = 'not str: nor rx:'
101
        rv = self.app.post('/rules/save/{0}'.format(_rule.sid), data=data)
102
        self.assertEqual(rv.status_code, 302)
103
        self.assertEqual(urlparse(rv.location).path, '/rules/edit/{}'.format(_rule.sid))
104
105
        _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...
106
        db.session.delete(_rule)
107
        db.session.commit()
108
109
    def test_del_rule(self):
110
        _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...
111
112
        db.session.add(NaxsiRules(u'PIF', 'str:test', u'BODY', u'$SQL:8', _rule.sid + 1, u'WEB_APPS',
113
                                  u'f hqewifueiwf hueiwhf uiewh fiewh fhw', '1', True, 1457101045))
114
        _sid = _rule.sid + 1
115
        rv = self.app.get('/rules/del/%d' % _sid)
116
        self.assertEqual(rv.status_code, 302)
117
118
        _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...
119
        self.assertEqual(_rule.sid, _rule.sid)
120
121
    def test_plain_rule(self):
122
        _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...
123
        rv = self.app.get('/rules/plain/%d' % _rule.sid)
124
        self.assertEqual(rv.status_code, 200)
125
        rdate = strftime("%F - %H:%M", localtime(float(str(_rule.timestamp))))
126
        rmks = "# ".join(_rule.rmks.strip().split("\n"))
127
        expected = """#
128
# sid: {0} | date: {1}
129
#
130
# {2}
131
#
132
{3}""".format(_rule.sid, rdate, rmks, str(_rule))
133
        self.assertEqual(expected.encode(), rv.data)
134
135
    def test_deact_rule(self):
136
        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...
137
138
        rv = self.app.get('/rules/deact/%d' % last_insert)  # deactivate
139
        self.assertEqual(rv.status_code, 200)
140
        _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...
141
        self.assertEqual(_rule.active, 0)
142
143
        rv = self.app.get('/rules/deact/%d' % last_insert)  # activate
144
        self.assertEqual(rv.status_code, 200)
145
        _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...
146
        self.assertEqual(_rule.active, 1)
147
148
        non_existent_sid = last_insert + 1
149
        rv = self.app.get('/rules/deact/%d' % non_existent_sid)
150
        self.assertEqual(rv.status_code, 302)
151
152
        rv = self.app.get('/rules/deact/')
153
        self.assertEqual(rv.status_code, 404)
154
155
    def test_search_rule(self):
156
        rv = self.app.get('/rules/search/')
157
        self.assertEqual(rv.status_code, 302)
158
159
        rv = self.app.get('/rules/search/?s=a')
160
        self.assertEqual(rv.status_code, 302)
161
162
        rv = self.app.get('/rules/search/?s="OR 1=1;--')
163
        self.assertEqual(rv.status_code, 200)
164
        self.assertIn('<input type="text" name="s" size="20" value="&#34;OR 1=1;--"', str(rv.data))
165
        self.assertIn('<p><strong>Search: OR 11--</strong></p>', str(rv.data))  # filtered data
166
167
        rv = self.app.get('/rules/search/?s=1337')  # 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
        rv = rule_parser.parse_rule('MainRule "rx:select|union|update|delete|insert|table|from|ascii|hex|unhex|drop"'
179
                                    '"msg:sql keywords" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1000;')
180
        self.assertEqual(rv, True)
181
        self.assertEqual(rule_parser.warnings,
182
                         ['Cookie in $HEADERS_VAR:Cookie is not lowercase. naxsi is case-insensitive',
183
                          'rule IDs below 10k are reserved (1000)'])
184
185
        rv = rule_parser.parse_rule('BasicRule "rx:^ratata$" "mz:$URL:/foobar|$BODY_VAR_X:^tutu$"'
186
                                    'id:4200001 "s:$SQL:8";')
187
        self.assertEqual(rv, False)
188
        self.assertIn('$BODY_VAR_X', str(rule_parser.error))
189
        self.assertIn('$URL', str(rule_parser.error))
190
        self.assertIn("You can't mix static $* with regex $*_X", str(rule_parser.error))
191
        self.assertIn("parsing of element 'mz:$URL:/foobar|$BODY_VAR_X:^tutu$' failed.", rule_parser.error)
192
193
        rv = rule_parser.parse_rule('"rx:^ratata$" "mz:$URL:/foobar|$BODY_VAR_X:^tutu$"'
194
                            'id:4200001 "s:$SQL:8";')
195
        self.assertEqual(rv, False)
196
        self.assertIn('No mainrule/basicrule keyword.', rule_parser.error)
197
198
        rv = rule_parser.parse_rule('MainRule BasicRule "rx:select"'
199
                                    '"msg:sql keywords" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1000;')
200
        self.assertEqual(rv, False)
201
        self.assertIn('Multiple mainrule/basicrule keywords.', rule_parser.error)
202
203
        rv = rule_parser.parse_rule('MainRule "rx:select"'
204
                                    '"msg:sql keywords" "mz:BODY" "s:$SQL:4" id:1000 "wrong:LOL";')
205
        self.assertEqual(rv, False)
206
        self.assertIn("'wrong:LOL' is an invalid element and thus can not be parsed.", rule_parser.error)
207
208
        rv = rule_parser.parse_rule('MainRule "rx:select"'
209
                                    '"msg:sql keywords" "mz:BODY" "s:$SQL:4" "id:non_numeric";')
210
        self.assertEqual(rv, False)
211
        self.assertEqual(['id:non_numeric is not numeric', "parsing of element 'id:non_numeric' failed."],
212
                         rule_parser.error)
213
214
        rv = rule_parser.parse_rule('MainRule "rx:select" "mz:wrong" "msg:sql keywords" "s:$SQL:4" "id:10000";')
215
        self.assertEqual(rv, False)
216
        self.assertIn("'wrong' is not a known sub-part of mz : ", str(rule_parser.error))
217
        self.assertIn("parsing of element 'mz:wrong' failed.", rule_parser.error)
218