mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-06 21:00:22 +00:00
fix
This commit is contained in:
parent
b5b196fd65
commit
eb7bbfd75c
@ -30,7 +30,10 @@ import java.security.UnrecoverableKeyException;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Objects;
|
||||
import java.util.logging.Level;
|
||||
import javax.net.ssl.KeyManager;
|
||||
@ -39,6 +42,8 @@ import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.collections4.MapUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpHost;
|
||||
@ -121,17 +126,33 @@ public class CTCloudHttpClient {
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public <O> O doPost(String urlPath, Object jsonBody, Class<O> classType) throws CTCloudException {
|
||||
return doPost(urlPath, Collections.emptyMap(), jsonBody, classType);
|
||||
}
|
||||
|
||||
public <O> O doPost(String urlPath, Map<String, String> urlReqParams, Object jsonBody, Class<O> classType) throws CTCloudException {
|
||||
String url = Constants.CT_CLOUD_SERVER + urlPath;
|
||||
try {
|
||||
|
||||
LOGGER.log(Level.INFO, "initiating http connection to ctcloud server");
|
||||
try (CloseableHttpClient httpclient = createConnection(getProxySettings(), sslContext)) {
|
||||
URIBuilder builder = new URIBuilder(url);
|
||||
|
||||
if (!MapUtils.isEmpty(urlReqParams)) {
|
||||
for (Entry<String, String> e : urlReqParams.entrySet()) {
|
||||
String key = e.getKey();
|
||||
String value = e.getValue();
|
||||
if (StringUtils.isNotBlank(key) || StringUtils.isNotBlank(value)) {
|
||||
builder.addParameter(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
URI postURI = builder.build();
|
||||
HttpPost postRequest = new HttpPost(postURI);
|
||||
|
||||
|
||||
configureRequestTimeout(postRequest);
|
||||
postRequest.setHeader("Content-type", "application/json");
|
||||
|
||||
|
@ -24,7 +24,9 @@ import com.basistech.df.cybertriage.autopsy.ctapi.json.LicenseRequest;
|
||||
import com.basistech.df.cybertriage.autopsy.ctapi.json.LicenseResponse;
|
||||
import com.basistech.df.cybertriage.autopsy.ctapi.util.CTHostIDGenerationUtil;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.sleuthkit.autopsy.coreutils.Version;
|
||||
|
||||
@ -38,9 +40,8 @@ public class CTApiDAO {
|
||||
private static final String AUTH_TOKEN_REQUEST_PATH = "/_ah/api/auth/v2/generate_token";
|
||||
private static final String CTCLOUD_SERVER_HASH_PATH = "/_ah/api/reputation/v1/query/file/hash/md5?query_types=CORRELATION,MALWARE";
|
||||
private static final String AUTOPSY_PRODUCT = "AUTOPSY";
|
||||
|
||||
|
||||
private static final CTApiDAO instance = new CTApiDAO();
|
||||
|
||||
|
||||
private CTApiDAO() {
|
||||
}
|
||||
@ -52,9 +53,8 @@ public class CTApiDAO {
|
||||
private static String getAppVersion() {
|
||||
return Version.getVersion();
|
||||
}
|
||||
|
||||
private final CTCloudHttpClient httpClient = CTCloudHttpClient.getInstance();
|
||||
|
||||
private final CTCloudHttpClient httpClient = CTCloudHttpClient.getInstance();
|
||||
|
||||
public LicenseResponse getLicenseInfo(String licenseString) throws CTCloudException {
|
||||
LicenseRequest licenseRequest = new LicenseRequest()
|
||||
@ -76,18 +76,31 @@ public class CTApiDAO {
|
||||
return httpClient.doPost(AUTH_TOKEN_REQUEST_PATH, authTokenRequest, AuthTokenResponse.class);
|
||||
}
|
||||
|
||||
private static Map<String, String> getAuthParams(AuthenticatedRequestData authenticatedRequestData) {
|
||||
return new HashMap<String, String>() {
|
||||
{
|
||||
put("api_key", authenticatedRequestData.getApiKey());
|
||||
put("token", authenticatedRequestData.getToken());
|
||||
put("host_id", authenticatedRequestData.getHostId());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public List<CTCloudBean> getReputationResults(AuthenticatedRequestData authenticatedRequestData, List<String> md5Hashes) throws CTCloudException {
|
||||
if (CollectionUtils.isEmpty(md5Hashes)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
FileReputationRequest fileRepReq = new FileReputationRequest()
|
||||
.setApiKey(authenticatedRequestData.getApiKey())
|
||||
.setHostId(CTHostIDGenerationUtil.generateLicenseHostID())
|
||||
.setToken(authenticatedRequestData.getToken())
|
||||
.setHashes(md5Hashes);
|
||||
|
||||
CTCloudBeanResponse resp = httpClient.doPost(CTCLOUD_SERVER_HASH_PATH, fileRepReq, CTCloudBeanResponse.class);
|
||||
CTCloudBeanResponse resp = httpClient.doPost(
|
||||
CTCLOUD_SERVER_HASH_PATH,
|
||||
getAuthParams(authenticatedRequestData),
|
||||
fileRepReq,
|
||||
CTCloudBeanResponse.class
|
||||
);
|
||||
|
||||
return resp == null || resp.getItems() == null
|
||||
? Collections.emptyList()
|
||||
: resp.getItems();
|
||||
|
@ -24,13 +24,16 @@ import java.time.Instant;
|
||||
* POJO for an auth token response.
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class AuthTokenResponse extends AuthenticatedRequestData {
|
||||
public class AuthTokenResponse {
|
||||
|
||||
private final Long hashLookupCount;
|
||||
private final Long hashLookupLimit;
|
||||
private final Long fileUploadLimit;
|
||||
private final Long fileUploadCount;
|
||||
private final String fileUploadUrl;
|
||||
private final Instant expiration;
|
||||
private final String token;
|
||||
private final String apiKey;
|
||||
|
||||
@JsonCreator
|
||||
public AuthTokenResponse(
|
||||
@ -41,7 +44,7 @@ public class AuthTokenResponse extends AuthenticatedRequestData {
|
||||
@JsonProperty("fileUploadLimit") Long fileUploadLimit,
|
||||
@JsonProperty("fileUploadCount") Long fileUploadCount,
|
||||
@JsonProperty("fileUploadUrl") String fileUploadUrl,
|
||||
@JsonDeserialize(using=InstantEpochSecsDeserializer.class)
|
||||
@JsonDeserialize(using = InstantEpochSecsDeserializer.class)
|
||||
@JsonProperty("expiration") Instant expiration
|
||||
) {
|
||||
this.token = token;
|
||||
@ -77,4 +80,13 @@ public class AuthTokenResponse extends AuthenticatedRequestData {
|
||||
public Instant getExpiration() {
|
||||
return expiration;
|
||||
}
|
||||
|
||||
public String getToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
public String getApiKey() {
|
||||
return apiKey;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -13,17 +13,24 @@
|
||||
************************************************************************** */
|
||||
package com.basistech.df.cybertriage.autopsy.ctapi.json;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* Data required for an authenticated request.
|
||||
*/
|
||||
public abstract class AuthenticatedRequestData {
|
||||
public class AuthenticatedRequestData {
|
||||
|
||||
@JsonProperty("token")
|
||||
protected String token;
|
||||
@JsonProperty("api_key")
|
||||
protected String apiKey;
|
||||
private final String token;
|
||||
private final String apiKey;
|
||||
private final String hostId;
|
||||
|
||||
public AuthenticatedRequestData(DecryptedLicenseResponse decrypted, AuthTokenResponse authResp) {
|
||||
this(authResp.getToken(), authResp.getApiKey(), decrypted.getLicenseHostId());
|
||||
}
|
||||
|
||||
public AuthenticatedRequestData(String token, String apiKey, String hostId) {
|
||||
this.token = token;
|
||||
this.apiKey = apiKey;
|
||||
this.hostId = hostId;
|
||||
}
|
||||
|
||||
public String getToken() {
|
||||
return token;
|
||||
@ -33,4 +40,8 @@ public abstract class AuthenticatedRequestData {
|
||||
return apiKey;
|
||||
}
|
||||
|
||||
public String getHostId() {
|
||||
return hostId;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -19,14 +19,11 @@ import java.util.List;
|
||||
/**
|
||||
* Request for file reputation results.
|
||||
*/
|
||||
public class FileReputationRequest extends AuthenticatedRequestData {
|
||||
public class FileReputationRequest {
|
||||
|
||||
@JsonProperty("hashes")
|
||||
private List<String> hashes;
|
||||
|
||||
@JsonProperty("host_id")
|
||||
private String hostId;
|
||||
|
||||
public List<String> getHashes() {
|
||||
return hashes;
|
||||
}
|
||||
@ -35,24 +32,4 @@ public class FileReputationRequest extends AuthenticatedRequestData {
|
||||
this.hashes = hashes;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FileReputationRequest setToken(String token) {
|
||||
this.token = token;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FileReputationRequest setApiKey(String apiKey) {
|
||||
this.apiKey = apiKey;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getHostId() {
|
||||
return hostId;
|
||||
}
|
||||
|
||||
public FileReputationRequest setHostId(String hostId) {
|
||||
this.hostId = hostId;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ package com.basistech.df.cybertriage.autopsy.malwarescan;
|
||||
|
||||
import com.basistech.df.cybertriage.autopsy.ctapi.CTApiDAO;
|
||||
import com.basistech.df.cybertriage.autopsy.ctapi.json.AuthTokenResponse;
|
||||
import com.basistech.df.cybertriage.autopsy.ctapi.json.AuthenticatedRequestData;
|
||||
import com.basistech.df.cybertriage.autopsy.ctapi.json.CTCloudBean;
|
||||
import com.basistech.df.cybertriage.autopsy.ctapi.json.LicenseInfo;
|
||||
import com.basistech.df.cybertriage.autopsy.ctoptions.ctcloud.CTLicensePersistence;
|
||||
@ -28,6 +29,7 @@ import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
@ -38,6 +40,7 @@ import org.sleuthkit.autopsy.ingest.IngestJobContext;
|
||||
import org.sleuthkit.autopsy.ingest.IngestModule;
|
||||
import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.AnalysisResult;
|
||||
import org.sleuthkit.datamodel.Blackboard;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.Score;
|
||||
@ -111,6 +114,7 @@ public class MalwareScanIngestModule implements FileIngestModule {
|
||||
private boolean noMoreHashLookups = false;
|
||||
private IngestModuleException startupException;
|
||||
private long dsId = 0;
|
||||
private long ingestJobId = 0;
|
||||
|
||||
@Messages({
|
||||
"MalwareScanIngestModule_ShareProcessing_lowLimitWarning_title=Hash Lookups Low",
|
||||
@ -157,6 +161,7 @@ public class MalwareScanIngestModule implements FileIngestModule {
|
||||
BlackboardArtifact.Category.ANALYSIS_RESULT);
|
||||
fileTypeDetector = new FileTypeDetector();
|
||||
dsId = context.getDataSource().getId();
|
||||
ingestJobId = context.getJobId();
|
||||
licenseInfo = licenseInfoOpt.get();
|
||||
startupException = null;
|
||||
noMoreHashLookups = false;
|
||||
@ -256,9 +261,13 @@ public class MalwareScanIngestModule implements FileIngestModule {
|
||||
}
|
||||
|
||||
// using auth token, get results
|
||||
List<CTCloudBean> repResult = ctApiDAO.getReputationResults(authTokenResponse, md5Hashes);
|
||||
List<CTCloudBean> repResult = ctApiDAO.getReputationResults(
|
||||
new AuthenticatedRequestData(licenseInfo.getDecryptedLicense(), authTokenResponse),
|
||||
md5Hashes
|
||||
);
|
||||
|
||||
if (repResult != null && !repResult.isEmpty()) {
|
||||
List<BlackboardArtifact> createdArtifacts = new ArrayList<>();
|
||||
if (!CollectionUtils.isEmpty(repResult)) {
|
||||
SleuthkitCase.CaseDbTransaction trans = null;
|
||||
try {
|
||||
trans = tskCase.beginTransaction();
|
||||
@ -270,7 +279,10 @@ public class MalwareScanIngestModule implements FileIngestModule {
|
||||
}
|
||||
|
||||
for (Long objId : objIds) {
|
||||
createAnalysisResult(objId, result, trans);
|
||||
AnalysisResult res = createAnalysisResult(objId, result, trans);
|
||||
if (res != null) {
|
||||
createdArtifacts.add(res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -279,10 +291,15 @@ public class MalwareScanIngestModule implements FileIngestModule {
|
||||
} finally {
|
||||
if (trans != null) {
|
||||
trans.rollback();
|
||||
createdArtifacts.clear();
|
||||
trans = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (!CollectionUtils.isEmpty(createdArtifacts)) {
|
||||
tskCase.getBlackboard().postArtifacts(createdArtifacts, Bundle.MalwareScanIngestModuleFactory_displayName(), ingestJobId);
|
||||
}
|
||||
|
||||
// if we only processed part of the batch, after processing, notify that we are out of scans.
|
||||
if (exceededScanLimit) {
|
||||
noMoreHashLookups = true;
|
||||
@ -309,22 +326,22 @@ public class MalwareScanIngestModule implements FileIngestModule {
|
||||
"MalwareScanIngestModule_SharedProcessing_createAnalysisResult_Yes=YES",
|
||||
"MalwareScanIngestModule_SharedProcessing_createAnalysisResult_No=NO"
|
||||
})
|
||||
private void createAnalysisResult(Long objId, CTCloudBean cloudBean, SleuthkitCase.CaseDbTransaction trans) throws Blackboard.BlackboardException {
|
||||
private AnalysisResult createAnalysisResult(Long objId, CTCloudBean cloudBean, SleuthkitCase.CaseDbTransaction trans) throws Blackboard.BlackboardException {
|
||||
if (objId == null || cloudBean == null || cloudBean.getMalwareResult() == null) {
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
Score score = cloudBean.getMalwareResult().getCTScore() == null
|
||||
? Score.SCORE_UNKNOWN
|
||||
? Score.SCORE_UNKNOWN
|
||||
: cloudBean.getMalwareResult().getCTScore().getTskCore();
|
||||
|
||||
|
||||
String conclusion = score.getSignificance() == Score.Significance.NOTABLE || score.getSignificance() == Score.Significance.LIKELY_NOTABLE
|
||||
? Bundle.MalwareScanIngestModule_SharedProcessing_createAnalysisResult_Yes()
|
||||
: Bundle.MalwareScanIngestModule_SharedProcessing_createAnalysisResult_No();
|
||||
|
||||
|
||||
String justification = cloudBean.getMalwareResult().getStatusDescription();
|
||||
|
||||
tskCase.getBlackboard().newAnalysisResult(
|
||||
return tskCase.getBlackboard().newAnalysisResult(
|
||||
malwareType,
|
||||
objId,
|
||||
dsId,
|
||||
@ -333,7 +350,7 @@ public class MalwareScanIngestModule implements FileIngestModule {
|
||||
MALWARE_CONFIG,
|
||||
justification,
|
||||
Collections.emptyList(),
|
||||
trans);
|
||||
trans).getAnalysisResult();
|
||||
}
|
||||
|
||||
@Messages({
|
||||
@ -356,8 +373,6 @@ public class MalwareScanIngestModule implements FileIngestModule {
|
||||
ex);
|
||||
} finally {
|
||||
// set state to shut down and clear any remaining
|
||||
malwareType = null;
|
||||
fileTypeDetector = null;
|
||||
noMoreHashLookups = false;
|
||||
runState = RunState.SHUT_DOWN;
|
||||
startupException = null;
|
||||
|
Loading…
x
Reference in New Issue
Block a user