Re: Potential Bash Script Vulnerability

2024-04-08 Thread Oğuz
On Tue, Apr 9, 2024 at 5:17 AM Robert Elz  wrote:
> Sure, it is possible to make a useless program like this ...

> Almost all real commands use stdio to read stdin.   Playing about
> any more with this absurd example isn't worth the bother.   The relevant
> text should simply be deleted from POSIX.   It is bizarre and unnecessary.

Using stdio to read stdin doesn't stop you from detecting if it is
connected to a file and adjusting the file offset before exit. In
fact, POSIX mandates that for standard utilities in XCU 1.4 Utility
Defaults, INPUT FILES section:

When a standard utility reads a seekable input file and terminates
without an error before it reaches end-of-file, the utility shall
ensure that the file offset in the open file description is properly
positioned just past the last byte processed by the utility. For files
that are not seekable, the state of the file offset in the open file
description for that file is unspecified. A conforming application
shall not assume that the following three commands are equivalent:

tail -n +2 file
(sed -n 1q; cat) < file
cat file | (sed -n 1q; cat)

The second command is equivalent to the first only when the file is
seekable. The third command leaves the file offset in the open file
description in an unspecified state. Other utilities, such as head,
read, and sh, have similar properties.


If the shell doesn't cooperate with other utilities in this, this can happen:

$ cat tst.sh
echo hi
sed -n 1q
# Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla gravida odio
# ultrices, consectetur libero eu, malesuada augue. Proin commodo faucibus ipsum
# et viverra. In dictum, risus eu hendrerit rutrum, lorem diam cursus sapien,
# nec mollis urna nunc non enim. Etiam at porttitor neque. Quisque elementum
# orci in nisi egestas, sit amet pretium est tincidunt. Pellentesque eleifend
# nec tellus eu lobortis. Praesent pharetra sed neque eleifend interdum.
#
# Aenean eget tincidunt sem. Etiam ac ultricies leo. Nunc tortor ante, finibus
# in ullamcorper id, mattis sit amet ipsum. Etiam ac diam sem. Aenean a purus
# ex. Proin tincidunt erat odio, ut suscipit purus commodo nec. Curabitur eget
# ante non mi sagittis congue ac non massa. Cras tincidunt bibendum erat, ut
# gravida arcu congue eu. Phasellus ex quam, blandit at interdum at, cursus eu
# nisi. Nullam interdum faucibus massa at luctus. Nullam eu sapien ut mauris
# eleifend pharetra sit amet quis ante. Nullam porttitor enim eros, e
if false; then
rm uh-oh
fi
$
$ busybox sh 

Re: Potential Bash Script Vulnerability

2024-04-08 Thread Robert Elz
Date:Mon, 8 Apr 2024 19:35:02 +0300
From:=?UTF-8?B?T8SfdXo=?= 
Message-ID:  



  | Why not? It works fine with other shells

Sure, it is possible to make a useless program like this ...

  | $ cat tst.sh
  | cat 

Re: Potential Bash Script Vulnerability

2024-04-08 Thread Martin D Kealey
Hmm, looks like I'm partially mistaken.

Vim never does the inode pivot trick *in circumstances where I might've
noticed*, so not when the file:
- has multiple links, or
- is a symlink, or
- is in an unwritable directory, or
- otherwise appears to be something other than a plain file.

But it turns out it does pivot the inode when it thinks it won't be
noticed, which makes sense because it's less risky than overwriting a file
(which could result in data loss if the write fails).

So I've learned something new, thankyou.

-Martin

On Tue, 9 Apr 2024 at 11:13, Kerin Millar  wrote:

> On Tue, 9 Apr 2024 10:42:58 +1200
> Martin D Kealey  wrote:
>
> > On Mon, 8 Apr 2024 at 01:49, Kerin Millar  wrote:
> >
> > > the method by which vim amends files is similar to that of sed -i.
> > >
> >
> > I was about to write "nonsense, vim **never** does that for me", but
> then I
> > remembered that using ":w!" instead of ":w" (or ":wq!" instead of ":wq")
> > will write the file as normal, but if that fails, it will attempt to
> remove
> > it and create a new one. Ironically, that's precisely one of the cases
> > where using "sed -i" is a bad idea, but at least with vim you've already
> > tried ":w" and noticed that it failed, and made a considered decision to
> > use ":w!" instead.
> >
> > Except that nowadays many folk always type ":wq!" to exit vim, and never
> > put any thought into this undesirable side effect.
> >
> > I put that in the same bucket as using "kill -9" to terminate daemons, or
> > liberally using "-f" or "--force" in lots of other places. Those  are bad
> > habits, since they override useful safety checks, and I recommend making
> a
> > strenuous effort to unlearn such patterns. Then you can use these
> stronger
> > versions only when (1) the soft versions fail, and (2) you understand the
> > collateral damage, and (3) you've thought about it and decided that it's
> > acceptable in the particular circumstances.
> >
> > -Martin
> >
> > PS: I've never understood the preference for ":wq" over "ZZ" (or ":x"); I
> > want to leave the modification time unchanged if I don't edit the file.
>
> Alright. In that case, I don't know why I wasn't able to 'inject' a
> replacement command with it. I'll give it another try and see whether I can
> determine what happened.
>
> --
> Kerin Millar
>


Re: Potential Bash Script Vulnerability

2024-04-08 Thread Kerin Millar
On Tue, 9 Apr 2024 10:42:58 +1200
Martin D Kealey  wrote:

> On Mon, 8 Apr 2024 at 01:49, Kerin Millar  wrote:
> 
> > the method by which vim amends files is similar to that of sed -i.
> >
> 
> I was about to write "nonsense, vim **never** does that for me", but then I
> remembered that using ":w!" instead of ":w" (or ":wq!" instead of ":wq")
> will write the file as normal, but if that fails, it will attempt to remove
> it and create a new one. Ironically, that's precisely one of the cases
> where using "sed -i" is a bad idea, but at least with vim you've already
> tried ":w" and noticed that it failed, and made a considered decision to
> use ":w!" instead.
> 
> Except that nowadays many folk always type ":wq!" to exit vim, and never
> put any thought into this undesirable side effect.
> 
> I put that in the same bucket as using "kill -9" to terminate daemons, or
> liberally using "-f" or "--force" in lots of other places. Those  are bad
> habits, since they override useful safety checks, and I recommend making a
> strenuous effort to unlearn such patterns. Then you can use these stronger
> versions only when (1) the soft versions fail, and (2) you understand the
> collateral damage, and (3) you've thought about it and decided that it's
> acceptable in the particular circumstances.
> 
> -Martin
> 
> PS: I've never understood the preference for ":wq" over "ZZ" (or ":x"); I
> want to leave the modification time unchanged if I don't edit the file.

Alright. In that case, I don't know why I wasn't able to 'inject' a replacement 
command with it. I'll give it another try and see whether I can determine what 
happened.

-- 
Kerin Millar



Re: Potential Bash Script Vulnerability

2024-04-08 Thread Martin D Kealey
On Mon, 8 Apr 2024 at 01:49, Kerin Millar  wrote:

> the method by which vim amends files is similar to that of sed -i.
>

I was about to write "nonsense, vim **never** does that for me", but then I
remembered that using ":w!" instead of ":w" (or ":wq!" instead of ":wq")
will write the file as normal, but if that fails, it will attempt to remove
it and create a new one. Ironically, that's precisely one of the cases
where using "sed -i" is a bad idea, but at least with vim you've already
tried ":w" and noticed that it failed, and made a considered decision to
use ":w!" instead.

Except that nowadays many folk always type ":wq!" to exit vim, and never
put any thought into this undesirable side effect.

I put that in the same bucket as using "kill -9" to terminate daemons, or
liberally using "-f" or "--force" in lots of other places. Those  are bad
habits, since they override useful safety checks, and I recommend making a
strenuous effort to unlearn such patterns. Then you can use these stronger
versions only when (1) the soft versions fail, and (2) you understand the
collateral damage, and (3) you've thought about it and decided that it's
acceptable in the particular circumstances.

-Martin

PS: I've never understood the preference for ":wq" over "ZZ" (or ":x"); I
want to leave the modification time unchanged if I don't edit the file.


Re: Potential Bash Script Vulnerability

2024-04-08 Thread Oğuz
On Mon, Apr 8, 2024 at 5:32 PM Robert Elz  wrote:
> The effect is that sharing stdin between the shell script, and other
> commands (than read), is almost certainly never going to work,

Why not? It works fine with other shells


$ cat tst.sh
cat 

Re: Potential Bash Script Vulnerability

2024-04-08 Thread Robert Elz
Date:Mon, 8 Apr 2024 12:32:13 +0300
From:=?UTF-8?B?T8SfdXo=?= 
Message-ID:  


  | The only ash clone that does this is gwsh, all others print "a" and a
  | command-not-found error.

I have (today, after your e-mail) changed the NetBSD shell so it works
like is (apparently) required (no real code ever seems to be affected):

jacaranda$ ./sh <

Re: Potential Bash Script Vulnerability

2024-04-08 Thread Chet Ramey

On 4/7/24 12:17 AM, ad...@osrc.rip wrote:

Hello everyone!

I've attached a minimal script which shows the issue, and my recommended 
solution.


Hi. Thanks for the report. This seems more like a case of mistmatched
expectations.

Bash tries, within reason, to read its input a command at a time, and to
leave child processes with the file pointer set to the location in a
script corresponding to the commands it's consumed. POSIX requires this
behavior if the shell is reading script input from stdin.

It seems like you expect the shell to read and buffer input (like stdio,
for instance) so that at any point it has read more input that it has
processed. This isn't unreasonable, but it's not how shells have behaved.

Not doing this file location sync isn't a solution to your theoretical
vulnerability, either. Since scripts are simply text files, you just have
to arrange to alter file contents beyond where the script has read and
buffered input data, subject to Kerin Millar's comments about not changing
the inode.

If you want the shell to read and parse an entire script before executing
any of it, the group command solution is a good one. This has the advantage
of potentially finding syntax errors before executing any commands, which
might be desirable.

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



OpenPGP_signature.asc
Description: OpenPGP digital signature


Re: Potential Bash Script Vulnerability

2024-04-08 Thread Andreas Schwab
On Apr 08 2024, Greg Wooledge wrote:

> Now imagine what happens if the shell is killed by a SIGKILL, or if
> the system simply crashes during the script's execution.  The script
> is left with altered permissions.

Or the script is executed by more than one process at the same time.

-- 
Andreas Schwab, SUSE Labs, sch...@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."



Re: Potential Bash Script Vulnerability

2024-04-08 Thread Greg Wooledge
On Mon, Apr 08, 2024 at 02:23:18PM +0300, ad...@osrc.rip wrote:
> Btw wouldn't it be possible (and worth) temporarily revoking write access to
> the user while it's being executed as root, and restoring original rights
> after execution?

I think that would be a huge overreach.  It would also lead to a whole
lot of breakage.

Imagine that we implement this change.  It would have to be done in
the shell, since the kernel simply offloads script execution to the
interpreter.  So, your change would essentially add code to the shell
which causes it to change the permissions on a script that it's
reading, if that script is given as a command-line argument, and if
the shell's EUID is 0.  Presumably it would change the permissions
back to normal at exit.

Now imagine what happens if the shell is killed by a SIGKILL, or if
the system simply crashes during the script's execution.  The script
is left with altered permissions.



Re: Potential Bash Script Vulnerability

2024-04-08 Thread admin

On 2024-04-08 14:02, Greg Wooledge wrote:

On Mon, Apr 08, 2024 at 12:40:55PM +0700, Robert Elz wrote:

or perhaps better just:

  main() { ... } ; main "$@"


You'd want to add an "exit" as well, to protect against new lines of
code being appended to the script.


Yes that is correct. it's far easier to add new lines then to edit the 
content unnoticed, since you would have to know where you can insert or 
replace something, eg. a comment.


Btw wouldn't it be possible (and worth) temporarily revoking write 
access to the user while it's being executed as root, and restoring 
original rights after execution? The problem isn't really how it's 
executed, but that it's writable during execution...
This could of course leave the temporary rights if the process is 
killed...



Tibor



Re: Potential Bash Script Vulnerability

2024-04-08 Thread Greg Wooledge
On Mon, Apr 08, 2024 at 12:40:55PM +0700, Robert Elz wrote:
> or perhaps better just:
> 
>   main() { ... } ; main "$@"

You'd want to add an "exit" as well, to protect against new lines of
code being appended to the script.



Re: Potential Bash Script Vulnerability

2024-04-08 Thread Oğuz
On Mon, Apr 8, 2024 at 5:58 AM Robert Elz  wrote:
> Shells interpret their input in much the same way, regardless of
> from where it comes.   Would you really want your login shell to
> just collect commands that you type (possibly objecting to those
> with syntax errors) but executing none of them (including "exit")
> until you log out (send EOF) ?

On a related note, POSIX says this:

When the shell is using standard input and it invokes a command that
also uses standard input, the shell shall ensure that the standard
input file pointer points directly after the command it has read when
the command begins execution. It shall not read ahead in such a manner
that any characters intended to be read by the invoked command are
consumed by the shell (whether interpreted by the shell or not) or
that characters that are not read by the invoked command are not seen
by the shell.

So this command

sh <

Re: Potential Bash Script Vulnerability

2024-04-08 Thread Kerin Millar
On Mon, 8 Apr 2024, at 5:29 AM, John Passaro wrote:
> if you wanted this for your script - read all then start semantics, as 
> opposed to read-as-you-execute - would it work to rewrite yourself 
> inside a function?
>
> function main() { ... } ; main

Mostly, yes. My initial post in this thread spoke of it. It isn't a panacea 
because a sufficiently large compound command can cause bash to run out of 
stack space. In that case, all one can do is to break the script down further 
into additional, smaller, functions.

-- 
Kerin Millar



Re: Potential Bash Script Vulnerability

2024-04-08 Thread admin

On 2024-04-08 05:58, Robert Elz wrote:

Date:Mon, 8 Apr 2024 02:50:29 +0100
From:Kerin Millar 
Message-ID:  
<20240408025029.e7585f2f52fe510d2a686...@plushkava.net>


  | which is to read scripts in their entirety before trying to execute
  | the resulting program. To go about it that way is not typical of sh
  | implementations, for whatever reason.

Shells interpret their input in much the same way, regardless of
from where it comes.   Would you really want your login shell to
just collect commands that you type (possibly objecting to those
with syntax errors) but executing none of them (including "exit")
until you log out (send EOF) ?

kre
My answer to that would be: No! I would expect it to handle file 
execution a bit differently then terminal input.
Anyway... I reported what I found concerning, you guys know best what's 
can and worth doing about it. I'm not involved in bash's development, 
the rest is up to you.
I'm gonna put my code in {} and end with exit from now on to make it at 
least somewhat safer.


Tibor



Re: Potential Bash Script Vulnerability

2024-04-07 Thread Robert Elz
Date:Mon, 8 Apr 2024 00:29:41 -0400
From:John Passaro 
Message-ID:  


  | if you wanted this for your script - read all then start semantics, as
  | opposed to read-as-you-execute - would it work to rewrite yourself inside a
  | function?
  |
  | function main() { ... } ; main

It would need to be:

  function main() { ... } ; main "$@"

or perhaps better just:

  main() { ... } ; main "$@"

but with that change, yes it should work almost always (and
can certainly be made to).

kre



Re: Potential Bash Script Vulnerability

2024-04-07 Thread John Passaro
if you wanted this for your script - read all then start semantics, as
opposed to read-as-you-execute - would it work to rewrite yourself inside a
function?

function main() { ... } ; main

On Sun, Apr 7, 2024, 22:58 Robert Elz  wrote:

> Date:Mon, 8 Apr 2024 02:50:29 +0100
> From:Kerin Millar 
> Message-ID:  <20240408025029.e7585f2f52fe510d2a686...@plushkava.net>
>
>   | which is to read scripts in their entirety before trying to execute
>   | the resulting program. To go about it that way is not typical of sh
>   | implementations, for whatever reason.
>
> Shells interpret their input in much the same way, regardless of
> from where it comes.   Would you really want your login shell to
> just collect commands that you type (possibly objecting to those
> with syntax errors) but executing none of them (including "exit")
> until you log out (send EOF) ?
>
> kre
>
>
>
>


Re: Potential Bash Script Vulnerability

2024-04-07 Thread Robert Elz
Date:Mon, 8 Apr 2024 02:50:29 +0100
From:Kerin Millar 
Message-ID:  <20240408025029.e7585f2f52fe510d2a686...@plushkava.net>

  | which is to read scripts in their entirety before trying to execute
  | the resulting program. To go about it that way is not typical of sh
  | implementations, for whatever reason.

Shells interpret their input in much the same way, regardless of
from where it comes.   Would you really want your login shell to
just collect commands that you type (possibly objecting to those
with syntax errors) but executing none of them (including "exit")
until you log out (send EOF) ?

kre





Re: Potential Bash Script Vulnerability

2024-04-07 Thread Kerin Millar
On Mon, 08 Apr 2024 00:23:38 +0300
ad...@osrc.rip wrote:

> On 2024-04-07 16:49, Kerin Millar wrote:
> > On Sun, 7 Apr 2024, at 5:17 AM, ad...@osrc.rip wrote:
> >> Hello everyone!
> >> 
> >> I've attached a minimal script which shows the issue, and my 
> >> recommended
> >> solution.
> >> 
> >> Affected for sure:
> >> System1: 64 bit Ubuntu 22.04.4 LTS - Bash: 5.1.16(1)-release - 
> >> Hardware:
> >> HP Pavilion 14-ec0013nq (Ryzen 5 5500u, 32GB RAM, Radeon grapics, nvme
> >> SSD.)
> >> System2: 64 bit Ubuntu 20.10 (No longer supported.) - Bash:
> >> 5.0.17(1)-release - Hardware: DIY (AMD A10-5800k, 32GB RAM, Radeon
> >> graphics, several SATA drives)
> >> and probably a lot more...
> >> 
> >> Not sure whether or not this is a know issue, truth be told I 
> >> discovered
> >> it years ago (back around 2016) as I was learning bash scripting, and
> >> accidentally appended a command to the running script, which got
> >> executed immediately after the script but back then I didn't find it
> >> important to report since I considered myself a noob. I figured 
> >> someone
> >> more experienced will probably find and fix it, or there must be a
> >> reason for it. I forgotű it. Now watching a video about clever use of
> >> shell in XZ stuff I remembered, tested it again and found it still
> >> unpatched. :S So now I'm reporting it and hope it helps!
> > 
> > It is a known pitfall, though perhaps not as widely known as it ought 
> > to be. The reason that your usage of (GNU) sed fails as a 
> > self-modification technique is that sed -i behaves as follows.
> > 
> > 1) it creates a temporary file
> > 2) it sends its output to the temporary file
> > 3) it renames the temporary file over the original file from which it 
> > read
> > 
> > The consequence of the third step is that the original file is 
> > unlinked. In its place will be a new hard link, bearing the same name, 
> > but otherwise quite distinct from the original. Such can be easily 
> > demonstrated:
> > 
> > $ touch file
> > $ stat -c %i file
> > 1548822
> > $ strace -erename sed -i -e '' file
> > rename("./sedP2oQ5I", "file")   = 0
> > +++ exited with 0 +++
> > $ stat -c %i file
> > 1548823
> > 
> > See how the revised file has an entirely new inode number? It proves 
> > that sed does not perform 'in-place' editing at all. For more 
> > information regarding that particular topic, take a look at 
> > https://backreference.org/2011/01/29/in-place-editing-of-files/index.html.
> > 
> > Now, at the point that the original file is unlinked, its contents will 
> > remain available until such time as its reference count drops to 0. 
> > This is a characteristic of unix and unix-like operating systems in 
> > general. Let's assume that the file in question is a bash script, that 
> > bash had the file open and that it was still reading from it. Bash will 
> > not yet 'see' your modifications. However, once bash closes the file 
> > and exits, should you then instruct bash to execute the script again, 
> > it will follow the new hard link and thereby read the new file. 
> > Further, assuming that no other processes also had the original file 
> > open at the time of bash exiting, its reference count will drop to 0, 
> > and the backing filesystem will free its associated data.
> > 
> > From this, we may reason that the pitfall you stumbled upon applies 
> > where the file is modified in such a way that its inode number does not 
> > change e.g. by truncating and re-writing the file. One way to 
> > demonstrate this distinction is to apply your edit with an editor that 
> > behaves in this way, such as nano. Consider the following script.
> > 
> > #!/bin/bash
> > echo begin
> > sleep 10
> > : do nothing
> > echo end
> > 
> > You can try opening this script with nano before executing it. While 
> > the sleep command is still running, replace ": do nothing" with a 
> > command of your choosing, then instruct nano to save the amended 
> > script. You will find that the replacement command ends up being 
> > executed. Repeat the experiment with vim and you will find that the 
> > outcome is different. That's because the method by which vim amends 
> > files is similar to that of sed -i.
> > 
> > You propose a method by which bash might implicitly work around this 
> > pitfall but it would not suffice. If you perform an in-place edit upon 
> > any portion of a script that bash has not yet read and/or buffered - 
> > while bash is still executing said script - then the behaviour of the 
> > script will be affected. If you consider this to be a genuine nuisance, 
> > a potential defence is to compose your scripts using compound commands. 
> > For example:
> > 
> > #!/bin/bash
> > {
> >: various commands here
> >exit
> > }
> > 
> > Alternatively, use functions - which are really just compound commands 
> > attached to names:
> > 
> > #!/bin/bash
> > main() {
> >: various commands here.
> >exit
> > }
> > main "$@"
> > 
> > Doing so helps somewhat 

Re: Potential Bash Script Vulnerability

2024-04-07 Thread Greg Wooledge
On Mon, Apr 08, 2024 at 12:23:38AM +0300, ad...@osrc.rip wrote:
> - Looks for list of PIDs started by the user, whether it's started in 
> terminal or command line, and saves them into $DotShProcessList

> - Takes $DotShProcessList and filters out those that don't have root access. 
> Those that do are saved into $UserScriptsRunningAsRoot

> - Searches for file names of $UserScriptsRunningAsRoot processes in 
> /home/$USER (aka ~) and save it to $ScriptFiles

So your "vulnerability" requires that the attacker has unprivileged
access to the system, and locates a shell script which is owned by a
second unprivileged user, and for some reason has world write access,
and is also currently being executed by root?

In that scenario I would say the real problem is that the second user
is leaving world-writable files sitting around.  If the attacker finds
such scripts, they can edit them ahead of time, and simply wait for
the second user to execute them via sudo.  There's no need to find the
script being executed in real time.



Re: Potential Bash Script Vulnerability

2024-04-07 Thread admin

On 2024-04-07 16:49, Kerin Millar wrote:

On Sun, 7 Apr 2024, at 5:17 AM, ad...@osrc.rip wrote:

Hello everyone!

I've attached a minimal script which shows the issue, and my 
recommended

solution.

Affected for sure:
System1: 64 bit Ubuntu 22.04.4 LTS - Bash: 5.1.16(1)-release - 
Hardware:

HP Pavilion 14-ec0013nq (Ryzen 5 5500u, 32GB RAM, Radeon grapics, nvme
SSD.)
System2: 64 bit Ubuntu 20.10 (No longer supported.) - Bash:
5.0.17(1)-release - Hardware: DIY (AMD A10-5800k, 32GB RAM, Radeon
graphics, several SATA drives)
and probably a lot more...

Not sure whether or not this is a know issue, truth be told I 
discovered

it years ago (back around 2016) as I was learning bash scripting, and
accidentally appended a command to the running script, which got
executed immediately after the script but back then I didn't find it
important to report since I considered myself a noob. I figured 
someone

more experienced will probably find and fix it, or there must be a
reason for it. I forgotű it. Now watching a video about clever use of
shell in XZ stuff I remembered, tested it again and found it still
unpatched. :S So now I'm reporting it and hope it helps!


It is a known pitfall, though perhaps not as widely known as it ought 
to be. The reason that your usage of (GNU) sed fails as a 
self-modification technique is that sed -i behaves as follows.


1) it creates a temporary file
2) it sends its output to the temporary file
3) it renames the temporary file over the original file from which it 
read


The consequence of the third step is that the original file is 
unlinked. In its place will be a new hard link, bearing the same name, 
but otherwise quite distinct from the original. Such can be easily 
demonstrated:


$ touch file
$ stat -c %i file
1548822
$ strace -erename sed -i -e '' file
rename("./sedP2oQ5I", "file")   = 0
+++ exited with 0 +++
$ stat -c %i file
1548823

See how the revised file has an entirely new inode number? It proves 
that sed does not perform 'in-place' editing at all. For more 
information regarding that particular topic, take a look at 
https://backreference.org/2011/01/29/in-place-editing-of-files/index.html.


Now, at the point that the original file is unlinked, its contents will 
remain available until such time as its reference count drops to 0. 
This is a characteristic of unix and unix-like operating systems in 
general. Let's assume that the file in question is a bash script, that 
bash had the file open and that it was still reading from it. Bash will 
not yet 'see' your modifications. However, once bash closes the file 
and exits, should you then instruct bash to execute the script again, 
it will follow the new hard link and thereby read the new file. 
Further, assuming that no other processes also had the original file 
open at the time of bash exiting, its reference count will drop to 0, 
and the backing filesystem will free its associated data.


From this, we may reason that the pitfall you stumbled upon applies 
where the file is modified in such a way that its inode number does not 
change e.g. by truncating and re-writing the file. One way to 
demonstrate this distinction is to apply your edit with an editor that 
behaves in this way, such as nano. Consider the following script.


#!/bin/bash
echo begin
sleep 10
: do nothing
echo end

You can try opening this script with nano before executing it. While 
the sleep command is still running, replace ": do nothing" with a 
command of your choosing, then instruct nano to save the amended 
script. You will find that the replacement command ends up being 
executed. Repeat the experiment with vim and you will find that the 
outcome is different. That's because the method by which vim amends 
files is similar to that of sed -i.


You propose a method by which bash might implicitly work around this 
pitfall but it would not suffice. If you perform an in-place edit upon 
any portion of a script that bash has not yet read and/or buffered - 
while bash is still executing said script - then the behaviour of the 
script will be affected. If you consider this to be a genuine nuisance, 
a potential defence is to compose your scripts using compound commands. 
For example:


#!/bin/bash
{
   : various commands here
   exit
}

Alternatively, use functions - which are really just compound commands 
attached to names:


#!/bin/bash
main() {
   : various commands here.
   exit
}
main "$@"

Doing so helps somewhat because bash is compelled to read all the way 
to the end of a compound command at the point that it encounters one, 
prior to its contents being executed.


Ultimately, the best defence against the potentially adverse 
consequences of performing an in-place edit is to to refrain entirely 
from performing in-place edits.



First of all: Thanks for the suggestions, I will definitely use it! :)
Second: "If you consider this to be a genuine nuisance(...)"
A nuisance?!? Ok... Well maybe my first message wasn't convincing 

Re: Potential Bash Script Vulnerability

2024-04-07 Thread Kerin Millar
On Sun, 7 Apr 2024, at 5:17 AM, ad...@osrc.rip wrote:
> Hello everyone!
>
> I've attached a minimal script which shows the issue, and my recommended 
> solution.
>
> Affected for sure:
> System1: 64 bit Ubuntu 22.04.4 LTS - Bash: 5.1.16(1)-release - Hardware: 
> HP Pavilion 14-ec0013nq (Ryzen 5 5500u, 32GB RAM, Radeon grapics, nvme 
> SSD.)
> System2: 64 bit Ubuntu 20.10 (No longer supported.) - Bash: 
> 5.0.17(1)-release - Hardware: DIY (AMD A10-5800k, 32GB RAM, Radeon 
> graphics, several SATA drives)
> and probably a lot more...
>
> Not sure whether or not this is a know issue, truth be told I discovered 
> it years ago (back around 2016) as I was learning bash scripting, and 
> accidentally appended a command to the running script, which got 
> executed immediately after the script but back then I didn't find it 
> important to report since I considered myself a noob. I figured someone 
> more experienced will probably find and fix it, or there must be a 
> reason for it. I forgotű it. Now watching a video about clever use of 
> shell in XZ stuff I remembered, tested it again and found it still 
> unpatched. :S So now I'm reporting it and hope it helps!

It is a known pitfall, though perhaps not as widely known as it ought to be. 
The reason that your usage of (GNU) sed fails as a self-modification technique 
is that sed -i behaves as follows.

1) it creates a temporary file
2) it sends its output to the temporary file
3) it renames the temporary file over the original file from which it read

The consequence of the third step is that the original file is unlinked. In its 
place will be a new hard link, bearing the same name, but otherwise quite 
distinct from the original. Such can be easily demonstrated:

$ touch file
$ stat -c %i file
1548822
$ strace -erename sed -i -e '' file
rename("./sedP2oQ5I", "file")   = 0
+++ exited with 0 +++
$ stat -c %i file
1548823

See how the revised file has an entirely new inode number? It proves that sed 
does not perform 'in-place' editing at all. For more information regarding that 
particular topic, take a look at 
https://backreference.org/2011/01/29/in-place-editing-of-files/index.html.

Now, at the point that the original file is unlinked, its contents will remain 
available until such time as its reference count drops to 0. This is a 
characteristic of unix and unix-like operating systems in general. Let's assume 
that the file in question is a bash script, that bash had the file open and 
that it was still reading from it. Bash will not yet 'see' your modifications. 
However, once bash closes the file and exits, should you then instruct bash to 
execute the script again, it will follow the new hard link and thereby read the 
new file. Further, assuming that no other processes also had the original file 
open at the time of bash exiting, its reference count will drop to 0, and the 
backing filesystem will free its associated data.

>From this, we may reason that the pitfall you stumbled upon applies where the 
>file is modified in such a way that its inode number does not change e.g. by 
>truncating and re-writing the file. One way to demonstrate this distinction is 
>to apply your edit with an editor that behaves in this way, such as nano. 
>Consider the following script.

#!/bin/bash
echo begin
sleep 10
: do nothing
echo end

You can try opening this script with nano before executing it. While the sleep 
command is still running, replace ": do nothing" with a command of your 
choosing, then instruct nano to save the amended script. You will find that the 
replacement command ends up being executed. Repeat the experiment with vim and 
you will find that the outcome is different. That's because the method by which 
vim amends files is similar to that of sed -i.

You propose a method by which bash might implicitly work around this pitfall 
but it would not suffice. If you perform an in-place edit upon any portion of a 
script that bash has not yet read and/or buffered - while bash is still 
executing said script - then the behaviour of the script will be affected. If 
you consider this to be a genuine nuisance, a potential defence is to compose 
your scripts using compound commands. For example:

#!/bin/bash
{
   : various commands here
   exit
}

Alternatively, use functions - which are really just compound commands attached 
to names:

#!/bin/bash
main() {
   : various commands here.
   exit
}
main "$@"

Doing so helps somewhat because bash is compelled to read all the way to the 
end of a compound command at the point that it encounters one, prior to its 
contents being executed.

Ultimately, the best defence against the potentially adverse consequences of 
performing an in-place edit is to to refrain entirely from performing in-place 
edits.

-- 
Kerin Millar



Re: Potential Bash Script Vulnerability

2024-04-07 Thread Jon Seymour
You do realise that if you allow an untrusted script to run at root, having
it modify itself is the least of your concerns. There are *so* many ways an
untrusted script can cause a problem that do not require your
self-modifying script and for which your proposed mitigation will do
nothing. What's the point in protecting against the 0.01% case if you
have done nothing to protect yourself against system
administrators executing untrusted scripts as root?

On Sun, 7 Apr 2024 at 14:18,  wrote:

> Hello everyone!
>
> I've attached a minimal script which shows the issue, and my recommended
> solution.
>
> Affected for sure:
> System1: 64 bit Ubuntu 22.04.4 LTS - Bash: 5.1.16(1)-release - Hardware:
> HP Pavilion 14-ec0013nq (Ryzen 5 5500u, 32GB RAM, Radeon grapics, nvme
> SSD.)
> System2: 64 bit Ubuntu 20.10 (No longer supported.) - Bash:
> 5.0.17(1)-release - Hardware: DIY (AMD A10-5800k, 32GB RAM, Radeon
> graphics, several SATA drives)
> and probably a lot more...
>
> Not sure whether or not this is a know issue, truth be told I discovered
> it years ago (back around 2016) as I was learning bash scripting, and
> accidentally appended a command to the running script, which got
> executed immediately after the script but back then I didn't find it
> important to report since I considered myself a noob. I figured someone
> more experienced will probably find and fix it, or there must be a
> reason for it. I forgotű it. Now watching a video about clever use of
> shell in XZ stuff I remembered, tested it again and found it still
> unpatched. :S So now I'm reporting it and hope it helps!
>
> Read the code, test it, fix it. More explanation in the comments.
>
> Since it's very old I'd recommend a silent fix before announcement,
> especially since I also found a potentially easy fix.
>
> Kind regards
> Tibor