mirror of
https://github.com/cliffe/BreakEscape.git
synced 2026-02-20 13:50:46 +00:00
Enhance game setup for VM and standalone modes
- Updated `GamesController` to use `current_player` for VM set retrieval. - Improved `MissionsController` to handle redirection for both Hacktivity and standalone modes. - Modified `new.html.erb` to include UI for standalone flag input alongside VM set selection. - Added new CSS styles for standalone mode instructions and flags input form. - Introduced new mission configuration for the SecGen VM Lab, integrating VM and flag capture elements.
This commit is contained in:
@@ -11,7 +11,7 @@ module BreakEscape
|
||||
authorize @mission, :create_game? if defined?(Pundit)
|
||||
|
||||
if @mission.requires_vms?
|
||||
@available_vm_sets = @mission.valid_vm_sets_for_user(current_user)
|
||||
@available_vm_sets = @mission.valid_vm_sets_for_user(current_player)
|
||||
@existing_games = Game.where(player: current_player, mission: @mission)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -20,10 +20,11 @@ module BreakEscape
|
||||
@mission = Mission.find(params[:id])
|
||||
authorize @mission if defined?(Pundit)
|
||||
|
||||
if @mission.requires_vms? && BreakEscape::Mission.hacktivity_mode?
|
||||
# VM missions need explicit game creation with VM set selection
|
||||
# Redirect to games#new which shows VM set selection UI
|
||||
# Use explicit path instead of route helper to ensure it works in engine context
|
||||
if @mission.requires_vms?
|
||||
# VM missions (Hacktivity or standalone) need explicit setup
|
||||
# Redirect to games#new which shows appropriate UI:
|
||||
# - Hacktivity mode: VM set selection
|
||||
# - Standalone mode: Flag input form
|
||||
redirect_to "/break_escape/games/new?mission_id=#{@mission.id}"
|
||||
else
|
||||
# Legacy behavior for non-VM missions - auto-create game
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<%# Game Setup / VM Set Selection Page %>
|
||||
<%# Game Setup / VM Set Selection or Standalone Flags Page %>
|
||||
<div class="game-setup container">
|
||||
<div class="game-setup-header">
|
||||
<h1><%= @mission.display_name %></h1>
|
||||
@@ -6,10 +6,12 @@
|
||||
</div>
|
||||
|
||||
<% if @mission.requires_vms? %>
|
||||
<div class="vm-selection">
|
||||
<h2>Select VM Environment</h2>
|
||||
|
||||
<% if @available_vm_sets.any? %>
|
||||
<% if BreakEscape::Mission.hacktivity_mode? %>
|
||||
<%# Hacktivity Mode: VM Set Selection %>
|
||||
<div class="vm-selection">
|
||||
<h2>Select VM Environment</h2>
|
||||
|
||||
<% if @available_vm_sets.any? %>
|
||||
<div class="vm-set-list">
|
||||
<% @available_vm_sets.each do |vm_set| %>
|
||||
<%= form_with url: break_escape.games_path, method: :post, local: true, class: 'vm-set-form' do |f| %>
|
||||
@@ -48,9 +50,8 @@
|
||||
<h3>Continue Existing Game</h3>
|
||||
<div class="existing-games-list">
|
||||
<% @existing_games.each do |game| %>
|
||||
<%= link_to game_path(game), class: "btn btn-secondary existing-game-btn" do %>
|
||||
<%= link_to "/break_escape/games/#{game.id}", class: "btn btn-secondary existing-game-btn" do %>
|
||||
Continue game started <%= time_ago_in_words(game.started_at) %> ago
|
||||
<span class="game-status badge"><%= game.status %></span>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
@@ -65,7 +66,43 @@
|
||||
<%= link_to "← Back to Missions", missions_path, class: "btn btn-secondary" %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<% else %>
|
||||
<%# Standalone Mode: Flags Input Form %>
|
||||
<div class="standalone-flags">
|
||||
<h2>Configure Test Flags</h2>
|
||||
<p class="flags-help">Enter the flags you expect to find in this scenario (comma-separated). These will be validated when you submit them at the flag station during gameplay.</p>
|
||||
|
||||
<%= form_with url: break_escape.games_path, method: :post, local: true, class: 'flags-form' do |f| %>
|
||||
<%= f.hidden_field :mission_id, value: @mission.id %>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="standalone_flags">Expected Flags:</label>
|
||||
<%= f.text_area :standalone_flags,
|
||||
id: 'standalone_flags',
|
||||
placeholder: "flag{example1}, flag{example2}, flag{example3}",
|
||||
rows: 8,
|
||||
class: 'flags-textarea' %>
|
||||
<p class="form-hint">Format: <code>flag{...}</code>, separated by commas</p>
|
||||
</div>
|
||||
|
||||
<div class="flags-info">
|
||||
<p><strong>💡 How it works:</strong></p>
|
||||
<ul>
|
||||
<li>Enter the flags you plan to capture in this scenario</li>
|
||||
<li>During the game, navigate to the Flag Station</li>
|
||||
<li>Submit your captured flags to verify them</li>
|
||||
<li>Receive rewards for correct flags</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<%= f.submit "Start Mission", class: "btn btn-primary btn-large" %>
|
||||
<% end %>
|
||||
|
||||
<%= link_to "← Back to Missions", missions_path, class: "btn btn-secondary" %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% else %>
|
||||
<%# Non-VM mission - just start %>
|
||||
@@ -108,6 +145,88 @@
|
||||
padding-bottom: 10px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.standalone-flags h2 {
|
||||
color: #00ff00;
|
||||
border-bottom: 2px solid #00ff00;
|
||||
padding-bottom: 10px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.flags-help {
|
||||
color: #cccccc;
|
||||
font-family: 'VT323', monospace;
|
||||
font-size: 14px;
|
||||
margin-bottom: 20px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.form-group label {
|
||||
display: block;
|
||||
color: #00ff00;
|
||||
margin-bottom: 10px;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.flags-textarea {
|
||||
width: 100%;
|
||||
background: #000;
|
||||
border: 2px solid #00ff00;
|
||||
color: #00ff00;
|
||||
padding: 12px;
|
||||
font-family: 'Courier New', monospace;
|
||||
font-size: 14px;
|
||||
box-sizing: border-box;
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
.flags-textarea:focus {
|
||||
outline: none;
|
||||
border-color: #00ff00;
|
||||
box-shadow: 0 0 5px rgba(0, 255, 0, 0.5);
|
||||
}
|
||||
|
||||
.form-hint {
|
||||
color: #888;
|
||||
font-size: 12px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.form-hint code {
|
||||
background: #1a1a1a;
|
||||
padding: 2px 6px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.flags-info {
|
||||
background: rgba(0, 255, 0, 0.05);
|
||||
border: 1px solid #00ff00;
|
||||
padding: 15px;
|
||||
margin: 20px 0;
|
||||
color: #cccccc;
|
||||
font-size: 13px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.flags-info p {
|
||||
margin: 0 0 10px 0;
|
||||
color: #00ff00;
|
||||
}
|
||||
|
||||
.flags-info ul {
|
||||
margin: 10px 0 0 20px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.flags-info li {
|
||||
margin: 5px 0;
|
||||
color: #cccccc;
|
||||
}
|
||||
|
||||
.vm-set-list {
|
||||
display: flex;
|
||||
@@ -181,6 +300,7 @@
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
@@ -196,6 +316,8 @@
|
||||
background: #333;
|
||||
color: #00ff00;
|
||||
border-color: #00ff00;
|
||||
width: auto;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
|
||||
@@ -14,7 +14,7 @@ export class FlagStationMinigame extends MinigameScene {
|
||||
this.stationName = params.stationName || 'Flag Submission Terminal';
|
||||
this.expectedFlags = params.flags || [];
|
||||
this.submittedFlags = params.submittedFlags || window.gameState?.submittedFlags || [];
|
||||
this.gameId = params.gameId || window.gameConfig?.gameId;
|
||||
this.gameId = params.gameId || window.breakEscapeConfig?.gameId || window.gameConfig?.gameId;
|
||||
this.isSubmitting = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -205,6 +205,28 @@ export class VmLauncherMinigame extends MinigameScene {
|
||||
color: #ffaa00;
|
||||
}
|
||||
|
||||
.vm-names {
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
justify-content: center;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.vm-name-badge {
|
||||
background: #00aa00;
|
||||
color: #000;
|
||||
padding: 12px 24px;
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
border: 2px solid #000;
|
||||
font-family: 'Courier New', monospace;
|
||||
}
|
||||
|
||||
.standalone-instructions h3 {
|
||||
color: #00ff00;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.standalone-instructions ol {
|
||||
margin: 0;
|
||||
padding-left: 20px;
|
||||
@@ -242,9 +264,9 @@ export class VmLauncherMinigame extends MinigameScene {
|
||||
`;
|
||||
} else {
|
||||
return `
|
||||
<div class="no-vms-message">
|
||||
<h4>Standalone Mode</h4>
|
||||
<p>VMs are not available in standalone mode.</p>
|
||||
<div class="no-vms-message standalone-mode">
|
||||
<h2>VM Terminal</h2>
|
||||
<p>You've discovered a computer terminal in the game. To interact with it, you need to launch the virtual machines on your local system.</p>
|
||||
${this.buildStandaloneInstructions()}
|
||||
</div>
|
||||
`;
|
||||
@@ -300,13 +322,17 @@ export class VmLauncherMinigame extends MinigameScene {
|
||||
buildStandaloneInstructions() {
|
||||
return `
|
||||
<div class="standalone-instructions">
|
||||
<h4>VirtualBox Instructions</h4>
|
||||
<h3>Load These VMs in VirtualBox:</h3>
|
||||
<div class="vm-names">
|
||||
<div class="vm-name-badge">kali</div>
|
||||
<div class="vm-name-badge">desktop</div>
|
||||
</div>
|
||||
<ol>
|
||||
<li>Open <code>VirtualBox</code> on your local machine</li>
|
||||
<li>Import the mission VM file (.ova)</li>
|
||||
<li>Start the VM and wait for it to boot</li>
|
||||
<li>Note the VM's IP address (shown on login screen)</li>
|
||||
<li>Return to this game and complete objectives</li>
|
||||
<li>Open VirtualBox on your local machine</li>
|
||||
<li>Import the <strong>kali</strong> and <strong>desktop</strong> VMs (.ova files)</li>
|
||||
<li>Start both VMs and wait for them to boot</li>
|
||||
<li>Note their IP addresses</li>
|
||||
<li>Return to this game to complete the mission</li>
|
||||
</ol>
|
||||
</div>
|
||||
`;
|
||||
|
||||
20
scenarios/secgen_vm_lab/mission.json
Normal file
20
scenarios/secgen_vm_lab/mission.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"display_name": "SecGen VM Lab - Linux Introduction",
|
||||
"description": "This mission demonstrates VM integration with BreakEscape. Launch the provided VMs (desktop and kali) and capture flags from the SecGen environment. Learn basic Linux attack techniques in a controlled lab setting.",
|
||||
"difficulty_level": 2,
|
||||
"secgen_scenario": "labs/introducing_attacks/1_intro_linux.xml",
|
||||
"collection": "vm_labs",
|
||||
"cybok": [
|
||||
{
|
||||
"ka": "SS",
|
||||
"topic": "System Security",
|
||||
"keywords": ["Virtual machines", "Linux security", "Attack vectors"]
|
||||
},
|
||||
{
|
||||
"ka": "F",
|
||||
"topic": "Forensics",
|
||||
"keywords": ["Evidence collection", "Log analysis"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
109
scenarios/secgen_vm_lab/scenario.json.erb
Normal file
109
scenarios/secgen_vm_lab/scenario.json.erb
Normal file
@@ -0,0 +1,109 @@
|
||||
{
|
||||
"scenario_brief": "Welcome to the SecGen VM Lab! This environment is designed to teach you about Linux security and attack techniques. You have access to two VMs:\n\n• **kali** - Attacker machine with penetration testing tools\n• **desktop** - Target system running vulnerable services\n\nYour mission is to launch these VMs, exploit vulnerabilities, and capture flags demonstrating your understanding of the attack vectors.",
|
||||
"endGoal": "Successfully launch the 'kali' and 'desktop' VMs, perform attacks, and capture all available flags to complete the lab.",
|
||||
"startRoom": "lab_entrance",
|
||||
"startItemsInInventory": [],
|
||||
"rooms": {
|
||||
"lab_entrance": {
|
||||
"type": "room_reception",
|
||||
"connections": {
|
||||
"north": "lab_workstation"
|
||||
},
|
||||
"locked": false,
|
||||
"objects": [
|
||||
{
|
||||
"type": "notes",
|
||||
"name": "Lab Welcome Guide",
|
||||
"takeable": true,
|
||||
"readable": true,
|
||||
"text": "Welcome to the SecGen Linux Introduction Lab!\n\nSTART HERE:\n1. Interact with the VM LAUNCHER TERMINAL\n2. Select and launch the 'kali' VM first\n3. Then launch the 'desktop' VM\n\nWhat each VM does:\n • kali - Your attack platform (Kali Linux with hacking tools)\n • desktop - The target system (vulnerable Linux services)\n\nOnce running:\n1. Connect to the desktop VM from kali\n2. Find and exploit vulnerabilities\n3. Capture flags along the way\n4. Submit flags at the FLAG STATION TERMINAL\n\nEach flag you submit will unlock rewards and progression.\n\nGood luck, and learn responsibly!",
|
||||
"observations": "A comprehensive guide to the lab environment"
|
||||
},
|
||||
{
|
||||
"type": "notes",
|
||||
"name": "Lab Rules",
|
||||
"takeable": true,
|
||||
"readable": true,
|
||||
"text": "Lab Rules & Information:\n\n- VMs are automatically destroyed after 1 hour of inactivity\n- Screenshots and evidence capture recommended\n- All traffic is logged for learning purposes\n- Contact lab administrator if VMs fail to start\n- Estimated time: 30-45 minutes\n- Difficulty: Beginner to Intermediate",
|
||||
"observations": "Important lab operational information"
|
||||
}
|
||||
]
|
||||
},
|
||||
"lab_workstation": {
|
||||
"type": "room_office",
|
||||
"connections": {
|
||||
"south": "lab_entrance",
|
||||
"east": "flag_room"
|
||||
},
|
||||
"locked": false,
|
||||
"objects": [
|
||||
{
|
||||
"type": "vm-launcher",
|
||||
"id": "vm_launcher_1",
|
||||
"name": "Kali Console Terminal",
|
||||
"takeable": false,
|
||||
"observations": "A terminal interface for accessing the Kali Linux VM. Ready to launch.",
|
||||
"hacktivityMode": <%= vm_context && vm_context['hacktivity_mode'] ? 'true' : 'false' %>,
|
||||
"vms": <%= vm_context && vm_context['vms'] ? vm_context['vms'].to_json : '[{"id":1,"title":"kali","ip":"192.168.1.10","enable_console":true}]' %>
|
||||
},
|
||||
{
|
||||
"type": "vm-launcher",
|
||||
"id": "vm_launcher_2",
|
||||
"name": "Desktop Lab Terminal",
|
||||
"takeable": false,
|
||||
"observations": "A terminal interface for accessing the Desktop Linux VM. Ready to launch.",
|
||||
"hacktivityMode": <%= vm_context && vm_context['hacktivity_mode'] ? 'true' : 'false' %>,
|
||||
"vms": <%= vm_context && vm_context['vms'] ? vm_context['vms'].to_json : '[{"id":2,"title":"desktop","ip":"192.168.1.20","enable_console":true}]' %>
|
||||
},
|
||||
{
|
||||
"type": "notes",
|
||||
"name": "Attack Hints",
|
||||
"takeable": true,
|
||||
"readable": true,
|
||||
"text": "Attack Strategy for kali → desktop:\n\n1. FROM KALI - Reconnaissance:\n - Use 'nmap' on desktop to scan open ports\n - Example: nmap -sV <desktop-ip>\n - Identify running services and versions\n - Research known vulnerabilities\n\n2. FROM KALI - Exploitation:\n - Look for weak credentials on desktop\n - Try common default passwords\n - Use Metasploit or manual exploitation\n - Escalate privileges if needed\n\n3. ON DESKTOP - Flag Capture:\n - Flags typically located in:\n /flag.txt (root flag)\n /home/*/flag.txt (user flags)\n /etc/shadow or /etc/passwd\n Database files (/var/lib/mysql/)\n\n4. Submit Flags:\n - Return to this game\n - Find the FLAG STATION TERMINAL\n - Enter captured flags (format: flag{...})\n - Receive points and unlock rewards",
|
||||
"observations": "Strategic guidance for completing the lab objectives"
|
||||
}
|
||||
]
|
||||
},
|
||||
"flag_room": {
|
||||
"type": "room_office",
|
||||
"connections": {
|
||||
"west": "lab_workstation"
|
||||
},
|
||||
"locked": false,
|
||||
"objects": [
|
||||
{
|
||||
"type": "flag-station",
|
||||
"id": "flag_station_1",
|
||||
"name": "Flag Submission Terminal",
|
||||
"takeable": false,
|
||||
"observations": "A secure terminal for submitting captured flags. All submissions are verified against the lab database.",
|
||||
"flags": <%= vm_context && vm_context['flags'] ? vm_context['flags'].map { |f| f['value'] }.to_json : '[]' %>,
|
||||
"flagRewards": {
|
||||
"default_reward": {
|
||||
"type": "emit_event",
|
||||
"event_name": "flag_captured"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "notes",
|
||||
"name": "Flag Format",
|
||||
"takeable": true,
|
||||
"readable": true,
|
||||
"text": "Flag Format Information:\n\nFlags in this lab follow the standard CTF format:\n flag{...}\n\nCommon flag locations:\n - /flag.txt\n - /root/flag.txt\n - /home/user/flag.txt\n - Environment variables\n - Application data\n\nWhen submitting:\n1. Enter the complete flag text (including 'flag{}' wrapper)\n2. Click SUBMIT\n3. Wait for verification\n4. Receive confirmation and rewards\n\nYou may submit multiple flags.\nAlready-submitted flags cannot be re-submitted.",
|
||||
"observations": "Guide on flag capture and submission"
|
||||
},
|
||||
{
|
||||
"type": "notes",
|
||||
"name": "Progress Tracker",
|
||||
"takeable": true,
|
||||
"readable": true,
|
||||
"text": "Lab Progress Tracking:\n\nTotal Flags Available: Multiple (see Flag Station for exact count)\n\nObjectives:\n□ Launch Kali VM\n□ Launch Desktop VM\n□ Complete reconnaissance\n□ Identify vulnerabilities\n□ Perform exploitation\n□ Capture flags\n□ Submit all flags\n\nEstimated Points:\n- Each flag: 10-50 points (varies by difficulty)\n- Lab completion bonus: 25 points\n- Documentation bonus: 10 points\n\nYour progress is auto-saved with each flag submission.",
|
||||
"observations": "Real-time progress tracking for lab completion"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
11
test/fixtures/break_escape_missions.yml
vendored
11
test/fixtures/break_escape_missions.yml
vendored
@@ -15,3 +15,14 @@ unpublished:
|
||||
difficulty_level: 1
|
||||
created_at: <%= Time.now %>
|
||||
updated_at: <%= Time.now %>
|
||||
|
||||
secgen_vm_lab:
|
||||
name: secgen_vm_lab
|
||||
display_name: SecGen VM Lab - Linux Introduction
|
||||
description: Test VM and flag integration with SecGen scenario
|
||||
published: true
|
||||
difficulty_level: 2
|
||||
secgen_scenario: labs/introducing_attacks/1_intro_linux.xml
|
||||
collection: vm_labs
|
||||
created_at: <%= Time.now %>
|
||||
updated_at: <%= Time.now %>
|
||||
|
||||
Reference in New Issue
Block a user