Es gibt eine ähnliche Frage , die sich mit dem 'Wrapping'-Szenario befasst, bei dem Sie beispielsweise cd
einen Befehl verwenden möchten , der das eingebaute Element aufruft cd
.
Angesichts von Shellshock et al. Und der Tatsache, dass Bash Funktionen aus der Umgebung importiert, habe ich einige Tests durchgeführt und kann das Builtin nicht sicher cd
aus meinem Skript aufrufen .
Bedenken Sie
cd() { echo "muahaha"; }
export -f cd
Alle Skripte, die in dieser Umgebung mit aufgerufen cd
werden, brechen ab (berücksichtigen Sie die Auswirkungen von etwas Ähnlichem cd dir && rm -rf .
).
Es gibt Befehle zum Überprüfen des Typs eines Befehls (bequemer Aufruf type
) und Befehle zum Ausführen der eingebauten Version anstelle einer Funktion ( builtin
und command
). Aber siehe da, diese können auch mit Funktionen überschrieben werden
builtin() { "$@"; }
command() { "$@"; }
type() { echo "$1 is a shell builtin"; }
Ergibt Folgendes:
$ type cd
cd is a shell builtin
$ cd x
muahaha
$ builtin cd x
muahaha
$ command cd x
muahaha
Gibt es eine Möglichkeit, bash sicher zur Verwendung des integrierten Befehls zu zwingen oder zumindest zu erkennen, dass ein Befehl kein integrierter Befehl ist, ohne die gesamte Umgebung zu löschen?
Mir ist klar, dass Sie wahrscheinlich sowieso bescheuert sind, wenn jemand Ihre Umgebung kontrolliert, aber zumindest für Aliase können Sie den Alias nicht aufrufen, indem Sie ein \
davor einfügen .
env
Befehlenv -i <SCRIPT.sh>
env
nicht auch als Funktion neu definiert. Das ist erschreckend. Ich dachte zuerst, dass Sonderzeichen helfen würden - Aufrufen mit vollem Pfad, einschließlich der/
Verwendung von.
to source und so weiter. Diese können aber auch für Funktionsnamen verwendet werden! Sie können jede gewünschte Funktion neu definieren, aber es ist schwierig, zum Aufrufen des ursprünglichen Befehls zurückzukehren.#/bin/sh
wenn dies nicht die standardmäßige interaktive Shell ist.Antworten:
Olivier D ist fast richtig, aber Sie müssen
POSIXLY_CORRECT=1
vor dem Laufen einstellenunset
. POSIX kennt sich mit speziellen integrierten Funktionen aus , und bash unterstützt dies .unset
ist eine solche eingebaut. Suchen nachSPECIAL_BUILTIN
inbuiltins/*.c
in der Bash - Quelle für eine Liste, enthält esset
,unset
,export
,eval
undsource
.Der Schurke
unset
ist nun aus der Umgebung entfernt, wenn Sie unsetcommand
,type
,builtin
dann sollten Sie in der Lage sein, zu gehen , aberunset POSIXLY_CORRECT
wenn Sie auf nicht-POSIX - Verhalten oder erweitern bash Funktionen angewiesen sind.Hiermit werden jedoch keine Aliase behandelt. Sie müssen
\unset
also sicherstellen, dass es in der interaktiven Shell funktioniert (oder immer, falls dies tatsächlich der Fallexpand_aliases
ist).Für die paranoid, dies sollte alles reparieren, denke ich:
(
while
,do
,done
Und[[
sind reservierte Worte und keine Vorsichtsmaßnahmen müssen.) Hinweis verwenden wirunset -f
auf ungesetzt Funktionen sicher sein, obwohl Variablen und Funktionen denselben Namespace ist es möglich , beide gleichzeitig zu existieren (dank Etan Reisner) , in dem Fall zweimaliges Einstellen würde ebenfalls ausreichen. Sie können eine Funktion schreibgeschützt markieren. Bash hindert Sie nicht daran, eine schreibgeschützte Funktion bis einschließlich Bash-4.2 zu deaktivieren. Bash-4.3 hindert Sie daran, berücksichtigt jedoch weiterhin die speziellen eingebauten Funktionen, wenn diesePOSIXLY_CORRECT
gesetzt sind.Ein Readonly
POSIXLY_CORRECT
ist kein echtes Problem, dies ist kein Boolescher Wert oder ein Flag, dessen Vorhandensein den POSIX-Modus aktiviert. Wenn es also als Readonly existiert, können Sie sich auf POSIX-Funktionen verlassen, auch wenn der Wert leer oder 0 ist. Das müssen Sie einfach ungeklärte problematische Funktionen anders als oben, vielleicht mit etwas Ausschneiden und Einfügen:(und ignorieren Sie alle Fehler) oder engagieren Sie sich in einem anderen Scriptobatics .
Weitere Hinweise:
function
Ist ein reserviertes Wort, kann es mit einem Alias versehen, aber nicht mit einer Funktion überschrieben werden. (Aliasingfunction
ist leicht störend, weil\function
es als Umgehungsmöglichkeit nicht akzeptabel ist.)[[
,]]
sind reservierte Wörter, sie können mit Alias versehen werden (was ignoriert wird), aber nicht mit einer Funktion überschrieben werden (obwohl Funktionen so benannt werden können)((
ist weder ein gültiger Name für eine Funktion noch ein Aliasquelle
unset
et al entfernt, überschrieben.-f
Argument,unset
nicht wahr? Wenn andernfalls sowohl eine Variable als auch eine Funktion definiert sind, die den gleichen Namen wie eine eingebaute haben,unset
wird zuerst die Variable ausgewählt, die nicht gesetzt werden soll. Auch dies schlägt fehl, wenn eine der verdeckenden Funktionen eingestelltreadonly
ist, nicht wahr? (Obwohl dies erkennbar ist und zu einem schwerwiegenden Fehler führen kann.) Auch hier fehlt das[
eingebaute System, wie es scheint.\unset -f unset
dass es Sinn macht, vorausgesetzt, es wird in der Leseschleife gemacht. Wennunset
es sich um eine Funktion handelt, die Sie\unset
normalerweise anstelle der eingebauten auflösen würden, können Sie sie\unset
sicher verwenden, solange der POSIX-Modus aktiv ist. Explizit Aufruf\unset -f
auf[
,.
und:
vielleicht eine gute Idee , wenn es , wie Ihr regex schließt sie. Ich würde auch-f
die\unset
in der Schleife hinzufügen , und würde\unset POSIXLY_CORRECT
nach der Schleife statt vor.\unalias -a
(after\unset -f unalias
) erlaubt es einem auch, bei nachfolgenden Befehlen sicher auf die Flucht zu verzichten.[[ ${POSIXLY_CORRECT?non-POSIX mode shell is untrusted}x ]]
Dies führt dazu, dass ein nicht interaktives Skript mit dem angegebenen Fehler beendet wird, wenn die Variable nicht gesetzt ist, oder fortgesetzt wird, wenn sie gesetzt ist (leer oder ein beliebiger Wert).\unset
" ... Es sollte beachtet werden, dass das Zitieren eines oder mehrerer Zeichen funktionieren würde, um die Alias-Erweiterung zu vermeiden, nicht nur die erste.un"se"t
würde genauso gut funktionieren, abeit weniger lesbar. Msgstr "Das erste Wort jedes einfachen Befehls wird, wenn es nicht in Anführungszeichen gesetzt ist, überprüft, um festzustellen, ob es einen Alias hat." - Bash RefJa das. Wenn Sie ein Skript in einer unbekannten Umgebung
LD_PRELOAD
ausführen , können alle möglichen Probleme auftreten, angefangen damit, dass der Shell-Prozess beliebigen Code ausführt, bevor er Ihr Skript überhaupt liest. Der Versuch, innerhalb des Skripts vor einer feindlichen Umgebung zu schützen, ist erfolglos.Sudo hat die Umgebung desinfiziert, indem es seit über einem Jahrzehnt alles entfernt, was wie eine Bash-Funktionsdefinition aussieht. Seit Shellshock sind andere Umgebungen, in denen Shell-Skripts in einer nicht vollständig vertrauenswürdigen Umgebung ausgeführt werden, dem Beispiel gefolgt.
Sie können ein Skript nicht sicher in einer Umgebung ausführen, die von einer nicht vertrauenswürdigen Entität festgelegt wurde. Sich über Funktionsdefinitionen Gedanken zu machen, ist also nicht produktiv. Bereinigen Sie Ihre Umgebung und verwenden Sie dabei Variablen, die von bash als Funktionsdefinitionen interpretiert werden.
quelle
/bin/cat
eine Chroot aufruft, alles aufrufen.) Wenn Sie die Umgebung bereinigen, erhalten Sie einen gesunden EindruckPATH
(vorausgesetzt, Sie tun es natürlich richtig). Ich verstehe deinen Standpunkt immer noch nicht.Sie können verwenden
unset -f
, um die Funktionen builtin, command und type zu entfernen.quelle
unset() { true; }
kümmert sich darum.