Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .github/skills/ctf-testing/deploy_and_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,29 @@ _copy_test_script() {
_sshpass_cmd scp ${SSH_OPTS} "${TEST_SCRIPT}" "${SSH_USER}@${ip}:/tmp/test_ctf_challenges.sh"
}

# Trigger challenge 10 the way learners do: scp a new file from this machine
# into ~/ctf_challenges. test_ctf_challenges.sh then checks the flag was set.
# Arguments:
# $1 - IP address of the VM
_upload_challenge_10_file() {
local ip="$1"
local upload_file

_log INFO "Uploading challenge 10 test file via scp..."
# Monitor waits for the setup marker plus a delay before inotifywait starts
# shellcheck disable=SC2086
_sshpass_cmd ssh ${SSH_OPTS} "${SSH_USER}@${ip}" \
'for _ in $(seq 1 30); do pgrep -x inotifywait >/dev/null && break; sleep 2; done
: > /tmp/.ctf_upload_triggered; rm -f ~/ctf_challenges/scp_upload_test' || true

upload_file=$(mktemp)
echo "challenge 10 scp upload test" > "${upload_file}"
# shellcheck disable=SC2086
_sshpass_cmd scp ${SSH_OPTS} "${upload_file}" "${SSH_USER}@${ip}:~/ctf_challenges/scp_upload_test" \
|| _log WARN "scp upload for challenge 10 failed"
rm -f "${upload_file}"
}

# Copy test script to VM and execute it
# Arguments:
# $1 - Cloud provider name
Expand All @@ -491,6 +514,7 @@ _run_tests() {
fi

_copy_test_script "${provider}" "${ip}"
_upload_challenge_10_file "${ip}"

_log INFO "Running tests on ${provider} VM (${ip})..."
echo ""
Expand Down
24 changes: 7 additions & 17 deletions .github/skills/ctf-testing/test_ctf_challenges.sh
Original file line number Diff line number Diff line change
Expand Up @@ -408,37 +408,27 @@ else
FLAGS[9]=""
fi

# Challenge 10: File Monitoring
# Hint: "Try creating a file in ctf_challenges"
echo "Challenge 10: File Monitoring"
# Challenge 10: Remote Upload
# Hint: "Run scp from your own computer into ~/ctf_challenges/"
# deploy_and_test.sh uploads a file with scp from the local machine before this
# script runs, so the flag should already be in the trigger file.
echo "Challenge 10: Remote Upload"
if ! systemctl is-active ctf-monitor-directory.service &>/dev/null; then
_fail "Challenge 10: Monitor service not running - SETUP BUG"
FLAGS[10]=""
else
# Wait for inotifywait process to actually be running (service starts but has internal delay)
echo " Waiting for inotifywait to be ready..."
for _ in {1..15}; do
pgrep -f "inotifywait.*ctf_challenges" &>/dev/null && break
sleep 2
done

true > /tmp/.ctf_upload_triggered 2>/dev/null || true
TRIGGER="/home/ctf_user/ctf_challenges/test_$$"
touch "${TRIGGER}"
sleep 3

FLAG_10=""
for _ in {1..10}; do
FLAG_10=$(grep -ao 'CTF{[^}]*}' /tmp/.ctf_upload_triggered 2>/dev/null | head -1) || true
[[ -n "${FLAG_10}" ]] && break
sleep 2
done
rm -f "${TRIGGER}"
rm -f /home/ctf_user/ctf_challenges/scp_upload_test

if [[ -n "${FLAG_10}" ]]; then
_verify_flag 10 "${FLAG_10}" "Solved challenge 10" "Challenge 10: Found flag but verify rejected it - SETUP BUG"
else
_fail "Challenge 10: File monitoring did not trigger - SETUP BUG"
_fail "Challenge 10: scp upload did not trigger the flag - SETUP BUG"
FLAGS[10]=""
fi
fi
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Test your Linux command line skills with 18 progressive Capture The Flag challen
| 7 | The Encoded Secret | Find and decode an encoded flag in `ctf_challenges` | ⭐⭐ | Base64, encoding |
| 8 | SSH Key Authentication | Configure SSH key authentication and find a hidden flag | ⭐⭐ | SSH configuration |
| 9 | DNS Inspection | Inspect the system DNS configuration without changing live resolver files | ⭐⭐ | DNS, `systemd-resolved` |
| 10 | Remote Upload | Transfer any file to `ctf_challenges` to trigger the flag | ⭐⭐ | File transfer, SCP |
| 10 | Remote Upload | From your own computer, upload a new file into `~/ctf_challenges` on the VM to trigger the flag | ⭐⭐ | File transfer, SCP |
| 11 | Web Configuration | The web server is running on a non-standard port. Find and fix it | ⭐⭐ | Nginx, services |
| 12 | Network Traffic Analysis | Someone is sending secret messages via ping packets | ⭐⭐⭐ | Packet inspection, tcpdump |
| 13 | Cron Job Hunter | A scheduled task contains a hidden flag. Find and read it | ⭐⭐ | Cron, scheduling |
Expand Down
13 changes: 12 additions & 1 deletion setup/challenges/ch10_remote_upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,19 @@ def setup(flags: dict[int, str]) -> None:
sleep 10
touch /tmp/.ctf_upload_triggered 2>/dev/null || true
chmod 666 /tmp/.ctf_upload_triggered 2>/dev/null || true
inotifywait -m -e create --format '%f' "$DIRECTORY" | while read FILE
LAST_TRIGGER=0
inotifywait -m -e create --format '%f' "$DIRECTORY" | while read -r FILE
do
# Ignore editor temp files (vim swap/backup/write-test files)
case "$FILE" in
.*.sw? | *~ | 4913) continue ;;
esac
# Show one banner per upload burst (e.g. scp of several files)
NOW=$(date +%s)
if [ $((NOW - LAST_TRIGGER)) -lt 5 ]; then
continue
fi
LAST_TRIGGER=$NOW
{
printf '\\n========== CHALLENGE 10: REMOTE UPLOAD =========='
printf '\\nA new file was uploaded to %s.' "$DIRECTORY"
Expand Down
2 changes: 1 addition & 1 deletion verify/src/verify/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
"The flag is encoded. Look for encoded files and use 'base64 -d' to decode.",
"SSH configurations often hide secrets. Explore ~/.ssh directory thoroughly.",
"Modern Ubuntu DNS is usually managed by systemd-resolved. Inspect /etc/resolv.conf, resolvectl status, and /etc/systemd/resolved.conf.d/.",
"Monitor file creation with tools like inotifywait, or try creating a file in ctf_challenges.",
"Run scp from your own computer, not the VM. The destination must be the ctf_challenges directory (e.g. user@ip:~/ctf_challenges/), and the file must be new - overwriting doesn't count.",
"Web servers serve content from specific directories. Check what ports nginx is listening on.",
"Network traffic can carry hidden messages. Look at ping patterns with tcpdump.",
"Cron jobs run on schedules. Check /etc/cron.d/, /etc/crontab, and user crontabs with 'crontab -l'.",
Expand Down
Loading