19 package org.sleuthkit.autopsy.report.modules.stix;
 
   21 import java.io.BufferedWriter;
 
   23 import java.io.FileWriter;
 
   24 import java.io.IOException;
 
   25 import java.util.Arrays;
 
   26 import java.util.HashMap;
 
   27 import java.util.List;
 
   29 import java.util.logging.Level;
 
   30 import javax.swing.JPanel;
 
   31 import javax.xml.bind.JAXBContext;
 
   32 import javax.xml.bind.JAXBException; 
 
   33 import javax.xml.bind.Unmarshaller;
 
   34 import javax.xml.namespace.QName;
 
   35 import org.mitre.cybox.cybox_2.ObjectType;
 
   36 import org.mitre.cybox.cybox_2.Observable;
 
   37 import org.mitre.cybox.cybox_2.ObservableCompositionType;
 
   38 import org.mitre.cybox.cybox_2.OperatorTypeEnum;
 
   39 import org.mitre.cybox.objects.AccountObjectType;
 
   40 import org.mitre.cybox.objects.Address;
 
   41 import org.mitre.cybox.objects.DomainName;
 
   42 import org.mitre.cybox.objects.EmailMessage;
 
   43 import org.mitre.cybox.objects.FileObjectType;
 
   44 import org.mitre.cybox.objects.SystemObjectType;
 
   45 import org.mitre.cybox.objects.URIObjectType;
 
   46 import org.mitre.cybox.objects.URLHistory;
 
   47 import org.mitre.cybox.objects.WindowsNetworkShare;
 
   48 import org.mitre.cybox.objects.WindowsRegistryKey;
 
   49 import org.mitre.stix.common_1.IndicatorBaseType;
 
   50 import org.mitre.stix.indicator_2.Indicator;
 
   51 import org.mitre.stix.stix_1.STIXPackage;
 
   52 import org.openide.util.NbBundle;
 
   53 import org.openide.util.NbBundle.Messages;
 
   77     private Map<String, ObservableResult> 
idToResult = 
new HashMap<>();
 
   89         if (instance == null) {
 
  100     @Messages({
"STIXReportModule.srcModuleName.text=STIX Report"})
 
  104         progressPanel.
start();
 
  106         progressPanel.
updateStatusLabel(NbBundle.getMessage(
this.getClass(), 
"STIXReportModule.progress.readSTIX"));        
 
  108         File reportFile = 
new File(reportPath);
 
  110         reportAllResults = configPanel.getShowAllResults();
 
  113         boolean hadErrors = 
false;
 
  116         String stixFileName = configPanel.getStixFile();
 
  118         if (stixFileName == null) {
 
  119             logger.log(Level.SEVERE, 
"STIXReportModuleConfigPanel.stixFile not initialized "); 
 
  120             progressPanel.
complete(
ReportStatus.
ERROR, NbBundle.getMessage(
this.getClass(), 
"STIXReportModule.progress.noFildDirProvided"));
 
  121             new File(baseReportDir).delete();
 
  124         if (stixFileName.isEmpty()) {
 
  125             logger.log(Level.SEVERE, 
"No STIX file/directory provided "); 
 
  126             progressPanel.
complete(
ReportStatus.
ERROR, NbBundle.getMessage(
this.getClass(), 
"STIXReportModule.progress.noFildDirProvided"));
 
  127             new File(baseReportDir).delete();
 
  130         File stixFile = 
new File(stixFileName);
 
  132         if (!stixFile.exists()) {
 
  133             logger.log(Level.SEVERE, String.format(
"Unable to open STIX file/directory %s", stixFileName)); 
 
  134             progressPanel.
complete(
ReportStatus.
ERROR, NbBundle.getMessage(
this.getClass(), 
"STIXReportModule.progress.couldNotOpenFileDir", stixFileName));
 
  135             new File(baseReportDir).delete();
 
  139         try (BufferedWriter output = 
new BufferedWriter(
new FileWriter(reportFile))) {
 
  143             if (stixFile.isFile()) {
 
  144                 stixFiles = 
new File[1];
 
  145                 stixFiles[0] = stixFile;
 
  147                 stixFiles = stixFile.listFiles();
 
  154             for (File file : stixFiles) {
 
  159                     processFile(file.getAbsolutePath(), progressPanel, output);
 
  160                 } 
catch (TskCoreException | JAXBException ex) {
 
  161                     String errMsg = String.format(
"Unable to process STIX file %s", file);
 
  162                     logger.log(Level.SEVERE, errMsg, ex); 
 
  168                 idToObjectMap = 
new HashMap<>();
 
  169                 idToResult = 
new HashMap<>();
 
  176                 progressPanel.
complete(
ReportStatus.
ERROR, NbBundle.getMessage(
this.getClass(), 
"STIXReportModule.progress.completedWithErrors"));
 
  180         } 
catch (IOException ex) {
 
  181             logger.log(Level.SEVERE, 
"Unable to complete STIX report.", ex); 
 
  182             progressPanel.
complete(
ReportStatus.
ERROR, NbBundle.getMessage(
this.getClass(), 
"STIXReportModule.progress.completedWithErrors"));
 
  184             logger.log(Level.SEVERE, 
"Unable to add report to database.", ex);
 
  199             JAXBException, TskCoreException {
 
  229     private STIXPackage 
loadSTIXFile(String stixFileName) 
throws JAXBException {
 
  232         ClassLoader original = Thread.currentThread().getContextClassLoader();
 
  234             Thread.currentThread().setContextClassLoader(
STIXReportModule.class.getClassLoader());
 
  235             File file = 
new File(stixFileName);
 
  236             JAXBContext jaxbContext = JAXBContext.newInstance(
"org.mitre.stix.stix_1:org.mitre.stix.common_1:org.mitre.stix.indicator_2:"  
  237                     + 
"org.mitre.cybox.objects:org.mitre.cybox.cybox_2:org.mitre.cybox.common_2"); 
 
  238             Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
 
  239             STIXPackage stix = (STIXPackage) jaxbUnmarshaller.unmarshal(file);
 
  242             Thread.currentThread().setContextClassLoader(original);
 
  253         if (stix.getObservables() != null) {
 
  254             List<Observable> obs = stix.getObservables().getObservables();
 
  255             for (Observable o : obs) {
 
  256                 if (o.getId() != null) {
 
  272         if (stix.getIndicators() != null) {
 
  273             List<IndicatorBaseType> s = stix.getIndicators().getIndicators();
 
  274             for (IndicatorBaseType t : s) {
 
  275                 if (t instanceof Indicator) {
 
  276                     Indicator ind = (Indicator) t;
 
  277                     if (ind.getObservable() != null) {
 
  278                         if (ind.getObservable().getObject() != null) {
 
  283                             if (result.isTrue()) {
 
  286                         } 
else if (ind.getObservable().getObservableComposition() != null) {
 
  292                             if (result.isTrue()) {
 
  313         if (result.getArtifacts() == null) {
 
  320         for (StixArtifactData s : result.getArtifacts()) {
 
  325             if (ind.getTitle() != null) {
 
  326                 s.createArtifact(ind.getTitle());
 
  327             } 
else if (ind.getId() != null) {
 
  328                 s.createArtifact(ind.getId().toString());
 
  330                 s.createArtifact(
"Unnamed indicator(s)"); 
 
  338                                 "STIXReportModule.notifyMsg.tooManyArtifactsgt1000"));
 
  354     private void writeResultsToFile(Indicator ind, String resultStr, 
boolean found, BufferedWriter output) {
 
  355         if (output != null) {
 
  358                     output.write(
"----------------\r\n" 
  359                             + 
"Found indicator:\r\n"); 
 
  361                     output.write(
"-----------------------\r\n" 
  362                             + 
"Did not find indicator:\r\n"); 
 
  364                 if (ind.getTitle() != null) {
 
  365                     output.write(
"Title: " + ind.getTitle() + 
"\r\n"); 
 
  367                     output.write(
"\r\n");
 
  369                 if (ind.getId() != null) {
 
  370                     output.write(
"ID: " + ind.getId() + 
"\r\n"); 
 
  373                 if (ind.getDescription() != null) {
 
  374                     String desc = ind.getDescription().getValue();
 
  376                     output.write(
"Description: " + desc + 
"\r\n"); 
 
  378                 output.write(
"\r\nObservable results:\r\n" + resultStr + 
"\r\n\r\n"); 
 
  379             } 
catch (IOException ex) {
 
  380                 logger.log(Level.SEVERE, String.format(
"Error writing to STIX report file %s", reportPath), ex); 
 
  392         if (output != null) {
 
  394                 char[] chars = 
new char[a_fileName.length() + 8];
 
  395                 Arrays.fill(chars, 
'#');
 
  396                 String header = 
new String(chars);
 
  397                 output.write(
"\r\n" + header);
 
  398                 output.write(
"\r\n");
 
  399                 output.write(
"### " + a_fileName + 
" ###\r\n");
 
  400                 output.write(header + 
"\r\n\r\n");
 
  401             } 
catch (IOException ex) {
 
  402                 logger.log(Level.SEVERE, String.format(
"Error writing to STIX report file %s", reportPath), ex); 
 
  418         if (obs.getId() != null) {
 
  420         } 
else if (obs.getIdref() != null) {
 
  421             idQ = obs.getIdref();
 
  426         return idQ.getLocalPart();
 
  436         if (obs.getObject() != null) {
 
  437             idToObjectMap.put(
makeMapKey(obs), obs.getObject());
 
  452         if (comp.getOperator() == null) {
 
  453             throw new TskCoreException(
"No operator found in composition"); 
 
  456         if (comp.getObservables() != null) {
 
  457             List<Observable> obsList = comp.getObservables();
 
  460             if (comp.getOperator() == OperatorTypeEnum.AND) {
 
  461                 ObservableResult result = 
new ObservableResult(OperatorTypeEnum.AND, spacing);
 
  462                 for (Observable o : obsList) {
 
  464                     ObservableResult newResult; 
 
  465                     if (o.getObservableComposition() != null) {
 
  467                         if (result == null) {
 
  470                             result.addResult(newResult, OperatorTypeEnum.AND);
 
  474                         if (result == null) {
 
  477                             result.addResult(newResult, OperatorTypeEnum.AND);
 
  481                     if ((!skipShortCircuit) && !result.isFalse()) {
 
  487                 if (result == null) {
 
  490                     return new ObservableResult(
"", 
"", spacing, ObservableResult.ObservableState.INDETERMINATE, null);
 
  496                 ObservableResult result = 
new ObservableResult(OperatorTypeEnum.OR, spacing);
 
  497                 for (Observable o : obsList) {
 
  499                     ObservableResult newResult;
 
  501                     if (o.getObservableComposition() != null) {
 
  503                         if (result == null) {
 
  506                             result.addResult(newResult, OperatorTypeEnum.OR);
 
  510                         if (result == null) {
 
  513                             result.addResult(newResult, OperatorTypeEnum.OR);
 
  517                     if ((!skipShortCircuit) && result.isTrue()) {
 
  523                 if (result == null) {
 
  526                     return new ObservableResult(
"", 
"", spacing, ObservableResult.ObservableState.INDETERMINATE, null);
 
  532             throw new TskCoreException(
"No observables found in list"); 
 
  550         if (idToResult.containsKey(
makeMapKey(obs))) {
 
  554         if (obs.getIdref() == null) {
 
  558             if (obs.getId() != null) {
 
  562             if (obs.getObject() != null) {
 
  570         if (idToObjectMap.containsKey(
makeMapKey(obs))) {
 
  576         throw new TskCoreException(
"Error loading/finding object for observable " + obs.getIdref()); 
 
  589     private ObservableResult 
evaluateObject(ObjectType obj, String spacing, String 
id) {
 
  591         EvaluatableObject evalObj;
 
  593         if (obj.getProperties() instanceof FileObjectType) {
 
  594             evalObj = 
new EvalFileObj((FileObjectType) obj.getProperties(), id, spacing);
 
  595         } 
else if (obj.getProperties() instanceof Address) {
 
  596             evalObj = 
new EvalAddressObj((Address) obj.getProperties(), id, spacing);
 
  597         } 
else if (obj.getProperties() instanceof URIObjectType) {
 
  598             evalObj = 
new EvalURIObj((URIObjectType) obj.getProperties(), id, spacing);
 
  599         } 
else if (obj.getProperties() instanceof EmailMessage) {
 
  600             evalObj = 
new EvalEmailObj((EmailMessage) obj.getProperties(), id, spacing);
 
  601         } 
else if (obj.getProperties() instanceof WindowsNetworkShare) {
 
  602             evalObj = 
new EvalNetworkShareObj((WindowsNetworkShare) obj.getProperties(), id, spacing);
 
  603         } 
else if (obj.getProperties() instanceof AccountObjectType) {
 
  604             evalObj = 
new EvalAccountObj((AccountObjectType) obj.getProperties(), id, spacing);
 
  605         } 
else if (obj.getProperties() instanceof SystemObjectType) {
 
  606             evalObj = 
new EvalSystemObj((SystemObjectType) obj.getProperties(), id, spacing);
 
  607         } 
else if (obj.getProperties() instanceof URLHistory) {
 
  608             evalObj = 
new EvalURLHistoryObj((URLHistory) obj.getProperties(), id, spacing);
 
  609         } 
else if (obj.getProperties() instanceof DomainName) {
 
  610             evalObj = 
new EvalDomainObj((DomainName) obj.getProperties(), id, spacing);
 
  611         } 
else if (obj.getProperties() instanceof WindowsRegistryKey) {
 
  612             evalObj = 
new EvalRegistryObj((WindowsRegistryKey) obj.getProperties(), id, spacing, 
registryFileData);
 
  615             String type = obj.getProperties().toString();
 
  616             type = type.substring(0, type.indexOf(
"@"));
 
  617             if ((type.lastIndexOf(
".") + 1) < type.length()) {
 
  618                 type = type.substring(type.lastIndexOf(
".") + 1);
 
  620             return new ObservableResult(
id, type + 
" not supported", 
 
  621                     spacing, ObservableResult.ObservableState.INDETERMINATE, null);
 
  625         return evalObj.evaluate();
 
  630         String name = NbBundle.getMessage(this.getClass(), 
"STIXReportModule.getName.text");
 
  641         String desc = NbBundle.getMessage(this.getClass(), 
"STIXReportModule.getDesc.text");
 
  652         if (configPanel == null) {
 
  664         return new STIXReportModuleSettings();
 
  675         return configPanel.getConfiguration();
 
  691         if (settings instanceof STIXReportModuleSettings) {
 
  692             configPanel.setConfiguration((STIXReportModuleSettings) settings);
 
  696         throw new IllegalArgumentException(
"Expected settings argument to be an instance of STIXReportModuleSettings");
 
void processFile(String stixFile, ReportProgressPanel progressPanel, BufferedWriter output)
 
String getRelativeFilePath()
 
void processObservables(STIXPackage stix)
 
void saveResultsAsArtifacts(Indicator ind, ObservableResult result, ReportProgressPanel progressPanel)
 
void writeResultsToFile(Indicator ind, String resultStr, boolean found, BufferedWriter output)
 
Map< String, ObservableResult > idToResult
 
ReportModuleSettings getDefaultConfiguration()
 
STIXReportModuleConfigPanel configPanel
 
void complete(ReportStatus reportStatus)
 
ObservableResult evaluateObservableComposition(ObservableCompositionType comp, String spacing)
 
void printFileHeader(String a_fileName, BufferedWriter output)
 
static STIXReportModule instance
 
ObservableResult evaluateSingleObservable(Observable obs, String spacing)
 
STIXPackage loadSTIXFile(String stixFileName)
 
void addReport(String localPath, String srcModuleName, String reportName)
 
Map< String, ObjectType > idToObjectMap
 
static synchronized STIXReportModule getDefault()
 
void setIndeterminate(boolean indeterminate)
 
void generateReport(GeneralReportSettings settings, ReportProgressPanel progressPanel)
 
ReportModuleSettings getConfiguration()
 
static final Logger logger
 
void setConfiguration(ReportModuleSettings settings)
 
List< EvalRegistryObj.RegistryFileInfo > registryFileData
 
void setMaximumProgress(int max)
 
JPanel getConfigurationPanel()
 
void saveToObjectMap(Observable obs)
 
ObservableResult evaluateObject(ObjectType obj, String spacing, String id)
 
synchronized static Logger getLogger(String name)
 
static Case getCurrentCaseThrows()
 
void updateStatusLabel(String statusMessage)
 
void processIndicators(STIXPackage stix, BufferedWriter output, ReportProgressPanel progressPanel)
 
final boolean skipShortCircuit
 
String getReportDirectoryPath()
 
String makeMapKey(Observable obs)