continued work to parse ranges.csv and then use it validate and enrich Accounts

This commit is contained in:
millmanorama 2016-08-18 16:19:36 +02:00
parent a3508ad064
commit 349310aab8
4 changed files with 107 additions and 58 deletions

1
.gitignore vendored
View File

@ -76,3 +76,4 @@ Core/src/org/sleuthkit/autopsy/casemodule/docs/screenshot.png
/test/script/*/*.xml /test/script/*/*.xml
.DS_Store .DS_Store
.*.swp .*.swp
KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/.~lock.ranges.csv#

View File

@ -1,93 +1,89 @@
package org.sleuthkit.autopsy.keywordsearch; package org.sleuthkit.autopsy.keywordsearch;
/** /**
* Representation of a range of Issuer Identifiaction Numbers for the same bank. * Representation of a range of Issuer/Bank Identifiaction Numbers (IIN/BIN) for
* the * same bank.
*/ */
public class IINRange { class IINRange {
private final int IIN_start; private final int IINStart;
private final int IIN_end; private final int IINEnd;
private final int number_length; private final int numberLength;
private final CreditCardScheme scheme; private final PaymentCardScheme scheme;
private final String brand; private final String brand;
private final PaymentCardType type; private final PaymentCardType type;
private final String country; private final String country;
private final String bank_name; private final String bankName;
private final String bank_logo; private final String bankURL;
private final String bank_url; private final String bankPhoneNumber;
private final String bank_phone; private final String bankCity;
private final String bank_city;
enum PaymentCardType { enum PaymentCardType {
DEBIT, DREDIT; DEBIT, DREDIT;
} }
enum CreditCardScheme { enum PaymentCardScheme {
AMEX, VISA, MASTERCARD, DINERS, DISCOVER AMEX, VISA, MASTERCARD, DINERS, DISCOVER
} }
IINRange(int IIN_start, int IIN_end, int number_length, CreditCardScheme scheme, String brand, PaymentCardType type, String country, String bank_name, String bank_logo, String bank_url, String bank_phone, String bank_city) { IINRange(int IIN_start, int IIN_end, int number_length, PaymentCardScheme scheme, String brand, PaymentCardType type, String country, String bank_name, String bank_url, String bank_phone, String bank_city) {
this.IIN_start = IIN_start; this.IINStart = IIN_start;
this.IIN_end = IIN_end; this.IINEnd = IIN_end;
this.number_length = number_length; this.numberLength = number_length;
this.scheme = scheme; this.scheme = scheme;
this.brand = brand; this.brand = brand;
this.type = type; this.type = type;
this.country = country; this.country = country;
this.bank_name = bank_name; this.bankName = bank_name;
this.bank_logo = bank_logo;
this.bank_url = bank_url; this.bankURL = bank_url;
this.bank_phone = bank_phone; this.bankPhoneNumber = bank_phone;
this.bank_city = bank_city; this.bankCity = bank_city;
} }
public int getIIN_start() { int getIINstart() {
return IIN_start; return IINStart;
} }
public int getIIN_end() { int getIINend() {
return IIN_end; return IINEnd;
} }
public int getNumber_length() { int getNumber_length() {
return number_length; return numberLength;
} }
public CreditCardScheme getScheme() { PaymentCardScheme getPaymentCardScheme() {
return scheme; return scheme;
} }
public String getBrand() { String getBrand() {
return brand; return brand;
} }
public PaymentCardType getType() { PaymentCardType getPaymentCardType() {
return type; return type;
} }
public String getCountry() { String getCountry() {
return country; return country;
} }
public String getBank_name() { String getBankName() {
return bank_name; return bankName;
} }
public String getBank_logo() { String getBankURL() {
return bank_logo; return bankURL;
} }
public String getBank_url() { String getBankPhoneNumber() {
return bank_url; return bankPhoneNumber;
} }
public String getBank_phone() { String getBankCity() {
return bank_phone; return bankCity;
}
public String getBank_city() {
return bank_city;
} }
} }

View File

@ -17,12 +17,12 @@ import org.apache.commons.csv.CSVRecord;
/** /**
* *
*/ */
public class IINValidator { public class IINValidator {
RangeMap<Integer, IINRange> iinRanges = TreeRangeMap.create(); RangeMap<Integer, IINRange> iinRanges = TreeRangeMap.create();
private IINValidator() throws FileNotFoundException, IOException {
IINValidator() throws FileNotFoundException, IOException {
Reader in = new FileReader("ranges.csv"); Reader in = new FileReader("ranges.csv");
Iterable<CSVRecord> records = CSVFormat.RFC4180.withFirstRecordAsHeader().parse(in); Iterable<CSVRecord> records = CSVFormat.RFC4180.withFirstRecordAsHeader().parse(in);
for (CSVRecord record : records) { for (CSVRecord record : records) {
@ -30,18 +30,24 @@ public class IINValidator {
IINRange iinRange = new IINRange(Integer.parseInt(record.get("iin_start")), IINRange iinRange = new IINRange(Integer.parseInt(record.get("iin_start")),
Integer.parseInt(record.get("iin_end")), Integer.parseInt(record.get("iin_end")),
Integer.parseInt(record.get("number_length")), Integer.parseInt(record.get("number_length")),
IINRange.CreditCardScheme.valueOf(record.get("scheme")), IINRange.PaymentCardScheme.valueOf(record.get("scheme")),
record.get("brand"), record.get("brand"),
IINRange.PaymentCardType.valueOf(record.get("type")), IINRange.PaymentCardType.valueOf(record.get("type")),
record.get("country"), record.get("country"),
record.get("bank_name"), record.get("bank_name"),
record.get("bank_logo"),
record.get("bank_url"), record.get("bank_url"),
record.get("bank_phone"), record.get("bank_phone"),
record.get("bank_city")); record.get("bank_city"));
iinRanges.put(Range.closed(iinRange.getIIN_start(), iinRange.getIIN_end()), iinRange); iinRanges.put(Range.closed(iinRange.getIINstart(), iinRange.getIINend()), iinRange);
} }
}
boolean contains(int iin) {
return iinRanges.get(iin) != null;
}
IINRange getIINRange(int iin) {
return iinRanges.get(iin);
} }
} }

View File

@ -19,6 +19,7 @@
// //
package org.sleuthkit.autopsy.keywordsearch; package org.sleuthkit.autopsy.keywordsearch;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
@ -31,6 +32,7 @@ import org.apache.commons.lang.StringUtils;
import org.apache.commons.validator.routines.checkdigit.LuhnCheckDigit; import org.apache.commons.validator.routines.checkdigit.LuhnCheckDigit;
import org.apache.solr.client.solrj.SolrQuery; import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.response.TermsResponse.Term; import org.apache.solr.client.solrj.response.TermsResponse.Term;
import org.openide.util.Exceptions;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.Version; import org.sleuthkit.autopsy.coreutils.Version;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
@ -51,6 +53,7 @@ final class TermComponentQuery implements KeywordSearchQuery {
private static final String MODULE_NAME = KeywordSearchModuleFactory.getModuleName(); private static final String MODULE_NAME = KeywordSearchModuleFactory.getModuleName();
private static final BlackboardAttribute.Type SOLR_DOCUMENT_ID_TYPE = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_SOLR_DOCUMENT_ID); private static final BlackboardAttribute.Type SOLR_DOCUMENT_ID_TYPE = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_SOLR_DOCUMENT_ID);
private static final BlackboardAttribute.Type ACCOUNT_NUMBER_TYPE = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_ACCOUNT_NUMBER);
//TODO: move these regex and the luhn check to a new class, something like: CreditCardNumberValidator //TODO: move these regex and the luhn check to a new class, something like: CreditCardNumberValidator
/* /*
@ -108,9 +111,19 @@ final class TermComponentQuery implements KeywordSearchQuery {
private final Keyword keyword; private final Keyword keyword;
private boolean isEscaped; private boolean isEscaped;
private final List<KeywordQueryFilter> filters = new ArrayList<>(); private final List<KeywordQueryFilter> filters = new ArrayList<>();
private IINValidator iinValidator;
TermComponentQuery(KeywordList keywordList, Keyword keyword) { TermComponentQuery(KeywordList keywordList, Keyword keyword) {
this.keyword = keyword; this.keyword = keyword;
if (keyword.getType() == ATTRIBUTE_TYPE.TSK_ACCOUNT_NUMBER) {
try {
iinValidator = new IINValidator();
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
}
}
this.keywordList = keywordList; this.keywordList = keywordList;
this.escapedQuery = keyword.getQuery(); this.escapedQuery = keyword.getQuery();
} }
@ -177,33 +190,59 @@ final class TermComponentQuery implements KeywordSearchQuery {
@Override @Override
public KeywordCachedArtifact writeSingleFileHitsToBlackBoard(String termHit, KeywordHit hit, String snippet, String listName) { public KeywordCachedArtifact writeSingleFileHitsToBlackBoard(String termHit, KeywordHit hit, String snippet, String listName) {
BlackboardArtifact bba; BlackboardArtifact newArtifact;
Collection<BlackboardAttribute> attributes = new ArrayList<>(); Collection<BlackboardAttribute> attributes = new ArrayList<>();
try { try {
//if the keyword hit matched the credit card number keyword/regex... //if the keyword hit matched the credit card number keyword/regex...
if (keyword.getType() == ATTRIBUTE_TYPE.TSK_ACCOUNT_NUMBER) { if (keyword.getType() == ATTRIBUTE_TYPE.TSK_ACCOUNT_NUMBER) {
bba = hit.getContent().newArtifact(ARTIFACT_TYPE.TSK_CREDIT_CARD_ACCOUNT); newArtifact = hit.getContent().newArtifact(ARTIFACT_TYPE.TSK_CREDIT_CARD_ACCOUNT);
// make account artifact // make account artifact
//try to match it against the track 1 regex //try to match it against the track 1 regex
Matcher matcher = TRACK1_PATTERN.matcher(hit.getSnippet()); Matcher matcher = TRACK1_PATTERN.matcher(hit.getSnippet());
if (matcher.find()) { if (matcher.find()) {
parseTrack1Data(bba, matcher); parseTrack1Data(newArtifact, matcher);
} }
//then try to match it against the track 2 regex //then try to match it against the track 2 regex
matcher = TRACK2_PATTERN.matcher(hit.getSnippet()); matcher = TRACK2_PATTERN.matcher(hit.getSnippet());
if (matcher.find()) { if (matcher.find()) {
parseTrack2Data(bba, matcher); parseTrack2Data(newArtifact, matcher);
} }
if (hit.getContent() instanceof AbstractFile) { if (hit.getContent() instanceof AbstractFile) {
AbstractFile file = (AbstractFile) hit.getContent(); AbstractFile file = (AbstractFile) hit.getContent();
if (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS if (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS
|| file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) { || file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) {
bba.addAttribute(new BlackboardAttribute(SOLR_DOCUMENT_ID_TYPE, MODULE_NAME, hit.getSolrDocumentId())); newArtifact.addAttribute(new BlackboardAttribute(SOLR_DOCUMENT_ID_TYPE, MODULE_NAME, hit.getSolrDocumentId()));
} }
} }
String ccn = newArtifact.getAttribute(ACCOUNT_NUMBER_TYPE).getValueString();
final int iin = Integer.parseInt(ccn.substring(0, 7));
IINRange iinRange = iinValidator.getIINRange(iin);
newArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_CREDIT_CARD_SCHEME, MODULE_NAME, iinRange.getPaymentCardScheme().name()));
newArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PAYMENT_CARD_TYPE, MODULE_NAME, iinRange.getPaymentCardType().name()));
if (StringUtils.isNotBlank(iinRange.getBrand())) {
newArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_BRAND, MODULE_NAME, iinRange.getBrand()));
}
if (StringUtils.isNotBlank(iinRange.getBankName())) {
newArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_BANK_NAME, MODULE_NAME, iinRange.getBankName()));
}
if (StringUtils.isNotBlank(iinRange.getBankPhoneNumber())) {
newArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER, MODULE_NAME, iinRange.getBankPhoneNumber()));
}
if (StringUtils.isNotBlank(iinRange.getBankURL())) {
newArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL, MODULE_NAME, iinRange.getBankURL()));
}
if (StringUtils.isNotBlank(iinRange.getCountry())) {
newArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COUNTRY, MODULE_NAME, iinRange.getCountry()));
}
if (StringUtils.isNotBlank(iinRange.getBankCity())) {
newArtifact.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_CITY, MODULE_NAME, iinRange.getBankCity()));
}
} else { } else {
//make keyword hit artifact //make keyword hit artifact
bba = hit.getContent().newArtifact(ARTIFACT_TYPE.TSK_KEYWORD_HIT); newArtifact = hit.getContent().newArtifact(ARTIFACT_TYPE.TSK_KEYWORD_HIT);
//regex match //regex match
attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD, MODULE_NAME, termHit)); attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD, MODULE_NAME, termHit));
@ -229,8 +268,8 @@ final class TermComponentQuery implements KeywordSearchQuery {
try { try {
//TODO: do we still/really need this KeywordCachedArtifact class? //TODO: do we still/really need this KeywordCachedArtifact class?
bba.addAttributes(attributes); newArtifact.addAttributes(attributes);
KeywordCachedArtifact writeResult = new KeywordCachedArtifact(bba); KeywordCachedArtifact writeResult = new KeywordCachedArtifact(newArtifact);
writeResult.add(attributes); writeResult.add(attributes);
return writeResult; return writeResult;
} catch (TskCoreException e) { } catch (TskCoreException e) {
@ -273,6 +312,7 @@ final class TermComponentQuery implements KeywordSearchQuery {
*/ */
QueryResults results = new QueryResults(this, keywordList); QueryResults results = new QueryResults(this, keywordList);
int resultSize = 0; int resultSize = 0;
for (Term term : terms) { for (Term term : terms) {
final String termStr = KeywordSearchUtil.escapeLuceneQuery(term.getTerm()); final String termStr = KeywordSearchUtil.escapeLuceneQuery(term.getTerm());
@ -280,9 +320,15 @@ final class TermComponentQuery implements KeywordSearchQuery {
//If the keyword is a credit card number, pass it through luhn validator //If the keyword is a credit card number, pass it through luhn validator
Matcher matcher = CCN_PATTERN.matcher(term.getTerm()); Matcher matcher = CCN_PATTERN.matcher(term.getTerm());
matcher.find(); matcher.find();
if (false == LUHN_CHECK.isValid(matcher.group("ccn"))) { final String ccn = matcher.group("ccn");
if (false == LUHN_CHECK.isValid(ccn)) {
continue; //if the hit does not pass the luhn check, skip it. continue; //if the hit does not pass the luhn check, skip it.
} }
final int iin = Integer.parseInt(ccn.substring(0, 7));
if (false == iinValidator.contains(iin)) {
continue;
}
} }
/* /*