Example #1
0
 def __init__(self, name, lineno, scope, ast_node=None):
     NodeRep.__init__(self, name, lineno, ast_node=ast_node)
     
     self._scope = scope
     self._formal_params = []
     self._parsed = False
     self._method_call = []
Example #2
0
 def __init__(self, name, lineno, ast_node, scope, parent_obj = None):
     NodeRep.__init__(self, name, lineno, ast_node=ast_node)
     ast_node._obj = self
     self._scope = scope
     self._parent_obj = parent_obj
     self._params = self._parse_params()
     # Funccall can be called multiple times (in custom function or method)
     self._vulntraces = []
Example #3
0
 def __init__(self, name, lineno, scope, ast_node=None):
     NodeRep.__init__(self, name, lineno, ast_node=ast_node)
     
     self._scope = scope
     # return statements are stored as VariableDef
     self._return_vars = []
     self._formal_params = []
     self._ast_node.obj = self
Example #4
0
File: obj.py Project: wvdongen/SCA
 def __init__(self, name, lineno, scope, object_var, ast_node=None):
     
     NodeRep.__init__(self, name, lineno, ast_node=ast_node)
     
     self._scope = scope
     self._object_var = object_var
     self._methods = {}
     self._scope.obj = self
Example #5
0
 def _get_ancestor_vars(self, node, vars = None, level=0):
     '''
     Return the ancestor Variables for this var.
     For next example php code:
         <? $a = 'ls' . $_GET['bar'] . $_POST['foo'];
            $b = somefunc($a);
         ?>
     we got that $_GET and $_POST are both $a's ancestor as well as $a is for $b.
     
     Also determines if this var is safe for vulns
     '''
     if vars is None:
         vars = []
     
     for n in NodeRep.parse(node):
         if type(node) is phpast.BinaryOp:
             # only parse direct nodes
             for item in NodeRep.parse(node, 0, 0, 1): 
                 self._get_ancestor_vars(item, vars, level + 1)
             break
         
         if type(n) is phpast.Variable:
             vars.append(n)
     
     if level == 0:
         
         # Securing functions
         safe_for = {}
         
         for n in vars:
             # todo look at all vars
             for fc in self._get_parent_nodes(n, [phpast.FunctionCall]):
             
                 # Don't set custom function calls params as parent, this is done by
                 # looking at the return vars
                 if fc in self.funccall_nodes and hasattr(fc, '_obj') and fc._obj.get_called_obj():
                     vars.remove(n)
                     continue
                 
                 vulnty = get_vulnty_for_sec(fc.name)
                 if vulnty:
                     if vulnty not in safe_for:
                         safe_for[vulnty] = 1
                     else:
                         safe_for[vulnty] = safe_for[vulnty] + 1
         
         for vulnty, count in safe_for.iteritems():
             if count == len(vars):
                 self._safe_for.append(vulnty)
                 
     return vars
Example #6
0
    def _get_ancestor_funccalls(self, node, funcs = None, level=0):
        if funcs is None:
            funcs = []
        
        for n in NodeRep.parse(node):
            if type(node) is phpast.BinaryOp:
                # only parse direct nodes
                for item in NodeRep.parse(node, 0, 0, 1): 
                    self._get_ancestor_funccalls(item, funcs, level + 1)
                break

            if type(n) is phpast.FunctionCall:
                funcs.append(n)
        
        return funcs         
Example #7
0
 def __init__(self, name, lineno, scope, ast_node=None):
     
     NodeRep.__init__(self, name, lineno, ast_node=ast_node)
     
     # Containing Scope.
     self._scope = scope
     # Parent VariableDef
     self._parents = []
     # Ancestors AST FunctionCall nodes
     self.funccall_nodes = []
     # Ancestors AST Variable nodes
     self.var_nodes = []
     # Is this var controlled by user?
     self._controlled_by_user = None
     # Vulns this variable is safe for. 
     self._safe_for = []
     # Being 'root' means that this var doesn't depend on any other.
     self._is_root = True if (name in VariableDef.USER_VARS) else None 
     # Request parameter name, source for a possible vuln.
     self._taint_source = None
     # Is object property?
     self._object_property = False
     # Anon var? (param var in functioncall).
     self._anon_var = False
Example #8
0
    def _parse_me(self, node, scope):
        '''
        TODO: add method call
        
        Traverse this AST subtree until either a Variable or FunctionCall node
        is found...
        '''
        for node in NodeRep.parse(node):
            
            if type(node) is phpast.BinaryOp:
                # only parse direct nodes
                for item in NodeRep.parse(node, 0, 0, 1): 
                    self._parse_me(item, scope)
                break
            
            if type(node) is phpast.Variable:
                # object properties are stored as $this->property
                varname = node.name
                if type(node._parent_node) is phpast.ObjectProperty:
                    varname = node._parent_node.node.name + '->' + node._parent_node.name 
                 
                vardef = VariableDef(varname + '__$temp_anon_var$_', node.lineno, scope)
                vardef.var_nodes = [node]
                # anon var is not stored in scope
                vardef._anon_var = True
                # get and set parent
                scopevar = scope.get_var(varname)
                vardef.add_parent(scopevar)
                # add Param to VarDef
                # TODO: not really necessary?
                vardef._parent_obj = self
                # add var to current scope
                scope.add_var(vardef)
                self.vars.append(vardef)
                break
            
            elif type(node) is phpast.FunctionCall:
                
                # TEST call functioncal visitor
                from core.visitors.base_visitor import BaseVisitor
                from core.visitors.function_call_visitor import FunctionCallVisitor
                
                visitor = FunctionCallVisitor(BaseVisitor);
                fc, stoponthis = visitor.visit(node, scope.get_state())
                
                vardef = VariableDef(node.name + '_funvar', node.lineno, scope)
                
#                 from core.nodes.function_call import FuncCall
#                 from core.nodes.function_call import FuncCall
#                 fc = FuncCall(node.name, node.lineno, node, scope, self)
                
                #TODO: Can we do this in a more extensible way? Why different ways for handling FILE_DISC / XSS?
                # Add vulntrace
                vulntype = fc.is_vulnerable_for()
                if vulntype and 'FILE_DISCLOSURE' in vulntype and \
                self._parent_obj.name in SENSITIVE_FUNCTIONS['XSS']: 
                    # Add vulntrace to parent call with pending trace
                    fc.add_vulntrace(vulntype)
                    self._parent_obj._pending_trace = fc.get_vulntraces()[-1]
                    vardef._safe_for.append('XSS')
                    vardef.set_clean()
                 
#                 elif vulntype:
#                     fc.add_vulntrace(vulntype)
#                     # Keep track of thin funccal
#                     self.get_root_obj()._functions.append(fc)
#                     vardef.set_clean()
                
                # return values (custom function)?
                called_obj = fc.get_called_obj();
                if called_obj:
                    # Set function scope as active code
                    called_obj._scope._dead_code = False
                    for var in called_obj._return_vars:
                        vardef.add_parent(var)
#                  
                else:
                    for param in fc.params:
                        for var in param.vars:
                            vardef.add_parent(var)
                   
                # Securing function?
                vulnty = get_vulnty_for_sec(fc.name)
                if vulnty:
                    vardef._safe_for.append(vulnty)
                
                self.vars.append(vardef)
                break