org.fiware.cybercaptor.server.api.InformationSystemManagement.java Source code

Java tutorial

Introduction

Here is the source code for org.fiware.cybercaptor.server.api.InformationSystemManagement.java

Source

/****************************************************************************************
 * This file is part of FIWARE CyberCAPTOR,                                             *
 * instance of FIWARE Cyber Security Generic Enabler                                    *
 * Copyright (C) 2012-2015  Thales Services S.A.S.,                                     *
 * 20-22 rue Grande Dame Rose 78140 VELIZY-VILACOUBLAY FRANCE                           *
 *                                                                                      *
 * FIWARE CyberCAPTOR is free software; you can redistribute                            *
 * it and/or modify it under the terms of the GNU General Public License                *
 * as published by the Free Software Foundation; either version 3 of the License,       *
 * or (at your option) any later version.                                               *
 *                                                                                      *
 * FIWARE CyberCAPTOR is distributed in the hope                                        *
 * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied           *
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
 * GNU General Public License for more details.                                         *
 *                                                                                      *
 * You should have received a copy of the GNU General Public License                    *
 * along with FIWARE CyberCAPTOR.                                                       *
 * If not, see <http://www.gnu.org/licenses/>.                                          *
 ****************************************************************************************/

package org.fiware.cybercaptor.server.api;

import org.fiware.cybercaptor.server.attackgraph.AttackGraph;
import org.fiware.cybercaptor.server.attackgraph.MulvalAttackGraph;
import org.fiware.cybercaptor.server.attackgraph.SecurityRequirement;
import org.fiware.cybercaptor.server.database.Database;
import org.fiware.cybercaptor.server.informationsystem.InformationSystem;
import org.fiware.cybercaptor.server.informationsystem.InformationSystemHost;
import org.fiware.cybercaptor.server.monitoring.Monitoring;
import org.fiware.cybercaptor.server.properties.ProjectProperties;
import org.fiware.cybercaptor.server.remediation.DeployableRemediation;
import org.fiware.cybercaptor.server.remediation.DeployableRemediationAction;
import org.fiware.cybercaptor.server.remediation.Patch;
import org.fiware.cybercaptor.server.remediation.Rule;
import org.fiware.cybercaptor.server.topology.asset.component.FirewallRule;
import org.fiware.cybercaptor.server.vulnerability.Vulnerability;
import org.json.JSONArray;
import org.json.JSONObject;

import java.io.File;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * An API class used to manage everything related to the information system and attack graph generation
 *
 * @author Francois-Xavier Aguessy
 */
public class InformationSystemManagement {
    /**
     * Load the information system from an XML File
     *
     * @param XMLInformationSystemFile the XML file path
     * @return the InformationSystem object
     */
    public static InformationSystem loadTopologyXMLFile(String XMLInformationSystemFile, Database db) {

        InformationSystem result = new InformationSystem();
        try {
            result.loadFromXMLFile(XMLInformationSystemFile, db);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * Execute MulVAL on the topology and return the attack graph
     *
     * @param informationSystem the input network
     * @return the associated attack graph object
     */
    public static AttackGraph prepareInputsAndExecuteMulVal(InformationSystem informationSystem) {
        if (informationSystem == null)
            return null;
        try {
            //Load MulVAL properties

            String mulvalPath = ProjectProperties.getProperty("mulval-path");
            String xsbPath = ProjectProperties.getProperty("xsb-path");
            String outputFolderPath = ProjectProperties.getProperty("output-path");

            File mulvalInputFile = new File(ProjectProperties.getProperty("mulval-input"));

            File mulvalOutputFile = new File(outputFolderPath + "/AttackGraph.xml");
            if (mulvalOutputFile.exists()) {
                mulvalOutputFile.delete();
            }
            Logger.getAnonymousLogger().log(Level.INFO, "Genering MulVAL inputs");
            informationSystem.exportToMulvalDatalogFile(mulvalInputFile.getAbsolutePath());

            Logger.getAnonymousLogger().log(Level.INFO, "Launching MulVAL");
            ProcessBuilder processBuilder = new ProcessBuilder(mulvalPath + "/utils/graph_gen.sh",
                    mulvalInputFile.getAbsolutePath(), "-l");

            if (ProjectProperties.getProperty("mulval-rules-path") != null) {
                processBuilder.command().add("-r");
                processBuilder.command().add(ProjectProperties.getProperty("mulval-rules-path"));
            }

            processBuilder.directory(new File(outputFolderPath));
            processBuilder.environment().put("MULVALROOT", mulvalPath);
            String path = System.getenv("PATH");
            processBuilder.environment().put("PATH", mulvalPath + "/utils/:" + xsbPath + ":" + path);
            Process process = processBuilder.start();
            process.waitFor();

            if (!mulvalOutputFile.exists()) {
                Logger.getAnonymousLogger().log(Level.INFO, "Empty attack graph!");
                return null;
            }

            MulvalAttackGraph ag = new MulvalAttackGraph(mulvalOutputFile.getAbsolutePath());

            ag.loadMetricsFromTopology(informationSystem);

            return ag;

        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * Execute MulVAL on the topology and return the attack graph
     *
     * @return the associated attack graph object
     */
    public static AttackGraph generateAttackGraphWithMulValUsingAlreadyGeneratedMulVALInputFile() {
        try {
            //Load MulVAL properties

            String mulvalPath = ProjectProperties.getProperty("mulval-path");
            String xsbPath = ProjectProperties.getProperty("xsb-path");
            String outputFolderPath = ProjectProperties.getProperty("output-path");

            File mulvalInputFile = new File(ProjectProperties.getProperty("mulval-input"));

            File mulvalOutputFile = new File(outputFolderPath + "/AttackGraph.xml");
            if (mulvalOutputFile.exists()) {
                mulvalOutputFile.delete();
            }

            Logger.getAnonymousLogger().log(Level.INFO, "Launching MulVAL");
            ProcessBuilder processBuilder = new ProcessBuilder(mulvalPath + "/utils/graph_gen.sh",
                    mulvalInputFile.getAbsolutePath(), "-l");

            if (ProjectProperties.getProperty("mulval-rules-path") != null) {
                processBuilder.command().add("-r");
                processBuilder.command().add(ProjectProperties.getProperty("mulval-rules-path"));
            }

            processBuilder.directory(new File(outputFolderPath));
            processBuilder.environment().put("MULVALROOT", mulvalPath);
            String path = System.getenv("PATH");
            processBuilder.environment().put("PATH", mulvalPath + "/utils/:" + xsbPath + ":" + path);
            Process process = processBuilder.start();
            process.waitFor();

            if (!mulvalOutputFile.exists()) {
                Logger.getAnonymousLogger().log(Level.INFO, "Empty attack graph!");
                return null;
            }

            MulvalAttackGraph ag = new MulvalAttackGraph(mulvalOutputFile.getAbsolutePath());

            return ag;

        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * @param informationSystem The initial topology
     * @param remediation       the remediation deployment that must be simulated
     * @param db                the vulnerability database
     * @return a clone of the topology, in which the remediation is applied
     */
    public static InformationSystem simulateRemediationOnNewInforationSystem(InformationSystem informationSystem,
            DeployableRemediation remediation, Database db) {
        InformationSystem simulatedTopology = null;
        try {
            simulatedTopology = informationSystem.clone();

            for (int i = 0; i < remediation.getActions().size(); i++) {
                DeployableRemediationAction action = remediation.getActions().get(i);
                Logger.getAnonymousLogger().log(Level.INFO, "Simulate the remediation "
                        + action.getRemediationAction().getActionType() + " on machine " + action.getHost());
                switch (action.getRemediationAction().getActionType()) {
                case APPLY_PATCH:
                    for (int j = 0; j < action.getRemediationAction().getRemediationParameters().size(); j++) {
                        Patch patch = (Patch) action.getRemediationAction().getRemediationParameters().get(j);
                        List<Vulnerability> correctedVulnerabilities = patch
                                .getCorectedVulnerabilities(db.getConn());
                        simulatedTopology.existingMachineByNameOrIPAddress(action.getHost().getName())
                                .correctVulnerabilities(correctedVulnerabilities);
                    }
                    break;
                case DEPLOY_FIREWALL_RULE:
                    FirewallRule rule = (FirewallRule) action.getRemediationAction().getRemediationParameters()
                            .get(0);
                    if (rule.getTable() == FirewallRule.Table.INPUT) {
                        simulatedTopology.existingMachineByNameOrIPAddress(action.getHost().getName())
                                .getInputFirewallRulesTable().getRuleList().add(0, rule);
                    } else if (rule.getTable() == FirewallRule.Table.OUTPUT) {
                        simulatedTopology.existingMachineByNameOrIPAddress(action.getHost().getName())
                                .getOutputFirewallRulesTable().getRuleList().add(0, rule);
                    }
                    break;
                case DEPLOY_SNORT_RULE:
                    for (int j = 0; j < action.getRemediationAction().getRemediationParameters().size(); j++) {
                        Rule snortRule = (Rule) action.getRemediationAction().getRemediationParameters().get(j);
                        List<Vulnerability> correctedVulnerabilities = snortRule
                                .getCorectedVulnerabilities(db.getConn());
                        //TODO: In fact, the vulnerability is not really corrected but rather suppressed on the path...
                        simulatedTopology
                                .existingMachineByNameOrIPAddress(
                                        action.getRemediationAction().getRelatedVertex().concernedMachine.getName())
                                .correctVulnerabilities(correctedVulnerabilities);
                    }
                    break;
                default:
                    break;
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return simulatedTopology;
    }

    /**
     * Execute the python script that builds MulVAL inputs
     *
     * @return boolean true if the execution was right
     */
    public static boolean prepareMulVALInputs() {
        try {
            //Load python script properties

            String pythonPath = ProjectProperties.getProperty("python-path");
            String mulvalInputScriptFolder = ProjectProperties.getProperty("mulval-input-script-folder");
            String mulvalInputScriptPath = mulvalInputScriptFolder + "main.py";

            String hostInterfacePath = ProjectProperties.getProperty("host-interfaces-path");
            String vlansPath = ProjectProperties.getProperty("vlans-path");
            String routingPath = ProjectProperties.getProperty("routing-path");
            String flowMatrixPath = ProjectProperties.getProperty("flow-matrix-path");
            String vulnerabilityScanPath = ProjectProperties.getProperty("vulnerability-scan-path");
            String mulvalInputPath = ProjectProperties.getProperty("mulval-input");
            String topologyPath = ProjectProperties.getProperty("topology-path");

            File mulvalInputFile = new File(mulvalInputPath);
            if (mulvalInputFile.exists()) {
                mulvalInputFile.delete();
            }

            Logger.getAnonymousLogger().log(Level.INFO, "Genering MulVAL inputs");

            //TODO: use parameter nessus-files-path rather than vulnerability-scan-path, in order to manage when
            // mutliple nessus files are provided.
            ProcessBuilder processBuilder = new ProcessBuilder(pythonPath, mulvalInputScriptPath,
                    "--hosts-interfaces-file", hostInterfacePath, "--vlans-file", vlansPath, "--flow-matrix-file",
                    flowMatrixPath, "--vulnerability-scan", vulnerabilityScanPath, "--routing-file", routingPath,
                    "--mulval-output-file", mulvalInputFile.getAbsolutePath(), "--to-fiware-xml-topology",
                    topologyPath);
            processBuilder.directory(new File(mulvalInputScriptFolder));
            StringBuilder command = new StringBuilder();
            for (String str : processBuilder.command())
                command.append(str + " ");
            Logger.getAnonymousLogger().log(Level.INFO,
                    "Launch generation of MulVAL inputs with command : \n" + command.toString());
            processBuilder.redirectOutput(
                    new File(ProjectProperties.getProperty("output-path") + "/input-generation.log"));
            processBuilder.redirectError(
                    new File(ProjectProperties.getProperty("output-path") + "/input-generation.log"));
            Process process = processBuilder.start();
            process.waitFor();

            if (!mulvalInputFile.exists()) {
                Logger.getAnonymousLogger().log(Level.WARNING,
                        "A problem happened in the generation of mulval inputs");
                return false;
            }

            return true;

        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * Load the json of hosts with security requirements
     *
     * @param monitoring
     * @param hostsJson
     */
    public static void loadHostsSecurityRequirementsFromJson(Monitoring monitoring, JSONObject hostsJson)
            throws Exception {
        JSONArray hostsJsonArray = hostsJson.getJSONArray("hosts");
        for (int i = 0; i < hostsJsonArray.length(); i++) {
            JSONObject hostJson = hostsJsonArray.getJSONObject(i);
            if (hostJson != null) {
                String hostName = hostJson.getString("name");
                InformationSystemHost host = monitoring.getInformationSystem().getHostByNameOrIPAddress(hostName);
                if (host == null)
                    throw new IllegalStateException("The host " + hostName + " can not be found ");

                host.removeAllSecurityRequirements();

                JSONArray securityRequirementsArray = hostJson.getJSONArray("security_requirements");
                for (int j = 0; j < securityRequirementsArray.length(); j++) {
                    JSONObject securityRequirementJson = securityRequirementsArray.getJSONObject(j);
                    SecurityRequirement securityRequirement = new SecurityRequirement(
                            securityRequirementJson.getString("name"), SecurityRequirement
                                    .getMetricValueFromPlainText(securityRequirementJson.getString("metric")));
                    host.addSecurityRequirements(securityRequirement);
                }

            }
        }
    }
}