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