Bash-4.3 crash BUG
Authors: | Hector Marco & Ismael Ripoll |
BUG: | Incorrect error handling resulting in Bash crash |
Dates: | 10 December 2013 - Discovered the bug |
| 25 March 2014 - Public disclosure |
Description
A bug in bash for versions prior to 4.3 has been
found. The bug is caused by the internal printf bash command
because an incorrect error handling resulting in a bash crash.
Impact
It is possible to force bash to try to print an incorrect
region of memory which results in a crash with the corresponding core
dump. A malicious user can prepare a bash script which when executed
under some X Windows Systems environments causes an xterm process to
terminate incorrectly which may in turn terminate the entire X11 session.
User data may get lost.
Vulnerable packages
Bash package 4.3 is vulnerable, version from
3.0 (released on August 2004) to the current 4.3 (last git commit on 26
February) are also affected.
The bug
The bug appears because the function getint()
does not print correctly the precision value when the value of it is not
valid.
The getint() call to getintmax() which forward rewind
the garglist to the next word. When back
to getint() function, if the precision is not valid this function
try to print the precision but incorrectly using
the printf_erange() function. Instead of printing the value of
the invalid precision, the pointer passed to printf_erange() is
the next parameter. Since there are not more parameters passed to the
bash, the printf_erange() prints from a wild pointer.
The bug appears in builtins/printf.def file, at lines 1118 and 1123:
static intmax_t
getintmax ()
{
intmax_t ret;
...
garglist = garglist->next; // Point to the next (but there are not more)
return (ret);
}
static int
getint ()
{
intmax_t ret;
ret = getintmax ();
if (ret > INT_MAX)
{
printf_erange (garglist->word->word); // Wrong pointer
ret = INT_MAX;
}
else if (ret < INT_MIN)
{
printf_erange (garglist->word->word); // Wrong pointer
ret = INT_MIN;
}
return ((int)ret);
}
Exploit PoC
In order to check if your bash is affected by this
bug you can execute the following:
$ printf "%.*x\n" 0x7f92514e5000
If your bash crashes then your are affected by this bug.
Another way to check if your bash is affected without causing a bash
crash is passing a second argument to the internal printf bash. If the
first error message showed is referring to Numerical error then your
bash is affected by this bug.
$ printf "%.*x\n" 0x7f92514e5000 "Hello world"
bash: printf: warning: Hello world: Numerical result out of range
bash: printf: Hello world: invalid number
As the second proof of concept shows, the internal printf
shows "Hello world" instead of "0x7f92514e5000" as an numerical result
out of range.
FIX
We have created a non official patch for bash 4.3:
diff --git builtins/printf.def builtins/printf.def
index 7f29126..a7b534b 100644
--- builtins/printf.def
+++ builtins/printf.def
@@ -1106,6 +1106,7 @@ static int
getint ()
{
intmax_t ret;
+ WORD_DESC *cword = garglist->word->word;
ret = getintmax ();
@@ -1114,12 +1115,12 @@ getint ()
if (ret > INT_MAX)
{
- printf_erange (garglist->word->word);
+ printf_erange (cword);
ret = INT_MAX;
}
else if (ret < INT_MIN)
{
- printf_erange (garglist->word->word);
+ printf_erange (cword);
ret = INT_MIN;
}
[ bash_4.3_printf_getint_bug.patch ]
Patching bash 4.3:
$ wget http://hmarco.org/bugs/patches/bash_4.3_printf_getint_bug.patch
$ cd bash.4.3
$ patch -p0 < ../bash_4.3_printf_getint_bug.patch
Hector Marco - http://hmarco.org