Passed
Push — master ( b3861f...097bb0 )
by -
01:38
created

del_sid()   A

Complexity

Conditions 3

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 3.1406
Metric Value
cc 3
dl 0
loc 14
ccs 9
cts 12
cp 0.75
crap 3.1406
rs 9.4285
1 1
import logging
2 1
import re
3 1
import string
4 1
from time import time, localtime, strftime
5
6 1
from flask import Blueprint, render_template, request, redirect, flash, Response
1 ignored issue
show
Configuration introduced by
The import flask could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
7 1
from sqlalchemy.exc import SQLAlchemyError
0 ignored issues
show
Configuration introduced by
The import sqlalchemy.exc could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
8
9 1
from spike.model import db
10 1
from spike.model.naxsi_rules import NaxsiRules
11 1
from spike.model.naxsi_rulesets import NaxsiRuleSets
12 1
from spike.model import naxsi_mz, naxsi_score
13
14 1
rules = Blueprint('rules', __name__)
15
16
17 1
@rules.route("/")
18
def index():
19 1
    _rules = NaxsiRules.query.order_by(NaxsiRules.sid.desc()).all()
20 1
    if not _rules:
21
        flash("no rules found, please create one", "success")
22
        return redirect("/rules/new")
23 1
    return render_template("rules/index.html", rules=_rules)
24
25
26 1
@rules.route("/plain/<int:sid>", methods=["GET"])
27
def plain(sid):
28 1
    _rule = NaxsiRules.query.filter(NaxsiRules.sid == sid).first()
29 1
    if not _rule:
30
        flash("no rules found, please create one", "error")
31
        return redirect("/rules/new")
32
33 1
    return Response(__get_textual_representation_rule(_rule), mimetype='text/plain')
34
35
36 1
@rules.route("/view/<int:sid>", methods=["GET"])
37
def view(sid):
38 1
    _rule = NaxsiRules.query.filter(NaxsiRules.sid == sid).first()
39 1
    if _rule is None:
40 1
        flash("no rules found, please create one", "error")
41 1
        return redirect("/rules/")
42
43 1
    return render_template("rules/view.html", rule=_rule, rtext=__get_textual_representation_rule(_rule, full=0))
44
45
46 1
@rules.route("/search/", methods=["GET"])
47
def search():
48 1
    terms = request.args.get('s', '')
49
50 1
    if len(terms) < 2:
51 1
        return redirect('/rules')
52
53
    # No fancy injections
54 1
    whitelist = set(string.ascii_letters + string.digits + ':-_ ')
55 1
    filtered = ''.join(filter(whitelist.__contains__, terms))
56
57 1
    if filtered.isdigit():  # get rule by id
58 1
        _rules = db.session.query(NaxsiRules).filter(NaxsiRules.sid == int(filtered)).all()
59
    else:
60 1
        expression = '%' + filtered + '%'
61 1
        _rules = db.session.query(NaxsiRules).filter(
62
            db.or_(
63
                NaxsiRules.msg.like(expression),
64
                NaxsiRules.rmks.like(expression),
65
                NaxsiRules.detection.like(expression)
66
            )
67
        ).order_by(NaxsiRules.sid.desc()).all()
68 1
    return render_template("rules/index.html", rules=_rules, selection="Search: %s" % filtered, lsearch=terms)
69
70
71 1
@rules.route("/new", methods=["GET", "POST"])
72
def new():
73 1
    latest_sid = NaxsiRules.query.order_by(NaxsiRules.sid.desc()).first()
74 1
    if latest_sid is None:
75
        sid = 200001
76
    else:
77 1
        sid = latest_sid.sid + 1
78
79 1
    if request.method == "GET":
80 1
        _rulesets = NaxsiRuleSets.query.all()
81 1
        return render_template("rules/new.html", mz=naxsi_mz, rulesets=_rulesets, score=naxsi_score, latestn=sid)
82
83
    # create new rule
84 1
    logging.debug('Posted new request: %s', request.form)
85
86 1
    detect = str(request.form["detection"]).strip()
87 1
    if not detect.startswith("str:") and not detect.startswith("rx:"):
88 1
        detect = "str:%s" % detect
89
90 1
    mz = "|".join(request.form.getlist("mz"))
91
92 1
    try:
93 1
        if request.form["custom_mz"] == "on":
94
            mz = "%s|%s" % (mz, request.form["custom_mz_val"])
95 1
    except:
0 ignored issues
show
Coding Style Best Practice introduced by
General except handlers without types should be used sparingly.

Typically, you would use general except handlers when you intend to specifically handle all types of errors, f.e. when logging. Otherwise, such general error handlers can mask errors in your application that you want to know of.

Loading history...
96 1
        pass
0 ignored issues
show
Unused Code introduced by
This except handler seems to be unused and could be removed.

Except handlers which only contain pass and do not have an else clause can usually simply be removed:

try:
    raises_exception()
except:  # Could be removed
    pass
Loading history...
97
98 1
    score_raw = request.form["score"].strip()
99 1
    score_val = request.form["score_%s" % score_raw].strip()
100 1
    score = "%s:%s" % (score_raw, score_val)
101 1
    rmks = request.form["rmks"]
102 1
    ruleset = request.form["ruleset"]
103 1
    negative = 'negative' in request.form and request.form['negative'] == 'checked'
104
105 1
    nrule = NaxsiRules(request.form["msg"], detect, mz, score, sid, ruleset, rmks, "1", negative, int(time()))
106 1
    db.session.add(nrule)
107
108 1
    try:
109 1
        db.session.commit()
110 1
        flash("OK: created %s : %s" % (sid, request.form["msg"]), "success")
111 1
        return redirect("/rules/edit/%s" % sid)
112
    except SQLAlchemyError:
113
        flash("ERROR while trying to create %s : %s" % (sid, request.form["msg"]), "error")
114
115
    return redirect("/rules/new")
116
117
118 1
@rules.route("/edit/<int:sid>", methods=["GET", "POST"])
119
def edit(sid):
120 1
    rinfo = NaxsiRules.query.filter(NaxsiRules.sid == sid).first()
121 1
    if not rinfo:
122 1
        return redirect("/rules/")
123
124 1
    _rulesets = NaxsiRuleSets.query.all()
125 1
    rruleset = NaxsiRuleSets.query.filter(NaxsiRuleSets.name == rinfo.ruleset).first()
126 1
    custom_mz = ""
127 1
    mz_check = rinfo.mz
128 1
    if re.search(r"^\$[A-Z]+:(.*)\|[A-Z]+", mz_check):
129
        custom_mz = mz_check
130
        rinfo.mz = "custom"
131 1
    return render_template("rules/edit.html", mz=naxsi_mz, rulesets=_rulesets, score=naxsi_score, rules_info=rinfo,
132
                           rule_ruleset=rruleset, custom_mz=custom_mz)
133
134
135 1
@rules.route("/save/<int:sid>", methods=["POST"])
136
def save(sid):  # FIXME this is the exact same method as the `new` one.
137
138
    # create new rule
139
    try:
140
        msg = request.form["msg"]
141
        detect = str(request.form["detection"]).strip()
142
        if not detect.startswith("str:") and not detect.startswith("rx:"):
143
            detect = "str:%s" % detect
144
        mz = "|".join(request.form.getlist("mz"))
145
        try:
146
            if request.form["custom_mz"] == "on":
147
                if len(mz) > 1:
148
                    mz = "%s|%s" % (request.form["custom_mz_val"], mz)
149
                else:
150
                    mz = "%s" % (request.form["custom_mz_val"])
151
        except:
0 ignored issues
show
Coding Style Best Practice introduced by
General except handlers without types should be used sparingly.

Typically, you would use general except handlers when you intend to specifically handle all types of errors, f.e. when logging. Otherwise, such general error handlers can mask errors in your application that you want to know of.

Loading history...
152
            pass
0 ignored issues
show
Unused Code introduced by
This except handler seems to be unused and could be removed.

Except handlers which only contain pass and do not have an else clause can usually simply be removed:

try:
    raises_exception()
except:  # Could be removed
    pass
Loading history...
153
        score_raw = request.form["score"].strip()
154
        score_val = request.form["score_%s" % score_raw].strip()
155
        score = "%s:%s" % (score_raw, score_val)
156
        # sid = nr["sid"]
157
        rmks = request.form["rmks"]
158
        ruleset = request.form["ruleset"]
159
        active = request.form["active"]
160
        negative = 'negative' in request.form and request.form['negative'] == 'checked'
161
    except:
0 ignored issues
show
Coding Style Best Practice introduced by
General except handlers without types should be used sparingly.

Typically, you would use general except handlers when you intend to specifically handle all types of errors, f.e. when logging. Otherwise, such general error handlers can mask errors in your application that you want to know of.

Loading history...
162
        flash('ERROR - please select MZ/Score <a href="javascript:alert(history.back)">Go Back</a>', "error")
163
        return redirect("/rules/edit/%s" % sid)
164
165
    nrule = NaxsiRules.query.filter(NaxsiRules.sid == sid).first()
166
    nrule.msg = msg
167
    nrule.detection = detect
168
    nrule.mz = mz
169
    nrule.score = score
170
    nrule.ruleset = ruleset
171
    nrule.rmks = rmks
172
    nrule.active = active
173
    nrule.negative = negative
174
    nrule.timestamp = int(time())
175
    db.session.add(nrule)
176
    try:
177
        db.session.commit()
178
    except SQLAlchemyError:
179
        flash("ERROR while trying to update %s : %s" % (sid, msg), "error")
180
    return redirect("/rules/edit/%s" % sid)
181
182
183 1
@rules.route("/del/<int:sid>", methods=["GET"])
184 1
def del_sid(sid=''):
185 1
    nrule = NaxsiRules.query.filter(NaxsiRules.sid == sid).first()
186 1
    if not nrule:
187
        return redirect("/rules/")
188
189 1
    db.session.delete(nrule)
190 1
    try:
191 1
        db.session.commit()
192 1
        flash("OK: deleted %s : %s" % (sid, nrule.msg), "success")
193
    except SQLAlchemyError:
194
        flash("ERROR while trying to update %s : %s" % (sid, nrule.msg), "error")
195
196 1
    return redirect("/rules/")
197
198
199 1
@rules.route("/deact/<int:sid>", methods=["GET"])
200
def deact(sid):
201 1
    nrule = NaxsiRules.query.filter(NaxsiRules.sid == sid).first()
202 1
    if nrule is None:
203 1
        return redirect("/rules/")
204
205 1
    fm = 'deactivate' if nrule.active else 'reactivate'
206 1
    nrule.active = not nrule.active
207
208 1
    db.session.add(nrule)
209 1
    try:
210 1
        db.session.commit()
211 1
        flash("OK: %s %sd : %s" % (fm, sid, nrule.msg), "success")
212
    except SQLAlchemyError:
213
        flash("ERROR while trying to %s %s : %s" % (fm, sid, nrule.msg), "error")
214
215 1
    _rulesets = NaxsiRuleSets.query.all()
216 1
    return render_template("rules/edit.html", mz=naxsi_mz, rulesets=_rulesets, score=naxsi_score, rules_info=nrule)
217
218
219 1
def __get_textual_representation_rule(rule, full=1):
0 ignored issues
show
Coding Style Naming introduced by
The name __get_textual_representation_rule does not conform to the function naming conventions ([a-z_][a-z0-9_]{1,30}$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
220 1
    rdate = strftime("%F - %H:%M", localtime(float(str(rule.timestamp))))
221 1
    rmks = "# ".join(rule.rmks.strip().split("\n"))
222 1
    detect = rule.detection.lower() if rule.detection.startswith("str:") else rule.detection
223 1
    negate = 'negative' if rule.negative == 1 else ''
224
225 1
    if full == 1:
226 1
        nout = """
227
#
228
# sid: %s | date: %s
229
#
230
# %s
231
#
232
MainRule %s "%s" "msg:%s" "mz:%s" "s:%s" id:%s ;
233
234
""" % (rule.sid, rdate, rmks, negate, detect, rule.msg, rule.mz, rule.score, rule.sid)
235
    else:
236 1
        nout = """MainRule %s "%s" "msg:%s" "mz:%s" "s:%s" id:%s  ;""" % \
237
               (negate, rule.detection, rule.msg, rule.mz, rule.score, rule.sid)
238
239
    return nout
240