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
.DS_Store
.*.swp
KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/.~lock.ranges.csv#

View File

@ -1,93 +1,89 @@
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 IIN_end;
private final int number_length;
private final CreditCardScheme scheme;
private final int IINStart;
private final int IINEnd;
private final int numberLength;
private final PaymentCardScheme scheme;
private final String brand;
private final PaymentCardType type;
private final String country;
private final String bank_name;
private final String bank_logo;
private final String bank_url;
private final String bank_phone;
private final String bank_city;
private final String bankName;
private final String bankURL;
private final String bankPhoneNumber;
private final String bankCity;
enum PaymentCardType {
DEBIT, DREDIT;
}
enum CreditCardScheme {
enum PaymentCardScheme {
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) {
this.IIN_start = IIN_start;
this.IIN_end = IIN_end;
this.number_length = number_length;
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.IINStart = IIN_start;
this.IINEnd = IIN_end;
this.numberLength = number_length;
this.scheme = scheme;
this.brand = brand;
this.type = type;
this.country = country;
this.bank_name = bank_name;
this.bank_logo = bank_logo;
this.bank_url = bank_url;
this.bank_phone = bank_phone;
this.bank_city = bank_city;
this.bankName = bank_name;
this.bankURL = bank_url;
this.bankPhoneNumber = bank_phone;
this.bankCity = bank_city;
}
public int getIIN_start() {
return IIN_start;
int getIINstart() {
return IINStart;
}
public int getIIN_end() {
return IIN_end;
int getIINend() {
return IINEnd;
}
public int getNumber_length() {
return number_length;
int getNumber_length() {
return numberLength;
}
public CreditCardScheme getScheme() {
PaymentCardScheme getPaymentCardScheme() {
return scheme;
}
public String getBrand() {
String getBrand() {
return brand;
}
public PaymentCardType getType() {
PaymentCardType getPaymentCardType() {
return type;
}
public String getCountry() {
String getCountry() {
return country;
}
public String getBank_name() {
return bank_name;
String getBankName() {
return bankName;
}
public String getBank_logo() {
return bank_logo;
String getBankURL() {
return bankURL;
}
public String getBank_url() {
return bank_url;
String getBankPhoneNumber() {
return bankPhoneNumber;
}
public String getBank_phone() {
return bank_phone;
}
public String getBank_city() {
return bank_city;
String getBankCity() {
return bankCity;
}
}

View File

@ -17,12 +17,12 @@ import org.apache.commons.csv.CSVRecord;
/**
*
*/
public class IINValidator {
RangeMap<Integer, IINRange> iinRanges = TreeRangeMap.create();
private IINValidator() throws FileNotFoundException, IOException {
IINValidator() throws FileNotFoundException, IOException {
Reader in = new FileReader("ranges.csv");
Iterable<CSVRecord> records = CSVFormat.RFC4180.withFirstRecordAsHeader().parse(in);
for (CSVRecord record : records) {
@ -30,18 +30,24 @@ public class IINValidator {
IINRange iinRange = new IINRange(Integer.parseInt(record.get("iin_start")),
Integer.parseInt(record.get("iin_end")),
Integer.parseInt(record.get("number_length")),
IINRange.CreditCardScheme.valueOf(record.get("scheme")),
IINRange.PaymentCardScheme.valueOf(record.get("scheme")),
record.get("brand"),
IINRange.PaymentCardType.valueOf(record.get("type")),
record.get("country"),
record.get("bank_name"),
record.get("bank_logo"),
record.get("bank_url"),
record.get("bank_phone"),
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;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
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.solr.client.solrj.SolrQuery;
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.Version;
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 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
/*
@ -108,9 +111,19 @@ final class TermComponentQuery implements KeywordSearchQuery {
private final Keyword keyword;
private boolean isEscaped;
private final List<KeywordQueryFilter> filters = new ArrayList<>();
private IINValidator iinValidator;
TermComponentQuery(KeywordList keywordList, 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.escapedQuery = keyword.getQuery();
}
@ -177,33 +190,59 @@ final class TermComponentQuery implements KeywordSearchQuery {
@Override
public KeywordCachedArtifact writeSingleFileHitsToBlackBoard(String termHit, KeywordHit hit, String snippet, String listName) {
BlackboardArtifact bba;
BlackboardArtifact newArtifact;
Collection<BlackboardAttribute> attributes = new ArrayList<>();
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) {
bba = hit.getContent().newArtifact(ARTIFACT_TYPE.TSK_CREDIT_CARD_ACCOUNT);
newArtifact = hit.getContent().newArtifact(ARTIFACT_TYPE.TSK_CREDIT_CARD_ACCOUNT);
// make account artifact
//try to match it against the track 1 regex
Matcher matcher = TRACK1_PATTERN.matcher(hit.getSnippet());
if (matcher.find()) {
parseTrack1Data(bba, matcher);
parseTrack1Data(newArtifact, matcher);
}
//then try to match it against the track 2 regex
matcher = TRACK2_PATTERN.matcher(hit.getSnippet());
if (matcher.find()) {
parseTrack2Data(bba, matcher);
parseTrack2Data(newArtifact, matcher);
}
if (hit.getContent() instanceof AbstractFile) {
AbstractFile file = (AbstractFile) hit.getContent();
if (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_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 {
//make keyword hit artifact
bba = hit.getContent().newArtifact(ARTIFACT_TYPE.TSK_KEYWORD_HIT);
newArtifact = hit.getContent().newArtifact(ARTIFACT_TYPE.TSK_KEYWORD_HIT);
//regex match
attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD, MODULE_NAME, termHit));
@ -229,8 +268,8 @@ final class TermComponentQuery implements KeywordSearchQuery {
try {
//TODO: do we still/really need this KeywordCachedArtifact class?
bba.addAttributes(attributes);
KeywordCachedArtifact writeResult = new KeywordCachedArtifact(bba);
newArtifact.addAttributes(attributes);
KeywordCachedArtifact writeResult = new KeywordCachedArtifact(newArtifact);
writeResult.add(attributes);
return writeResult;
} catch (TskCoreException e) {
@ -273,6 +312,7 @@ final class TermComponentQuery implements KeywordSearchQuery {
*/
QueryResults results = new QueryResults(this, keywordList);
int resultSize = 0;
for (Term term : terms) {
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
Matcher matcher = CCN_PATTERN.matcher(term.getTerm());
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.
}
final int iin = Integer.parseInt(ccn.substring(0, 7));
if (false == iinValidator.contains(iin)) {
continue;
}
}
/*