コード例 #1
0
ファイル: variable_def.py プロジェクト: andresriancho/SCA
 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
コード例 #2
0
ファイル: parameter.py プロジェクト: andresriancho/SCA
    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