#3110 UC2 Notebook changes:
- YAML obs nest dict updated - `friendly_output_red_action` updated - `NMNE` section moved into the same timestep that the attack takes place. - General OBS print is neater and less bloated - ACL's code snippets assumed that ACL's indexed at 1 (as they did previously). However, this is no longer the case. (Updated config to reflect this) - Remove un-necessary env.reset(). (We already reset at the start of the notebook - users can just run-run the notebook)
This commit is contained in:
@@ -404,7 +404,7 @@ agents:
|
||||
action: "router-acl-add-rule"
|
||||
options:
|
||||
target_router: router_1
|
||||
position: 1
|
||||
position: 0
|
||||
permission: DENY
|
||||
src_ip: 192.168.10.21 # client 1
|
||||
dst_ip: ALL # ALL
|
||||
@@ -417,7 +417,7 @@ agents:
|
||||
action: "router-acl-add-rule"
|
||||
options:
|
||||
target_router: router_1
|
||||
position: 2
|
||||
position: 1
|
||||
permission: DENY
|
||||
src_ip: 192.168.10.22 # client 2
|
||||
dst_ip: ALL # ALL
|
||||
@@ -430,7 +430,7 @@ agents:
|
||||
action: "router-acl-add-rule"
|
||||
options:
|
||||
target_router: router_1
|
||||
position: 3
|
||||
position: 2
|
||||
permission: DENY
|
||||
src_ip: 192.168.10.21 # client 1
|
||||
dst_ip: 192.168.1.12 # web server
|
||||
@@ -443,7 +443,7 @@ agents:
|
||||
action: "router-acl-add-rule"
|
||||
options:
|
||||
target_router: router_1
|
||||
position: 4
|
||||
position: 3
|
||||
permission: DENY
|
||||
src_ip: 192.168.10.22 # client 2
|
||||
dst_ip: 192.168.1.12 # web server
|
||||
@@ -456,7 +456,7 @@ agents:
|
||||
action: "router-acl-add-rule"
|
||||
options:
|
||||
target_router: router_1
|
||||
position: 5
|
||||
position: 4
|
||||
permission: DENY
|
||||
src_ip: 192.168.10.21 # client 1
|
||||
dst_ip: 192.168.1.14 # database
|
||||
@@ -469,7 +469,7 @@ agents:
|
||||
action: "router-acl-add-rule"
|
||||
options:
|
||||
target_router: router_1
|
||||
position: 6
|
||||
position: 5
|
||||
permission: DENY
|
||||
src_ip: 192.168.10.22 # client 2
|
||||
dst_ip: 192.168.1.14 # database
|
||||
|
||||
@@ -121,32 +121,37 @@
|
||||
"## Observation Space\n",
|
||||
"\n",
|
||||
"The blue agent's observation space is structured as nested dictionary with the following information:\n",
|
||||
"```\n",
|
||||
"``` yaml\n",
|
||||
"\n",
|
||||
"- ICS\n",
|
||||
"- LINKS\n",
|
||||
" - <link_id>\n",
|
||||
" - PROTOCOLS\n",
|
||||
" - <protocol>\n",
|
||||
" - load\n",
|
||||
"- NODES\n",
|
||||
" - <node_id 1-7>\n",
|
||||
" - <node_id>\n",
|
||||
" - SERVICES\n",
|
||||
" - <service_id 1-1>\n",
|
||||
" - <service_id>\n",
|
||||
" - operating_status\n",
|
||||
" - health_status\n",
|
||||
" - FOLDERS\n",
|
||||
" - <folder_id 1-1>\n",
|
||||
" - <folder_id>\n",
|
||||
" - health_status\n",
|
||||
" - FILES\n",
|
||||
" - <file_id 1-1>\n",
|
||||
" - <file_id>\n",
|
||||
" - health_status\n",
|
||||
" - NETWORK_INTERFACES\n",
|
||||
" - <nic_id 1-2>\n",
|
||||
" - <nic_id>\n",
|
||||
" - nic_status\n",
|
||||
" - nmne\n",
|
||||
" - inbound\n",
|
||||
" - outbound\n",
|
||||
" - operating_status\n",
|
||||
"- LINKS\n",
|
||||
" - <link_id 1-10>\n",
|
||||
" - PROTOCOLS\n",
|
||||
" - ALL\n",
|
||||
" - load\n",
|
||||
" - users \n",
|
||||
" - local_login\n",
|
||||
" - remote_sessions\n",
|
||||
" - <router_id>\n",
|
||||
" - ACL\n",
|
||||
" - <rule_number 1-10>\n",
|
||||
" - position\n",
|
||||
@@ -156,7 +161,10 @@
|
||||
" - dest_node_id\n",
|
||||
" - dest_port\n",
|
||||
" - protocol\n",
|
||||
"- ICS\n",
|
||||
" - users \n",
|
||||
" - local_login\n",
|
||||
" - remote_session\n",
|
||||
"\n",
|
||||
"```\n",
|
||||
"\n",
|
||||
"### Mappings\n",
|
||||
@@ -447,13 +455,20 @@
|
||||
" red_info : AgentHistoryItem = info['agent_actions']['data_manipulation_attacker']\n",
|
||||
" red_action = red_info.action\n",
|
||||
" if red_action == 'do-nothing':\n",
|
||||
" red_str = 'DO NOTHING'\n",
|
||||
" red_str = \"do-nothing\"\n",
|
||||
" elif red_action == 'node-application-execute':\n",
|
||||
" client = \"client 1\" if red_info.parameters['node_name'] == 0 else \"client 2\"\n",
|
||||
" client = \"client 1\" if red_info.parameters['node_name'] == \"client_1\" else \"client_2\"\n",
|
||||
" red_str = f\"ATTACK from {client}\"\n",
|
||||
" return red_str"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Also, the NMNE outbound of either client 1 (node 5) or client 2 (node 6) has increased from 0 to 1. This tells us which client is being used by the red agent."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
@@ -462,7 +477,25 @@
|
||||
"source": [
|
||||
"for step in range(35):\n",
|
||||
" obs, reward, terminated, truncated, info = env.step(0)\n",
|
||||
" print(f\"step: {env.game.step_counter}, Red action: {friendly_output_red_action(info)}, Blue reward:{reward:.2f}\" )"
|
||||
" red_info : AgentHistoryItem = info['agent_actions']['data_manipulation_attacker']\n",
|
||||
" red_action = red_info.action\n",
|
||||
" if red_action == 'do-nothing':\n",
|
||||
" pass\n",
|
||||
" else:\n",
|
||||
" # Immediate drop in reward from the red agent attack.\n",
|
||||
" print(f\"step: {env.game.step_counter}, Red action: {friendly_output_red_action(info)}, Blue reward: {reward:.2f}\" )\n",
|
||||
" print(f\"step: {env.game.step_counter}, client 1 NMNE: {obs['NODES']['HOST5']['NICS'][1]['NMNE']}\")\n",
|
||||
" print(f\"step: {env.game.step_counter}, client 2 NMNE: {obs['NODES']['HOST6']['NICS'][1]['NMNE']}\")\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Reward drops even further as green agents are unable to access the web-server after the red agent attack\n",
|
||||
"print(f\"step: {env.game.step_counter}, Current (Post Attack) Blue reward: {reward:.2f}\" )"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -472,20 +505,11 @@
|
||||
"Now the reward is -0.8, let's have a look at blue agent's observation."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"pprint(obs['NODES'])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"The true statuses of the database file and webapp are not updated. The blue agent needs to perform a scan to see that they have degraded."
|
||||
"The true statuses of the database file and web-server are not updated. The blue agent needs to perform a scan to see that they have degraded."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -495,26 +519,19 @@
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"obs, reward, terminated, truncated, info = env.step(9) # scan database file\n",
|
||||
"obs, reward, terminated, truncated, info = env.step(1) # scan webapp service\n",
|
||||
"\n",
|
||||
"pprint(obs['NODES'])\n"
|
||||
"print(f\"step: {env.game.step_counter}, database file obs: {obs['NODES']['HOST2']['FOLDERS'][1]['FILES']}\")\n",
|
||||
"obs, reward, terminated, truncated, info = env.step(1) # scan web-server service\n",
|
||||
"print(f\"step: {env.game.step_counter}, webserver status {obs['NODES']['HOST1']['SERVICES'][1]}\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Now service 1 on HOST1 has `health_status = 3`, indicating that the webapp is compromised.\n",
|
||||
"Now service 1 on HOST1 has `health_status = 3`, indicating that the web-server is compromised.\n",
|
||||
"File 1 in folder 1 on HOST2 has `health_status = 2`, indicating that the database file is compromised."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Also, the NMNE outbound of either client 1 (node 6) or client 2 (node 7) has increased from 0 to 1. This tells us which client is being used by the red agent."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
@@ -556,8 +573,8 @@
|
||||
"obs, reward, terminated, truncated, info = env.step(0) # do nothing\n",
|
||||
"print(f\"step: {env.game.step_counter}\")\n",
|
||||
"print(f\"Red action: {info['agent_actions']['data_manipulation_attacker'].action}\" )\n",
|
||||
"print(f\"Green action: {info['agent_actions']['client_2_green_user']}\" )\n",
|
||||
"print(f\"Green action: {info['agent_actions']['client_1_green_user']}\" )\n",
|
||||
"print(f\"Green action: {info['agent_actions']['client_2_green_user'].action}\" )\n",
|
||||
"print(f\"Green action: {info['agent_actions']['client_1_green_user'].action}\" )\n",
|
||||
"print(f\"Blue reward: {reward:.2f}\" )"
|
||||
]
|
||||
},
|
||||
@@ -603,7 +620,7 @@
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Let's also have a look at the ACL observation to verify our new ACL rule at positions 5 and 6."
|
||||
"Let's also have a look at the ACL observation to verify our new ACL rule at positions 4 and 5."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -612,7 +629,8 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"obs['NODES']['ROUTER0']"
|
||||
"pprint(obs['NODES']['ROUTER0']['ACL'][4])\n",
|
||||
"pprint(obs['NODES']['ROUTER0']['ACL'][5])"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -685,36 +703,15 @@
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Reset the environment, you can rerun the other cells to verify that the attack works the same every episode. (except the red agent will move between `client_1` and `client_2`.)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"env.reset()"
|
||||
"You can rerun the notebook to verify that the attack works the same every episode. (except the red agent will move between `client_1` and `client_2`.)"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": ".venv",
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"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.10.12"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
|
||||
@@ -403,7 +403,7 @@ agents:
|
||||
action: "router-acl-add-rule"
|
||||
options:
|
||||
target_router: router_1
|
||||
position: 1
|
||||
position: 0
|
||||
permission: DENY
|
||||
src_ip: 192.168.10.21 # client 1
|
||||
dst_ip: ALL # ALL
|
||||
@@ -416,7 +416,7 @@ agents:
|
||||
action: "router-acl-add-rule"
|
||||
options:
|
||||
target_router: router_1
|
||||
position: 2
|
||||
position: 1
|
||||
permission: DENY
|
||||
src_ip: 192.168.10.22 # client 2
|
||||
dst_ip: ALL # ALL
|
||||
@@ -429,7 +429,7 @@ agents:
|
||||
action: "router-acl-add-rule"
|
||||
options:
|
||||
target_router: router_1
|
||||
position: 3
|
||||
position: 2
|
||||
permission: DENY
|
||||
src_ip: 192.168.10.21 # client 1
|
||||
dst_ip: 192.168.1.12 # web server
|
||||
@@ -442,7 +442,7 @@ agents:
|
||||
action: "router-acl-add-rule"
|
||||
options:
|
||||
target_router: router_1
|
||||
position: 4
|
||||
position: 3
|
||||
permission: DENY
|
||||
src_ip: 192.168.10.22 # client 2
|
||||
dst_ip: 192.168.1.12 # web server
|
||||
@@ -455,7 +455,7 @@ agents:
|
||||
action: "router-acl-add-rule"
|
||||
options:
|
||||
target_router: router_1
|
||||
position: 5
|
||||
position: 4
|
||||
permission: DENY
|
||||
src_ip: 192.168.10.21 # client 1
|
||||
dst_ip: 192.168.1.14 # database
|
||||
@@ -468,7 +468,7 @@ agents:
|
||||
action: "router-acl-add-rule"
|
||||
options:
|
||||
target_router: router_1
|
||||
position: 6
|
||||
position: 5
|
||||
permission: DENY
|
||||
src_ip: 192.168.10.22 # client 2
|
||||
dst_ip: 192.168.1.14 # database
|
||||
|
||||
Reference in New Issue
Block a user