{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Quick Start" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

BooLEVARD Tutorials

\n", "
\n", " [Tutorial 1] Quick Start: Finding vulnerabilities in a Cybersecurity model\n", "
\n", "

\n", " In this tutorial, we will explore a small Boolean model designed to simulate different cybersecurity scenarios. The model consists of nodes representing key components of a cybersecurity system, and the goal of this tutorial is to evaluate how different conditions and guidelines affect the overall security state of the system.\n", "

\n", "

\n", " The model includes the following nodes:

\n", "

\n", "\n", "

" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/home/marco/.local/lib/python3.11/site-packages/pandas/core/arrays/masked.py:60: UserWarning: Pandas requires version '1.3.6' or newer of 'bottleneck' (version '1.3.5' currently installed).\n", " from pandas.core import (\n" ] }, { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import boolevard as blv\n", "import pandas as pd\n", "from boolevard import CountPaths" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "model = blv.Load(\"resources/security.bnet\") # Load the model (BoolNet format)\n", "check = [\"Security_State\"] # Set node(s) to check" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
0321674581512119141310DNFNDNF
User_Education0000000011111111User_Education~User_Education
Security_Policies0000111100001111Security_Policies~Security_Policies
Security_Patches0011001100110011Security_Patches~Security_Patches
Network_Monitoring0101010101010101Network_Monitoring~Network_Monitoring
Backups0000011100001111And(~Malware, Security_Policies)Or(Malware, ~Security_Policies)
Malware1000100000000000And(~Antivirus, Exploits, ~Firewall, ~Strong_P...Or(Antivirus, ~Exploits, Firewall, Strong_Pass...
Security_State0000011100001111And(Backups, ~Unauthorized_Access)Or(~Backups, Unauthorized_Access)
Firewall0111011101110111Or(Network_Monitoring, Security_Patches)And(~Network_Monitoring, ~Security_Patches)
Unauthorized_Access1000000000000000Or(And(~Firewall, Malware, ~Strong_Password, ~...Or(Firewall, Strong_Password, TwoFactAut, And(...
Exploits1111111100000000Or(~Strong_Password, ~TwoFactAut)And(Strong_Password, TwoFactAut)
Antivirus0011001111111111Or(Security_Patches, User_Education)And(~Security_Patches, ~User_Education)
Strong_Password0000000011111111User_Education~User_Education
TwoFactAut0000111111111111Or(Security_Policies, Strong_Password, User_Ed...And(~Security_Policies, ~Strong_Password, ~Use...
Phishing_Attack1111111100000000Or(~TwoFactAut, ~User_Education)And(TwoFactAut, User_Education)
\n", "
" ], "text/plain": [ " 0 3 2 1 6 7 4 5 8 15 12 11 9 14 13 10 \\\n", "User_Education 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 \n", "Security_Policies 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 \n", "Security_Patches 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 \n", "Network_Monitoring 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 \n", "Backups 0 0 0 0 0 1 1 1 0 0 0 0 1 1 1 1 \n", "Malware 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 \n", "Security_State 0 0 0 0 0 1 1 1 0 0 0 0 1 1 1 1 \n", "Firewall 0 1 1 1 0 1 1 1 0 1 1 1 0 1 1 1 \n", "Unauthorized_Access 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \n", "Exploits 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 \n", "Antivirus 0 0 1 1 0 0 1 1 1 1 1 1 1 1 1 1 \n", "Strong_Password 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 \n", "TwoFactAut 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 \n", "Phishing_Attack 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 \n", "\n", " DNF \\\n", "User_Education User_Education \n", "Security_Policies Security_Policies \n", "Security_Patches Security_Patches \n", "Network_Monitoring Network_Monitoring \n", "Backups And(~Malware, Security_Policies) \n", "Malware And(~Antivirus, Exploits, ~Firewall, ~Strong_P... \n", "Security_State And(Backups, ~Unauthorized_Access) \n", "Firewall Or(Network_Monitoring, Security_Patches) \n", "Unauthorized_Access Or(And(~Firewall, Malware, ~Strong_Password, ~... \n", "Exploits Or(~Strong_Password, ~TwoFactAut) \n", "Antivirus Or(Security_Patches, User_Education) \n", "Strong_Password User_Education \n", "TwoFactAut Or(Security_Policies, Strong_Password, User_Ed... \n", "Phishing_Attack Or(~TwoFactAut, ~User_Education) \n", "\n", " NDNF \n", "User_Education ~User_Education \n", "Security_Policies ~Security_Policies \n", "Security_Patches ~Security_Patches \n", "Network_Monitoring ~Network_Monitoring \n", "Backups Or(Malware, ~Security_Policies) \n", "Malware Or(Antivirus, ~Exploits, Firewall, Strong_Pass... \n", "Security_State Or(~Backups, Unauthorized_Access) \n", "Firewall And(~Network_Monitoring, ~Security_Patches) \n", "Unauthorized_Access Or(Firewall, Strong_Password, TwoFactAut, And(... \n", "Exploits And(Strong_Password, TwoFactAut) \n", "Antivirus And(~Security_Patches, ~User_Education) \n", "Strong_Password ~User_Education \n", "TwoFactAut And(~Security_Policies, ~Strong_Password, ~Use... \n", "Phishing_Attack And(TwoFactAut, User_Education) " ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "model.Info" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

\n", "A total of 16 stable states are reached upon different input combinations. We will check the how secure our system is based on the number of paths leading to the activation or inactivation of the Security_State node.\n", "

\n" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Evaluating Stable State: 0\n", "Security_State: -35, 4.168351491292318e-06 minutes.\n", "Evaluating Stable State: 3\n", "Security_State: -1, 8.424123128255208e-07 minutes.\n", "Evaluating Stable State: 2\n", "Security_State: -1, 8.821487426757813e-07 minutes.\n", "Evaluating Stable State: 1\n", "Security_State: -1, 6.914138793945312e-07 minutes.\n", "Evaluating Stable State: 6\n", "Security_State: -6, 2.173582712809245e-06 minutes.\n", "Evaluating Stable State: 7\n", "Security_State: 4, 1.5695889790852864e-06 minutes.\n", "Evaluating Stable State: 4\n", "Security_State: 5, 1.9272168477376303e-06 minutes.\n", "Evaluating Stable State: 5\n", "Security_State: 7, 2.276897430419922e-06 minutes.\n", "Evaluating Stable State: 8\n", "Security_State: -1, 4.569689432779948e-07 minutes.\n", "Evaluating Stable State: 15\n", "Security_State: -1, 8.781750996907552e-07 minutes.\n", "Evaluating Stable State: 12\n", "Security_State: -1, 5.125999450683594e-07 minutes.\n", "Evaluating Stable State: 11\n", "Security_State: -1, 4.172325134277344e-07 minutes.\n", "Evaluating Stable State: 9\n", "Security_State: 21, 3.3338864644368488e-06 minutes.\n", "Evaluating Stable State: 14\n", "Security_State: 24, 2.0265579223632812e-06 minutes.\n", "Evaluating Stable State: 13\n", "Security_State: 26, 2.193450927734375e-06 minutes.\n", "Evaluating Stable State: 10\n", "Security_State: 29, 3.83456548055013e-06 minutes.\n" ] } ], "source": [ "sec_status = model.CountPaths(check, ss_wise = True) # Average signed path counts leading to the local state of Security_State across all the stable states of the model" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
0632181512117459141310
Security_State-35-6-1-1-1-1-1-1-145721242629
\n", "
" ], "text/plain": [ " 0 6 3 2 1 8 15 12 11 7 4 5 9 14 13 10\n", "Security_State -35 -6 -1 -1 -1 -1 -1 -1 -1 4 5 7 21 24 26 29" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Sort the security outcomes in ascending order\n", "security_outcomes = pd.DataFrame(sec_status, columns = [\"Security_State\"], index = model.Info.columns[:-2]).transpose().sort_values(by = \"Security_State\", axis = 1)\n", "security_outcomes" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
0632181512117459141310
User_Education0000011110001111
Security_Policies0100000001111111
Security_Patches0001100110110011
Network_Monitoring0010101011010101
\n", "
" ], "text/plain": [ " 0 6 3 2 1 8 15 12 11 7 4 5 9 14 13 10\n", "User_Education 0 0 0 0 0 1 1 1 1 0 0 0 1 1 1 1\n", "Security_Policies 0 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1\n", "Security_Patches 0 0 0 1 1 0 0 1 1 0 1 1 0 0 1 1\n", "Network_Monitoring 0 0 1 0 1 0 1 0 1 1 0 1 0 1 0 1" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Sort the stable states based on security outcomes and check the input configurations triggering them\n", "inputs = [\"User_Education\", \"Security_Policies\", \"Security_Patches\", \"Network_Monitoring\"]\n", "model.Info.loc[inputs, security_outcomes.columns]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "

\n", "In the table above, we can see that the absence of all inputs simultaneously results in the worst security outcome (SS = 0, Path count = 35). Activating any single input is not sufficient to change the inactive state of Security_States, although it reduces the number of paths leading to inactivation to one, except for Security_Policies, which leads to a slightly improved outcome (SS = 6, Path count = -6).

\n", "Most input combinations result in a positive security state, except for the combination of Security_Patches and Network_Monitoring. The strongest security state occurs when all inputs are active, but the combination of User_Education, Security_Policies, and any additional input is enough to trigger almost the maximum observed secure paths.\n", "

" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "

\n", "Lastly, we will examine how common scenarios impact security, either by reducing the number of activating paths or shifting the system toward insecurity. To do so, we will perturb the model by simulating virus triggers and system bugs affecting the defenders, introducing additive activations or inactivations of specific nodes.\n", "\n", "BooLEVARD allows for two types of perturbations: non-additive, where the perturbation completely overrides the target node’s regulation, and additive, where its regulatory effect is combined with the existing one. We will analyze the effects of these perturbations when all inputs are ON.\n", "

" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Evaluating Stable State: 29\n", "Security_State: 23, 2.5908152262369793e-06 minutes.\n", "Evaluating Stable State: 30\n", "Security_State: -1, 9.258588155110677e-07 minutes.\n", "Evaluating Stable State: 28\n", "Security_State: 21, 3.949801127115885e-06 minutes.\n", "Evaluating Stable State: 23\n", "Security_State: 25, 4.315376281738282e-06 minutes.\n", "Evaluating Stable State: 9\n", "Security_State: 16, 2.3404757181803385e-06 minutes.\n", "Evaluating Stable State: 27\n", "Security_State: 9, 2.642472585042318e-06 minutes.\n", "Evaluating Stable State: 28\n", "Security_State: 16, 2.3484230041503905e-06 minutes.\n" ] }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Unauthorized_Access%ACTTwoFactAut%INHStrong_Password%INHPhishing_Attack%ACTExploits%ACTFirewall%INHAntivirus%INH
Security_State-191616212325
\n", "
" ], "text/plain": [ " Unauthorized_Access%ACT TwoFactAut%INH Strong_Password%INH \\\n", "Security_State -1 9 16 \n", "\n", " Phishing_Attack%ACT Exploits%ACT Firewall%INH Antivirus%INH \n", "Security_State 16 21 23 25 " ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "perturbations = [\"Firewall%INH\", \"Unauthorized_Access%ACT\", \"Exploits%ACT\", \"Antivirus%INH\", \"Strong_Password%INH\", \"TwoFactAut%INH\", \"Phishing_Attack%ACT\"] # Define the perturbations\n", "res = []\n", "for p in perturbations:\n", " pmodel = model.Pert(p, additive = True) # Perturb the model\n", " pmodel.Info = pmodel.Info.loc[:, (pmodel.Info.loc[inputs] == 1).all(axis = 0) | pmodel.Info.columns.str.contains(\"DNF\")] # Retrieve only stable states reached when all inputs are on\n", " \n", " if len(pmodel.Info.columns) <= 2:\n", " res.append(\"NA\")\n", " else:\n", " sec_status = pmodel.CountPaths(check, ss_wise = True)\n", " res.append(sec_status)\n", "\n", "res = [item[0] for item in res]\n", "res = pd.DataFrame(res, index = perturbations, columns = [\"Security_State\"]).transpose().sort_values(by = \"Security_State\", axis = 1) # Store results in a dataframe\n", "res" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "

\n", "We observe that, except for the activation of Unauthorized_Access, all perturbations still allow for security, albeit with varying strengths. In this system, the loss of security strategies is predicted to have a greater impact than losing the antivirus or deactivating the firewall.\n", "

" ] } ], "metadata": { "kernelspec": { "display_name": "usr", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.2" } }, "nbformat": 4, "nbformat_minor": 2 }