fix: CTF challenge lifecycle status#189
Closed
niklashaug wants to merge 48 commits into
Closed
Conversation
Implements the update mechanism described in issue #3: - Python daemon polling http://update.cybics:8080 for firmware updates - MAC verification using MD5(secret || firmware) - vulnerable to Length Extension Attack - Flash via OpenOCD telnet (port 4444) - Docker container with entrypoint that generates a 16-byte MAC key on first run - CTF setup helper (generate_mac.py) - Integration into both software/docker-compose.yaml and .devcontainer/virtual/docker-compose.yml Co-authored-by: zierh <48314848+zierh@users.noreply.github.com> Agent-Logs-Url: https://github.com/niklashaug/CybICS/sessions/cfab9622-f941-46ac-b589-03acc5207742
Tests cover: - MAC verification (valid/invalid MAC, modified firmware, wrong secret) - Pure-Python MD5 Length Extension Attack proof (forges valid MAC without the secret) - save_firmware function - flash_via_openocd with mock OpenOCD TCP server - poll_for_update: happy path, 404, bad MAC, unreachable server - Docker image build, entrypoint key generation, generate_mac.py script Co-authored-by: zierh <48314848+zierh@users.noreply.github.com> Agent-Logs-Url: https://github.com/niklashaug/CybICS/sessions/ce8276a7-c2c6-45a1-a7f0-ca5e43cffd92
…ded.sh) - Add flash_firmware.sh: pipes OpenOCD program command via nc to the running OpenOCD telnet server, following the same shell-script pattern as flash_if_needed.sh in the stm32 container - Update Dockerfile to install netcat-openbsd and copy flash_firmware.sh - Replace raw Python socket/telnet code in update_daemon.py with a subprocess call to flash_firmware.sh - Add _SCRIPT_TIMEOUT_BUFFER constant for clarity; all 16 tests still pass Co-authored-by: zierh <48314848+zierh@users.noreply.github.com> Agent-Logs-Url: https://github.com/niklashaug/CybICS/sessions/136a9380-5004-431e-8cf2-252dc04cc859
Co-authored-by: zierh <48314848+zierh@users.noreply.github.com> Agent-Logs-Url: https://github.com/niklashaug/CybICS/sessions/719a51a4-17a1-43a7-b01a-33151f6d8506
…h_if_needed.sh)" This reverts commit 4b49cb3.
…into 7-router-virtualsiert
…into 7-router-virtualsiert
7 router virtualsiert
# Conflicts: # software/landing/templates/challenge.html
add draft for CTF challenge
the /home/docker/zephyrproject/app/ directory was owned by root, which stopped the docker user from building or rather creating the build directory and finishing 'west build'.
the url path '../OpenPLC_v3' could not be resolved on any other dev machine.
Contributor
Author
|
Sorry, this was a mistake and this PR should have landed in our fork repo. |
| firmware = f.read() | ||
| with open(key_path, "rb") as f: | ||
| secret = f.read() | ||
| return hashlib.md5(secret + firmware).hexdigest() |
| Intentionally vulnerable to Length Extension Attack because MD5 uses | ||
| the Merkle-Damgård construction. | ||
| """ | ||
| expected = hashlib.md5(secret + firmware).hexdigest() |
| def challenge_status(challenge_id): | ||
| """Get lifecycle status for a challenge""" | ||
| result, status_code = lifecycle_manager.get_status(challenge_id) | ||
| return jsonify(result), status_code |
| def start_challenge_environment(challenge_id): | ||
| """Start lifecycle resources for a challenge""" | ||
| result, status_code = lifecycle_manager.start_challenge(challenge_id) | ||
| return jsonify(result), status_code |
| def stop_challenge_environment(challenge_id): | ||
| """Stop lifecycle resources for a challenge""" | ||
| result, status_code = lifecycle_manager.stop_challenge(challenge_id) | ||
| return jsonify(result), status_code |
| def challenge_status(challenge_id): | ||
| """Get lifecycle status for a challenge""" | ||
| result, status_code = lifecycle_manager.get_status(challenge_id) | ||
| return jsonify(result), status_code |
| def start_challenge_environment(challenge_id): | ||
| """Start lifecycle resources for a challenge""" | ||
| result, status_code = lifecycle_manager.start_challenge(challenge_id) | ||
| return jsonify(result), status_code |
| def start_challenge_environment(challenge_id): | ||
| """Start lifecycle resources for a challenge""" | ||
| result, status_code = lifecycle_manager.start_challenge(challenge_id) | ||
| return jsonify(result), status_code |
| def stop_challenge_environment(challenge_id): | ||
| """Stop lifecycle resources for a challenge""" | ||
| result, status_code = lifecycle_manager.stop_challenge(challenge_id) | ||
| return jsonify(result), status_code |
| def stop_challenge_environment(challenge_id): | ||
| """Stop lifecycle resources for a challenge""" | ||
| result, status_code = lifecycle_manager.stop_challenge(challenge_id) | ||
| return jsonify(result), status_code |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes the lifecycle status so it automatically shows "Starting", "Started" and "Stopped" status in the UI.