diff mbox series

expand: Add ifsfree to expand to fix a logic error that leaks the heap

Message ID CAOKKkHeAkWxtgm6=0eq6D6pPt+QV3SuEhrq=YNO-Jj7vospf-w@mail.gmail.com (mailing list archive)
State Superseded
Delegated to: Herbert Xu
Headers show
Series expand: Add ifsfree to expand to fix a logic error that leaks the heap | expand

Commit Message

Alex Gorinson April 30, 2022, 7:30 p.m. UTC
Description of problem:
First bug:
Due to a logic error in the ifsbreakup function in expand.c if a
heredoc and normal command is run one after the other by means of a
semi-colon, when the second command drops into ifsbreakup the command
will be evaluated with the ifslastp/ifsfirst struct that was set when
the here doc was evaluated. This results in a buffer over-read that
can leak the program's heap, stack, and arena addresses which can be
used to beat ASLR.
Second bug:
If the heap is sprayed with a certain amount of bash variables and
part of the first bug is sent, a predictable heap value can be free'd
and put into the tcache. After the heap value is free'd, if the heap
was sprayed correctly, an attacker can overwrite the free’d tcache
address to obtain numerous write-what-where and the ability to
arbitrarily overwrite any writable memory address. This could lead to
a DoS or arbitrary code execution.

Steps to Reproduce:
First bug:
cmd args: ~/exampleDir/example> dash
$ M='AAAAAAAAAAAAAAAAA'    <note: 17 A's>
$ q00(){
$ <<000;echo
$ ${D?$M$M$M$M$M$M}        <note: 6 $M's>
$ 000
$ }
$ q00                      <note: After the q00 is typed in, the leak
should be echo'd out; this works with ash, busybox ash, and dash and
with all option args.>

Second bug:
cmd args: ~/exampleDir/example> dash
<Everything in the `` is not meant to show what exactly is typed in
but more or less an action if that makes sense.>
$ AAAAAAAAAAAAAA    <note: These 14 A's are necessary to get initial
heap groom correct>
$ `spray 400 bash variables with size of 0x30 bytes`
$ `send bash variable with size of 0x20 bytes`
$ `send bash variable with size of 0x60 bytes`
$ `spray 12 bash variables with size of 0x20 bytes`
$ `Send part of first vulnerability`
   $ <<000000;V
   $ <Z*16+$Y*19>${x?0p$^?A<$B*442>$0b<B*10>dbasdfg$0<S*10>}
<note: The <> in this line are not meant to be entered in as is, but
instead shows amount of letter inside <> that would be entered in.>
   $ 000000      <note: After the 000000 is entered in the
vulnerability should trigger and attempt to free a predictable heap
address; while it can differ on each host, typically around variable
C20 - C5 is where the predictable free'd address will be.>

Patch:
Adding the following to expand.c will fix both bugs in one go.
(Thank you to Harald van Dijk and Michael Greenberg for doing the
heavy lifting for this patch!)
--
diff mbox series

Patch

--- a/src/expand.c
+++ b/src/expand.c
@@ -859,6 +859,7 @@ 
                               if (discard)
                                          return -1;

+                             ifsfree();
                               sh_error("Bad substitution");
                    }

@@ -1739,6 +1740,7 @@ 
                                 } else
                                              msg = umsg;
                   }
+                 ifsfree();
                   sh_error("%.*s: %s%s", end - var - 1, var, msg, tail);
 }
--