it-swarm.com.de

Wo liegt die Sicherheitsanfälligkeit von Bash Shellshock im Quellcode?

Ich habe seit gestern von dem Problem Bash Shellshock gehört und bin gespannt, wo im Quellcode dieses Problem auftritt. Ich habe die Quelle für Bash 4.2 von hier heruntergeladen.

Wo genau soll ich im Quellcode von Bash 4.2 nach Shellshock suchen?

Ich konnte diesen Patch Informationen für 4.2 (von diesem Seite ) finden, aber wenn jemand klar erklären könnte, wo Shellshock auftritt, wäre dies hilfreich.

25
Jake

CVE-2014-6271

CVE-2014-6271 war die erste entdeckte Sicherheitslücke. Ein Patch kann gefunden werden hier .

Von Wikipedia :

Funktionsdefinitionen werden exportiert, indem sie in der Liste der Umgebungsvariablen als Variablen codiert werden, deren Werte mit Klammern ("()") gefolgt von einer Funktionsdefinition beginnen. Die neue Instanz von Bash durchsucht beim Start die Liste der Umgebungsvariablen nach Werten in diesem Format und konvertiert sie zurück in interne Funktionen.

Bash führt diese Konvertierung durch, indem ein Codefragment erstellt wird, das die Funktion definiert und ausführt. Es überprüft jedoch nicht , ob das Fragment lediglich eine Funktionsdefinition ist . Daher kann jeder, der Bash veranlassen kann, mit einem bestimmten Name/Wert-Paar in seiner Umgebung ausgeführt zu werden, auch beliebige Befehle ausführen, indem er diese Befehle an eine exportierte Funktionsdefinition anfügt.

Im Quellcode sehen wir den Import der Funktionsvariablen in variables.c :

/* Initialize the Shell variables from the current environment.
   If PRIVMODE is nonzero, don't import functions from ENV or
   parse $SHELLOPTS. */
void
initialize_Shell_variables (env, privmode)
     char **env;
     int privmode;
{
  [...]
  for (string_index = 0; string = env[string_index++]; )
    {

      [...]
      /* If exported function, define it now.  Don't import functions from
     the environment in privileged mode. */
      if (privmode == 0 && read_but_dont_execute == 0 && STREQN ("() {", string, 4))
      {
        [...]
        parse_and_execute (temp_string, name, SEVAL_NONINT|SEVAL_NOHIST);
        [...]
      }
}

Wir können eine for-Schleife über alle Umgebungsvariablen sehen, die der Funktion zugewiesen wurden, und dann ein if darüber, ob wir uns im privilegierten Modus befinden, aber das ist meistens deaktiviert. Der Teil "Nicht überprüfen, ob das Fragment lediglich eine Funktionsdefinition ist" befindet sich in der Zeile parse_and_execute. Die Funktionsbeschreibung von builtins/evalstring.c :

/* Parse and execute the commands in STRING.  Returns whatever
   execute_command () returns.  This frees STRING.  FLAGS is a
   flags Word; look in common.h for the possible values.  Actions
   are:
    (flags & SEVAL_NONINT) -> interactive = 0;
    (flags & SEVAL_INTERACT) -> interactive = 1;
    (flags & SEVAL_NOHIST) -> call bash_history_disable ()
    (flags & SEVAL_NOFREE) -> don't free STRING when finished
    (flags & SEVAL_RESETLINE) -> reset line_number to 1
*/
int
parse_and_execute (string, from_file, flags)
     char *string;
     const char *from_file;
     int flags;
{

Alles, was an die Funktion übergeben wird, wird so ausgeführt, als wäre es ein gewöhnlicher Bash-Befehl. Die Flags SEVAL_NONINT Und SEVAL_NOHIST Sind selbsterklärend ( Erklärung der Interaktivität , NOHIST fügt die Definition nicht zu Ihrer Bash-Historie hinzu). t verhindern, dass andere Dinge als Funktionsdefinitionen übergeben werden. Der Patch führt die Flags SEVAL_FUNCDEF Und SEVAL_ONECMD Ein, die im Feld flags an parse_and_execute Übergeben werden können:

+ #define SEVAL_FUNCDEF 0x080       /* only allow function definitions */
+ #define SEVAL_ONECMD  0x100       /* only allow a single command */

Der Patch fügt parse_and_execute Außerdem Funktionen hinzu, um diesen neuen Flags zu entsprechen, und ändert den Aufruf in parse_and_execute, Um diese Flags zu übergeben:

-     parse_and_execute (temp_string, name, SEVAL_NONINT|SEVAL_NOHIST);
+     /* Don't import function names that are invalid identifiers from the
+        environment. */
+     if (legal_identifier (name))
+       parse_and_execute (temp_string, name, SEVAL_NONINT|SEVAL_NOHIST|SEVAL_FUNCDEF|SEVAL_ONECMD);

CVE-2014-7169

CVE-2014-7169 basiert auf einem Funktionsanalyseproblem, das von Tavis Ormandy hervorgehoben wurde. Das Update von parse.y Scheint sehr einfach zu sein, ist aber schwieriger als CVE-2014-6271:

/* Called from Shell.c when Control-C is typed at top level.  Or
   by the error rule at top level. */
void
reset_parser ()
  [...]
  FREE (Word_desc_to_read);
  Word_desc_to_read = (Word_DESC *)NULL;
+ eol_ungetc_lookahead = 0;
+
  current_token = '\n'; /* XXX */
  last_read_token = '\n';
  token_to_read = '\n';

Die Variable eol_ungetc_lookahead Wird in ihrer Definition erläutert:

/* This implements one-character lookahead/lookbehind across physical input
   lines, to avoid something being lost because it's pushed back with
   Shell_ungetc when we're at the start of a line. */
static int eol_ungetc_lookahead = 0;

Es wird in der Funktion Shell_getc Gelesen, und wenn es gesetzt ist, wird stattdessen sein (einstelliger) Inhalt gelesen.

Der Befehl rm echo; env -i X='() { function a .>\' bash -c 'echo date'; cat echo erzeugt zuerst einen Syntaxfehler mit dem Zeichen . (Sie können hier auch andere Zeichen wie a oder = Verwenden) und dann verwendet die unzureichende Bereinigung der Variablen eol_ungetc_lookahead in der Funktion reset_parser, um das Zeichen > in die Zeichenfolge 'echo date' einzufügen, die auch bash zugewiesen wird. Es entspricht rm echo; bash -c '> echo date'; cat echo.

Weitere Ressourcen auf der Oss-Sec-Mailingliste .

33
user10008