org.fiware.cybercaptor.server.informationsystem.InformationSystem.java Source code

Java tutorial

Introduction

Here is the source code for org.fiware.cybercaptor.server.informationsystem.InformationSystem.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.informationsystem;

import org.fiware.cybercaptor.server.attackgraph.SecurityRequirement;
import org.fiware.cybercaptor.server.database.Database;
import org.fiware.cybercaptor.server.flowmatrix.FlowMatrix;
import org.fiware.cybercaptor.server.flowmatrix.FlowMatrixElement;
import org.fiware.cybercaptor.server.flowmatrix.FlowMatrixLine;
import org.fiware.cybercaptor.server.topology.Topology;
import org.fiware.cybercaptor.server.topology.asset.Host;
import org.fiware.cybercaptor.server.topology.asset.IPAddress;
import org.fiware.cybercaptor.server.topology.asset.VLAN;
import org.fiware.cybercaptor.server.topology.asset.component.FirewallRule;
import org.fiware.cybercaptor.server.topology.asset.component.Interface;
import org.fiware.cybercaptor.server.vulnerability.Vulnerability;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;
import org.json.JSONArray;
import org.json.JSONObject;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

//TODO: check if some functions are not already defined in the topology.
// TODO: Perhaps this package should be merge with the topology.* package

/**
 * Class that represent the information system
 *
 * @author Francois-Xavier Aguessy
 */
public class InformationSystem implements Cloneable {

    /**
     * The network topology of the information system
     */
    private Topology topology = new Topology();

    /**
     * Is the attacker located on the internet in addition to {@link #machinesOfAttacker} ?
     */
    private boolean attackerLocatedOnInternet = false;

    /**
     * The flow matrix of the Information System
     */
    private FlowMatrix flowMatrix;

    /**
     * The list of machines that are mastered by the attacker
     */
    private List<InformationSystemHost> machinesOfAttacker = new ArrayList<InformationSystemHost>();

    /**
     * Create an empty information system
     */
    public InformationSystem() {

    }

    @Override
    public InformationSystem clone() throws CloneNotSupportedException {
        InformationSystem copie = (InformationSystem) super.clone();
        copie.topology = copie.topology.clone();
        return copie;
    }

    /**
     * Create a file with Datalog rules for the input of Mulval
     *
     * @param mulvalFilePath the filePath to store MulVAL input Datalog file
     * @throws Exception
     */
    public void exportToMulvalDatalogFile(String mulvalFilePath) throws Exception {
        PrintWriter fichier = new PrintWriter(new BufferedWriter(new FileWriter(mulvalFilePath)));

        //Add internet
        fichier.println("/**********************************/");
        fichier.println("/*    Add Internet                */");
        fichier.println("/**********************************/");

        fichier.println("attackerLocated(internet_host).");
        fichier.println("hasIP(internet_host,'1.1.1.1').");
        fichier.println("defaultLocalFilteringBehavior('internet_host',allow).");
        fichier.println("isInVlan('1.1.1.1','internet').");
        fichier.println();

        for (Host host : topology.getHosts()) {
            fichier.println("/**********************************/");
            fichier.println("/*    Add Host " + host.getName() + " */");
            fichier.println("/**********************************/");
            InformationSystemHost informationSystemHost = (InformationSystemHost) host;
            fichier.println("attackerLocated('" + host.getName() + "').");
            fichier.println("attackGoal(execCode('" + host.getName() + "', _)).");
            for (Interface networkInterface : host.getInterfaces().values()) {
                fichier.println(
                        "hasIP('" + host.getName() + "','" + networkInterface.getAddress().toString() + "').");
                if (networkInterface.getVlan() != null && !networkInterface.getVlan().getName().isEmpty()) {
                    fichier.println("isInVlan('" + networkInterface.getAddress().toString() + "','"
                            + networkInterface.getVlan().getName() + "').");
                }
            }
            fichier.println("hostAllowAccessToAllIP('" + host.getName() + "').");
            for (Service service : informationSystemHost.getServices().values()) {
                fichier.println("installed('" + host.getName() + "','" + service.getName() + "').");
                if (service.getPortNumber() != 0) {
                    fichier.println("networkServiceInfo('" + service.getIpAddress() + "', '" + service.getName()
                            + "', '" + service.getProtocol().toString() + "', " + service.getPortNumber()
                            + ", 'user').");
                }

                for (String cve : service.getVulnerabilities().keySet()) {
                    Vulnerability vulnerability = service.getVulnerabilities().get(cve);
                    fichier.println("vulProperty('" + vulnerability.cve + "', " + vulnerability.exploitType + ", "
                            + vulnerability.exploitGoal + ").");
                    fichier.println(
                            "vulExists('" + host.getName() + "', '" + vulnerability.cve + "', '" + service.getName()
                                    + "', " + vulnerability.exploitType + ", " + vulnerability.exploitGoal + ").");
                    if (vulnerability.cvss != null && vulnerability.cvss.getScore() >= 6.6) {
                        fichier.println("cvss('" + vulnerability.cve + "',h).");
                    } else if (vulnerability.cvss != null && vulnerability.cvss.getScore() >= 3.3) {
                        fichier.println("cvss('" + vulnerability.cve + "',m).");
                    } else if (vulnerability.cvss != null && vulnerability.cvss.getScore() > 0) {
                        fichier.println("cvss('" + vulnerability.cve + "',l).");
                    } else {
                        fichier.println("cvss('" + vulnerability.cve + "',m).");
                    }
                }
            }
            fichier.println();

        }

        //Add flow matrix elements
        if (this.flowMatrix != null && this.flowMatrix.getFlowMatrixLines().size() > 0) {
            for (FlowMatrixLine flowMatrixLine : this.flowMatrix.getFlowMatrixLines()) {
                String mulvalDestinationPort;
                if (flowMatrixLine.getDestination_port().isAny()) {
                    mulvalDestinationPort = "_";
                } else if (flowMatrixLine.getDestination_port().getMax() == flowMatrixLine.getDestination_port()
                        .getMin()) {
                    mulvalDestinationPort = "" + flowMatrixLine.getDestination_port().getMax();
                } else {
                    throw new IllegalStateException("Minimum and Maximum port range are not yet managed.");
                }

                String mulvalProtocol;
                if (flowMatrixLine.getProtocol().equals(FirewallRule.Protocol.ANY)) {
                    mulvalProtocol = "_";
                } else {
                    mulvalProtocol = "'" + flowMatrixLine.getProtocol().toString() + "'";
                }

                if (!mulvalDestinationPort.isEmpty() && !mulvalProtocol.isEmpty()) {
                    FlowMatrixElement sourceElement = flowMatrixLine.getSource();
                    FlowMatrixElement destinationElement = flowMatrixLine.getDestination();

                    if (sourceElement.getType().equals(FlowMatrixElement.FlowMatrixElementType.IP)
                            && destinationElement.getType().equals(FlowMatrixElement.FlowMatrixElementType.IP)) {
                        if (sourceElement.getResource() instanceof Interface
                                && destinationElement.getResource() instanceof Interface) {
                            Interface sourceInterface = (Interface) sourceElement.getResource();
                            Interface destinationInterface = (Interface) destinationElement.getResource();
                            fichier.println("haclprimit('" + sourceInterface.getAddress() + "','"
                                    + destinationInterface.getAddress() + "', " + mulvalDestinationPort + ","
                                    + mulvalProtocol + ").");
                        } else {
                            throw new IllegalStateException("Illegal resource type");
                        }
                    } else if (sourceElement.getType().equals(FlowMatrixElement.FlowMatrixElementType.INTERNET)
                            && destinationElement.getType().equals(FlowMatrixElement.FlowMatrixElementType.IP)) {
                        if (destinationElement.getResource() instanceof Interface) {
                            Interface destinationInterface = (Interface) destinationElement.getResource();
                            fichier.println("vlanToIP('internet','" + destinationInterface.getAddress() + "', "
                                    + mulvalDestinationPort + "," + mulvalProtocol + ").");
                        } else {
                            throw new IllegalStateException("Illegal resource type");
                        }
                    } else if (sourceElement.getType().equals(FlowMatrixElement.FlowMatrixElementType.VLAN)
                            && destinationElement.getType().equals(FlowMatrixElement.FlowMatrixElementType.IP)) {
                        if (sourceElement.getResource() instanceof VLAN
                                && destinationElement.getResource() instanceof Interface) {
                            VLAN sourceVlan = (VLAN) sourceElement.getResource();
                            Interface destinationInterface = (Interface) destinationElement.getResource();
                            fichier.println(
                                    "vlanToIP('" + sourceVlan.getName() + "','" + destinationInterface.getAddress()
                                            + "', " + mulvalDestinationPort + "," + mulvalProtocol + ").");
                        } else {
                            throw new IllegalStateException("Illegal resource type");
                        }
                    } else if (sourceElement.getType().equals(FlowMatrixElement.FlowMatrixElementType.IP)
                            && destinationElement.getType().equals(FlowMatrixElement.FlowMatrixElementType.VLAN)) {
                        if (sourceElement.getResource() instanceof Interface
                                && destinationElement.getResource() instanceof VLAN) {
                            Interface sourceInterface = (Interface) sourceElement.getResource();
                            VLAN destinationVlan = (VLAN) destinationElement.getResource();
                            fichier.println(
                                    "ipToVlan('" + sourceInterface.getAddress() + "','" + destinationVlan.getName()
                                            + "', " + mulvalDestinationPort + "," + mulvalProtocol + ").");
                        } else {
                            throw new IllegalStateException("Illegal resource type");
                        }
                    } else if (sourceElement.getType().equals(FlowMatrixElement.FlowMatrixElementType.INTERNET)
                            && destinationElement.getType().equals(FlowMatrixElement.FlowMatrixElementType.VLAN)) {
                        if (destinationElement.getResource() instanceof VLAN) {
                            VLAN destinationVLAN = (VLAN) destinationElement.getResource();
                            fichier.println("vlanToVlan('internet','" + destinationVLAN.getName() + "', "
                                    + mulvalDestinationPort + "," + mulvalProtocol + ").");
                        } else {
                            throw new IllegalStateException("Illegal resource type");
                        }
                    } else if (sourceElement.getType().equals(FlowMatrixElement.FlowMatrixElementType.VLAN)
                            && destinationElement.getType().equals(FlowMatrixElement.FlowMatrixElementType.VLAN)) {
                        if (sourceElement.getResource() instanceof VLAN
                                && destinationElement.getResource() instanceof VLAN) {
                            VLAN sourceVLAN = (VLAN) sourceElement.getResource();
                            VLAN destinationVLAN = (VLAN) destinationElement.getResource();
                            fichier.println(
                                    "vlanToVlan('" + sourceVLAN.getName() + "','" + destinationVLAN.getName()
                                            + "', " + mulvalDestinationPort + "," + mulvalProtocol + ").");
                        } else {
                            throw new IllegalStateException("Illegal resource type");
                        }
                    } else if (sourceElement.getType().equals(FlowMatrixElement.FlowMatrixElementType.IP)
                            && destinationElement.getType()
                                    .equals(FlowMatrixElement.FlowMatrixElementType.INTERNET)) {
                        if (sourceElement.getResource() instanceof Interface) {
                            Interface sourceInterface = (Interface) sourceElement.getResource();
                            fichier.println("ipToVlan('" + sourceInterface.getAddress() + "','internet', "
                                    + mulvalDestinationPort + "," + mulvalProtocol + ").");
                        } else {
                            throw new IllegalStateException("Illegal resource type");
                        }
                    } else if (sourceElement.getType().equals(FlowMatrixElement.FlowMatrixElementType.VLAN)
                            && destinationElement.getType()
                                    .equals(FlowMatrixElement.FlowMatrixElementType.INTERNET)) {
                        if (sourceElement.getResource() instanceof VLAN) {
                            VLAN sourceVLAN = (VLAN) sourceElement.getResource();
                            fichier.println("vlanToVlan('" + sourceVLAN.getName() + "','internet', "
                                    + mulvalDestinationPort + "," + mulvalProtocol + ").");
                        } else {
                            throw new IllegalStateException("Illegal resource type");
                        }
                    } else {
                        throw new IllegalStateException("Unknown values of flow matrix");
                    }

                } else {
                    throw new IllegalStateException("Empty port or protocol");
                }
            }
        } else { //Empty flow matrix, add access betwen each couples of VLANs
            for (VLAN vlanFrom : this.topology.getVlans().values()) {
                for (VLAN vlanTo : this.topology.getVlans().values()) {
                    if (!vlanFrom.equals(vlanTo)) {
                        fichier.println("vlanToVlan('" + vlanFrom.getName() + "','" + vlanTo.getName() + "',_,_).");
                    }

                }
            }
        }

        fichier.println("/**********************************/");
        fichier.println("/******     General Rules    ******/");
        fichier.println("/**********************************/");
        fichier.println("defaultLocalFilteringBehavior(_,allow)."); //Attacker is on the internet

        fichier.close();
    }

    /**
     * Get a machine by its name or IP address. If the machine doesn't exist, add it to the topology
     *
     * @param str the name or IP address of the machine
     * @return the created or existing machine.
     * @throws Exception
     */
    public InformationSystemHost getHostByNameOrIPAddress(String str) throws Exception {
        if (IPAddress.isAnIPAddress(str)) {
            return getMachineByIPAddress(new IPAddress(str));
        } else {
            InformationSystemHost existingMachine = existingMachineByName(str);
            if (existingMachine != null)
                return existingMachine;
            InformationSystemHost newMachine = new InformationSystemHost(str, this.topology);
            this.topology.getHosts().add(newMachine);
            return newMachine;
        }
    }

    /**
     * get the routes from the internet to a host
     *
     * @param to the destination host
     * @return The list of routes
     * @throws Exception
     */
    public List<List<InformationSystemHost>> routesFromInternetTo(Host to) throws Exception {
        List<List<InformationSystemHost>> result = new ArrayList<List<InformationSystemHost>>();
        List<List<Host>> routes = to.getRoutesFromInternet();

        for (List<Host> route : routes) {
            List<InformationSystemHost> tmpResult = new ArrayList<InformationSystemHost>();
            for (Host aRoute : route) {
                tmpResult.add((InformationSystemHost) aRoute);
            }
            result.add(tmpResult);
        }

        return result;
    }

    /**
     * Get an existing machine of the information system with its name
     *
     * @param name the name of the machine
     * @return the machine if it exists else null
     */
    public InformationSystemHost existingMachineByName(String name) {
        for (int i = 0; i < this.topology.getHosts().size(); i++) {
            if (this.topology.getHosts().get(i).getName().equals(name))
                return (InformationSystemHost) this.topology.getHosts().get(i);
        }
        if (name.equals("internet"))
            return new InformationSystemHost("internet", topology);

        return null;
    }

    /**
     * Get an existing machine of the information system with its name or ip address
     *
     * @param str the name or ip address of the machine
     * @return the machine if it exists else null
     * @throws Exception
     */
    public InformationSystemHost existingMachineByNameOrIPAddress(String str) throws Exception {
        if (IPAddress.isAnIPAddress(str))
            return (InformationSystemHost) topology.existingHostByIPAddress(new IPAddress(str));
        else
            return existingMachineByName(str);
    }

    /**
     * Get an existing machine of the information system with a specific user
     *
     * @param username the name of the user
     * @return an existing machine that have the user that can use it.
     */
    public InformationSystemHost existingMachineByUserName(String username) {
        for (int i = 0; i < this.topology.getHosts().size(); i++) {
            InformationSystemHost machine = (InformationSystemHost) this.topology.getHosts().get(i);
            for (String j : machine.getUsers().keySet()) {
                if (machine.getUsers().get(j).getName().equals(username))
                    return machine;
            }
        }
        return null;
    }

    /**
     * Get a machine by its IP address, or create a new one if it does not exist
     *
     * @param ipAddress an IP Address
     * @return The machine in the topology that has this IP Address. If this machine doesn't exists, just add a new one.
     * @throws Exception
     */
    public InformationSystemHost getMachineByIPAddress(IPAddress ipAddress) throws Exception {
        InformationSystemHost existingMachine = (InformationSystemHost) topology.existingHostByIPAddress(ipAddress);
        if (existingMachine != null)
            return existingMachine;
        InformationSystemHost newMachine = new InformationSystemHost(ipAddress.getAddress(), topology);
        newMachine.addInterface("int1", ipAddress.getAddress());
        this.topology.getHosts().add(newMachine);
        return newMachine;
    }

    /**
     * Get the route from a host to the internet
     *
     * @param from the start of the route.
     * @return the route from a host to the internet
     * @throws Exception
     */
    public List<InformationSystemHost> routeToInternetFrom(Host from) throws Exception {
        List<InformationSystemHost> result = new ArrayList<InformationSystemHost>();
        List<Host> hosts = from.getRouteToInternet();
        for (Host host : hosts) {
            result.add((InformationSystemHost) host);
        }
        return result;
    }

    /**
     * Get the route between two hosts
     *
     * @param from the start of the route
     * @param to   the destination host
     * @return the route between two hosts
     * @throws Exception
     */
    public List<InformationSystemHost> routeBetweenHosts(InformationSystemHost from, InformationSystemHost to)
            throws Exception {
        List<InformationSystemHost> result = new ArrayList<InformationSystemHost>();
        List<Host> route = topology.routeBetweenHosts(from, to);
        for (Host aRoute : route) {
            result.add((InformationSystemHost) aRoute);
        }
        return result;
    }

    /**
     * Save the attack graph in an xml file
     *
     * @param filePath the file path where the attack graph will be save
     * @throws Exception
     */
    public void saveToXmlFile(String filePath) throws Exception {
        XMLOutputter output = new XMLOutputter(Format.getPrettyFormat());
        output.output(toDomXMLElement(), new FileOutputStream(filePath));
    }

    /**
     * Get the XML DOM element of this information system
     *
     * @return the dom element corresponding to this topology with the format of the tva report file
     */
    public Element toDomXMLElement() {
        Element root = new Element("topology");

        //machines
        for (int i = 0; i < this.topology.getHosts().size(); i++) {
            InformationSystemHost machine = (InformationSystemHost) this.topology.getHosts().get(i);
            root.addContent(machine.toDomXMLElement());
        }

        return root;
    }

    /**
     * Load a network topology from a dom element
     *
     * @param domElement the dom element of an xml file
     * @throws Exception
     */
    public void loadFromDomElement(Element domElement, Database db) throws Exception {
        if (domElement == null)
            return;
        List<Element> hostsElement = domElement.getChildren("machine");
        for (Element hostElement : hostsElement) {
            InformationSystemHost host = new InformationSystemHost(this.topology);
            host.loadFromDomElement(hostElement, this.topology, db);
            this.topology.getHosts().add(host);
        }
        this.flowMatrix = new FlowMatrix(domElement.getChild("flow-matrix"), this.topology);
    }

    /**
     * Load the topology from an xml file
     *
     * @param XMLFilePath the path to the xml file
     * @throws Exception
     */
    public void loadFromXMLFile(String XMLFilePath, Database db) throws Exception {
        FileInputStream file = new FileInputStream(XMLFilePath);
        SAXBuilder sxb = new SAXBuilder();
        Document document = sxb.build(file);
        Element root = document.getRootElement();

        this.loadFromDomElement(root, db);
    }

    /**
     * Generates the Json object relative to the hosts list
     * @return the Json Object containing the hosts list
     */
    public JSONObject getHostsListJson() {
        //Build the json list of hosts
        JSONObject json = new JSONObject();
        JSONArray hosts_array = new JSONArray();
        for (Host host : this.getTopology().getHosts()) {
            InformationSystemHost informationSystemHost = (InformationSystemHost) host;
            JSONObject host_object = new JSONObject();
            host_object.put("name", informationSystemHost.getName());
            JSONArray security_requirements_array = new JSONArray();
            for (SecurityRequirement securityRequirement : informationSystemHost.getSecurityRequirements()) {
                JSONObject security_requirement = new JSONObject();
                security_requirement.put("name", securityRequirement.getName());
                security_requirement.put("metric", securityRequirement.getMetricPlainText());
                security_requirements_array.put(security_requirement);
            }
            host_object.put("security_requirements", security_requirements_array);
            hosts_array.put(host_object);
        }
        json.put("hosts", hosts_array);
        return json;
    }

    /**
     * Get the network topology
     *
     * @return the topology
     */
    public Topology getTopology() {
        return topology;
    }

    /**
     * Is the attacker located on the internet in addition to {@link #machinesOfAttacker} ?
     */
    public boolean isAttackerLocatedOnInternet() {
        return attackerLocatedOnInternet;
    }

    /**
     * Set the attacker on the internet status
     *
     * @param attackerLocatedOnInternet the new value of attackerLocatedOnInternet
     */
    public void setAttackerLocatedOnInternet(boolean attackerLocatedOnInternet) {
        this.attackerLocatedOnInternet = attackerLocatedOnInternet;
    }

    /**
     * Get the list of machines where the attacker is located (in addition to the internet)
     */
    public List<InformationSystemHost> getMachinesOfAttacker() {
        return machinesOfAttacker;
    }

    /**
     * Set the list of machines of the internet
     *
     * @param machinesOfAttacker new machines of the attacker
     */
    public void setMachinesOfAttacker(List<InformationSystemHost> machinesOfAttacker) {
        this.machinesOfAttacker = machinesOfAttacker;
    }
}