CVE-2020-7248: libubox, OpenWrt 19.07.0 to 19.07.1
OpenWrt 19.07.1 updates libubox, and with it libblobmsg_json.so, the
library that turns a blob message into JSON. Petr Štetiar and Jo-Philipp
Wich found that a large enough double overflows the buffer on the stack
that blobmsg_format_json writes each number into
(advisory 2020-01-31-2).
The update pulls in ten commits of libubox
(OpenWrt commit 5c73bb1),
of which these touch the library:
1ffa41535369, “blobmsg_json: prefer snprintf usage”: the fix. Each value is written withsnprintfand the size of the buffer, in place ofsprintf.a36ee96618a9, “blobmsg: blobmsg_add_json_element() 64-bit values”.f0da3a4283b7, “blobmsg_json: fix int16 serialization”.
19.07.2 ships the same bytes. OpenWrt runs sstrip on what it ships,
so only the segments of the file and its exports are left.
Get the binaries
armvirt before 21.02 ships an empty rootfs.cpio.gz, so the files come
from the tar of the root file system:
$ for v in 19.07.0 19.07.1; do
mkdir -p $v
curl -s https://downloads.openwrt.org/releases/$v/targets/armvirt/64/openwrt-$v-armvirt-64-default-rootfs.tar.gz \
| tar -xz -C $v ./lib/libblobmsg_json.so
done
Compare
$ hereticus --format markdown 19.07.0/lib/libblobmsg_json.so 19.07.1/lib/libblobmsg_json.so
| FUNCTION | CHANGE | SCORE | +/-/~ | TOUCHED | MATCHED BY |
|---|---|---|---|---|---|
sub_1184 -> sub_1188 | changed | 0.95 | 10/5/3 | 2 call, 2 callee, 3 mem | similar |
sub_e70 | changed | 0.99 | 1/0/1 | 1 callee, 1 text | similar |
blobmsg_add_json_element | changed | 0.89 | 17/3/3 | 1 branch, 1 call, 1 callee, 1 jump, 6 mem, 2 const, 1 text | same name |
19 matched (16 unchanged, 3 changed), 0 gone, 0 new
The first row is the fix: sub_1184 is blobmsg_format_element, the
static function that blobmsg_format_json calls for each value. The
third row is the change to 64-bit values. The build for ARMv7 reads the
same, with the fix on row 1 of
3 too, and so does the MIPS16e build for
malta, on row 1 of
5. OpenWrt ships no root file system for malta
before 21.02, but its vmlinux-initramfs.elf holds one, as a newc
cpio archive in .init.data.
Read the fix
$ hereticus --view il --diff sub_1184 19.07.0/lib/libblobmsg_json.so 19.07.1/lib/libblobmsg_json.so
...
- x1 = &"%d"
- x3 = load.64 [@sprintf]
- call sprintf
+ call snprintf
...
- x1 = &"%ld"
- x0 = x19
- x2 = rev(x2)
- call sprintf
+ x2 = &"%ld"
...
Each format moves from the second argument to the third, as the size of
the buffer comes before it, and each call of sprintf turns into one of
snprintf. The default order ranks a call turned into its bounded form
first; by the count of instructions added alone, the fix is on row 2,
below blobmsg_add_json_element.