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

2015-12-16 Thread Chet Ramey
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

On 12/14/15 12:17 AM, Mike Frysinger wrote:

> 
> (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.

You didn't really provide any examples. You mentioned ChromeOS and vaguely
referenced "other verified boot systems".

If non-general-purpose systems is the set of systems for which this
proposal is in scope, that changes the impact.  Since you generally build
custom versions for such systems, a configuration-time option to enable
this behavior is more reasonable.

> (2) choice over runtime functionality is by the sysadmin, not the user.

In this case, or in general?

> (3) i disagree over the scope of noexec.  i think this is in-scope.

I really don't agree that it's in the spirit of noexec.

- -- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/
-BEGIN PGP SIGNATURE-
Version: GnuPG v2

iEUEARECAAYFAlZxyEoACgkQu1hp8GTqdKs7iwCeN3RSffaijMfXrzceHrbksjXE
W1oAl0qJHWNo/qNu0cOijRbbNEzDJt4=
=kLgz
-END PGP SIGNATURE-



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

2015-12-16 Thread Chet Ramey
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

On 12/14/15 12:32 AM, Mike Frysinger wrote:
> On 13 Dec 2015 17:24, Chet Ramey wrote:
>> On 12/12/15 4:01 PM, 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:
>>
>> It's hard to see how this proposal improves overall system security.  Th
ere
>> are a dozen ways a minimally-competent attacker can circumvent it.
> 
> you're assuming the attacker has unlimited access to resources and contro
l
> over the environment and execution.  

Of course -- that's the general case.  You're talking about changes to a
general tool installed in such environments.



> i already noted there are ways to run
> arbitrary code -- when you have arbitrary code access.  there also are ca
ses
> (such as i described) which this change would block attacks because the
> attacker does not have such unfettered access.  they're leveraging a smal
l
> bug elsewhere to escalate to a fuller environment.

What's the intended set of systems for which this would be useful?


>> A worse problem is that the abstraction is in the wrong place.  The shel
l,
>> like other programs, requests services from the kernel to do things.  Th
e
>> kernel is the arbiter of restrictions on those services.  If asked to
>> execute a file, the shell asks the kernel whether the file is executable
,
>> then tries to execute it.  If asked to read a file, the shell tries to
>> open it.  The kernel, or some agent it invokes, is where the access
>> decision is made.  If you want to, for instance, disallow the shell and
>> other utilities from opening executable files for reading on file system
s
>> with noexec set, the shell binary is not the place to embed that policy.
> 
> i'm aware of the fundamental structure of UNIX-like systems.

Yes, I know you are.  I'm placing my point in context.

> bash itself
> is providing services to a program by executing the requested code 

I suppose you can make that argument, but I don't think it fits within what
I understand the intent of `noexec' to be.

> and in
> a sense, has a responsibility to control that.  otherwise, you seem to be
> arguing against the existence of rbash, or job control, or similar shell
> limiting/control functionality.

I actually think rbash is kind of useless.  In the case of job control,
or ulimit, or trap, or cd, the shell is exposing kernel functionality to
the user and allowing him to access it.

> i understand this is a disruptive change.  how about making it a compile
> time flag, or perhaps a new shopt ?

It depends on the set of intended target systems and the users' scope of
access to the entire system.  On some captive system like a chromebook or
a linux-based video player (like an airplane seat-back player, for
instance), I can see a compile-time flag making sense.  I don't think this
has a place on a general-purpose user system.

- -- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/
-BEGIN PGP SIGNATURE-
Version: GnuPG v2

iEYEARECAAYFAlZxzE0ACgkQu1hp8GTqdKv0bACfb3m6AM0N59cQZJkWe3GYFwKb
Ic0An28bMKeihs7sVsfG9EXoFCB0MGmH
=ALQH
-END PGP SIGNATURE-



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

2015-12-16 Thread Chet Ramey
On 12/16/15 3:29 PM, John McKown wrote:
> FWIW (not much), I'm going to go with Chet on this. It may be my ignorance
> speaking, but what can I do in a BASH shell script which I cannot do (at
> all) just by entering the commands by hand?

That's where the scope of the proposal makes a difference.  If it's
intended for captive systems where the user does not have direct access
to the shell or the file system, that's a different thing than a general
purpose system.

Chet

-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/



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

2015-12-16 Thread Chet Ramey
On 12/15/15 4:53 AM, konsolebox wrote:

> 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.

Correct.  If this were to be in effect, anything that you wanted to
source would fail if the file to be read were on a file system mounted
noexec.


> 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.

This raises the queation of the set of systems to which this is intended
to apply.  It's clearly inappropriate for general-purpose Unix/Linux
systems, but single-purpose systems on which the user does not have
access to the file system or the shell are a different story.


> 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.  

This is true.  The question is whether or not your mental model of how
`noexec' should work includes this case.  It's clearly true that the
proposal embeds policy in the bash binary.  Whether or not that policy
is appropriate depends on your answer to the previous question.

-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/



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

2015-12-15 Thread konsolebox
On Tue, Dec 15, 2015 at 7:30 AM, Mike Frysinger  wrote:
> On 15 Dec 2015 06:47, konsolebox wrote:
>> t On Mon, Dec 14, 2015 at 1:17 PM, Mike Frysinger  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 > >> >   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 

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

2015-12-14 Thread Mike Frysinger
On 15 Dec 2015 06:47, konsolebox wrote:
> t On Mon, Dec 14, 2015 at 1:17 PM, Mike Frysinger  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  >> >   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.

> Also consider use of `source` or `eval` may it be in a subshell or not.

these cases have already been cited in this thread, and still are not
relevant to the scenarios described

> > (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

> > (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.
-mike


signature.asc

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

2015-12-14 Thread konsolebox
t On Mon, Dec 14, 2015 at 1:17 PM, Mike Frysinger  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 > >   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? Also consider use of `source` or `eval` may it
be in a subshell or not.

eval "$(cat /path/script.sh)"
source <(cat /path/script.sh)

> (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.

> (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.



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

2015-12-13 Thread Stephane Chazelas
2015-12-12 17:53:35 -0500, Mike Frysinger:
[...]
> > It will almost
> > certainly get in the way of a reasonable use case.
> 
> can you name a reasonable use case this breaks ?

bash << EOF
some code
EOF

here-documents with many shells (including bash) are implemented
as deleted temporary files (typically in /tmp which sometimes has
noexec).

-- 
Stephane



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

2015-12-13 Thread Stephane Chazelas
2015-12-12 16:01:26 -0500, Mike Frysinger:
[...]
> 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

Or

cat /dev/shm/test.sh | bash

I think this kind of hardening is better left to things like
selinux/apparmor.

-- 
Stephane



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

2015-12-13 Thread Mike Frysinger
On 13 Dec 2015 12:21, Piotr Grzybowski wrote:
> On Sat, Dec 12, 2015 at 11:53 PM, Mike Frysinger wrote:
> > On 12 Dec 2015 15:06, Bob Proulx wrote:
> >> It will almost
> >> certainly get in the way of a reasonable use case.
> >
> > can you name a reasonable use case this breaks ?
> 
> source /media/noexecmountpoint/sh/functions.sh;
> find_all_files_with_executable_bit /media/noexecmountpoint;

i think you're doing it wrong.  if you want to run code off of mount
point, then you should be mounting it executable.

>  Mike: I kind of understand your idea, but noexec flag given in the
> mount significates something else then your patch addresses.

i disagree
-mike


signature.asc
Description: Digital signature


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

2015-12-13 Thread Mike Frysinger
On 12 Dec 2015 23:05, Stephane Chazelas wrote:
> 2015-12-12 16:01:26 -0500, Mike Frysinger:
> [...]
> > 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
> 
> Or
> 
> cat /dev/shm/test.sh | bash

right, there's no way to look through pipes

> I think this kind of hardening is better left to things like
> selinux/apparmor.

security is not an all-or-nothing proposotion.  the whole point is to
have defence in depth.
-mike


signature.asc
Description: Digital signature


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

2015-12-13 Thread Chet Ramey
On 12/12/15 4:01 PM, Mike Frysinger wrote:
> From: Mike Frysinger 
> 
> 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:

It's hard to see how this proposal improves overall system security.  There
are a dozen ways a minimally-competent attacker can circumvent it.  Unless
you want to completely remove the ability for bash and other utilities to
read files from a noexec file system, or run on a system with no writable
file systems at all, this does no good.  Its primary effect would seem to
be annoying and frustrating users.

A worse problem is that the abstraction is in the wrong place.  The shell,
like other programs, requests services from the kernel to do things.  The
kernel is the arbiter of restrictions on those services.  If asked to
execute a file, the shell asks the kernel whether the file is executable,
then tries to execute it.  If asked to read a file, the shell tries to
open it.  The kernel, or some agent it invokes, is where the access
decision is made.  If you want to, for instance, disallow the shell and
other utilities from opening executable files for reading on file systems
with noexec set, the shell binary is not the place to embed that policy.

Chet
-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/



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

2015-12-13 Thread Mike Frysinger
On 13 Dec 2015 17:24, Chet Ramey wrote:
> On 12/12/15 4:01 PM, 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:
> 
> It's hard to see how this proposal improves overall system security.  There
> are a dozen ways a minimally-competent attacker can circumvent it.

you're assuming the attacker has unlimited access to resources and control
over the environment and execution.  i already noted there are ways to run
arbitrary code -- when you have arbitrary code access.  there also are cases
(such as i described) which this change would block attacks because the
attacker does not have such unfettered access.  they're leveraging a small
bug elsewhere to escalate to a fuller environment.

> Unless
> you want to completely remove the ability for bash and other utilities to
> read files from a noexec file system, or run on a system with no writable
> file systems at all, this does no good.  Its primary effect would seem to
> be annoying and frustrating users.
> 
> A worse problem is that the abstraction is in the wrong place.  The shell,
> like other programs, requests services from the kernel to do things.  The
> kernel is the arbiter of restrictions on those services.  If asked to
> execute a file, the shell asks the kernel whether the file is executable,
> then tries to execute it.  If asked to read a file, the shell tries to
> open it.  The kernel, or some agent it invokes, is where the access
> decision is made.  If you want to, for instance, disallow the shell and
> other utilities from opening executable files for reading on file systems
> with noexec set, the shell binary is not the place to embed that policy.

i'm aware of the fundamental structure of UNIX-like systems.  bash itself
is providing services to a program by executing the requested code and in
a sense, has a responsibility to control that.  otherwise, you seem to be
arguing against the existence of rbash, or job control, or similar shell
limiting/control functionality.

i understand this is a disruptive change.  how about making it a compile
time flag, or perhaps a new shopt ?
-mike


signature.asc
Description: Digital signature


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

2015-12-13 Thread Mike Frysinger
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  >   hi
> >
> > This detracts from the security of the overall system.  People writing
> > scripts sometimes want to save/restore state (like variables) 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.
(2) choice over runtime functionality is by the sysadmin, not the user.
(3) i disagree over the scope of noexec.  i think this is in-scope.
-mike


signature.asc
Description: Digital signature


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

2015-12-12 Thread John McKown
On Sat, Dec 12, 2015 at 3:01 PM, Mike Frysinger  wrote:

> From: Mike Frysinger 
>
> 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:
>   $ bashhi
>
> This detracts from the security of the overall system.  People writing
> scripts sometimes want to save/restore state (like variables) 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

​

If this is a bug in BASH, then it is likely also a bug in: Python, PERL,
Ruby, LUA, oorexx, . But,
quite honestly, I haven't checked it out because I don't have a "noexec"
mountpoint handy here at home.​




-- 

Schrodinger's backup: The condition of any backup is unknown until a
restore is attempted.

Yoda of Borg, we are. Futile, resistance is, yes. Assimilated, you will be.

He's about as useful as a wax frying pan.

10 to the 12th power microphones = 1 Megaphone

Maranatha! <><
John McKown


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

2015-12-12 Thread Mike Frysinger
On 12 Dec 2015 22:12, John McKown wrote:
> On Sat, Dec 12, 2015 at 3:01 PM, 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  >   hi
> >
> > This detracts from the security of the overall system.  People writing
> > scripts sometimes want to save/restore state (like variables) 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
> 
> ​
> 
> If this is a bug in BASH, then it is likely also a bug in: Python, PERL,
> Ruby, LUA, oorexx, . But,
> quite honestly, I haven't checked it out because I don't have a "noexec"
> mountpoint handy here at home.​

i'm aware.  it'd make sense in my mind to have all dynamic interpreters
detect the source files before attempting to execute them.  i'm looking
at shells to start with as they're way more common to be installed and
to be a target.
-mike


signature.asc
Description: Digital signature


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

2015-12-12 Thread Mike Frysinger
On 12 Dec 2015 15:06, Bob Proulx wrote:
> Mike Frysinger wrote:
> > But bash itself has no problem running this file:
> >   $ bash /dev/shm/test.sh
> >   hi
> >...
> > This detracts from the security of the overall system.  People
> > writing scripts sometimes want to save/restore state (like
> > variables) 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.
> 
> I don't think it makes sense for a userland program to be an enforcer
> of this type of check.  It gives a false impression of a security that
> does not exist.  Which I think is more dangerous.

i disagree, and it's the right place imo: the program that does the
interpreting in the first place (i.e. the shell) should be checking
for the settings where it's going to be loading that interpreted
code.

the reason binary loaders (e.g. ELF ldso's) don't need to do this is
the kernel either prevents it directly (`./foo`) or indirectly (when
the ldso tries to mmap the file with exec bits, the kernel will check
for the noexec mount setting).

> It will almost
> certainly get in the way of a reasonable use case.

can you name a reasonable use case this breaks ?

> And nothing
> prevents one from running a private copy of a shell without such a
> check.  Or any of the many compatible /bin/sh variants such as ksh,
> zsh, ash, dash, and so forth.

you're assuming (1) the user has access to a writable && exec mount point
and (2) those other shells are installed.  clamping both of those loop
holes are trivial and i've seen a number of systems that do exactly that.
Chrome OS for example only mounts / as executable and that is also read
only.  i imagine other verified boot systems enforce similar sanity, as
do remote hosts (a number of systems i have ssh access do this).

i also plan on sending patches for shells i care about (e.g. dash).
-mike


signature.asc
Description: Digital signature


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

2015-12-12 Thread Mike Frysinger
From: Mike Frysinger 

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 
 #include 
 
+#if defined (HAVE_SYS_STATVFS_H)
+#  include 
+#endif
+
 #include "../bashansi.h"
 #include "../bashintl.h"
 
@@ -160,6 +164,26 @@ file_error_and_exit:
   return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1);
 }  
 
+#if defined (HAVE_SYS_STATVFS_H) && defined (ST_NOEXEC)
+  /* If the script is loaded from a noexec mount point, throw an error.  */
+  {
+struct statvfs stvfs;
+
+if (fstatvfs (fd, ) == -1)
+  {
+   close (fd);
+   goto file_error_and_exit;
+  }
+
+if (stvfs.f_flag & ST_NOEXEC)
+  {
+   close (fd);
+   errno = EACCES;
+   goto file_error_and_exit;
+  }
+  }
+#endif
+
   if (S_ISREG (finfo.st_mode) && file_size <= SSIZE_MAX)
 {
   string = (char *)xmalloc (1 + file_size);
diff --git a/config.h.in b/config.h.in
index 894892f..b16f1d6 100644
--- a/config.h.in
+++ b/config.h.in
@@ -1039,6 +1039,9 @@
 /* Define if you have the  header file. */
 #undef HAVE_SYS_STAT_H
 
+/* Define if you have .  */
+#undef HAVE_SYS_STATVFS_H
+
 /* Define if you have the  header file.  */
 #undef HAVE_SYS_STREAM_H
 
diff --git a/configure b/configure
index 52f6f5c..061b15e 100755
--- a/configure
+++ b/configure
@@ -9301,7 +9301,7 @@ fi
 done
 
 for ac_header in sys/pte.h sys/stream.h sys/select.h sys/file.h sys/ioctl.h \
-sys/param.h sys/socket.h sys/stat.h \
+sys/param.h sys/socket.h sys/stat.h sys/statvfs.h \
 sys/time.h sys/times.h sys/types.h sys/wait.h
 do :
   as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
diff --git a/configure.ac b/configure.ac
index f0d4aee..81b2a7c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -717,7 +717,7 @@ AC_CHECK_HEADERS(unistd.h stdlib.h stdarg.h varargs.h 
limits.h string.h \
 stdbool.h stddef.h stdint.h netdb.h pwd.h grp.h strings.h \
 regex.h syslog.h ulimit.h)
 AC_CHECK_HEADERS(sys/pte.h sys/stream.h sys/select.h sys/file.h sys/ioctl.h \
-sys/param.h sys/socket.h sys/stat.h \
+sys/param.h sys/socket.h sys/stat.h sys/statvfs.h \
 sys/time.h sys/times.h sys/types.h sys/wait.h)
 AC_CHECK_HEADERS(netinet/in.h arpa/inet.h)
 
diff --git a/shell.c b/shell.c
index 0e47cf4..4739a31 100644
--- a/shell.c
+++ b/shell.c
@@ -46,6 +46,10 @@
 #  include 
 #endif
 
+#if defined (HAVE_SYS_STATVFS_H)
+#  include 
+#endif
+
 #include "bashintl.h"
 
 #define NEED_SH_SETLINEBUF_DECL/* used in externs.h */
@@ -334,6 +338,8 @@ static void shell_reinitialize __P((void));
 
 static void show_shell_usage __P((FILE *, int));
 
+static void check_noexec __P((int, const char *));
+
 #ifdef __CYGWIN__
 static void
 _cygwin32_check_tmp ()
@@ -717,6 +723,7 @@ main (argc, argv, env)
 {
   /* In this mode, bash is reading a script from stdin, which is a
 pipe or redirected file. */
+  check_noexec (0, "stdin");
 #if defined (BUFFERED_INPUT)
   default_buffered_input = fileno (stdin); /* == 0 */
 #else
@@ -1442,6 +1449,28 @@ start_debugger ()
 #endif
 }
 
+static void
+check_noexec (int fd, const char *filename)
+{
+#if defined (HAVE_SYS_STATVFS_H) && defined (ST_NOEXEC)
+  /* Make sure the file isn't on a noexec mount point.  */
+  struct statvfs stvfs;
+
+  if (fstatvfs (fd, ) == -1)
+{
+  file_error (filename);
+  exit (EX_NOTFOUND);
+}
+
+  if (stvfs.f_flag & ST_NOEXEC)
+{
+  errno = EACCES;
+  file_error (filename);
+  exit (EX_NOEXEC);
+}
+#endif
+}
+
 static int
 open_shell_script (script_name)
  char *script_name;
@@ -1579,6 +1608,8 @@ open_shell_script (script_name)
 SET_CLOSE_ON_EXEC (fileno (default_input));
 #endif /* !BUFFERED_INPUT */
 
+  check_noexec (fd, filename);
+
   /* Just about the only way for this code to be executed is if something
  like `bash -i /dev/stdin' is executed. */
   if (interactive_shell && fd_is_tty)
-- 
2.6.2




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

2015-12-12 Thread Piotr Grzybowski
Hello Mike,

 you want to forbid reading and interpreting scripts from the mount
point that is marked as noexec. If nothing gets executed from the
noexec area, as in your example, this is going to far.
 After this, do I have to move all my scripts away from the noexec
area if I want bash to read them and run the commands (neither of
which executes from the noexec mountpoint)?

sincerely,
pg




On Sat, Dec 12, 2015 at 10:01 PM, Mike Frysinger  wrote:
> From: Mike Frysinger 
>
> 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:
>   $ bashhi
>
> This detracts from the security of the overall system.  People writing
> scripts sometimes want to save/restore state (like variables) 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.
> ---
>  builtins/evalfile.c | 24 
>  config.h.in |  3 +++
>  configure   |  2 +-
>  configure.ac|  2 +-
>  shell.c | 31 +++
>  5 files changed, 60 insertions(+), 2 deletions(-)
>
> diff --git a/builtins/evalfile.c b/builtins/evalfile.c
> index eb51c27..ed031d6 100644
> --- a/builtins/evalfile.c
> +++ b/builtins/evalfile.c
> @@ -32,6 +32,10 @@
>  #include 
>  #include 
>
> +#if defined (HAVE_SYS_STATVFS_H)
> +#  include 
> +#endif
> +
>  #include "../bashansi.h"
>  #include "../bashintl.h"
>
> @@ -160,6 +164,26 @@ file_error_and_exit:
>return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1);
>  }
>
> +#if defined (HAVE_SYS_STATVFS_H) && defined (ST_NOEXEC)
> +  /* If the script is loaded from a noexec mount point, throw an error.  */
> +  {
> +struct statvfs stvfs;
> +
> +if (fstatvfs (fd, ) == -1)
> +  {
> +   close (fd);
> +   goto file_error_and_exit;
> +  }
> +
> +if (stvfs.f_flag & ST_NOEXEC)
> +  {
> +   close (fd);
> +   errno = EACCES;
> +   goto file_error_and_exit;
> +  }
> +  }
> +#endif
> +
>if (S_ISREG (finfo.st_mode) && file_size <= SSIZE_MAX)
>  {
>string = (char *)xmalloc (1 + file_size);
> diff --git a/config.h.in b/config.h.in
> index 894892f..b16f1d6 100644
> --- a/config.h.in
> +++ b/config.h.in
> @@ -1039,6 +1039,9 @@
>  /* Define if you have the  header file. */
>  #undef HAVE_SYS_STAT_H
>
> +/* Define if you have .  */
> +#undef HAVE_SYS_STATVFS_H
> +
>  /* Define if you have the  header file.  */
>  #undef HAVE_SYS_STREAM_H
>
> diff --git a/configure b/configure
> index 52f6f5c..061b15e 100755
> --- a/configure
> +++ b/configure
> @@ -9301,7 +9301,7 @@ fi
>  done
>
>  for ac_header in sys/pte.h sys/stream.h sys/select.h sys/file.h sys/ioctl.h \
> -sys/param.h sys/socket.h sys/stat.h \
> +sys/param.h sys/socket.h sys/stat.h sys/statvfs.h \
>  sys/time.h sys/times.h sys/types.h sys/wait.h
>  do :
>as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
> diff --git a/configure.ac b/configure.ac
> index f0d4aee..81b2a7c 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -717,7 +717,7 @@ AC_CHECK_HEADERS(unistd.h stdlib.h stdarg.h varargs.h 
> limits.h string.h \
>  stdbool.h stddef.h stdint.h netdb.h pwd.h grp.h strings.h \
>  regex.h syslog.h ulimit.h)
>  AC_CHECK_HEADERS(sys/pte.h sys/stream.h sys/select.h sys/file.h sys/ioctl.h \
> -sys/param.h sys/socket.h sys/stat.h \
> +sys/param.h sys/socket.h sys/stat.h sys/statvfs.h \
>  sys/time.h sys/times.h sys/types.h sys/wait.h)
>  AC_CHECK_HEADERS(netinet/in.h arpa/inet.h)
>
> diff --git a/shell.c b/shell.c
> index 0e47cf4..4739a31 100644
> --- a/shell.c
> +++ b/shell.c
> @@ -46,6 +46,10 @@
>  #  include 
>  #endif
>
> +#if defined (HAVE_SYS_STATVFS_H)
> +#  include 
> +#endif
> +
>  #include "bashintl.h"
>
>  #define NEED_SH_SETLINEBUF_DECL/* used in externs.h */
> @@ -334,6 +338,8 @@ static void shell_reinitialize __P((void));
>
>  static void show_shell_usage 

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

2015-12-12 Thread Bob Proulx
Mike Frysinger wrote:
> But bash itself has no problem running this file:
>   $ bash /dev/shm/test.sh
>   hi
>...
> This detracts from the security of the overall system.  People
> writing scripts sometimes want to save/restore state (like
> variables) 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.

I don't think it makes sense for a userland program to be an enforcer
of this type of check.  It gives a false impression of a security that
does not exist.  Which I think is more dangerous.  It will almost
certainly get in the way of a reasonable use case.  And nothing
prevents one from running a private copy of a shell without such a
check.  Or any of the many compatible /bin/sh variants such as ksh,
zsh, ash, dash, and so forth.

Bob