Example #1
0
def swallows_exceptions(java_dest: str, exclude: list = None) -> bool:
    """
    Search for ``catch`` blocks that are empty or only have comments.

    See `REQ.161 <https://fluidattacks.com/web/rules/161/>`_.

    See `CWE-391 <https://cwe.mitre.org/data/definitions/391.html>`_.

    :param java_dest: Path to a Java source file or package.
    :param exclude: Paths that contains any string from this list are ignored.
    """
    # Empty() grammar matches 'anything'
    # ~Empty() grammar matches 'not anything' or 'nothing'
    grammar = Suppress(Keyword('catch')) + nestedExpr(opener='(', closer=')') \
        + nestedExpr(opener='{', closer='}', content=~Empty())
    grammar.ignore(javaStyleComment)

    try:
        matches = lang.path_contains_grammar(grammar, java_dest,
                                             LANGUAGE_SPECS, exclude)
    except FileNotFoundError:
        show_unknown('File does not exist', details=dict(code_dest=java_dest))
    else:
        if matches:
            show_open('Code has empty "catch" blocks',
                      details=dict(matched=matches))
            return True
        show_close('Code does not have empty "catch" blocks',
                   details=dict(code_dest=java_dest))
    return False
Example #2
0
def has_switch_without_default(js_dest: str, exclude: list = None) -> bool:
    r"""
    Check if all ``switch``\ es have a ``default`` clause.

    See `REQ.161 <https://fluidattacks.com/web/rules/161/>`_.

    See `CWE-478 <https://cwe.mitre.org/data/definitions/478.html>`_.

    :param js_dest: Path to a JavaScript source file or package.
    :param exclude: Paths that contains any string from this list are ignored.
    """
    switch = Keyword('switch') + nestedExpr(opener='(', closer=')')
    switch_block = Suppress(switch) + nestedExpr(opener='{', closer='}')
    switch_block.ignore(cppStyleComment)
    switch_block.ignore(L_CHAR)
    switch_block.ignore(L_STRING)
    switch_block.addCondition(lambda x: not RE_HAVES_DEFAULT.search(str(x)))
    try:
        matches = lang.path_contains_grammar(switch_block, js_dest,
                                             LANGUAGE_SPECS, exclude)
    except FileNotFoundError:
        show_unknown('File does not exist', details=dict(code_dest=js_dest))
        return False
    if matches:
        show_open('Code does not have "switch" with "default" clause',
                  details=dict(matched=matches))
        return True
    show_close('Code has "switch" with "default" clause',
               details=dict(code_dest=js_dest))
    return False
Example #3
0
def _declares_catch_for_exceptions(
        java_dest: str,
        exceptions_list: list,
        open_msg: str,
        closed_msg: str,
        exclude: list = None) -> bool:
    """Search for the declaration of catch for the given exceptions."""
    any_exception = L_VAR_CHAIN_NAME
    provided_exception = MatchFirst(
        [Keyword(exception) for exception in exceptions_list])

    exception_group = delimitedList(expr=any_exception, delim='|')
    exception_group.addCondition(
        # Ensure that at least one exception in the group is the provided one
        lambda tokens: any(provided_exception.matches(tok) for tok in tokens))

    grammar = Suppress(Keyword('catch')) + nestedExpr(
        opener='(', closer=')', content=(
            exception_group + Suppress(Optional(L_VAR_NAME))))
    grammar.ignore(javaStyleComment)
    grammar.ignore(L_STRING)
    grammar.ignore(L_CHAR)

    try:
        matches = lang.path_contains_grammar(grammar, java_dest,
                                             LANGUAGE_SPECS, exclude)
    except FileNotFoundError:
        show_unknown('File does not exist', details=dict(code_dest=java_dest))
    else:
        if matches:
            show_open(open_msg, details=dict(matched=matches))
            return True
        show_close(closed_msg, details=dict(code_dest=java_dest))
    return False
Example #4
0
def uses_insecure_cipher(java_dest: str, algorithm: str,
                         exclude: list = None) -> bool:
    """
    Check if code uses an insecure cipher algorithm.

    See `REQ.148 <https://fluidattacks.com/web/rules/148/>`_.
    See `REQ.149 <https://fluidattacks.com/web/rules/149/>`_.

    :param java_dest: Path to a Java source file or package.
    :param algorithm: Insecure algorithm.
    :param exclude: Paths that contains any string from this list are ignored.
    """
    method = 'Cipher.getInstance("{}")'.format(algorithm.upper())
    op_mode = '/' + oneOf('CBC ECB', caseless=True)
    padding = '/' + oneOf('NoPadding PKCS5Padding', caseless=True)
    algorithm = '"' + CaselessKeyword(algorithm) + Optional(
        op_mode + Optional(padding)) + '"'

    grammar = Suppress(Keyword('Cipher') + '.' + Keyword('getInstance')) + \
        nestedExpr()
    grammar.ignore(javaStyleComment)
    grammar.addCondition(
        # Ensure that at least one token is the provided algorithm
        lambda tokens: tokens.asList() and any(
            algorithm.matches(tok) for tok in tokens[0]))
    try:
        matches = lang.path_contains_grammar(grammar, java_dest,
                                             LANGUAGE_SPECS, exclude)
    except FileNotFoundError:
        show_unknown('File does not exist', details=dict(location=java_dest))
        return False
    if not matches:
        show_close('Code does not use {} method'.format(method),
                   details=dict(location=java_dest))
        return False
    show_open('Code uses {} method'.format(method),
              details=dict(matches=matches))
    return True
Example #5
0
def has_if_without_else(java_dest: str, exclude: list = None) -> bool:
    r"""
    Check if all ``if``\ s have an ``else`` clause.

    See `REQ.161 <https://fluidattacks.com/web/rules/161/>`_.

    :param java_dest: Path to a Java source file or package.
    :param exclude: Paths that contains any string from this list are ignored.
    """
    args = nestedExpr(opener='(', closer=')')

    if_ = Keyword('if') + args
    if_line = Optional('}') + if_ + Optional('{')

    try:
        conds = lang.check_grammar(if_line, java_dest, LANGUAGE_SPECS, exclude)
    except FileNotFoundError:
        show_unknown('File does not exist', details=dict(code_dest=java_dest))
        return False
    else:
        if not conds:
            show_close('Code does not use "if" statements',
                       details=dict(code_dest=java_dest))
            return False

    block = nestedExpr(opener='{', closer='}')

    if_block = if_ + block
    else_if_block = Keyword('else') + Keyword('if') + args + block
    else_block = Keyword('else') + block

    cond_block = \
        Suppress(if_block + ZeroOrMore(else_if_block)) + Optional(else_block)
    cond_block.ignore(javaStyleComment)
    cond_block.ignore(L_CHAR)
    cond_block.ignore(L_STRING)

    vulns = {}
    for code_file, val in conds.items():
        vulns.update(lang.block_contains_empty_grammar(cond_block,
                                                       code_file, val['lines'],
                                                       _get_block))
    if not vulns:
        show_close('Code has "if" with "else" clause',
                   details=dict(file=java_dest,
                                fingerprint=get_sha256(java_dest)))
    else:
        show_open('Code has "if" without "else" clause',
                  details=dict(matched=vulns,
                               total_vulns=len(vulns)))
        return True
    return False
Example #6
0
def has_switch_without_default(csharp_dest: str, exclude: list = None) -> bool:
    r"""
    Check if all ``switch``\ es have a ``default`` clause.

    See `REQ.161 <https://fluidattacks.com/web/rules/161/>`_.

    See `CWE-478 <https://cwe.mitre.org/data/definitions/478.html>`_.

    :param csharp_dest: Path to a C# source file or package.
    :param exclude: Paths that contains any string from this list are ignored.
    """
    switch = Keyword('switch') + nestedExpr(opener='(', closer=')')
    switch_line = Optional('}') + switch + Optional('{')

    result = False
    try:
        switches = lang.check_grammar(switch_line, csharp_dest, LANGUAGE_SPECS,
                                      exclude)
    except FileNotFoundError:
        show_unknown('File does not exist',
                     details=dict(code_dest=csharp_dest))
        return False
    else:
        if not switches:
            show_close('Code does not have switches',
                       details=dict(code_dest=csharp_dest))
            return False

    switch_block = Suppress(switch) + nestedExpr(opener='{', closer='}')
    switch_block.ignore(javaStyleComment)
    switch_block.ignore(L_CHAR)
    switch_block.ignore(L_STRING)

    vulns = {}
    for code_file, val in switches.items():
        vulns.update(
            lang.block_contains_grammar(switch_block,
                                        code_file,
                                        val['lines'],
                                        _get_block,
                                        should_not_have=r'(?:default\s*:)'))
    if not vulns:
        show_close('Code has "switch" with "default" clause',
                   details=dict(file=csharp_dest,
                                fingerprint=get_sha256(csharp_dest)))
    else:
        show_open('Code does not have "switch" with "default" clause',
                  details=dict(matched=vulns, total_vulns=len(vulns)))
        result = True
    return result
Example #7
0
    def __init__(self):
        name = Word(alphas, alphanums + '_' + '-')
        variable = Suppress('?') + name

        require_def = Suppress('(') + ':requirements' + \
            OneOrMore(one_of(':strips :typing :negative-preconditions :disjunctive-preconditions :equality :existential-preconditions :universal-preconditions :quantified-preconditions :conditional-effects :fluents :numeric-fluents :adl :durative-actions :duration-inequalities :timed-initial-literals :action-costs')) \
            + Suppress(')')

        types_def = Suppress('(') + ':types' + \
            OneOrMore(Group(Group(OneOrMore(name)) + \
                            Optional(Suppress('-') + name))).setResultsName('types') \
                            + Suppress(')')

        constants_def = Suppress('(') + ':constants' + \
            OneOrMore(Group(Group(OneOrMore(name)) + \
                            Optional(Suppress('-') + name))).setResultsName('constants') \
                            + Suppress(')')

        predicate = Suppress('(') + \
            Group(name + Group(ZeroOrMore(Group(Group(OneOrMore(variable)) + \
                                                Optional(Suppress('-') + name))))) \
                                                + Suppress(')')

        predicates_def = Suppress('(') + ':predicates' + \
            Group(OneOrMore(predicate)).setResultsName('predicates') \
            + Suppress(')')

        functions_def = Suppress('(') + ':functions' + \
            Group(OneOrMore(predicate)).setResultsName('functions') \
            + Suppress(')')

        parameters = ZeroOrMore(Group(Group(OneOrMore(variable)) \
                                     + Optional(Suppress('-') + name))).setResultsName('params')
        action_def = Group(Suppress('(') + ':action' + name.setResultsName('name') \
                           + ':parameters' + Suppress('(') + parameters + Suppress(')') \
                           + Optional(':precondition' + nestedExpr().setResultsName('pre')) \
                           + Optional(':effect' + nestedExpr().setResultsName('eff')) \
                           + Suppress(')'))

        dur_action_def = Group(Suppress('(') + ':durative-action' + name.setResultsName('name') \
                               + ':parameters' + Suppress('(') + parameters + Suppress(')') \
                               + ':duration' + nestedExpr().setResultsName('duration') \
                               + ':condition' + nestedExpr().setResultsName('cond') \
                               + ':effect' + nestedExpr().setResultsName('eff') \
                               + Suppress(')'))

        domain = Suppress('(') + 'define' \
            + Suppress('(') + 'domain' + name.setResultsName('name') + Suppress(')') \
            + Optional(require_def) + Optional(types_def) + Optional(constants_def) \
            + Optional(predicates_def) + Optional(functions_def) \
            + Group(ZeroOrMore(action_def | dur_action_def)).setResultsName('actions') + Suppress(')')

        objects = OneOrMore(Group(Group(OneOrMore(name)) \
                                  + Optional(Suppress('-') + name))).setResultsName('objects')

        metric = (Keyword('minimize') | Keyword('maximize')).setResultsName('optimization') \
            + (name | nestedExpr()).setResultsName('metric')

        problem = Suppress('(') + 'define' \
            + Suppress('(') + 'problem' + name.setResultsName('name') + Suppress(')') \
            + Suppress('(') + ':domain' + name + Suppress(')') + Optional(require_def) \
            + Optional(Suppress('(') + ':objects' + objects + Suppress(')')) \
            + Suppress('(') + ':init' + ZeroOrMore(nestedExpr()).setResultsName('init') + Suppress(')') \
            + Suppress('(') + ':goal' + nestedExpr().setResultsName('goal') + Suppress(')') \
            + Optional(Suppress('(') + ':metric' + metric + Suppress(')')) \
            + Suppress(')')

        domain.ignore(';' + restOfLine)
        problem.ignore(';' + restOfLine)

        self._domain = domain
        self._problem = problem
        self._parameters = parameters