def store_index(self, target_dir):
     """ Zip files in target_dir/central-index dir and store to S3 """
     with tempdir() as temp_dir:
         central_index_dir = os.path.join(target_dir, self._INDEX_DIRNAME)
         archive_path = os.path.join(temp_dir, self._INDEX_ARCHIVE)
         Archive.zip_file(central_index_dir, archive_path, junk_paths=True)
         self.store_file(archive_path, self._INDEX_ARCHIVE)
Esempio n. 2
0
 def store_depcheck_db(self, data_dir):
     """ Zip CVE DB file and store to S3 """
     with tempdir() as archive_dir:
         archive_path = os.path.join(archive_dir, self._DB_ARCHIVE)
         db_file_path = os.path.join(data_dir, self._DB_FILENAME)
         Archive.zip_file(db_file_path, archive_path, junk_paths=True)
         self.store_file(archive_path, self._DB_ARCHIVE)
Esempio n. 3
0
    def retrieve_depcheck_db_if_exists(self, data_dir):
        """ Retrieve zipped CVE DB file as stored on S3 and extract"""
        if self.object_exists(self._DB_ARCHIVE):
            with tempdir() as archive_dir:
                archive_path = os.path.join(archive_dir, self._DB_ARCHIVE)
                self.retrieve_file(self._DB_ARCHIVE, archive_path)
                Archive.extract_zip(archive_path, data_dir)
                return True

        return False
Esempio n. 4
0
 def _resolve_versions(to_solve):
     """
     Resolve version ranges in to_solve
     :param to_solve: {"groupId:artifactId": "version-range"}
     :return: {"groupId:artifactId": "version"}
     """
     if not to_solve:
         return {}
     with tempdir() as tmpdir:
         with cwd(tmpdir):
             MavenSolver._generate_pom_xml(to_solve)
             return MavenSolver._dependencies_from_pom_xml()
    def retrieve_index_if_exists(self, target_dir):
        """ Retrieve central-index.zip from S3 and extract into target_dir/central-index"""
        if self.object_exists(self._INDEX_ARCHIVE):
            with tempdir() as temp_dir:
                archive_path = os.path.join(temp_dir, self._INDEX_ARCHIVE)
                central_index_dir = os.path.join(target_dir,
                                                 self._INDEX_DIRNAME)
                self.retrieve_file(self._INDEX_ARCHIVE, archive_path)
                Archive.extract_zip(archive_path,
                                    central_index_dir,
                                    mkdest=True)
                return True

        return False
    def execute(self, arguments):
        """

        :param arguments: optional argument 'only_already_scanned' to run only on already analysed packages
        :return: EPV dict describing which packages should be analysed
        """
        only_already_scanned = arguments.pop('only_already_scanned',
                                             True) if arguments else True
        ignore_modification_time = arguments.pop('ignore_modification_time',
                                                 False) if arguments else False
        self._strict_assert(not arguments)

        s3 = StoragePool.get_connected_storage('S3OWASPDepCheck')
        with tempdir() as temp_data_dir:
            s3.retrieve_depcheck_db_if_exists(temp_data_dir)
            self._update_dep_check_db(temp_data_dir)
            s3.store_depcheck_db(temp_data_dir)

        cve_db = self._get_snyk_vulndb()
        s3 = StoragePool.get_connected_storage('S3Snyk')
        s3.store_vulndb(cve_db)
        last_sync_datetime = s3.update_sync_date()

        to_update = []
        for package_name, cve_records in cve_db.get('npm', {}).items():
            for record in cve_records:
                modification_time = datetime_parser.parse(
                    record['modificationTime'])

                if ignore_modification_time or modification_time >= last_sync_datetime:
                    affected_versions = self._get_versions_to_scan(
                        package_name, record['semver']['vulnerable'],
                        only_already_scanned)

                    for version in affected_versions:
                        to_update.append({
                            'ecosystem': 'npm',
                            'name': package_name,
                            'version': version
                        })

        return {'modified': to_update}
    def _get_snyk_vulndb(self):
        """
        :return: retrieve Snyk CVE db
        """

        with tempdir() as vulndb_dir:
            # clone vulndb git repo
            self.log.debug("Cloning snyk/vulndb repo")
            Git.clone(self._VULNDB_GIT_REPO, vulndb_dir)
            with cwd(vulndb_dir):
                # install dependencies
                self.log.debug("Installing snyk/vulndb dependencies")
                TimedCommand.get_command_output(['npm', 'install'])
                # generate database (json in file)
                self.log.debug("Generating snyk/vulndb")
                TimedCommand.get_command_output([
                    os.path.join('cli', 'shrink.js'), 'data',
                    self._VULNDB_FILENAME
                ])
                # parse the JSON so we are sure that we have a valid JSON
                with open(self._VULNDB_FILENAME) as f:
                    return json.load(f)
Esempio n. 8
0
    def _run_owasp_dep_check(self, scan_path, experimental=False):
        def _clean_dep_check_tmp():
            for dcdir in glob.glob(os.path.join(gettempdir(), 'dctemp*')):
                rmtree(dcdir)

        s3 = StoragePool.get_connected_storage('S3OWASPDepCheck')
        depcheck = os.path.join(os.environ['OWASP_DEP_CHECK_PATH'], 'bin', 'dependency-check.sh')
        with tempdir() as temp_data_dir:
            retrieved = s3.retrieve_depcheck_db_if_exists(temp_data_dir)
            if not retrieved:
                self.log.debug('No cached OWASP Dependency-Check DB, generating fresh now ...')
                command = [depcheck, '--updateonly', '--data', temp_data_dir]
                # give DependencyCheck 30 minutes to download the DB
                TimedCommand.get_command_output(command, graceful=False, timeout=1800)
            report_path = os.path.join(temp_data_dir, 'report.xml')
            command = [depcheck,
                       '--noupdate',
                       '--format', 'XML',
                       '--project', 'test',
                       '--data', temp_data_dir,
                       '--scan', scan_path,
                       '--out', report_path]
            if experimental:
                command.extend(['--enableExperimental'])
            output = []
            try:
                self.log.debug('Running OWASP Dependency-Check to scan %s for vulnerabilities' %
                               scan_path)
                output = TimedCommand.get_command_output(command,
                                                         graceful=False,
                                                         timeout=600)  # 10 minutes
                with open(report_path) as r:
                    report_dict = anymarkup.parse(r.read())
            except (TaskError, FileNotFoundError) as e:
                _clean_dep_check_tmp()
                for line in output:
                    self.log.warning(line)
                self.log.exception(str(e))
                return {'summary': ['OWASP Dependency-Check scan failed'],
                        'status': 'error',
                        'details': []}
            # If the CVEDBSyncTask has never been run before, we just had to create the DB ourselves
            # Make the life easier for other workers and store it to S3
            s3.store_depcheck_db_if_not_exists(temp_data_dir)
            _clean_dep_check_tmp()


        results = []
        dependencies = report_dict.get('analysis', {}).get('dependencies', {}).get('dependency', [])
        if not isinstance(dependencies, list):
            dependencies = [dependencies]
        for dependency in dependencies:
            vulnerabilities = dependency.get('vulnerabilities', {}).get('vulnerability', [])
            if not isinstance(vulnerabilities, list):
                vulnerabilities = [vulnerabilities]
            for vulnerability in vulnerabilities:
                av = vulnerability.get('cvssAccessVector')
                av = av[0] if av else '?'
                ac = vulnerability.get('cvssAccessComplexity')
                ac = ac[0] if ac else '?'
                au = vulnerability.get('cvssAuthenticationr')
                au = au[0] if au else '?'
                c = vulnerability.get('cvssConfidentialImpact')
                c = c[0] if c else '?'
                i = vulnerability.get('cvssIntegrityImpact')
                i = i[0] if i else '?'
                a = vulnerability.get('cvssAvailabilityImpact')
                a = a[0] if a else '?'
                vector = "AV:{AV}/AC:{AC}/Au:{Au}/C:{C}/I:{I}/A:{A}".\
                    format(AV=av, AC=ac, Au=au, C=c, I=i, A=a)
                result = {
                    'cvss': {
                        'score': vulnerability.get('cvssScore'),
                        'vector': vector
                    }
                }
                references = vulnerability.get('references', {}).get('reference', [])
                if not isinstance(references, list):
                    references = [references]
                result['references'] = [r.get('url') for r in references]
                for field in ['severity', 'description']:
                    result[field] = vulnerability.get(field)
                result['id'] = vulnerability.get('name')
                results.append(result)

        return {'summary': [r['id'] for r in results],
                'status': 'success',
                'details': results}