Skip to main content

PWN Debugging and 1-day exploit development for CVE-2018-1160

· 5 min read
MuelNova
Pwner who wants to write codes.

Attachment download link: https://pwnable.tw/static/chall/netatalk.tgz + https://pwnable.tw/static/libc/libc-18292bd12d37bfaf58e8dded9db7f1f5da1192cb.so

It took about 1.5 days, and overall it was a very productive debugging and reproducing process. I learned some exploitation and debugging techniques, and it was very helpful for expanding my mindset.

The discovery process of the vulnerability is explained clearly by the author in Exploiting an 18 Year Old Bug. A Write-up for CVE-2018–1160 | by Jacob Baines, which is very interesting. You can also find a translated version at Discovery and Exploitation of Netatalk CVE-2018-1160_c01dkit's Blog-CSDN Blog.

The author mentioned in their blog that this vulnerability can only be exploited on NAS with -no-pie. However, the creator of the HITCON 2019 challenge, DDAA, provided an exploit approach in HITCON CTF 2019 Pwn 371 Netatalk (ddaa.tw), which basically involves leveraging the nature of fork where child processes do not change the memory layout — in other words, ASLR plays a very minor role (laughs). This way, we can expose a valid address through a side channel and then exploit it.

0x01 Environment Setup

Setting up the environment was an extremely difficult task, and about half a day was spent pondering over the environment setup.

Let's directly talk about the final solution: based on the libc version, I made modifications using skysider/pwndocker: A docker environment for pwn in CTF (github.com) and then ran it in a docker container. The kernel version was challenging to resolve, and I couldn't compile the 4.9.0 kernel in WSL2 even after numerous attempts. However, since the kernel only affects the offset of chunk allocation through mmap, we can ignore this in the local environment.

FROM ubuntu:18.04

RUN dpkg --add-architecture i386 && \
apt-get -y update && \
apt install -y \
libc6:i386 \
libc6-dbg:i386 \
libc6-dbg \
lib32stdc++6 \
g++-multilib \
cmake \
ipython3 \
vim \
net-tools \
iputils-ping \
libffi-dev \
libssl-dev \
python3-dev \
python3-pip \
build-essential \
ruby \
ruby-dev \
tmux \
strace \
ltrace \
nasm \
wget \
gdb \
gdb-multiarch \
gdbserver \
netcat \
socat \
git \
patchelf \
gawk \
file \
python3-distutils \
bison \
rpm2cpio cpio \
zstd

COPY afpd /
COPY afp.conf /
COPY libatalk.so.18 /

USER 0000:0000

EXPOSE 5566
EXPOSE 1234

ENV LD_LIBRARY_PATH=/

CMD ./afpd -d -F ./afp.conf
sudo docker rm pwnable
sudo docker rmi pwnable:cve-2018-1160

sudo docker build . -t pwnable:cve-2018-1160
sudo docker run -dit -p 5566:5566 -p 1234:1234 --name pwnable pwnable:cve-2018-1160

0x02 Vulnerability Analysis

After opening afpd in IDA and observing the strings, we can determine the version of netatalk, and downloading the source code can help with further analysis.

Before that, you may need to understand about Data Stream Interface - Wikipedia

According to the blog, we can directly locate the vulnerable function.

You can observe that dsi->commands is user-controllable, and the size in the memcpy operation is controlled by dsi->commands[i].

After that, the server will try to reply with dsi->server_quantum.

By observing the DSI structure

typedef struct DSI {
// structure fields
}

It is evident that dsi->commands[i] is a uint8 type value, allowing us to write a maximum of 0xff bytes, thus controlling attn_quantum, datasize, server_quantum, serverID, clientID, commands, and parts of data(DSI_DATASIZ = 65536).

Finally, let's take a look at the operations on commands.

Now, let's consider the exploit phase.

Exploitation

Address Bruteforcing

In an environment with ASLR enabled, the first thing we need to do is obtain the base address of libc (or other useful addresses). This can be easily achieved under the condition of forking a child process.

Based on the above analysis, if the address the server wants to send back is placed in an illegal memory, it will cause an error and exit. This means we can determine a legitimate address by whether there is feedback. By using a side-channel, we can bruteforce and obtain a valid address.

A simple script for address bruteforcing:

# Address bruteforcing script

# Script code goes here

Attack Strategy

In the local environment, we can directly use the known offset for ease of debugging.

Once we know the libc version and the offset, we can find the necessary gadgets. The challenge lies in achieving RCE with only one arbitrary write operation.

In an unchanged environment, we can exploit the _rtld_global table in ld.so, specifically targeting _dl_load_lock (_rtld_global+3840), and overwrite it with system, with rdi pointing to _dl_rtld_lock_recursive (_rtld_global+2312). These two are 0x600 bytes apart, which can be written in the Total data length field.

Afterwards, we can bounce a shell to gain control (which should work).

# Exploit script using locally known data

# Script code goes here

References

Learning Pwn with Xu: Pwnable.tw CVE-2018-1160 | Clang Tailor Shop (xuanxuanblingbling.github.io)11/06/netatalk/

pwnable.tw CVE-2018-1160 | gtrboy's blog

CVE-2018-1160 netatalk Buffer Overflow Vulnerability Reproduction and Analysis | Ama2in9

Exploiting an 18 Year Old Bug. A Write-up for CVE-2018–1160 | by Jacob Baines | Tenable TechBlog | Medium

Netatalk CVE-2018–1160 Buffer Overflow Vulnerability Analysis - Knownsec Community (aliyun.com)

info

This Content is generated by ChatGPT and might be wrong / incomplete, refer to Chinese version if you find something wrong.

Loading Comments...