WebP Cloud Services Blog

Manually Compiling libwebp - Our Mitigation Approach for CVE 2023-4863

· Nova Kwok

CVE-2023-4863 is a buffer overflow vulnerability affecting the libwebp library. This library is an open-source tool developed by Google for handling WebP images. Coincidentally, both our open-source component, WebP Server Go, and our SaaS service, WebP Cloud Services, rely on this library.

The related fix PR can be found here: Fix PR. The PR attempts to address the following issues:

  1. Huffman Encoding Table Construction Issue: In the VP8L image encoding/decoding library, there is a function called BuildHuffmanTable responsible for constructing Huffman encoding tables. The previous code had a potential problem where constructing these tables could sometimes result in accessing memory beyond the allocated range, potentially leading to a memory overflow issue. The fix for this issue involves stricter control over memory allocation and access to ensure it stays within the allocated memory range.

  2. Memory Allocation and Deallocation for Huffman Encoding Tables: This patch also introduces a new way to manage memory allocation and deallocation for Huffman encoding tables. By introducing the HuffmanTables structure and the HuffmanTablesSegment structure, it provides more flexible memory management. This allows dynamic allocation of additional memory segments as needed to avoid memory shortage issues and ensures that the allocated memory blocks are contiguous.

Considering that we haven’t found a PoC (Proof of Concept) publicly available, and we haven’t explored how to create one ourselves, our primary focus has been on the fix. The main impact of this vulnerability lies in the decoding process. For web browsers, it could potentially lead to an overflow by using a malicious WebP image. For WebP Server Go and WebP Cloud Services, the attack surface likely involves crafting a malicious WebP image at the source and triggering the overflow when attempting to decode it in our services.

There are two ways to mitigate/fix this issue:

  • Disable the use of WebP as source images. However, upon investigation, we found that many users on WebP Cloud Services are already using WebP as source images, making this solution impractical.

  • Update the libwebp library.

Currently, the packaging speed of various distributions is still relatively slow. At the time of writing this article, the following distributions have addressed the issue (the fixed version is 1.3.2, so versions of libwebp below this may not include this fix, although there are exceptions where distributions apply patches to older versions):

Ubuntu 22.04

root@6134fe90ec67:/# apt-cache policy libwebp-dev
libwebp-dev:
  Installed: (none)
  Candidate: 1.2.2-2ubuntu0.22.04.2
  Version table:
     1.2.2-2ubuntu0.22.04.2 500
        500 http://ports.ubuntu.com/ubuntu-ports jammy-updates/main arm64 Packages
        500 http://ports.ubuntu.com/ubuntu-ports jammy-security/main arm64 Packages
     1.2.2-2 500
        500 http://ports.ubuntu.com/ubuntu-ports jammy/main arm64 Packages

According to https://changelogs.ubuntu.com/changelogs/pool/main/libw/libwebp/libwebp_1.2.2-2ubuntu0.22.04.2/changelog, this patched version includes the fix.

libwebp (1.2.2-2ubuntu0.22.04.2) jammy-security; urgency=medium

  • SECURITY UPDATE: Heap buffer overflow in BuildHuffmanTable
    • debian/patches/CVE-2023-4863.patch: fix OOB write in BuildHuffmanTable in src/dec/vp8l_dec.c, src/dec/vp8li_dec.h, src/utils/huffman_utils.c, src/utils/huffman_utils.h.
    • CVE-2023-4863

– Marc Deslauriers marc.deslauriers@ubuntu.com Wed, 13 Sep 2023 13:57:14 -0400

Debian 12

root@581497e00c7b:/# apt-cache policy libwebp-dev
libwebp-dev:
  Installed: (none)
  Candidate: 1.2.4-0.2+deb12u1
  Version table:
     1.2.4-0.2+deb12u1 500
        500 http://deb.debian.org/debian-security bookworm-security/main arm64 Packages
     1.2.4-0.2 500
        500 http://deb.debian.org/debian bookworm/main arm64 Packages

According to https://metadata.ftp-master.debian.org/changelogs//main/libw/libwebp/libwebp_1.2.4-0.2+deb12u1_changelog, this patched version includes the fix.

libwebp (1.2.2-2ubuntu0.22.04.2) jammy-security; urgency=medium

  • SECURITY UPDATE: Heap buffer overflow in BuildHuffmanTable
    • debian/patches/CVE-2023-4863.patch: fix OOB write in BuildHuffmanTable in src/dec/vp8l_dec.c, src/dec/vp8li_dec.h, src/utils/huffman_utils.c, src/utils/huffman_utils.h.
    • CVE-2023-4863

– Marc Deslauriers marc.deslauriers@ubuntu.com Wed, 13 Sep 2023 13:57:14 -0400

libwebp (1.2.4-0.2+deb12u1) bookworm-security; urgency=medium

  • CVE-2023-4863

– Moritz Mühlenhoff jmm@debian.org Tue, 12 Sep 2023 21:35:44 +0200

Alpine 3.18

/ # cat /etc/issue
Welcome to Alpine Linux 3.18
Kernel \r on an \m (\l)

/ # apk info libwebp-dev
libwebp-dev-1.3.2-r0 description:
Libraries for working with WebP images (development files)

libwebp-dev-1.3.2-r0 webpage:
https://developers.google.com/speed/webp

libwebp-dev-1.3.2-r0 installed size:
160 KiB

Fedora 38

[root@9dd00c8c57b8 ~]# yum info libwebp-devel
Last metadata expiration check: 0:00:37 ago on Sat Sep 16 12:25:45 2023.
Available Packages
Name         : libwebp-devel
Version      : 1.3.1
Release      : 3.fc38
Architecture : aarch64
Size         : 38 k
Source       : libwebp-1.3.1-3.fc38.src.rpm

Arch Linux

[root@bbacbc426a03 ~]# pacman -Ss libwebp
extra/libwebp 1.3.2-1
    WebP library and conversion tools

CentOS Stream 9

[root@69de863356a0 /]# yum info libwebp-devel.x86_64
Last metadata expiration check: 0:01:42 ago on Sat Sep 16 12:35:25 2023.
Available Packages
Name         : libwebp-devel
Version      : 1.2.0
Release      : 7.el9
Architecture : x86_64

OpenSUSE Tumbleweed

9f749cc56bcb:/ # zypper info libwebp-devel
Loading repository data...
Reading installed packages...

Information for package libwebp-devel:
--------------------------------------
Repository     : openSUSE-Tumbleweed-Oss
Name           : libwebp-devel
Version        : 1.3.1-2.1
Arch           : x86_64
Vendor         : openSUSE

Our Fix

Considering that several distributions have not addressed the issue, and we are affected by this vulnerability, and because we utilize a multi-stage containerized build process, the preceding section, including the RUN apt update && apt install --no-install-recommends libvips-dev -y && mkdir /build and beyond, may remain cached. This has resulted in us not being able to obtain a version with the patch. Coincidentally, we are planning to upgrade the version of libwebp. Therefore, we need to manually compile a new version of libwebp.

Compilation

As our services run in Docker containers and our Dockerfile uses multi-stage builds, we only needed to add a stage to compile the so files we needed. Then, we copied the final so file into the running stage.

Checking so Files

When installing libwebp, it automatically includes the following dependencies: libwebp-dev libwebp7 libwebpdemux2 libwebpmux3

You can see the so files with the dpkg -L command. We need to replace all of them

root@ee54b6e5dbfa:/# dpkg -L libwebp-dev libwebp7 libwebpdemux2 libwebpmux3 | grep "so"
/usr/lib/aarch64-linux-gnu/libwebp.so
/usr/lib/aarch64-linux-gnu/libwebpdemux.so
/usr/lib/aarch64-linux-gnu/libwebpmux.so
/usr/lib/aarch64-linux-gnu/libwebp.so.7.1.5
/usr/lib/aarch64-linux-gnu/libwebp.so.7
/usr/lib/aarch64-linux-gnu/libwebpdemux.so.2.0.11
/usr/lib/aarch64-linux-gnu/libwebpdemux.so.2
/usr/lib/aarch64-linux-gnu/libwebpmux.so.3.0.10
/usr/lib/aarch64-linux-gnu/libwebpmux.so.3

Installing Compilation Dependencies

Make sure to install the necessary dependencies for compilation. Note the inclusion of libgif-dev for GIF support.

apt install -y wget gcc make autoconf automake libtool libgif-dev \
    libjpeg-dev libjpeg62-turbo libjpeg62-turbo-dev libpng-dev libpng-tools libpng16-16 libtiff-dev libtiff6 libtiffxx6

Downloading Source Code and Configuring Compilation

mkdir libwebp && mkdir -p /build/usr && mkdir /build/usr/lib/ && cd libwebp &&  \
        wget https://chromium.googlesource.com/webm/libwebp/+archive/refs/heads/1.3.2.tar.gz && \
        tar xf 1.3.2.tar.gz && rm -f 1.3.2.tar.gz && \
        ./autogen.sh && \
        ./configure --prefix=/build/usr --libdir=/build/usr/lib --enable-everything && \
       

During ./configure, we specify the /build directory as the prefix and libdir for the output so files.

After configuration, you’ll see information about what’s included in the build. Ensure that shared libraries, encoders, decoders, mux, and demux are present, along with support for JPEG, PNG, TIFF, and GIF formats. This will produce the desired runtime-linked so files.

WebP Configuration Summary
--------------------------

Shared libraries: yes
Static libraries: yes
Threading support: yes
libwebp: yes
libwebpdecoder: yes
libwebpdemux: yes
libwebpmux: yes
libwebpextras: yes

Tools:
cwebp : yes
  Input format support
  ====================
  JPEG : yes
  PNG  : yes
  TIFF : yes
  WIC  : no
dwebp : yes
  Output format support
  =====================
  PNG  : yes
  WIC  : no
GIF support : yes
anim_diff   : yes
gif2webp    : yes
img2webp    : yes
webpmux     : yes
vwebp       : no
webpinfo    : yes
SDL support : no
vwebp_sdl   : no

Compilation

make && make install

Check the compilation results:

root@ee54b6e5dbfa:~/libwebp# tree /build
/build
`-- usr
    |-- bin
    |   |-- cwebp
    |   |-- dwebp
    |   |-- gif2webp
    |   |-- img2webp
    |   |-- webpinfo
    |   `-- webpmux
    |-- include
    |   `-- webp
    |       |-- decode.h
    |       |-- demux.h
    |       |-- encode.h
    |       |-- mux.h
    |       |-- mux_types.h
    |       |-- sharpyuv
    |       |   |-- sharpyuv.h
    |       |   `-- sharpyuv_csp.h
    |       `-- types.h
    |-- lib
    |   |-- libsharpyuv.a
    |   |-- libsharpyuv.la
    |   |-- libsharpyuv.so -> libsharpyuv.so.0.0.1
    |   |-- libsharpyuv.so.0 -> libsharpyuv.so.0.0.1
    |   |-- libsharpyuv.so.0.0.1
    |   |-- libwebp.a
    |   |-- libwebp.la
    |   |-- libwebp.so -> libwebp.so.7.1.8
    |   |-- libwebp.so.7 -> libwebp.so.7.1.8
    |   |-- libwebp.so.7.1.8
    |   |-- libwebpdecoder.a
    |   |-- libwebpdecoder.la
    |   |-- libwebpdecoder.so -> libwebpdecoder.so.3.1.8
    |   |-- libwebpdecoder.so.3 -> libwebpdecoder.so.3.1.8
    |   |-- libwebpdecoder.so.3.1.8
    |   |-- libwebpdemux.a
    |   |-- libwebpdemux.la
    |   |-- libwebpdemux.so -> libwebpdemux.so.2.0.14
    |   |-- libwebpdemux.so.2 -> libwebpdemux.so.2.0.14
    |   |-- libwebpdemux.so.2.0.14
    |   |-- libwebpmux.a
    |   |-- libwebpmux.la
    |   |-- libwebpmux.so -> libwebpmux.so.3.0.13
    |   |-- libwebpmux.so.3 -> libwebpmux.so.3.0.13
    |   |-- libwebpmux.so.3.0.13
    |   `-- pkgconfig
    |       |-- libsharpyuv.pc
    |       |-- libwebp.pc
    |       |-- libwebpdecoder.pc
    |       |-- libwebpdemux.pc
    |       `-- libwebpmux.pc

Copying to the Final Stage

We need to first forcefully remove the libwebp related packages installed with libvips-dev.

dpkg --remove --force-depends libwebp-dev libwebp7 libwebpdemux2 libwebpmux3

Then, we need to find a way to copy the so files. The challenge is that our Docker image should support multiple architectures. For amd64, the shared library directory is /usr/lib/x86_64-linux-gnu/, and for arm64, it’s /usr/lib/aarch64-linux-gnu/.

You might think of using uname -m to determine the architecture and copy the appropriate files. However, Dockerfiles do not support this syntax. For example, trying to use the following command won’t work:

COPY --from=libwebp /build/usr/lib/* /usr/lib/$(uname -m)-linux-gnu/

It won’t resolve correctly.

So, here’s a workaround: first, copy to a temporary directory and then use RUN to move the files to their correct location. Don’t forget the * at the end of /build/usr/lib/* and the final ldconfig command.

COPY --from=libwebp /build/usr/lib/* /usr/lib/temp-linux-gnu/
RUN mv /usr/lib/temp-linux-gnu/* /usr/lib/$(uname -m)-linux-gnu/ && ldconfig

Complete Dockerfile Reference

FROM golang:1.21-bookworm as builder

ARG IMG_PATH=/opt/pics
ARG EXHAUST_PATH=/opt/exhaust
RUN apt update && apt install --no-install-recommends libvips-dev -y && mkdir /build
COPY go.mod /build
RUN cd /build && go mod download

COPY . /build
RUN cd /build && sed -i "s|.\/pics|${IMG_PATH}|g" config.json  \
    && sed -i "s|\"\"|\"${EXHAUST_PATH}\"|g" config.json  \
    && sed -i 's/127.0.0.1/0.0.0.0/g' config.json  \
    && go build -ldflags="-s -w" -o webp-server .

FROM debian:bookworm-slim as libwebp
RUN apt update && apt install -y wget gcc make autoconf automake libtool libgif-dev \
    libjpeg-dev libjpeg62-turbo libjpeg62-turbo-dev libpng-dev libpng-tools libpng16-16 libtiff-dev libtiff6 libtiffxx6
RUN mkdir libwebp && mkdir -p /build/usr && mkdir /build/usr/lib/ && cd libwebp &&  \
        wget https://chromium.googlesource.com/webm/libwebp/+archive/refs/heads/1.3.2.tar.gz && \
        tar xf 1.3.2.tar.gz && rm -f 1.3.2.tar.gz && \
        ./autogen.sh && \
        ./configure --prefix=/build/usr --libdir=/build/usr/lib --enable-everything && \
        make && make install

FROM debian:bookworm-slim

RUN apt update && apt install --no-install-recommends libvips ca-certificates libjemalloc2 libtcmalloc-minimal4 -y && rm -rf /var/lib/apt/lists/* &&  rm -rf /var/cache/apt/archives/*

# for CVE-2023-4863
RUN dpkg --remove --force-depends libwebp-dev libwebp7 libwebpdemux2 libwebpmux3
COPY --from=libwebp /build/usr/lib/* /usr/lib/temp-linux-gnu/
RUN mv /usr/lib/temp-linux-gnu/* /usr/lib/$(uname -m)-linux-gnu/ && ldconfig

COPY --from=builder /build/webp-server  /usr/bin/webp-server
COPY --from=builder /build/config.json /etc/config.json

WORKDIR /opt
VOLUME /opt/exhaust
CMD ["/usr/bin/webp-server", "--config", "/etc/config.json"]

Similarly, we applied a similar patch to WebP Cloud Services to reduce the vulnerability’s impact on our system.

References

  1. https://news.ycombinator.com/item?id=37478403
  2. https://github.com/webmproject/libwebp/commit/902bc9190331343b2017211debcec8d2ab87e17a

The WebP Cloud Services team is a small team of three individuals from Shanghai and Helsingborg. Since we are not funded and have no profit pressure, we remain committed to doing what we believe is right. We strive to do our best within the scope of our resources and capabilities. We also engage in various activities without affecting the services we provide to the public, and we continuously explore novel ideas in our products.

If you find this service interesting, feel free to log in to the WebP Cloud Dashboard to experience it. If you’re curious about other magical features it offers, take a look at our WebP Cloud Services Docs. We hope everyone enjoys using it!


Discuss on Hacker News