Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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 with snprintf and the size of the buffer, in place of sprintf.
  • 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
FUNCTIONCHANGESCORE+/-/~TOUCHEDMATCHED BY
sub_1184 -> sub_1188changed0.9510/5/32 call, 2 callee, 3 memsimilar
sub_e70changed0.991/0/11 callee, 1 textsimilar
blobmsg_add_json_elementchanged0.8917/3/31 branch, 1 call, 1 callee, 1 jump, 6 mem, 2 const, 1 textsame 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.