Search in sources :

Example 1 with SoftwareIdentity

use of com.google.tsunami.plugins.fingerprinters.web.proto.SoftwareIdentity in project tsunami-security-scanner-plugins by google.

the class FingerprintUpdater method updateFingerprints.

private Fingerprints updateFingerprints(Map<String, Hash> fileHashes, Fingerprints existingFingerprints) {
    SoftwareIdentity.Builder softwareIdentityBuilder = SoftwareIdentity.newBuilder().setSoftware(options.softwareName);
    if (options.pluginName != null) {
        softwareIdentityBuilder.setPlugin(options.pluginName);
    }
    SoftwareIdentity newSoftwareIdentity = softwareIdentityBuilder.build();
    if (!options.init && !newSoftwareIdentity.equals(existingFingerprints.getSoftwareIdentity())) {
        throw new AssertionError("Target software is different from existing fingerprint!");
    }
    Map<String, ContentHash> newContentHashes = Maps.newHashMap(Maps.uniqueIndex(existingFingerprints.getContentHashesList(), ContentHash::getContentPath));
    Map<Hash, HashVersion> newHashVersions = Maps.newHashMap(Maps.uniqueIndex(existingFingerprints.getHashVersionsList(), HashVersion::getHash));
    Map<String, PathVersion> newPathVersions = Maps.newHashMap(Maps.uniqueIndex(existingFingerprints.getPathVersionsList(), PathVersion::getContentPath));
    for (String filePath : fileHashes.keySet()) {
        Hash fileHash = fileHashes.get(filePath);
        // Update content to hash mapping.
        newContentHashes.putIfAbsent(filePath, ContentHash.getDefaultInstance());
        newContentHashes.compute(filePath, (path, oldContentHash) -> ContentHash.newBuilder().setContentPath(path).addAllHashes(ImmutableSet.<Hash>builder().addAll(oldContentHash.getHashesList()).add(fileHash).build()).build());
        // Update hash to version mapping.
        newHashVersions.putIfAbsent(fileHash, HashVersion.getDefaultInstance());
        newHashVersions.compute(fileHash, (hash, oldHashVersion) -> HashVersion.newBuilder().setHash(hash).addAllVersions(ImmutableSet.<Version>builder().addAll(oldHashVersion.getVersionsList()).add(Version.newBuilder().setFullName(options.version).build()).build()).build());
        // Update path to version mapping.
        newPathVersions.putIfAbsent(filePath, PathVersion.getDefaultInstance());
        newPathVersions.compute(filePath, (path, oldPathVersion) -> PathVersion.newBuilder().setContentPath(path).addAllVersions(ImmutableSet.<Version>builder().addAll(oldPathVersion.getVersionsList()).add(Version.newBuilder().setFullName(options.version).build()).build()).build());
    }
    return Fingerprints.newBuilder().setSoftwareIdentity(newSoftwareIdentity).addAllContentHashes(newContentHashes.values()).addAllHashVersions(newHashVersions.values()).addAllPathVersions(newPathVersions.values()).build();
}
Also used : HashVersion(com.google.tsunami.plugins.fingerprinters.web.proto.HashVersion) ContentHash(com.google.tsunami.plugins.fingerprinters.web.proto.ContentHash) PathVersion(com.google.tsunami.plugins.fingerprinters.web.proto.PathVersion) HashVersion(com.google.tsunami.plugins.fingerprinters.web.proto.HashVersion) Version(com.google.tsunami.plugins.fingerprinters.web.proto.Version) PathVersion(com.google.tsunami.plugins.fingerprinters.web.proto.PathVersion) SoftwareIdentity(com.google.tsunami.plugins.fingerprinters.web.proto.SoftwareIdentity) ContentHash(com.google.tsunami.plugins.fingerprinters.web.proto.ContentHash) Hash(com.google.tsunami.plugins.fingerprinters.web.proto.Hash)

Example 2 with SoftwareIdentity

use of com.google.tsunami.plugins.fingerprinters.web.proto.SoftwareIdentity in project tsunami-security-scanner-plugins by google.

the class ResourceFingerprintLoader method loadFingerprints.

@Override
public ImmutableMap<SoftwareIdentity, FingerprintData> loadFingerprints() throws IOException {
    Stopwatch loadTimeStopwatch = Stopwatch.createStarted();
    ResourceList fingerprintsResources = scanResult.getResourcesMatchingPattern(FINGERPRINTS_RESOURCE_PATTERN);
    ImmutableMap.Builder<SoftwareIdentity, FingerprintData> fingerprintsBuilder = ImmutableMap.builder();
    for (Resource resource : fingerprintsResources) {
        logger.atInfo().log("Loading fingerprints from resource %s.", resource.getPath());
        Fingerprints fingerprints = Fingerprints.parseFrom(resource.load());
        fingerprintsBuilder.put(fingerprints.getSoftwareIdentity(), FingerprintData.fromProto(fingerprints));
    }
    ImmutableMap<SoftwareIdentity, FingerprintData> fingerprints = fingerprintsBuilder.build();
    logger.atInfo().log("Finished loading %s web fingerprints data in %s.", fingerprints.size(), loadTimeStopwatch.stop());
    return fingerprints;
}
Also used : ResourceList(io.github.classgraph.ResourceList) Fingerprints(com.google.tsunami.plugins.fingerprinters.web.proto.Fingerprints) Stopwatch(com.google.common.base.Stopwatch) SoftwareIdentity(com.google.tsunami.plugins.fingerprinters.web.proto.SoftwareIdentity) Resource(io.github.classgraph.Resource) ImmutableMap(com.google.common.collect.ImmutableMap)

Example 3 with SoftwareIdentity

use of com.google.tsunami.plugins.fingerprinters.web.proto.SoftwareIdentity in project tsunami-security-scanner-plugins by google.

the class SoftwareDetector method findRootPath.

private String findRootPath(SoftwareIdentity softwareIdentity, ImmutableMap<CrawlResult, Hash> crawlResultHashes) {
    logger.atInfo().log("Found %d indicators for %s", crawlResultHashes.size(), softwareIdentity.getSoftware());
    Optional<FingerprintData> fingerprintData = fingerprintRegistry.getFingerprintData(softwareIdentity);
    if (!fingerprintData.isPresent()) {
        logger.atWarning().log("Fingerprint data for software %s doesn't exist.", softwareIdentity.getSoftware());
        return "";
    }
    HashMultiset<String> rootUrls = HashMultiset.create();
    for (CrawlResult crawlResult : crawlResultHashes.keySet()) {
        // For each crawled URL, if one of the known URLs from the fingerprint data is part of the
        // crawled URL, then the difference between them is the subfolder that serves the crawled
        // content.
        String crawledUrl = crawlResult.getCrawlTarget().getUrl();
        HttpUrl parsedCrawlUrl = HttpUrl.parse(crawledUrl);
        if (parsedCrawlUrl == null) {
            logger.atSevere().log("Crawled URL %s cannot be parsed.", crawlResult.getCrawlTarget().getUrl());
            continue;
        }
        fingerprintData.get().contentHashes().keySet().stream().filter(knownPath -> parsedCrawlUrl.encodedPath().endsWith(knownPath)).forEach(knownPath -> {
            logger.atInfo().log("Found known path %s that matches crawled URL %s", knownPath, crawlResult.getCrawlTarget().getUrl());
            String rootUrl = crawledUrl.substring(0, crawledUrl.indexOf(knownPath));
            rootUrls.add(rootUrl);
        });
    }
    logger.atInfo().log("Confirmed %d of %d root path indicators for %s.", rootUrls.size(), crawlResultHashes.size(), softwareIdentity.getSoftware());
    if (rootUrls.isEmpty()) {
        return "";
    }
    return determineRootPath(rootUrls);
}
Also used : Iterables(com.google.common.collect.Iterables) Hash(com.google.tsunami.plugins.fingerprinters.web.proto.Hash) Function(java.util.function.Function) Inject(javax.inject.Inject) Lists(com.google.common.collect.Lists) CrawlResult(com.google.tsunami.proto.CrawlResult) HashMultiset(com.google.common.collect.HashMultiset) FingerprintData(com.google.tsunami.plugins.fingerprinters.web.data.FingerprintData) SoftwareIdentity(com.google.tsunami.plugins.fingerprinters.web.proto.SoftwareIdentity) FingerprintUtils(com.google.tsunami.plugins.fingerprinters.web.common.FingerprintUtils) ImmutableSetMultimap(com.google.common.collect.ImmutableSetMultimap) ImmutableSet(com.google.common.collect.ImmutableSet) ImmutableMap(com.google.common.collect.ImmutableMap) Collection(java.util.Collection) Preconditions.checkNotNull(com.google.common.base.Preconditions.checkNotNull) Math.min(java.lang.Math.min) Streams(com.google.common.collect.Streams) GoogleLogger(com.google.common.flogger.GoogleLogger) FingerprintRegistry(com.google.tsunami.plugins.fingerprinters.web.data.FingerprintRegistry) ImmutableMap.toImmutableMap(com.google.common.collect.ImmutableMap.toImmutableMap) List(java.util.List) AutoValue(com.google.auto.value.AutoValue) Optional(java.util.Optional) HttpUrl(okhttp3.HttpUrl) Joiner(com.google.common.base.Joiner) FingerprintData(com.google.tsunami.plugins.fingerprinters.web.data.FingerprintData) CrawlResult(com.google.tsunami.proto.CrawlResult) HttpUrl(okhttp3.HttpUrl)

Example 4 with SoftwareIdentity

use of com.google.tsunami.plugins.fingerprinters.web.proto.SoftwareIdentity in project tsunami-security-scanner-plugins by google.

the class SoftwareDetector method detectSoftware.

/**
 * Detect potential software for a given collection of web crawling results.
 *
 * <p>This method performs the software detection in the following steps:
 *
 * <ol>
 *   <li>Calculate hashes of each crawling result
 *   <li>Match the crawl result hashes against all known software hashes to guess potential
 *       software for the given crawl results. This step could generate multiple software matches
 *       because of common libraries that could potentially be used across software.
 *   <li>Finally for each identified software, try to locate the root path of the application.
 * </ol>
 *
 * @param crawlResults a collection of web crawling results.
 * @return the detected software set based on the crawling results.
 */
public ImmutableSet<DetectedSoftware> detectSoftware(Collection<CrawlResult> crawlResults) {
    logger.atInfo().log("Trying to detect potential software for the scan target.");
    ImmutableMap<CrawlResult, Hash> crawlResultHashes = crawlResults.stream().collect(toImmutableMap(Function.identity(), FingerprintUtils::hashCrawlResult));
    ImmutableSetMultimap<SoftwareIdentity, CrawlResult> crawlResultsBySoftware = matchPotentialSoftware(crawlResultHashes);
    if (crawlResultsBySoftware.isEmpty()) {
        logger.atWarning().log("No known software found.");
        return ImmutableSet.of();
    }
    ImmutableSet.Builder<DetectedSoftware> detectedSoftwareBuilder = ImmutableSet.builder();
    for (SoftwareIdentity softwareIdentity : crawlResultsBySoftware.keySet()) {
        ImmutableMap<CrawlResult, Hash> contentHashes = crawlResultsBySoftware.get(softwareIdentity).stream().collect(toImmutableMap(Function.identity(), crawlResultHashes::get));
        if (!hasGloballyUniqueHash(contentHashes)) {
            logger.atInfo().log("All detected hashes for '%s' are potentially common libs. Ignored.", softwareIdentity.getSoftware());
            continue;
        }
        String rootPath = findRootPath(softwareIdentity, contentHashes);
        if (rootPath.isEmpty()) {
            logger.atInfo().log("%s likely running somewhere, but root path unknown.", softwareIdentity.getSoftware());
        } else {
            logger.atInfo().log("Software %s is likely running under path %s", softwareIdentity.getSoftware(), rootPath);
        }
        detectedSoftwareBuilder.add(DetectedSoftware.builder().setSoftwareIdentity(softwareIdentity).setRootPath(rootPath).setContentHashes(contentHashes).build());
    }
    return detectedSoftwareBuilder.build();
}
Also used : ImmutableSet(com.google.common.collect.ImmutableSet) CrawlResult(com.google.tsunami.proto.CrawlResult) SoftwareIdentity(com.google.tsunami.plugins.fingerprinters.web.proto.SoftwareIdentity) Hash(com.google.tsunami.plugins.fingerprinters.web.proto.Hash)

Example 5 with SoftwareIdentity

use of com.google.tsunami.plugins.fingerprinters.web.proto.SoftwareIdentity in project tsunami-security-scanner-plugins by google.

the class VersionDetectorTest method setUp.

@Before
public void setUp() {
    mockWebServer = new MockWebServer();
    fakeNetworkService = NetworkService.getDefaultInstance();
    Guice.createInjector(new AbstractModule() {

        @Override
        protected void configure() {
            install(new HttpClientModule.Builder().build());
            install(new FactoryModuleBuilder().build(VersionDetector.Factory.class));
        }

        @Provides
        ImmutableMap<SoftwareIdentity, FingerprintData> provideFingerprints() {
            return ImmutableMap.of(SOFTWARE_IDENTITY_1, FINGERPRINT_DATA_1, SOFTWARE_IDENTITY_2, FINGERPRINT_DATA_2);
        }
    }).injectMembers(this);
}
Also used : FactoryModuleBuilder(com.google.inject.assistedinject.FactoryModuleBuilder) FingerprintData(com.google.tsunami.plugins.fingerprinters.web.data.FingerprintData) FactoryModuleBuilder(com.google.inject.assistedinject.FactoryModuleBuilder) MockWebServer(okhttp3.mockwebserver.MockWebServer) SoftwareIdentity(com.google.tsunami.plugins.fingerprinters.web.proto.SoftwareIdentity) AbstractModule(com.google.inject.AbstractModule) Before(org.junit.Before)

Aggregations

SoftwareIdentity (com.google.tsunami.plugins.fingerprinters.web.proto.SoftwareIdentity)5 Hash (com.google.tsunami.plugins.fingerprinters.web.proto.Hash)3 ImmutableMap (com.google.common.collect.ImmutableMap)2 ImmutableSet (com.google.common.collect.ImmutableSet)2 FingerprintData (com.google.tsunami.plugins.fingerprinters.web.data.FingerprintData)2 CrawlResult (com.google.tsunami.proto.CrawlResult)2 AutoValue (com.google.auto.value.AutoValue)1 Joiner (com.google.common.base.Joiner)1 Preconditions.checkNotNull (com.google.common.base.Preconditions.checkNotNull)1 Stopwatch (com.google.common.base.Stopwatch)1 HashMultiset (com.google.common.collect.HashMultiset)1 ImmutableMap.toImmutableMap (com.google.common.collect.ImmutableMap.toImmutableMap)1 ImmutableSetMultimap (com.google.common.collect.ImmutableSetMultimap)1 Iterables (com.google.common.collect.Iterables)1 Lists (com.google.common.collect.Lists)1 Streams (com.google.common.collect.Streams)1 GoogleLogger (com.google.common.flogger.GoogleLogger)1 AbstractModule (com.google.inject.AbstractModule)1 FactoryModuleBuilder (com.google.inject.assistedinject.FactoryModuleBuilder)1 FingerprintUtils (com.google.tsunami.plugins.fingerprinters.web.common.FingerprintUtils)1