mbox series

[RFC,v19,0/5] Script execution control (was O_MAYEXEC)

Message ID 20240704190137.696169-1-mic@digikod.net (mailing list archive)
Headers show
Series Script execution control (was O_MAYEXEC) | expand

Message

Mickaël Salaün July 4, 2024, 7:01 p.m. UTC
Hi,

The ultimate goal of this patch series is to be able to ensure that
direct file execution (e.g. ./script.sh) and indirect file execution
(e.g. sh script.sh) lead to the same result, especially from a security
point of view.

Overview
--------

This patch series is a new approach of the initial O_MAYEXEC feature,
and a revamp of the previous patch series.  Taking into account the last
reviews [1], we now stick to the kernel semantic for file executability.
One major change is the clear split between access check and policy
management.

The first patch brings the AT_CHECK flag to execveat(2).  The goal is to
enable user space to check if a file could be executed (by the kernel).
Unlike stat(2) that only checks file permissions, execveat2(2) +
AT_CHECK take into account the full context, including mount points
(noexec), caller's limits, and all potential LSM extra checks (e.g.
argv, envp, credentials).

The second patch brings two new securebits used to set or get a security
policy for a set of processes.  For this to be meaningful, all
executable code needs to be trusted.  In practice, this means that
(malicious) users can be restricted to only run scripts provided (and
trusted) by the system.

[1] https://lore.kernel.org/r/CAHk-=wjPGNLyzeBMWdQu+kUdQLHQugznwY7CvWjmvNW47D5sog@mail.gmail.com

Script execution
----------------

One important thing to keep in mind is that the goal of this patch
series is to get the same security restrictions with these commands:
* ./script.py
* python script.py
* python < script.py
* python -m script.py

However, on secure systems, we should be able to forbid these commands
because there is no way to reliably identify the origin of the script:
* xargs -a script.py -d '\r' -- python -c
* cat script.py | python
* python

Background
----------

Compared to the previous patch series, there is no more dedicated
syscall nor sysctl configuration.  This new patch series only add new
flags: one for execveat(2) and four for prctl(2).

This kind of script interpreter restriction may already be used in
hardened systems, which may need to fork interpreters and install
different versions of the binaries.  This mechanism should enable to
avoid the use of duplicate binaries (and potential forked source code)
for secure interpreters (e.g. secure Python [2]) by making it possible
to dynamically enforce restrictions or not.

The ability to control script execution is also required to close a
major IMA measurement/appraisal interpreter integrity [3].

This new execveat + AT_CHECK should not be confused with the O_EXEC flag
(for open) which is intended for execute-only, which obviously doesn't
work for scripts.

I gave a talk about controlling script execution where I explain the
previous approaches [4].  The design of the WIP RFC I talked about
changed quite a bit since then.

[2] https://github.com/zooba/spython
[3] https://lore.kernel.org/lkml/20211014130125.6991-1-zohar@linux.ibm.com/
[4] https://lssna2023.sched.com/event/1K7bO

Execution policy
----------------

The "execution" usage means that the content of the file descriptor is
trusted according to the system policy to be executed by user space,
which means that it interprets the content or (try to) maps it as
executable memory.

It is important to note that this can only enable to extend access
control managed by the kernel.  Hence it enables current access control
mechanism to be extended and become a superset of what they can
currently control.  Indeed, the security policy could also be delegated
to an LSM, either a MAC system or an integrity system.

Complementary W^X protections can be brought by SELinux or IPE [5].

Being able to restrict execution also enables to protect the kernel by
restricting arbitrary syscalls that an attacker could perform with a
crafted binary or certain script languages.  It also improves multilevel
isolation by reducing the ability of an attacker to use side channels
with specific code.  These restrictions can natively be enforced for ELF
binaries (with the noexec mount option) but require this kernel
extension to properly handle scripts (e.g. Python, Perl).  To get a
consistent execution policy, additional memory restrictions should also
be enforced (e.g. thanks to SELinux).

[5] https://lore.kernel.org/lkml/1716583609-21790-1-git-send-email-wufan@linux.microsoft.com/

Prerequisite for security use
-----------------------------

Because scripts might not currently have the executable permission and
still run well as is, or because we might want specific users to be
allowed to run arbitrary scripts, we also need a configuration
mechanism.

According to the threat model, to get a secure execution environment on
top of these changes, it might be required to configure and enable
existing security mechanisms such as secure boot, restrictive mount
points (e.g. with rw AND noexec), correct file permissions (including
executable libraries), IMA/EVM, SELinux policy...

The first thing to patch is the libc to check loaded libraries (e.g. see
chromeOS changes).  The second thing to patch are the script
interpreters by checking direct scripts executability and by checking
their own libraries (e.g. Python's imported files or argument-passed
modules).  For instance, the PEP 578 [6] (Runtime Audit Hooks) enables
Python 3.8 to be extended with policy enforcement points related to code
interpretation, which can be used to align with the PowerShell audit
features.  Additional Python security improvements (e.g. a limited
interpreter without -c, stdin piping of code) are developed [2] [7].

[6] https://www.python.org/dev/peps/pep-0578/
[7] https://lore.kernel.org/lkml/0c70debd-e79e-d514-06c6-4cd1e021fa8b@python.org/

libc patch
----------

Dynamic linking needs still need to check the libraries the same way
interpreters need to check scripts.

chromeOS patches glibc with a fstatvfs check [8] [9]. This enables to
check against noexec mount points, which is OK but doesn't fit with
execve semantics.  Moreover, the kernel is not aware of such check, so
all access control checks are not performed (e.g. file permission, LSMs
security policies, integrity and authenticity checks), it is not handled
with audit, and more importantly this would not work on generic
distributions because of the strict requirement and chromeOS-specific
assumptions.

[8] https://issuetracker.google.com/issues/40054993
[9] https://chromium.googlesource.com/chromiumos/overlays/chromiumos-overlay/+/6abfc9e327241a5f684b8b941c899b7ca8b6dbc1/sys-libs/glibc/files/local/glibc-2.37/0007-Deny-LD_PRELOAD-of-files-in-NOEXEC-mount.patch

Examples
--------

The initial idea comes from CLIP OS 4 and the original implementation
has been used for more than a decade:
https://github.com/clipos-archive/clipos4_doc
Chrome OS has a similar approach:
https://www.chromium.org/chromium-os/developer-library/guides/security/noexec-shell-scripts/

User space patches can be found here:
https://github.com/clipos-archive/clipos4_portage-overlay/search?q=O_MAYEXEC
There is more than the O_MAYEXEC changes (which matches this search)
e.g., to prevent Python interactive execution. There are patches for
Bash, Wine, Java (Icedtea), Busybox's ash, Perl and Python. There are
also some related patches which do not directly rely on O_MAYEXEC but
which restrict the use of browser plugins and extensions, which may be
seen as scripts too:
https://github.com/clipos-archive/clipos4_portage-overlay/tree/master/www-client

Past talks and articles
-----------------------

An introduction to O_MAYEXEC was given at the Linux Security Summit
Europe 2018 - Linux Kernel Security Contributions by ANSSI:
https://www.youtube.com/watch?v=chNjCRtPKQY&t=17m15s
The "write xor execute" principle was explained at Kernel Recipes 2018 -
CLIP OS: a defense-in-depth OS:
https://www.youtube.com/watch?v=PjRE0uBtkHU&t=11m14s
See also a first LWN article about O_MAYEXEC and a new one about
trusted_for(2) and its background:
* https://lwn.net/Articles/820000/
* https://lwn.net/Articles/832959/

Previous versions:
v18: https://lore.kernel.org/r/20220104155024.48023-1-mic@digikod.net
v17: https://lore.kernel.org/r/20211115185304.198460-1-mic@digikod.net
v16: https://lore.kernel.org/r/20211110190626.257017-1-mic@digikod.net
v15: https://lore.kernel.org/r/20211012192410.2356090-1-mic@digikod.net
v14: https://lore.kernel.org/r/20211008104840.1733385-1-mic@digikod.net
v13: https://lore.kernel.org/r/20211007182321.872075-1-mic@digikod.net
v12: https://lore.kernel.org/r/20201203173118.379271-1-mic@digikod.net
v11: https://lore.kernel.org/r/20201019164932.1430614-1-mic@digikod.net
v10: https://lore.kernel.org/r/20200924153228.387737-1-mic@digikod.net
v9: https://lore.kernel.org/r/20200910164612.114215-1-mic@digikod.net
v8: https://lore.kernel.org/r/20200908075956.1069018-1-mic@digikod.net
v7: https://lore.kernel.org/r/20200723171227.446711-1-mic@digikod.net
v6: https://lore.kernel.org/r/20200714181638.45751-1-mic@digikod.net
v5: https://lore.kernel.org/r/20200505153156.925111-1-mic@digikod.net
v4: https://lore.kernel.org/r/20200430132320.699508-1-mic@digikod.net
v3: https://lore.kernel.org/r/20200428175129.634352-1-mic@digikod.net
v2: https://lore.kernel.org/r/20190906152455.22757-1-mic@digikod.net
v1: https://lore.kernel.org/r/20181212081712.32347-1-mic@digikod.net

Regards,

Mickaël Salaün (5):
  exec: Add a new AT_CHECK flag to execveat(2)
  security: Add new SHOULD_EXEC_CHECK and SHOULD_EXEC_RESTRICT
    securebits
  selftests/exec: Add tests for AT_CHECK and related securebits
  selftests/landlock: Add tests for execveat + AT_CHECK
  samples/should-exec: Add set-should-exec

 fs/exec.c                                  |   5 +-
 include/linux/binfmts.h                    |   7 +-
 include/uapi/linux/fcntl.h                 |  30 ++
 include/uapi/linux/securebits.h            |  56 ++-
 kernel/audit.h                             |   1 +
 kernel/auditsc.c                           |   1 +
 samples/Kconfig                            |   7 +
 samples/Makefile                           |   1 +
 samples/should-exec/.gitignore             |   1 +
 samples/should-exec/Makefile               |  13 +
 samples/should-exec/set-should-exec.c      |  88 ++++
 security/commoncap.c                       |  63 ++-
 tools/testing/selftests/exec/.gitignore    |   2 +
 tools/testing/selftests/exec/Makefile      |   8 +
 tools/testing/selftests/exec/config        |   2 +
 tools/testing/selftests/exec/false.c       |   5 +
 tools/testing/selftests/exec/should-exec.c | 449 +++++++++++++++++++++
 tools/testing/selftests/landlock/fs_test.c |  26 ++
 18 files changed, 753 insertions(+), 12 deletions(-)
 create mode 100644 samples/should-exec/.gitignore
 create mode 100644 samples/should-exec/Makefile
 create mode 100644 samples/should-exec/set-should-exec.c
 create mode 100644 tools/testing/selftests/exec/config
 create mode 100644 tools/testing/selftests/exec/false.c
 create mode 100644 tools/testing/selftests/exec/should-exec.c


base-commit: f2661062f16b2de5d7b6a5c42a9a5c96326b8454

Comments

Mimi Zohar July 8, 2024, 8:35 p.m. UTC | #1
Hi Mickaël,

On Thu, 2024-07-04 at 21:01 +0200, Mickaël Salaün wrote:
> Hi,
> 
> The ultimate goal of this patch series is to be able to ensure that
> direct file execution (e.g. ./script.sh) and indirect file execution
> (e.g. sh script.sh) lead to the same result, especially from a security
> point of view.
> 
> Overview
> --------
> 
> This patch series is a new approach of the initial O_MAYEXEC feature,
> and a revamp of the previous patch series.  Taking into account the last
> reviews [1], we now stick to the kernel semantic for file executability.
> One major change is the clear split between access check and policy
> management.
> 
> The first patch brings the AT_CHECK flag to execveat(2).  The goal is to
> enable user space to check if a file could be executed (by the kernel).
> Unlike stat(2) that only checks file permissions, execveat2(2) +
> AT_CHECK take into account the full context, including mount points
> (noexec), caller's limits, and all potential LSM extra checks (e.g.
> argv, envp, credentials).
> 
> The second patch brings two new securebits used to set or get a security
> policy for a set of processes.  For this to be meaningful, all
> executable code needs to be trusted.  In practice, this means that
> (malicious) users can be restricted to only run scripts provided (and
> trusted) by the system.
> 
> [1] https://lore.kernel.org/r/CAHk-=wjPGNLyzeBMWdQu+kUdQLHQugznwY7CvWjmvNW47D5sog@mail.gmail.com
> 
> Script execution
> ----------------
> 
> One important thing to keep in mind is that the goal of this patch
> series is to get the same security restrictions with these commands:
> * ./script.py
> * python script.py
> * python < script.py
> * python -m script.pyT

This is really needed, but is it the "only" purpose of this patch set or can it
be used to also monitor files the script opens (for read) with the intention of
executing.

> 
> However, on secure systems, we should be able to forbid these commands
> because there is no way to reliably identify the origin of the script:
> * xargs -a script.py -d '\r' -- python -c
> * cat script.py | python
> * python
> 
> Background
> ----------
> 
> Compared to the previous patch series, there is no more dedicated
> syscall nor sysctl configuration.  This new patch series only add new
> flags: one for execveat(2) and four for prctl(2).
> 
> This kind of script interpreter restriction may already be used in
> hardened systems, which may need to fork interpreters and install
> different versions of the binaries.  This mechanism should enable to
> avoid the use of duplicate binaries (and potential forked source code)
> for secure interpreters (e.g. secure Python [2]) by making it possible
> to dynamically enforce restrictions or not.
> 
> The ability to control script execution is also required to close a
> major IMA measurement/appraisal interpreter integrity [3].

Definitely.  But it isn't limited to controlling script execution, but also
measuring the script.  Will it be possible to measure and appraise the indirect
script calls with this patch set?

Mimi

> This new execveat + AT_CHECK should not be confused with the O_EXEC flag
> (for open) which is intended for execute-only, which obviously doesn't
> work for scripts.
> 
> I gave a talk about controlling script execution where I explain the
> previous approaches [4].  The design of the WIP RFC I talked about
> changed quite a bit since then.
> 
> [2] https://github.com/zooba/spython
> [3] https://lore.kernel.org/lkml/20211014130125.6991-1-zohar@linux.ibm.com/
> [4] https://lssna2023.sched.com/event/1K7bO
>
Mickaël Salaün July 9, 2024, 8:43 p.m. UTC | #2
On Mon, Jul 08, 2024 at 04:35:38PM -0400, Mimi Zohar wrote:
> Hi Mickaël,
> 
> On Thu, 2024-07-04 at 21:01 +0200, Mickaël Salaün wrote:
> > Hi,
> > 
> > The ultimate goal of this patch series is to be able to ensure that
> > direct file execution (e.g. ./script.sh) and indirect file execution
> > (e.g. sh script.sh) lead to the same result, especially from a security
> > point of view.
> > 
> > Overview
> > --------
> > 
> > This patch series is a new approach of the initial O_MAYEXEC feature,
> > and a revamp of the previous patch series.  Taking into account the last
> > reviews [1], we now stick to the kernel semantic for file executability.
> > One major change is the clear split between access check and policy
> > management.
> > 
> > The first patch brings the AT_CHECK flag to execveat(2).  The goal is to
> > enable user space to check if a file could be executed (by the kernel).
> > Unlike stat(2) that only checks file permissions, execveat2(2) +
> > AT_CHECK take into account the full context, including mount points
> > (noexec), caller's limits, and all potential LSM extra checks (e.g.
> > argv, envp, credentials).
> > 
> > The second patch brings two new securebits used to set or get a security
> > policy for a set of processes.  For this to be meaningful, all
> > executable code needs to be trusted.  In practice, this means that
> > (malicious) users can be restricted to only run scripts provided (and
> > trusted) by the system.
> > 
> > [1] https://lore.kernel.org/r/CAHk-=wjPGNLyzeBMWdQu+kUdQLHQugznwY7CvWjmvNW47D5sog@mail.gmail.com
> > 
> > Script execution
> > ----------------
> > 
> > One important thing to keep in mind is that the goal of this patch
> > series is to get the same security restrictions with these commands:
> > * ./script.py
> > * python script.py
> > * python < script.py
> > * python -m script.pyT
> 
> This is really needed, but is it the "only" purpose of this patch set or can it
> be used to also monitor files the script opens (for read) with the intention of
> executing.

This feature can indeed also be used to monitor files requested by
scripts to be executed e.g. using
https://docs.python.org/3/library/io.html#io.open_code

IMA/EVM can include this check in its logs.

> 
> > 
> > However, on secure systems, we should be able to forbid these commands
> > because there is no way to reliably identify the origin of the script:
> > * xargs -a script.py -d '\r' -- python -c
> > * cat script.py | python
> > * python
> > 
> > Background
> > ----------
> > 
> > Compared to the previous patch series, there is no more dedicated
> > syscall nor sysctl configuration.  This new patch series only add new
> > flags: one for execveat(2) and four for prctl(2).
> > 
> > This kind of script interpreter restriction may already be used in
> > hardened systems, which may need to fork interpreters and install
> > different versions of the binaries.  This mechanism should enable to
> > avoid the use of duplicate binaries (and potential forked source code)
> > for secure interpreters (e.g. secure Python [2]) by making it possible
> > to dynamically enforce restrictions or not.
> > 
> > The ability to control script execution is also required to close a
> > major IMA measurement/appraisal interpreter integrity [3].
> 
> Definitely.  But it isn't limited to controlling script execution, but also
> measuring the script.  Will it be possible to measure and appraise the indirect
> script calls with this patch set?

Yes. You should only need to implement security_bprm_creds_for_exec()
for IMA/EVM.

BTW, I noticed that IMA only uses the security_bprm_check() hook (which
can be called several times for one execve), but
security_bprm_creds_for_exec() might be more appropriate.

> 
> Mimi
> 
> > This new execveat + AT_CHECK should not be confused with the O_EXEC flag
> > (for open) which is intended for execute-only, which obviously doesn't
> > work for scripts.
> > 
> > I gave a talk about controlling script execution where I explain the
> > previous approaches [4].  The design of the WIP RFC I talked about
> > changed quite a bit since then.
> > 
> > [2] https://github.com/zooba/spython
> > [3] https://lore.kernel.org/lkml/20211014130125.6991-1-zohar@linux.ibm.com/
> > [4] https://lssna2023.sched.com/event/1K7bO
> > 
> 
>
Jonathan Corbet July 15, 2024, 8:16 p.m. UTC | #3
Mickaël Salaün <mic@digikod.net> writes:

FYI:

> User space patches can be found here:
> https://github.com/clipos-archive/clipos4_portage-overlay/search?q=O_MAYEXEC

That link appears to be broken.

Thanks,

jon
Mickaël Salaün July 16, 2024, 7:13 a.m. UTC | #4
On Mon, Jul 15, 2024 at 02:16:41PM -0600, Jonathan Corbet wrote:
> Mickaël Salaün <mic@digikod.net> writes:
> 
> FYI:
> 
> > User space patches can be found here:
> > https://github.com/clipos-archive/clipos4_portage-overlay/search?q=O_MAYEXEC
> 
> That link appears to be broken.

Unfortunately, GitHub's code search links only work with an account.
git grep prints a similar output though.

> 
> Thanks,
> 
> jon
Roberto Sassu July 16, 2024, 3:57 p.m. UTC | #5
On Tue, 2024-07-09 at 22:43 +0200, Mickaël Salaün wrote:
> On Mon, Jul 08, 2024 at 04:35:38PM -0400, Mimi Zohar wrote:
> > Hi Mickaël,
> > 
> > On Thu, 2024-07-04 at 21:01 +0200, Mickaël Salaün wrote:
> > > Hi,
> > > 
> > > The ultimate goal of this patch series is to be able to ensure that
> > > direct file execution (e.g. ./script.sh) and indirect file execution
> > > (e.g. sh script.sh) lead to the same result, especially from a security
> > > point of view.
> > > 
> > > Overview
> > > --------
> > > 
> > > This patch series is a new approach of the initial O_MAYEXEC feature,
> > > and a revamp of the previous patch series.  Taking into account the last
> > > reviews [1], we now stick to the kernel semantic for file executability.
> > > One major change is the clear split between access check and policy
> > > management.
> > > 
> > > The first patch brings the AT_CHECK flag to execveat(2).  The goal is to
> > > enable user space to check if a file could be executed (by the kernel).
> > > Unlike stat(2) that only checks file permissions, execveat2(2) +
> > > AT_CHECK take into account the full context, including mount points
> > > (noexec), caller's limits, and all potential LSM extra checks (e.g.
> > > argv, envp, credentials).
> > > 
> > > The second patch brings two new securebits used to set or get a security
> > > policy for a set of processes.  For this to be meaningful, all
> > > executable code needs to be trusted.  In practice, this means that
> > > (malicious) users can be restricted to only run scripts provided (and
> > > trusted) by the system.
> > > 
> > > [1] https://lore.kernel.org/r/CAHk-=wjPGNLyzeBMWdQu+kUdQLHQugznwY7CvWjmvNW47D5sog@mail.gmail.com
> > > 
> > > Script execution
> > > ----------------
> > > 
> > > One important thing to keep in mind is that the goal of this patch
> > > series is to get the same security restrictions with these commands:
> > > * ./script.py
> > > * python script.py
> > > * python < script.py
> > > * python -m script.pyT
> > 
> > This is really needed, but is it the "only" purpose of this patch set or can it
> > be used to also monitor files the script opens (for read) with the intention of
> > executing.
> 
> This feature can indeed also be used to monitor files requested by
> scripts to be executed e.g. using
> https://docs.python.org/3/library/io.html#io.open_code
> 
> IMA/EVM can include this check in its logs.
> 
> > 
> > > 
> > > However, on secure systems, we should be able to forbid these commands
> > > because there is no way to reliably identify the origin of the script:
> > > * xargs -a script.py -d '\r' -- python -c
> > > * cat script.py | python
> > > * python
> > > 
> > > Background
> > > ----------
> > > 
> > > Compared to the previous patch series, there is no more dedicated
> > > syscall nor sysctl configuration.  This new patch series only add new
> > > flags: one for execveat(2) and four for prctl(2).
> > > 
> > > This kind of script interpreter restriction may already be used in
> > > hardened systems, which may need to fork interpreters and install
> > > different versions of the binaries.  This mechanism should enable to
> > > avoid the use of duplicate binaries (and potential forked source code)
> > > for secure interpreters (e.g. secure Python [2]) by making it possible
> > > to dynamically enforce restrictions or not.
> > > 
> > > The ability to control script execution is also required to close a
> > > major IMA measurement/appraisal interpreter integrity [3].
> > 
> > Definitely.  But it isn't limited to controlling script execution, but also
> > measuring the script.  Will it be possible to measure and appraise the indirect
> > script calls with this patch set?
> 
> Yes. You should only need to implement security_bprm_creds_for_exec()
> for IMA/EVM.
> 
> BTW, I noticed that IMA only uses the security_bprm_check() hook (which
> can be called several times for one execve), but
> security_bprm_creds_for_exec() might be more appropriate.

Ok, I tried a trivial modification to have this working:

diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index f04f43af651c..2a6b04c91601 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -554,6 +554,14 @@ static int ima_bprm_check(struct linux_binprm *bprm)
                                   MAY_EXEC, CREDS_CHECK);
 }
 
+static int ima_bprm_creds_for_exec(struct linux_binprm *bprm)
+{
+       if (!bprm->is_check)
+               return 0;
+
+       return ima_bprm_check(bprm);
+}
+
 /**
  * ima_file_check - based on policy, collect/store measurement.
  * @file: pointer to the file to be measured
@@ -1177,6 +1185,7 @@ static int __init init_ima(void)
 
 static struct security_hook_list ima_hooks[] __ro_after_init = {
        LSM_HOOK_INIT(bprm_check_security, ima_bprm_check),
+       LSM_HOOK_INIT(bprm_creds_for_exec, ima_bprm_creds_for_exec),
        LSM_HOOK_INIT(file_post_open, ima_file_check),
        LSM_HOOK_INIT(inode_post_create_tmpfile, ima_post_create_tmpfile),
        LSM_HOOK_INIT(file_release, ima_file_free),


I also adapted the Clip OS 4 patch for bash.

The result seems good so far:

# echo "measure fowner=2000 func=BPRM_CHECK" > /sys/kernel/security/ima/policy

# ./bash /root/test.sh
Hello World

# cat /sys/kernel/security/ima/ascii_runtime_measurements
10 35435d0858d895b90097306171a2e5fcc7f5da9e ima-ng sha256:0e4acf326a82c6bded9d86f48d272d7a036b6490081bb6466ecc2a0e416b244a boot_aggregate
10 4cd9df168a2cf8d18be46543e66c76a53ca6a03d ima-ng sha256:e7f3c2dab66f56fef963fbab55fc6d64bc22a5f900c29042e6ecd87e08f2b535 /root/test.sh

So, it is there.

It works only with +x permission. If not, I get:

# ./bash /root/test.sh
./bash: /root/test.sh: Permission denied

But the Clip OS 4 patch does not cover the redirection case:

# ./bash < /root/test.sh
Hello World

Do you have a more recent patch for that?

Thanks

Roberto

> > 
> > Mimi
> > 
> > > This new execveat + AT_CHECK should not be confused with the O_EXEC flag
> > > (for open) which is intended for execute-only, which obviously doesn't
> > > work for scripts.
> > > 
> > > I gave a talk about controlling script execution where I explain the
> > > previous approaches [4].  The design of the WIP RFC I talked about
> > > changed quite a bit since then.
> > > 
> > > [2] https://github.com/zooba/spython
> > > [3] https://lore.kernel.org/lkml/20211014130125.6991-1-zohar@linux.ibm.com/
> > > [4] https://lssna2023.sched.com/event/1K7bO
> > > 
> > 
> >
James Bottomley July 16, 2024, 4:12 p.m. UTC | #6
On Tue, 2024-07-16 at 17:57 +0200, Roberto Sassu wrote:
> But the Clip OS 4 patch does not cover the redirection case:
> 
> # ./bash < /root/test.sh
> Hello World
> 
> Do you have a more recent patch for that?

How far down the rabbit hole do you want to go?  You can't forbid a
shell from executing commands from stdin because logging in then won't
work.  It may be possible to allow from a tty backed file and not from
a file backed one, but you still have the problem of the attacker
manually typing in the script.

The saving grace for this for shells is that they pretty much do
nothing on their own (unlike python) so you can still measure all the
executables they call out to, which provides reasonable safety.

James
Mickaël Salaün July 16, 2024, 5:31 p.m. UTC | #7
On Tue, Jul 16, 2024 at 12:12:49PM -0400, James Bottomley wrote:
> On Tue, 2024-07-16 at 17:57 +0200, Roberto Sassu wrote:
> > But the Clip OS 4 patch does not cover the redirection case:
> > 
> > # ./bash < /root/test.sh
> > Hello World
> > 
> > Do you have a more recent patch for that?

Bash was only partially restricted for CLIP OS because it was used for
administrative tasks (interactive shell).

Python was also restricted for user commands though:
https://github.com/clipos-archive/clipos4_portage-overlay/blob/master/dev-lang/python/files/python-2.7.9-clip-mayexec.patch

Steve and Christian could help with a better Python implementation.

> 
> How far down the rabbit hole do you want to go?  You can't forbid a
> shell from executing commands from stdin because logging in then won't
> work.  It may be possible to allow from a tty backed file and not from
> a file backed one, but you still have the problem of the attacker
> manually typing in the script.

Yes, that's why we'll have the (optional) SECBIT_EXEC_DENY_INTERACTIVE:
https://lore.kernel.org/all/20240710.eiKohpa4Phai@digikod.net/

> 
> The saving grace for this for shells is that they pretty much do
> nothing on their own (unlike python) so you can still measure all the
> executables they call out to, which provides reasonable safety.

Exactly. Python is a much more interesting target for attacker because
it opens the door for arbitrary syscalls (see the cover letter).

If we want to have a more advanced access control (e.g. allow Bash but
not Python), we should extend existing LSMs to manage the appropriate
securebits according to programs/subjects.
Mickaël Salaün July 16, 2024, 5:47 p.m. UTC | #8
(adding back other people in Cc)

On Tue, Jul 16, 2024 at 01:29:43PM -0400, Boris Lukashev wrote:
> Wouldn't count those shell chickens - awk alone is enough and we can
> use ssh and openssl clients (all in metasploit public code). As one of
> the people who makes novel shell types, I can assure you that this
> effort is only going to slow skiddies and only until the rest of us
> publish mitigations for this mitigation :)

Security is not binary. :)

Not all Linux systems are equals. Some hardened systems need this kind
of feature and they can get guarantees because they fully control and
trust their executable binaries (e.g. CLIP OS, chromeOS) or they
properly sandbox them.  See context in the cover letter.

awk is a script interpreter that should be patched too, like other Linux
tools.

> 
> -Boris (RageLtMan)
> 
> On July 16, 2024 12:12:49 PM EDT, James Bottomley <James.Bottomley@HansenPartnership.com> wrote:
> >On Tue, 2024-07-16 at 17:57 +0200, Roberto Sassu wrote:
> >> But the Clip OS 4 patch does not cover the redirection case:
> >> 
> >> # ./bash < /root/test.sh
> >> Hello World
> >> 
> >> Do you have a more recent patch for that?
> >
> >How far down the rabbit hole do you want to go?  You can't forbid a
> >shell from executing commands from stdin because logging in then won't
> >work.  It may be possible to allow from a tty backed file and not from
> >a file backed one, but you still have the problem of the attacker
> >manually typing in the script.
> >
> >The saving grace for this for shells is that they pretty much do
> >nothing on their own (unlike python) so you can still measure all the
> >executables they call out to, which provides reasonable safety.
> >
> >James
> >
Boris Lukashev July 17, 2024, 5:59 p.m. UTC | #9
Apologies, sent from phone so plain-text wasn't flying.
To elaborate a bit on the quick commentary there - i'm the happy
camper behind most of the SSL shells, SSH stuff, AWS shells, and so on
in Metasploit. So please take the following with a grain of
tinfoil-hat salt as i'm well aware that there is no perfect defense
against these things which covers all bases while permitting any level
of sane operation in a general-purpose linux system (also work w/
GrapheneOS which is a far more suitable context for this sort of
thing). Having loosely followed the discussion thread, my offsec-brain
$0.02 are:

Shells are the provenance of the post-exploitation world - it's what
we want to get as a result of the exploit succeeding. So i think we
want to keep clear delineation between exploit and post-exp mitigation
as they're actually separate concerns of the killchain.
1. Command shells tend to differentiate from interpreted or binary
execution environments in their use of POSIX file descriptor
primitives such as pipes. How those are marshalled, chained, and
maintained (in a loop or whatever, hiding args, etc) are the only real
IOCs available at this tier for interdiction as observation of data
flow through the pipes is too onerous and complex. Target systems vary
in the post-exp surfaces exposed (/dev/tcp for example) with the
mechanics of that exposure necessitating adaptation of marshalling,
chaining, and maintenance to fit the environment; but the basic
premise of what forms a command shell cannot be mitigated without
breaking POSIX mechanics themselves - offsec devs are no different
from anyone else, we want our code to utilize architectural primitives
instead of undefined behavior for longevity and ecosystem
persistence/relevance.
2. The conversation about interpreted languages is probably a dead-end
unless you want to neuter the interpreter - check out Spencer
McIntyre's work re Python meterpreter or HDs/mine/etc on the PHP side.
The stagers, loaded contexts, execution patterns, etc are all
trivially modified to avoid detection (private versions not submitted
for free ripping by lazy commercial entities to the FOSS ecosystem,
yet). Dynamic code loading of interpreted languages is trivial and
requires no syscalls, just text/serialized IL/etc. The complexity of
loaded context available permits much more advanced functionality than
we get in most basic command interpreter shells - <advanced evasions
go here before doing something that'll get you caught> sort of thing.
3. Lastly, binary payloads such as Mettle have their own advantages re
portability, skipping over libc, etc but need to be "harnessed-in"
from say a command-injection exploit via memfd or similar. We haven't
published our memfd stagers while the relevant sysctl gets adopted
more widely, but we've had them for a long time (meaning real bad guys
have as well) and have other ways to get binary content into
executable memory or make memory containing it executable
(to-the-gills Grsec/PaX systems notwithstanding). IMO, interdiction of
the harnessed injection from a command context is the last time when
anything of use can be done at this layer unless we're sure that we
can trace all related and potentially async (not within the process
tree anyway) syscalls emanating from what happens next. Subsequent
actions are separate "remedial" workflows which is a wholly separate
philosophical discussion about how to handle having been compromised
already.

Security is very much not binary and in that vein of logic i think
that we should probably define our shades of gray as ranges of what we
want to protect/how and at what operational cost to then permit
"dial-in" knobs to actually garner adoption from a broad range of
systems outside the "real hardened efforts." At some point this turns
into "limit users to sftp or git shells" which is a perfectly valid
approach when the context permits that level of draconian restriction
but the architectural breakdown of "native command, interpreted
context, fully binary" shell types is pretty universal with new ones
being API access into runtimes of clouds (SSM/serial/etc) which have
their own set of limitations at execution and interface layers.
Organizing defensive functions to handle the primitives necessary for
each of these shell classes would likely help stratify/simplify this
conversation and allow for more granular tasking toward those specific
objectives.

Thanks,
-Boris


On Tue, Jul 16, 2024 at 1:48 PM Mickaël Salaün <mic@digikod.net> wrote:
>
> (adding back other people in Cc)
>
> On Tue, Jul 16, 2024 at 01:29:43PM -0400, Boris Lukashev wrote:
> > Wouldn't count those shell chickens - awk alone is enough and we can
> > use ssh and openssl clients (all in metasploit public code). As one of
> > the people who makes novel shell types, I can assure you that this
> > effort is only going to slow skiddies and only until the rest of us
> > publish mitigations for this mitigation :)
>
> Security is not binary. :)
>
> Not all Linux systems are equals. Some hardened systems need this kind
> of feature and they can get guarantees because they fully control and
> trust their executable binaries (e.g. CLIP OS, chromeOS) or they
> properly sandbox them.  See context in the cover letter.
>
> awk is a script interpreter that should be patched too, like other Linux
> tools.
>
> >
> > -Boris (RageLtMan)
> >
> > On July 16, 2024 12:12:49 PM EDT, James Bottomley <James.Bottomley@HansenPartnership.com> wrote:
> > >On Tue, 2024-07-16 at 17:57 +0200, Roberto Sassu wrote:
> > >> But the Clip OS 4 patch does not cover the redirection case:
> > >>
> > >> # ./bash < /root/test.sh
> > >> Hello World
> > >>
> > >> Do you have a more recent patch for that?
> > >
> > >How far down the rabbit hole do you want to go?  You can't forbid a
> > >shell from executing commands from stdin because logging in then won't
> > >work.  It may be possible to allow from a tty backed file and not from
> > >a file backed one, but you still have the problem of the attacker
> > >manually typing in the script.
> > >
> > >The saving grace for this for shells is that they pretty much do
> > >nothing on their own (unlike python) so you can still measure all the
> > >executables they call out to, which provides reasonable safety.
> > >
> > >James
> > >
Mickaël Salaün July 18, 2024, 1 p.m. UTC | #10
On Wed, Jul 17, 2024 at 01:59:22PM -0400, Boris Lukashev wrote:
> Apologies, sent from phone so plain-text wasn't flying.
> To elaborate a bit on the quick commentary there - i'm the happy
> camper behind most of the SSL shells, SSH stuff, AWS shells, and so on
> in Metasploit. So please take the following with a grain of
> tinfoil-hat salt as i'm well aware that there is no perfect defense
> against these things which covers all bases while permitting any level
> of sane operation in a general-purpose linux system (also work w/
> GrapheneOS which is a far more suitable context for this sort of
> thing). Having loosely followed the discussion thread, my offsec-brain
> $0.02 are:
> 
> Shells are the provenance of the post-exploitation world - it's what
> we want to get as a result of the exploit succeeding. So i think we
> want to keep clear delineation between exploit and post-exp mitigation
> as they're actually separate concerns of the killchain.

Indeed.  The goal of this patch series is to control executable code, so
mostly to make exploitation more difficult. When an attacker can execute
code (e.g. with ROP), execution control is already bypassed.

> 1. Command shells tend to differentiate from interpreted or binary
> execution environments in their use of POSIX file descriptor
> primitives such as pipes. How those are marshalled, chained, and
> maintained (in a loop or whatever, hiding args, etc) are the only real
> IOCs available at this tier for interdiction as observation of data
> flow through the pipes is too onerous and complex.

I agree. Only files can reliably be inspected.

> Target systems vary
> in the post-exp surfaces exposed (/dev/tcp for example) with the
> mechanics of that exposure necessitating adaptation of marshalling,
> chaining, and maintenance to fit the environment; but the basic
> premise of what forms a command shell cannot be mitigated without
> breaking POSIX mechanics themselves - offsec devs are no different
> from anyone else, we want our code to utilize architectural primitives
> instead of undefined behavior for longevity and ecosystem
> persistence/relevance.
> 2. The conversation about interpreted languages is probably a dead-end
> unless you want to neuter the interpreter - check out Spencer
> McIntyre's work re Python meterpreter or HDs/mine/etc on the PHP side.
> The stagers, loaded contexts, execution patterns, etc are all
> trivially modified to avoid detection (private versions not submitted
> for free ripping by lazy commercial entities to the FOSS ecosystem,
> yet). Dynamic code loading of interpreted languages is trivial and
> requires no syscalls, just text/serialized IL/etc. The complexity of
> loaded context available permits much more advanced functionality than
> we get in most basic command interpreter shells - <advanced evasions
> go here before doing something that'll get you caught> sort of thing.

Right, if attackers can bring their own code (or even do ROP), it
doesn't matter what it interprets, its arbitrary code execution.

> 3. Lastly, binary payloads such as Mettle have their own advantages re
> portability, skipping over libc, etc but need to be "harnessed-in"
> from say a command-injection exploit via memfd or similar. We haven't
> published our memfd stagers while the relevant sysctl gets adopted
> more widely, but we've had them for a long time (meaning real bad guys
> have as well) and have other ways to get binary content into
> executable memory or make memory containing it executable
> (to-the-gills Grsec/PaX systems notwithstanding). IMO, interdiction of
> the harnessed injection from a command context is the last time when
> anything of use can be done at this layer unless we're sure that we
> can trace all related and potentially async (not within the process
> tree anyway) syscalls emanating from what happens next. Subsequent
> actions are separate "remedial" workflows which is a wholly separate
> philosophical discussion about how to handle having been compromised
> already.

Indeed, there are some prerequisites for a secure system.  In this case
we trust all the system-installed executable code.  If attackers can
fill a memfd with arbitrary code, it means that they already have code
execution.  This patch series will help mitigate some ways to get code
execution.

> 
> Security is very much not binary and in that vein of logic i think
> that we should probably define our shades of gray as ranges of what we
> want to protect/how and at what operational cost to then permit
> "dial-in" knobs to actually garner adoption from a broad range of
> systems outside the "real hardened efforts." At some point this turns
> into "limit users to sftp or git shells" which is a perfectly valid
> approach when the context permits that level of draconian restriction
> but the architectural breakdown of "native command, interpreted
> context, fully binary" shell types is pretty universal with new ones
> being API access into runtimes of clouds (SSM/serial/etc) which have
> their own set of limitations at execution and interface layers.
> Organizing defensive functions to handle the primitives necessary for
> each of these shell classes would likely help stratify/simplify this
> conversation and allow for more granular tasking toward those specific
> objectives.

Thanks for the discussion.  I agree, but the difficulty with this patch
series is that it brings a simple *building block*.  Of course, this
will definitely not be enough to secure any systems, but it will fill a
gap in some secure systems, and it could also harden more generic
systems (e.g. restricted system services which should not need shell
access).  I listed some examples with the new securebits proposal:
https://lore.kernel.org/all/20240710.eiKohpa4Phai@digikod.net/

> 
> Thanks,
> -Boris
> 
> 
> On Tue, Jul 16, 2024 at 1:48 PM Mickaël Salaün <mic@digikod.net> wrote:
> >
> > (adding back other people in Cc)
> >
> > On Tue, Jul 16, 2024 at 01:29:43PM -0400, Boris Lukashev wrote:
> > > Wouldn't count those shell chickens - awk alone is enough and we can
> > > use ssh and openssl clients (all in metasploit public code). As one of
> > > the people who makes novel shell types, I can assure you that this
> > > effort is only going to slow skiddies and only until the rest of us
> > > publish mitigations for this mitigation :)
> >
> > Security is not binary. :)
> >
> > Not all Linux systems are equals. Some hardened systems need this kind
> > of feature and they can get guarantees because they fully control and
> > trust their executable binaries (e.g. CLIP OS, chromeOS) or they
> > properly sandbox them.  See context in the cover letter.
> >
> > awk is a script interpreter that should be patched too, like other Linux
> > tools.
> >
> > >
> > > -Boris (RageLtMan)
> > >
> > > On July 16, 2024 12:12:49 PM EDT, James Bottomley <James.Bottomley@HansenPartnership.com> wrote:
> > > >On Tue, 2024-07-16 at 17:57 +0200, Roberto Sassu wrote:
> > > >> But the Clip OS 4 patch does not cover the redirection case:
> > > >>
> > > >> # ./bash < /root/test.sh
> > > >> Hello World
> > > >>
> > > >> Do you have a more recent patch for that?
> > > >
> > > >How far down the rabbit hole do you want to go?  You can't forbid a
> > > >shell from executing commands from stdin because logging in then won't
> > > >work.  It may be possible to allow from a tty backed file and not from
> > > >a file backed one, but you still have the problem of the attacker
> > > >manually typing in the script.
> > > >
> > > >The saving grace for this for shells is that they pretty much do
> > > >nothing on their own (unlike python) so you can still measure all the
> > > >executables they call out to, which provides reasonable safety.
> > > >
> > > >James
> > > >
Mickaël Salaün July 18, 2024, 4:21 p.m. UTC | #11
On Tue, Jul 16, 2024 at 07:31:45PM +0200, Mickaël Salaün wrote:
> On Tue, Jul 16, 2024 at 12:12:49PM -0400, James Bottomley wrote:
> > On Tue, 2024-07-16 at 17:57 +0200, Roberto Sassu wrote:
> > > But the Clip OS 4 patch does not cover the redirection case:
> > > 
> > > # ./bash < /root/test.sh
> > > Hello World
> > > 
> > > Do you have a more recent patch for that?
> 
> Bash was only partially restricted for CLIP OS because it was used for
> administrative tasks (interactive shell).
> 
> Python was also restricted for user commands though:
> https://github.com/clipos-archive/clipos4_portage-overlay/blob/master/dev-lang/python/files/python-2.7.9-clip-mayexec.patch
> 
> Steve and Christian could help with a better Python implementation.

I'll include a toy interpreter in the next patch series.  That should
help for experiments.