Esempio n. 1
0
    def test_explain_rule(self):
        rv = self.app.get('/sandbox/explain_rule/')
        self.assertEqual(rv.status_code, 302)
        self.assertEqual(urlparse(rv.location).path, '/sandbox/')

        _rule = NaxsiRules.query.order_by(NaxsiRules.sid.desc()).first()
        rv = self.app.get('/sandbox/explain_rule/?rule={0}'.format(_rule.sid + 1), follow_redirects=True)
        self.assertIn('Not rule with id {0}'.format(_rule.sid + 1), str(rv.data))

        rv = self.app.get('/sandbox/explain_rule/?rule={0}'.format(_rule.sid))
        self.assertEqual(rv.status_code, 200)
        self.assertIn(_rule.explain(), str(rv.data))

        rv = self.app.get('/sandbox/explain_rule/?rule=lol')
        self.assertEqual(rv.status_code, 302)
        self.assertEqual(urlparse(rv.location).path, '/sandbox/')

        data = 'MainRule "rx:^POUET$" "msg: sqli"  "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8" id:1005 ;'
        rv = self.app.post('/sandbox/explain_rule/', data={'rule': data})
        self.assertEqual(rv.status_code, 200)
        _rule = NaxsiRules()
        _rule.parse_rule(data)
        self.assertIn(_rule.explain(), str(rv.data))

        data = 'MainRule "lol:^POUET$" "msg: sqli" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8" id:1005 ;'
        rv = self.app.post('/sandbox/explain_rule/', data={'rule': data})
        self.assertEqual(rv.status_code, 200)
Esempio n. 2
0
    def test_explain_rule(self):
        rv = self.app.get('/sandbox/explain_rule/')
        self.assertEqual(rv.status_code, 302)
        self.assertEqual(urlparse(rv.location).path, '/sandbox/')

        _rule = NaxsiRules.query.order_by(NaxsiRules.sid.desc()).first()
        rv = self.app.get('/sandbox/explain_rule/?rule={0}'.format(_rule.sid +
                                                                   1),
                          follow_redirects=True)
        self.assertIn('Not rule with id {0}'.format(_rule.sid + 1),
                      str(rv.data))

        rv = self.app.get('/sandbox/explain_rule/?rule={0}'.format(_rule.sid))
        self.assertEqual(rv.status_code, 200)
        self.assertIn(_rule.explain(), str(rv.data))

        rv = self.app.get('/sandbox/explain_rule/?rule=lol')
        self.assertEqual(rv.status_code, 302)
        self.assertEqual(urlparse(rv.location).path, '/sandbox/')

        data = 'MainRule "rx:^POUET$" "msg: sqli"  "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8" id:1005 ;'
        rv = self.app.post('/sandbox/explain_rule/', data={'rule': data})
        self.assertEqual(rv.status_code, 200)
        _rule = NaxsiRules()
        _rule.parse_rule(data)
        self.assertIn(_rule.explain(), str(rv.data))

        data = 'MainRule "lol:^POUET$" "msg: sqli" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:8" id:1005 ;'
        rv = self.app.post('/sandbox/explain_rule/', data={'rule': data})
        self.assertEqual(rv.status_code, 200)
Esempio n. 3
0
    def test_parse_rule(self):
        rule_parser = NaxsiRules()

        errors, warnings, ret = rule_parser.parse_rule('MainRule "rx:select|union|update|delete|insert|table|from|ascii|hex|unhex|drop"'
                                    '"msg:sql keywords" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1000;')
        self.assertEqual(warnings,
                         ['Cookie in $HEADERS_VAR:Cookie is not lowercase. naxsi is case-insensitive',
                          'rule IDs below 10k are reserved (1000)'])

        errors, warnings, ret = rule_parser.parse_rule('BasicRule "rx:^ratata$" "mz:$URL:/foobar" '
                                    'id:4200001 "s:$SQL:8";')
        self.assertIn('$URL', str(errors))
        self.assertIn("The rule/whitelist doesn\'t target any zone.", str(errors))
        self.assertIn("Parsing of element \'mz:$URL:/foobar\' failed.", str(errors))

        errors, warnings, ret = rule_parser.parse_rule('"rx:^ratata$" "mz:$URL:/foobar|$BODY_VAR_X:^tutu$"'
                                    'id:4200001 "s:$SQL:8";')
        self.assertIn('No mainrule/basicrule keyword.', str(errors))

        errors, warnings, ret = rule_parser.parse_rule('MainRule BasicRule "rx:select"'
                                    '"msg:sql keywords" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1000;')
        self.assertEqual(['Both BasicRule and MainRule are present.'], errors)

        errors, warnings, ret = rule_parser.parse_rule('MainRule "rx:select"'
                                    '"msg:sql keywords" "mz:BODY" "s:$SQL:4" id:1000 "wrong:LOL";')
        self.assertIn("'wrong:LOL' is an invalid element and thus can not be parsed.", str(errors))

        errors, warnings, ret = rule_parser.parse_rule('MainRule "rx:select"'
                                    '"msg:sql keywords" "mz:BODY" "s:$SQL:4" "id:non_numeric";')
        self.assertEqual(['id:non_numeric is not numeric', "Parsing of element 'id:non_numeric' failed."],
                         errors)

        errors, warnings, ret = rule_parser.parse_rule('MainRule "rx:select" "mz:wrong" "msg:sql keywords" "s:$SQL:4" "id:10000";')
        self.assertIn("'wrong' is not a known sub-part of mz : ", str(errors))
        self.assertIn("Parsing of element 'mz:wrong' failed.", str(errors))
Esempio n. 4
0
def new():
    latest_sid = NaxsiRules.query.order_by(NaxsiRules.sid.desc()).first()
    if latest_sid is None:
        sid = 200001
    else:
        sid = latest_sid.sid + 1

    if request.method == "GET":
        _rulesets = NaxsiRuleSets.query.all()
        return render_template("rules/new.html",
                               mz=naxsi_mz,
                               rulesets=_rulesets,
                               score=naxsi_score,
                               latestn=sid)

    # create new rule
    logging.debug('Posted new request: %s', request.form)
    mz = "|".join(
        filter(
            len,
            request.form.getlist("mz") +
            request.form.getlist("custom_mz_val")))

    score = request.form.get("score", "")
    score += ':'
    score += request.form.get("score_%s" % request.form.get("score", ""), "")

    nrule = NaxsiRules(request.form.get("msg", ""),
                       request.form.get("detection", ""), mz, score, sid,
                       request.form.get("ruleset", ""),
                       request.form.get("rmks", ""), "1",
                       request.form.get("negative", "") == 'checked',
                       int(time()))

    errors, warnings = nrule.validate()

    if errors:
        for error in errors:
            flash(error, category='error')
        return redirect(url_for("rules.new"))
    elif warnings:
        for warning in warnings:
            flash(warning, category='warnings')

    db.session.add(nrule)
    db.session.commit()

    return redirect("/rules/edit/%s" % sid)
Esempio n. 5
0
    def test_parse_rule(self):
        rule_parser = NaxsiRules()

        errors, warnings, ret = rule_parser.parse_rule(
            'MainRule "rx:select|union|update|delete|insert|table|from|ascii|hex|unhex|drop"'
            '"msg:sql keywords" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1000;'
        )
        self.assertEqual(warnings, [
            'Cookie in $HEADERS_VAR:Cookie is not lowercase. naxsi is case-insensitive',
            'rule IDs below 10k are reserved (1000)'
        ])

        errors, warnings, ret = rule_parser.parse_rule(
            'BasicRule "rx:^ratata$" "mz:$URL:/foobar" '
            'id:4200001 "s:$SQL:8";')
        self.assertIn('$URL', str(errors))
        self.assertIn("The rule/whitelist doesn\'t target any zone.",
                      str(errors))
        self.assertIn("Parsing of element \'mz:$URL:/foobar\' failed.",
                      str(errors))

        errors, warnings, ret = rule_parser.parse_rule(
            '"rx:^ratata$" "mz:$URL:/foobar|$BODY_VAR_X:^tutu$"'
            'id:4200001 "s:$SQL:8";')
        self.assertIn('No mainrule/basicrule keyword.', str(errors))

        errors, warnings, ret = rule_parser.parse_rule(
            'MainRule BasicRule "rx:select"'
            '"msg:sql keywords" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1000;'
        )
        self.assertEqual(['Both BasicRule and MainRule are present.'], errors)

        errors, warnings, ret = rule_parser.parse_rule(
            'MainRule "rx:select"'
            '"msg:sql keywords" "mz:BODY" "s:$SQL:4" id:1000 "wrong:LOL";')
        self.assertIn(
            "'wrong:LOL' is an invalid element and thus can not be parsed.",
            str(errors))

        errors, warnings, ret = rule_parser.parse_rule(
            'MainRule "rx:select"'
            '"msg:sql keywords" "mz:BODY" "s:$SQL:4" "id:non_numeric";')
        self.assertEqual([
            'id:non_numeric is not numeric',
            "Parsing of element 'id:non_numeric' failed."
        ], errors)

        errors, warnings, ret = rule_parser.parse_rule(
            'MainRule "rx:select" "mz:wrong" "msg:sql keywords" "s:$SQL:4" "id:10000";'
        )
        self.assertIn("'wrong' is not a known sub-part of mz : ", str(errors))
        self.assertIn("Parsing of element 'mz:wrong' failed.", str(errors))
Esempio n. 6
0
def import_rules():
    if request.method == "GET":
        return render_template("rules/import.html",
                               rulesets=NaxsiRuleSets.query.all())

    ruleset = request.form.get("ruleset", "")
    upfile = request.files.get('file', '')

    if not ruleset or not upfile:
        flash("Missing rule file and/or ruleset name.", 'error')
        return redirect(url_for("rules.new"))

    raw = upfile.stream.getvalue()

    success_imports = 0
    potential_imports = 0
    for potential_rule in raw.split('\n'):
        potential_rule = potential_rule.strip()
        if not potential_rule or potential_rule.startswith(
                "#"
        ):  # Save ourselves some time by not trying to import comments
            continue
        potential_imports += 1
        _rule = NaxsiRules(ruleset=ruleset, active=1)
        errors, warnings, rule = _rule.parse_rule(potential_rule)

        if errors:
            flash("Fail to parse %s: %s" % (potential_rule, ', '.join(errors)),
                  'error')
            continue
        else:
            db.session.add(rule)
            try:
                db.session.commit()
                success_imports += 1
            except IntegrityError:
                db.session.rollback()
                flash("Rule %s has not an unique ID" % rule['sid'])
    flash("Imported %d rules out of %d lines in ruleset %s" %
          (success_imports, potential_imports, ruleset))

    return render_template("rules/import.html",
                           rulesets=NaxsiRuleSets.query.all())
Esempio n. 7
0
def explain_rule():
    errors = warnings = list()
    rule_get = request.args.get('rule', '')
    rule_post = request.form.get("rule", '')
    if rule_get.isdigit():  # explain a rule by id
        _rule = NaxsiRules.query.filter(NaxsiRules.sid == rule_get).first()
        if _rule is None:
            flash('Not rule with id %s' % rule_get)
            return redirect(url_for("sandbox.index"))
    elif rule_get is not '':
        flash('Please provide a numeric id')
        return redirect(url_for("sandbox.index"))
    elif not rule_post:
        flash('Please provide a rule')
        return redirect(url_for("sandbox.index"))
    else:
        _rule = NaxsiRules()
        errors, warnings, rdict = _rule.parse_rule(rule_post)
        _rule = NaxsiRules()
        _rule.from_dict(rdict)
        _rule.errors = errors
        _rule.warnings = warnings

        if _rule.errors:
            flash('You rule is wrong', 'error')
            return render_template("misc/sandbox.html")

    if 'visualise_rule' in request.form:
        if _rule.detection.startswith('rx:'):
            return redirect('https://regexper.com/#' + _rule.detection[3:])
        else:
            flash('The rule is not a regexp, so you can not visualize it.', category='error')

    if errors:
        for error in errors:
            flash(error, category='error')
    if warnings:
        for warnings in warnings:
            flash(warnings, category='warning')

    return render_template("misc/sandbox.html", rule_explaination=_rule.explain(), rule=_rule)
Esempio n. 8
0
    def test_del_rule(self):
        _rule = NaxsiRules.query.order_by(NaxsiRules.sid.desc()).first()

        db.session.add(
            NaxsiRules(u'PIF', 'str:test', u'BODY', u'$SQL:8', _rule.sid + 1,
                       u'WEB_APPS', u'f hqewifueiwf hueiwhf uiewh fiewh fhw',
                       '1', True, 1457101045))
        _sid = _rule.sid + 1
        rv = self.app.get('/rules/del/%d' % _sid)
        self.assertEqual(rv.status_code, 302)

        _rule = NaxsiRules.query.order_by(NaxsiRules.sid.desc()).first()
        self.assertEqual(_rule.sid, _rule.sid)
Esempio n. 9
0
def new():
    latest_sid = NaxsiRules.query.order_by(NaxsiRules.sid.desc()).first()
    if latest_sid is None:
        sid = 200001
    else:
        sid = latest_sid.sid + 1

    if request.method == "GET":
        _rulesets = NaxsiRuleSets.query.all()
        return render_template("rules/new.html", mz=naxsi_mz, rulesets=_rulesets, score=naxsi_score, latestn=sid)

    # create new rule
    logging.debug('Posted new request: %s', request.form)
    mz = "|".join(filter(len, request.form.getlist("mz") + request.form.getlist("custom_mz_val")))

    score = request.form.get("score", "")
    score += ':'
    score += request.form.get("score_%s" % request.form.get("score", ""), "")

    nrule = NaxsiRules(request.form.get("msg", ""), request.form.get("detection", ""), mz, score, sid,
                       request.form.get("ruleset", ""), request.form.get("rmks", ""), "1",
                       request.form.get("negative", "") == 'checked', int(time()))

    errors, warnings = nrule.validate()

    if errors:
        for error in errors:
            flash(error, category='error')
        return redirect(url_for("rules.new"))
    elif warnings:
        for warning in warnings:
            flash(warning, category='warnings')

    db.session.add(nrule)
    db.session.commit()

    return redirect("/rules/edit/%s" % sid)
Esempio n. 10
0
def import_rules():
    if request.method == "GET":
        return render_template("rules/import.html", rulesets=NaxsiRuleSets.query.all())

    ruleset = request.form.get("ruleset", "")
    upfile = request.files.get('file', '')

    if not ruleset or not upfile:
        flash("Missing rule file and/or ruleset name.", 'error')
        return redirect(url_for("rules.new"))

    raw = upfile.stream.getvalue()

    success_imports = 0
    potential_imports = 0
    for potential_rule in raw.split('\n'):
        potential_rule = potential_rule.strip()
        if not potential_rule or potential_rule.startswith("#"):  # Save ourselves some time by not trying to import comments
            continue
        potential_imports += 1
        _rule = NaxsiRules(ruleset=ruleset, active=1)
        errors, warnings, rule = _rule.parse_rule(potential_rule)

        if errors:
            flash("Fail to parse %s: %s" % (potential_rule, ', '.join(errors)), 'error')
            continue
        else:
            db.session.add(rule)
            try:
                db.session.commit()
                success_imports += 1
            except IntegrityError:
                db.session.rollback()
                flash("Rule %s has not an unique ID" % rule['sid'])
    flash("Imported %d rules out of %d lines in ruleset %s" % (success_imports, potential_imports, ruleset))

    return render_template("rules/import.html", rulesets=NaxsiRuleSets.query.all())
Esempio n. 11
0
    def test_parse_rule(self):
        rule_parser = NaxsiRules()

        rv = rule_parser.parse_rule('MainRule "rx:select|union|update|delete|insert|table|from|ascii|hex|unhex|drop"'
                                    '"msg:sql keywords" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1000;')
        self.assertEqual(rv, True)
        self.assertEqual(rule_parser.warnings,
                         ['Cookie in $HEADERS_VAR:Cookie is not lowercase. naxsi is case-insensitive',
                          'rule IDs below 10k are reserved (1000)'])

        rv = rule_parser.parse_rule('BasicRule "rx:^ratata$" "mz:$URL:/foobar|$BODY_VAR_X:^tutu$"'
                                    'id:4200001 "s:$SQL:8";')
        self.assertEqual(rv, False)
        self.assertIn('$BODY_VAR_X', str(rule_parser.error))
        self.assertIn('$URL', str(rule_parser.error))
        self.assertIn("You can't mix static $* with regex $*_X", str(rule_parser.error))
        self.assertIn("parsing of element 'mz:$URL:/foobar|$BODY_VAR_X:^tutu$' failed.", rule_parser.error)

        rv = rule_parser.parse_rule('"rx:^ratata$" "mz:$URL:/foobar|$BODY_VAR_X:^tutu$"'
                                    'id:4200001 "s:$SQL:8";')
        self.assertEqual(rv, False)
        self.assertIn('No mainrule/basicrule keyword.', rule_parser.error)

        rv = rule_parser.parse_rule('MainRule BasicRule "rx:select"'
                                    '"msg:sql keywords" "mz:BODY|URL|ARGS|$HEADERS_VAR:Cookie" "s:$SQL:4" id:1000;')
        self.assertEqual(rv, False)
        self.assertIn('Multiple mainrule/basicrule keywords.', rule_parser.error)

        rv = rule_parser.parse_rule('MainRule "rx:select"'
                                    '"msg:sql keywords" "mz:BODY" "s:$SQL:4" id:1000 "wrong:LOL";')
        self.assertEqual(rv, False)
        self.assertIn("'wrong:LOL' is an invalid element and thus can not be parsed.", rule_parser.error)

        rv = rule_parser.parse_rule('MainRule "rx:select"'
                                    '"msg:sql keywords" "mz:BODY" "s:$SQL:4" "id:non_numeric";')
        self.assertEqual(rv, False)
        self.assertEqual(['id:non_numeric is not numeric', "parsing of element 'id:non_numeric' failed."],
                         rule_parser.error)

        rv = rule_parser.parse_rule('MainRule "rx:select" "mz:wrong" "msg:sql keywords" "s:$SQL:4" "id:10000";')
        self.assertEqual(rv, False)
        self.assertIn("'wrong' is not a known sub-part of mz : ", str(rule_parser.error))
        self.assertIn("parsing of element 'mz:wrong' failed.", rule_parser.error)
Esempio n. 12
0
    def test_select(self):
        current_sid = NaxsiRules.query.order_by(NaxsiRules.sid.desc()).first()
        current_sid = 1337 if current_sid is None else current_sid.sid + 1

        db.session.add(NaxsiRules(u'POUET', 'str:test', u'BODY', u'$SQL:8', current_sid, u'WEB_APPS',
                                  u'f hqewifueiwf hueiwhf uiewh fiewh fhw', '1', True, 1457101045))
        db.session.commit()

        _ruleset = NaxsiRules.query.first().ruleset
        rv = self.app.get('/rulesets/select/%s' % _ruleset)
        self.assertEqual(rv.status_code, 200)
        self.assertIn(_ruleset, str(rv.data))

        random_name = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(16))
        rv = self.app.get('/rulesets/select/%s' % random_name)
        self.assertEqual(rv.status_code, 200)

        db.session.delete(NaxsiRules.query.filter(current_sid == NaxsiRules.sid).first())
Esempio n. 13
0
def explain_rule():
    errors = warnings = list()
    rule_get = request.args.get("rule", "")
    rule_post = request.form.get("rule", "")
    if rule_get.isdigit():  # explain a rule by id
        _rule = NaxsiRules.query.filter(NaxsiRules.sid == rule_get).first()
        if _rule is None:
            flash("Not rule with id %s" % rule_get)
            return redirect(url_for("sandbox.index"))
    elif rule_get is not "":
        flash("Please provide a numeric id")
        return redirect(url_for("sandbox.index"))
    elif not rule_post:
        flash("Please provide a rule")
        return redirect(url_for("sandbox.index"))
    else:
        _rule = NaxsiRules()
        errors, warnings, rdict = _rule.parse_rule(rule_post)
        _rule = NaxsiRules()
        _rule.from_dict(rdict)
        _rule.errors = errors
        _rule.warnings = warnings

        if _rule.errors:
            flash("You rule is wrong", "error")
            return render_template("misc/sandbox.html")

    if "visualise_rule" in request.form:
        if _rule.detection.startswith("rx:"):
            return redirect("https://regexper.com/#" + _rule.detection[3:])
        else:
            flash("The rule is not a regexp, so you can not visualize it.", category="error")

    if errors:
        for error in errors:
            flash(error, category="error")
    if warnings:
        for warnings in warnings:
            flash(warnings, category="warning")

    return render_template("misc/sandbox.html", rule_explaination=_rule.explain(), rule=_rule)