Manually Compiling libwebp - Our Mitigation Approach for CVE 2023-4863
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:
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.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 theHuffmanTablesSegment
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
.
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
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