Completed
Push — master ( 77348d...b5200a )
by -
01:45
created

FlaskrTestCase.test_sandbox_rule()   A

Complexity

Conditions 1

Size

Total Lines 15

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 1
dl 0
loc 15
rs 9.4285
1
from time import strftime, localtime
2
import re
3
4
from spike import create_app
5
from spike.model import db
6
from spike.model.naxsi_rules import NaxsiRules
7
8
try:
9
    from urlparse import urlparse
10
except ImportError:  # python3
11
    from urllib.parse import urlparse
12
13
import unittest
14
15
16
class FlaskrTestCase(unittest.TestCase):
17
    def setUp(self):
18
        app = create_app()
19
        db.init_app(app)
20
        app.config['TESTING'] = True
21
        self.app = app.test_client()
22
        self.created_rules = list()
23
        self.__create_rule()
24
25
    def tearDown(self):
26
        self.__delete_rule()
27
28
    def __create_rule(self):
29
        """
30
31
        :return int: The id of the new rule
32
        """
33
        current_sid = 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...
34
        current_sid = 1337 if current_sid is None else current_sid.sid + 1
35
36
        db.session.add(NaxsiRules(u'POUET', 'str:test', u'BODY', u'$SQL:8', current_sid, u'WEB_APPS',
37
                                  u'f hqewifueiwf hueiwhf uiewh fiewh fhw', '1', True, 1457101045))
38
        self.created_rules.append(current_sid)
39
        return int(current_sid)
40
41
    def __delete_rule(self, sid=None):
42
        if sid:
43
            db.session.delete(NaxsiRules.query.filter(sid == NaxsiRules.sid).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...
44
        for sid in self.created_rules:
45
            _rule = NaxsiRules.query.filter(sid == NaxsiRules.sid).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...
46
            if _rule:
47
                db.session.delete(_rule)
48
49
    def test_index(self):
50
        rv = self.app.get('/', follow_redirects=True)
51
        self.assertEqual(rv.status_code, 200)
52
        self.assertIn('<title>SPIKE! - WAF Rules Builder</title>', str(rv.data))
53
        self.assertTrue(re.search(r'<h2>Naxsi - Rules \( \d+ \)</h2>', str(rv.data)) is not None)
54
55
    def test_view(self):
56
        _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...
57
        rv = self.app.get('/rules/view/%d' % _rule.sid)
58
        self.assertEqual(rv.status_code, 200)
59
60
        _sid = _rule.sid + 1
61
        rv = self.app.get('/rules/view/%d' % _sid)
62
        self.assertEqual(urlparse(rv.location).path, '/rules/')
63
64
    def test_new_rule(self):
65
        rv = self.app.get('/rules/new')
66
        self.assertEqual(rv.status_code, 200)
67
68
        data = {
69
            'msg': 'this is a test message',
70
            'detection': 'str:DETECTION',
71
            'mz': 'BODY',
72
            'custom_mz_val': '',
73
            'negative': 'checked',
74
            'score_$SQL': 8,
75
            'score': '$SQL',
76
            'rmks': 'this is a test remark',
77
            'ruleset': 'WEB_APPS'
78
        }
79
        rv = self.app.post('/rules/new', data=data, follow_redirects=True)
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
83
        self.assertIn(('<li> - OK: created %d : %s</li>' % (_rule.sid, _rule.msg)), str(rv.data))
84
        self.assertEqual(_rule.msg, data['msg'])
85
        self.assertEqual(_rule.detection, data['detection'])
86
        self.assertEqual(_rule.mz, data['mz'])
87
        self.assertEqual(_rule.score, data['score'] + ':' + str(data['score_$SQL']))
88
        self.assertEqual(_rule.rmks, data['rmks'])
89
        self.assertEqual(_rule.ruleset, data['ruleset'])
90
        db.session.delete(_rule)
91
        db.session.commit()
92
93
        # Try to insert an invalid rule
94
        _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...
95
        data['detection'] = 'this string does not start with "str:" or "rx:", sorry'
96
        rv = self.app.post('/rules/new', data=data)
97
        self.assertEqual(rv.status_code, 302)
98
        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...
99
100
    def test_save_rule(self):
101
        rv = self.app.get('/rules/save')
102
        self.assertEqual(rv.status_code, 404)
103
104
        data = {
105
            'msg': 'POUET',
106
            'detection': 'str:test',
107
            'mz': 'BODY',
108
            'custom_mz_val': '',
109
            'negative': 'checked',
110
            'score_$SQL': 8,
111
            'score': '$SQL',
112
            'rmks': 'f hqewifueiwf hueiwhf uiewh fiewh fhw',
113
            'ruleset': 'WEB_APPS'
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
        rv = self.app.post('/rules/save/{0}'.format(_rule.sid), data=data, follow_redirects=True)
117
118
        self.assertIn(data['msg'], str(rv.data))
119
        self.assertIn(data['detection'], str(rv.data))
120
        self.assertIn(data['mz'], str(rv.data))
121
        self.assertIn(data['score'], str(rv.data))
122
        self.assertIn(data['rmks'], str(rv.data))
123
        self.assertIn(data['ruleset'], str(rv.data))
124
125
        _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...
126
        data['detection'] = 'rx:^lol$'
127
        rv = self.app.post('/rules/save/{0}'.format(_rule.sid), data=data, follow_redirects=True)
128
        self.assertIn(data['detection'], str(rv.data))
129
130
        _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...
131
        data['detection'] = 'not str: nor rx:'
132
        rv = self.app.post('/rules/save/{0}'.format(_rule.sid), data=data)
133
        self.assertEqual(rv.status_code, 302)
134
        self.assertEqual(urlparse(rv.location).path, '/rules/edit/{}'.format(_rule.sid))
135
136
        _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...
137
        db.session.delete(_rule)
138
        db.session.commit()
139
140
    def test_del_rule(self):
141
        _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...
142
143
        db.session.add(NaxsiRules(u'PIF', 'str:test', u'BODY', u'$SQL:8', _rule.sid + 1, u'WEB_APPS',
144
                                  u'f hqewifueiwf hueiwhf uiewh fiewh fhw', '1', True, 1457101045))
145
        _sid = _rule.sid + 1
146
        rv = self.app.get('/rules/del/%d' % _sid)
147
        self.assertEqual(rv.status_code, 302)
148
149
        _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...
150
        self.assertEqual(_rule.sid, _rule.sid)
151
152
    def test_explain_rule(self):
153
        rv = self.app.get('/rules/explain/')
154
        self.assertEqual(rv.status_code, 302)
155
        self.assertEqual(urlparse(rv.location).path, '/rules/')
156
157
        _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...
158
        rv = self.app.get('/rules/explain/?rule={0}'.format(_rule.sid + 1), follow_redirects=True)
159
        self.assertIn('Not rule with id {0}'.format(_rule.sid + 1), str(rv.data))
160
161
        rv = self.app.get('/rules/explain/?rule={0}'.format(_rule.sid))
162
        self.assertEqual(rv.status_code, 200)
163
        self.assertIn(_rule.explain(), str(rv.data))
164
165
    def test_plain_rule(self):
166
        _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...
167
        rv = self.app.get('/rules/plain/%d' % _rule.sid)
168
        self.assertEqual(rv.status_code, 200)
169
        rdate = strftime("%F - %H:%M", localtime(float(str(_rule.timestamp))))
170
        rmks = "# ".join(_rule.rmks.strip().split("\n"))
171
        expected = """#
172
# sid: {0} | date: {1}
173
#
174
# {2}
175
#
176
{3}""".format(_rule.sid, rdate, rmks, str(_rule))
177
        self.assertEqual(expected.encode(), rv.data)
178
179
    def test_deact_rule(self):
180
        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...
181
182
        rv = self.app.get('/rules/deact/%d' % last_insert)  # deactivate
183
        self.assertEqual(rv.status_code, 200)
184
        _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...
185
        self.assertEqual(_rule.active, 0)
186
187
        rv = self.app.get('/rules/deact/%d' % last_insert)  # activate
188
        self.assertEqual(rv.status_code, 200)
189
        _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...
190
        self.assertEqual(_rule.active, 1)
191
192
        non_existent_sid = last_insert + 1
193
        rv = self.app.get('/rules/deact/%d' % non_existent_sid)
194
        self.assertEqual(rv.status_code, 302)
195
196
        rv = self.app.get('/rules/deact/')
197
        self.assertEqual(rv.status_code, 404)
198
199
    def test_search_rule(self):
200
        rv = self.app.get('/rules/search/')
201
        self.assertEqual(rv.status_code, 302)
202
203
        rv = self.app.get('/rules/search/?s=a')
204
        self.assertEqual(rv.status_code, 302)
205
206
        rv = self.app.get('/rules/search/?s="OR 1=1;--')
207
        self.assertEqual(rv.status_code, 200)
208
        self.assertIn('<input type="text" name="s" size="20" value="&#34;OR 1=1;--"', str(rv.data))
209
        self.assertIn('<p><strong>Search: OR 11--</strong></p>', str(rv.data))  # filtered data
210
211
        rv = self.app.get('/rules/search/?s=1337')  # get rule by id
212
        self.assertEqual(rv.status_code, 200)
213
214
    def test_edit_rule(self):
215
        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...
216
        rv = self.app.get('/rules/edit/%d' % non_existent_sid)
217
        self.assertEqual(rv.status_code, 302)
218
219
    def test_sandbox_rule(self):
220
        rv = self.app.get('/rules/sandbox/')
221
        self.assertEqual(rv.status_code, 200)
222
223
        data = {'rule': 'MainRule "rx:^POUET$" "msg: sqli"  "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8" id:1005;',
224
                'visualise': '1'}
225
        rv = self.app.post('/rules/sandbox/', data=data)
226
        self.assertEqual(rv.status_code, 302)
227
        self.assertIn('https://regexper.com/#^POUET$', str(rv.data))
228
229
        del data['visualise']
230
        data['explain'] = 1
231
        rv = self.app.post('/rules/sandbox/', data=data)
232
        _rule = NaxsiRules('sqli', 'rx:^POUET$', 'BODY|URL|ARGS|$HEADERS_VAR:Cookie', '$SQL:8', '1005', "", "sqli")
233
        self.assertIn(str(_rule.explain()), str(rv.data).replace('\\', ''))
234
235
    def test_parse_rule(self):
236
        rule_parser = NaxsiRules()
237
        rv = rule_parser.parse_rule('MainRule "rx:select|union|update|delete|insert|table|from|ascii|hex|unhex|drop"'
238
                                    '"msg:sql keywords" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1000;')
239
        self.assertEqual(rv, True)
240
241
        self.assertEqual(rule_parser.warnings,
242
                         ['Cookie in $HEADERS_VAR:Cookie is not lowercase. naxsi is case-insensitive',
243
                          'rule IDs below 10k are reserved (1000)'])
244
        rv = rule_parser.parse_rule('BasicRule "rx:^ratata$" "mz:$URL:/foobar|$BODY_VAR_X:^tutu$"'
245
                                    'id:4200001 "s:$SQL:8";')
246
        self.assertEqual(rv, False)
247
        self.assertIn('$BODY_VAR_X', str(rule_parser.error))
248
        self.assertIn('$URL', str(rule_parser.error))
249
        self.assertIn("You can't mix static $* with regex $*_X", str(rule_parser.error))
250
        self.assertIn("parsing of element 'mz:$URL:/foobar|$BODY_VAR_X:^tutu$' failed.", rule_parser.error)
251