bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH/RFC] do not source/exec scripts on noexec mount points


From: konsolebox
Subject: Re: [PATCH/RFC] do not source/exec scripts on noexec mount points
Date: Tue, 15 Dec 2015 17:53:23 +0800

On Tue, Dec 15, 2015 at 7:30 AM, Mike Frysinger <vapier@gentoo.org> wrote:
> On 15 Dec 2015 06:47, konsolebox wrote:
>> t On Mon, Dec 14, 2015 at 1:17 PM, Mike Frysinger <vapier@gentoo.org> wrote:
>> > On 13 Dec 2015 16:50, konsolebox wrote:
>> >> On Sun, Dec 13, 2015 at 5:01 AM, Mike Frysinger wrote:
>> >> > Today, if you have a script that lives on a noexec mount point, the
>> >> > kernel will reject attempts to run it directly:
>> >> >   $ printf '#!/bin/sh\necho hi\n' > /dev/shm/test.sh
>> >> >   $ chmod a+rx /dev/shm/test.sh
>> >> >   $ /dev/shm/test.sh
>> >> >   bash: /dev/shm/test.sh: Permission denied
>> >> >
>> >> > But bash itself has no problem running this file:
>> >> >   $ bash /dev/shm/test.sh
>> >> >   hi
>> >> > Or with letting other scripts run this file:
>> >> >   $ bash -c '. /dev/shm/test.sh'
>> >> >   hi
>> >> > Or with reading the script from stdin:
>> >> >   $ bash </dev/shm/test.sh
>> >> >   hi
>> >> >
>> >> > This detracts from the security of the overall system.  People writing
>> >> > scripts sometimes want to save/restore state (s) and will
>> >> > restore the content from a noexec point using the aforementioned source
>> >> > command without realizing that it executes code too.  Of course their
>> >> > code is wrong, but it would be nice if the system would catch & reject
>> >> > it explicitly to stave of inadvertent usage.
>> >> >
>> >> > This is not a perfect solution as it can still be worked around by
>> >> > inlining the code itself:
>> >> >   $ bash -c "$(cat /dev/shm/test.sh)"
>> >> >   hi
>> >> >
>> >> > But this makes things a bit harder for malicious attackers (depending
>> >> > how exactly they've managed to escalate), but it also helps developers
>> >> > from getting it wrong in the first place.
>> >>
>> >> Application-level based security on an environment where people using
>> >> the application has direct control over the environment for me is not
>> >> so sensible, and is a dirty hack.  A shell is also not meant for that.
>> >> If you want such feature perhaps you should add it on a restricted
>> >> shell, granting it really makes sense adding it.  But forcing that
>> >> feature to be default on every user (like me who doesn't want its
>> >> inconsistency) is wrong.  A shell reads and executes and is something
>> >> not in the scope of `noexec`, not in the scope of kernel-land
>> >> security, so we have to deal with it.
>> >
>> > (1) the examples i already provided do not involve the user at all, and
>> >     include systems where the user has no direct access to the shell.
>>
>> And the one that made the code execute remotely through for example an
>> exploit is not a user?
>
> you're conflating concepts, but still, the answer is no.  having a user
> sitting at an interactive terminal and typing in commands or getting the
> system to directly execute bash is not what i described.  systems that
> do not permit access to any shells anywhere, and instead the attack is
> breaking out of one process to write a text file somewhere that a diff
> system/periodic process will later source.  you could get the same setup
> as having a system you can only access over HTTP (i.e. no shell access)
> and exploiting apache/php/whatever to write to a cache file that will be
> read by another app.
>
> i recall some router firmwares being attacked in this way -- a remote
> bug only permitted the writing of data to common data locations, but
> they picked a place where privileged init scripts would source saved
> state.

Ok I accept your point.  So it's actually about `source` and `bash
file`, correct?  So would this mean every script I `source` would need
+x bit now?  And if it's not about the +x bit and only about `noexec`,
would stuff I place that I would want to not execute (with execve(),
etc.) in a `noexec` directory no longer be `source`-able, even though
I'm still wanting those to be `source`-d?  `source` is meant to only
require readable permission.

>> > (2) choice over runtime functionality is by the sysadmin, not the user.
>>
>> Doesn't matter to me. And I'm referring to the real user or the
>> person, and not the account. I don't want an inconsistent
>> functionality running in my bash whether I'm using a privileged
>> account or not.
>
> it isn't inconsistent: no user gets to exec code from noexec points

You complicate it.  I'm both a user and an administrator to my
personal system and I don't want that function running by default in
my bash.  Simple.

>> > (3) i disagree over the scope of noexec.  i think this is in-scope.
>>
>> Being a little forgiving, I could say that scripts with #! headers
>> -perhaps- are still in the scope of `noexec` since they are respected
>> by the kernel as executables, even though they are not real
>> instructions running within the processor's transistors themselves
>> (they are just read and -virtually- executed where the shell acts on
>> behalf of them), but how about those scripts without #! headers?
>> Clearly they're no longer -executables-.  And clearly you're just
>> wanting bash to restrict things based on the conceptual purpose of
>> `noexec`, even though it is not exactly or strictly in the scope of
>> `noexec`.  I'm a purist and I don't like that, and I don't want to
>> have that inconsistency in default bash.
>
> you're describing libraries which the kernel also blocks.  there's no
> relevant difference between fragments you source and libraries that
> ELF programs link against either directly (e.g. -lfoo) or indirectly
> (e.g. dlopen(libfoo)).  the kernel blocks both as i described in my
> first e-mail.

Yes, but this time it's no longer the kernel that blocks the scripts,
but bash.  The kernel doesn't know anything about it, and the kernel
doesn't see those as codes, just data.  The restriction is no longer
in the kernel-land, but user-land.  Also, whether to bash "fragments
you source" are codes, both codes and data, or simply just data (only
needs +r), depends on one's perception and use of it.

The thing is, you're trying to implement the concept of `noexec` in
the application level.  You're making use of `noexec` as a flag to
make bash restrict itself from `source`-ing scripts located on a mount
point or directory with such attribute.  `noexec` (and the kernel that
implements `noexec`) really has nothing to do with it.  You're just
trying to -extend- the scope of `noexec` to applications.  That is the
inconsistency which is clear.  You're just wanting bash to behave
based on its concept, and not really based on a rule of a system or a
particular system feature.  It's not really about how similar module
scripts are to ELF libraries when they get used, or how virtually
similar an interpret-and-emulate application works compared to the
parse-and-execute kernel.

At least place it on restricted shell, or have `bash` make it a
feature enabled at compile-time with a flag disabled by default, but
never make it as a default function.  It's more of a feature, and not
a functionality every shell should have by default.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]