CVE-2025-14282: dropbear, OpenWrt 24.10.4 to 24.10.5
This repeats the fix of
OpenWrt security advisory 2025-12-16-1.
With Unix domain socket forwarding, a user who logged in to Dropbear could
make the server, still running as root, open a socket as root. OpenWrt
24.10.5 takes the upstream fix
(OpenWrt commit 0f52a05):
the server now drops to the privileges of the user as soon as the user
logs in, in a new svr_switch_user, and no longer when it starts the
shell, in execchild. The same update keeps the utmp group to record
the logout, offers only the first host key when it rekeys, and fixes
CVE-2019-6111 in scp.
OpenWrt runs sstrip on what it ships, so only the segments of the file
are left. OpenWrt builds Dropbear as plain MIPS32, not MIPS16e as most of
its MIPS user space, so this case and the ubusd case of CVE-2025-62526
read different instruction sets on MIPS.
Get the binaries
$ for v in 24.10.4 24.10.5; do
mkdir -p $v
curl -s https://downloads.openwrt.org/releases/$v/targets/armsr/armv8/openwrt-$v-armsr-armv8-rootfs.cpio.gz \
| gunzip | (cd $v && cpio -id usr/sbin/dropbear)
done
Compare
$ hereticus --format markdown 24.10.4/usr/sbin/dropbear 24.10.5/usr/sbin/dropbear
| FUNCTION | CHANGE | SCORE | +/-/~ | TOUCHED | MATCHED BY |
|---|---|---|---|---|---|
sub_15fd0 -> sub_1650c | changed | 0.95 | 74/37/0 | 8 branch, 16 call, 2 jump, 22 mem, 1 text | similar |
sub_15048 -> sub_1513c | changed | 0.21 | 64/2/0 | 8 branch, 8 call, 2 jump, 17 mem, 4 text | same place |
sub_19acc -> sub_19c14 | changed | 0.91 | 42/20/0 | 5 branch, 10 call, 2 jump, 16 mem, 1 const | similar |
sub_3c48 -> sub_3d08 | changed | 0.99 | 25/18/7 | 5 branch, 2 call, 1 jump, 8 mem, 6 const, 1 text | similar |
sub_13f8c -> sub_14078 | changed | 0.92 | 5/6/2 | 3 call, 6 mem | similar |
sub_17e94 -> sub_18078 | changed | 0.98 | 5/6/2 | 3 call, 5 mem | similar |
sub_18488 -> sub_18674 | changed | 0.94 | 4/39/4 | 4 branch, 10 call, 3 jump, 7 mem, 2 text | similar |
sub_17b48 -> sub_17dc0 | changed | 0.81 | 2/45/1 | 7 branch, 7 call, 2 jump, 10 mem, 3 text | similar |
sub_13e0c -> sub_13f90 | changed | 0.58 | 0/38/0 | 4 branch, 7 call, 1 jump, 8 mem, 2 text | same references |
sub_2293c -> sub_22ad4 | changed | 0.99 | 0/0/2 | - | similar |
sub_c328 -> sub_c40c | changed values | 1.00 | - | 1 text | identical shape |
sub_1c2a8 -> sub_1c440 | changed values | 1.00 | - | 1 text | identical shape |
sub_13070: newsub_130c0: new
417 matched (404 unchanged, 13 changed), 0 gone, 2 new
The texts each function points at name the rows:
| Row | Function | What changed |
|---|---|---|
sub_15fd0 | sink of scp | CVE-2019-6111: names from the server must match the wildcard |
sub_15048 | send_msg_userauth_success | the fix: svr_switch_user, inlined, drops to the user |
sub_19acc | recv_msg_kexdh_init | a rekey offers only the host key in use |
sub_3c48 | the options of the server | not read further |
sub_13f8c | the owner of the pty | the utmp group is raised around it |
sub_17b48 | execchild | no longer changes the user |
sub_13e0c | svr_agentcleanup | no longer takes the user’s IDs to remove the agent socket: the server runs as the user by then |
sub_13070, sub_130c0 | svr_raise_gid_utmp, svr_restore_gid | new |
The fix is on row 2. GCC inlined the new svr_switch_user into
send_msg_userauth_success, which grew from 20 instructions to 77, so
the code scores only 0.21. The pair holds because the function stays in
its place between pairs on both sides.
Read the fix
$ hereticus --view il --diff sub_15048 24.10.4/usr/sbin/dropbear 24.10.5/usr/sbin/dropbear
...
w0 = 1
store.32 [@0x50ac8] = w0
- if (w1 != 0) goto $+0x8
+ call getuid
+ if (w0 != 0) goto $+0xb0
+ w0 = load.32 [@0x50aec]
+ if (w0 == 0) goto $+0x38
+ x1 = &page
+ x1 = load.64 [@setgid]
+ call setgid
+ if ((w0 & 0x80000000) == 0) goto $+0x10
+ x0 = &page
+ x0 = &"Error changing user group"
...
+ x0 = &"utmp"
+ call getgrnam
...
+ call setresgid
...
+ call setuid
...
ses.authstate.authdone = 1 is the store of 1; after it, the server now
calls setgid, initgroups, setresgid and setuid while it is still
in the authentication handler.
The other architectures
The same comparison on the other builds of the release:
| Build | Rows | Row of the fix | Score |
|---|---|---|---|
armsr/armv8, AArch64 | 14 | 2 | 0.21 |
armsr/armv7, A32 | 33 | 1 | 0.25 |
malta/be, MIPS32 big endian | 22 | 2 | 0.28 |
malta/le, MIPS32 little endian | 19 | 2 | 0.28 |
hereticus-cli/tests/truth_cves.rs locks these ranks, and
fixtures/cve_binaries.py fetches and pins the binaries.