Vérification des binaires de commande avant exécution

13

Existe-t-il des méthodes pour vérifier ce que vous exécutez réellement à partir d'un script bash?

Supposons que votre script bash appelle plusieurs commandes (par exemple: tar, mail, scp, mysqldump) et vous êtes prêt à vous assurer que tarle réel, réel tar, qui est déterminable par l' rootutilisateur étant le fichier et le répertoire parent propriétaire et le seul avec des autorisations d'écriture et pas certains /tmp/surprise/taravec www-dataou apache2étant le propriétaire.

Bien sûr, je connais PATHet l'environnement, je suis curieux de savoir si cela peut également être vérifié à partir d'un script bash en cours d'exécution et, si oui, comment exactement?

Exemple: (pseudo-code)

tarfile=$(which tar)
isroot=$(ls -l "$tarfile") | grep "root root"
#and so on...
Miloš Đakonović
la source
2
Si vous êtes si paranoïaque, utilisez vos propres binaires!
Ipor Sircer du
8
En plus de whichne pas dire correctement ce qui tarva faire, comme l'a répondu xhienne, il lspourrait être piraté pour renvoyer de fausses informations sur le ou les fichiers, le cas échéant. grepPeut également être piraté pour renvoyer de fausses informations; cela pourrait être évité en utilisant la correspondance du shell à la place, mais le shell pourrait être piraté. Et le shell pourrait être piraté pour donner des résultats erronés typeen premier lieu - ou remplacé entièrement car la remplaçabilité du shell était une innovation importante d'Unix par rapport aux systèmes d'exploitation vieux de 50 ans. Voir l'adresse Turing de 1984 de Ken Thompson. C'est des tortues tout le long.
dave_thompson_085
2
Je ne peux pas répondre à cela pour Linux - seulement AIX - qui a un composant appelé Trusted Execution ( TE) - qui a une base de données avec des signatures (c'est-à-dire plus étendue qu'une somme de contrôle MD5. Lorsque TE est actif ET qu'un fichier est dans la base de données, vous pouvez choisir si le programme s'exécute - ou avertit uniquement qu'il ne correspond pas à la base de données. En outre, il existe deux autres paramètres: TEP(PATH d'exécution approuvé) et TLP(CHEMIN LIBrary approuvé). Seuls les programmes dans TEP peuvent être exécutés et les bibliothèques ne peuvent être chargées qu'avec le répertoire est inclus dans TLP. Dans Linux I, il y a quelque chose appelé "AppArmor" qui peut vous aider.
Michael Felt
1
Vous pouvez avoir ce type de sécurité, mais pas à partir d'un script - au moment où votre script s'exécute dans un environnement non contrôlé, il est trop tard. Pour tout ce que vous savez, tout ce que vous pouvez voir est un chroot créé par un attaquant.
Charles Duffy
2
... si vous voulez avoir un système fiable jusqu'à la fin, vous devez suivre l'approche ChromeOS: faites signer votre firmware avec une clé intégrée à votre matériel; votre chargeur de démarrage / noyau vérifié par le firmware; votre partition du système d'exploitation racine en lecture seule à l'aide de signatures de niveau bloc pour la vérification; etc. Il existe également des approches similaires à celles décrites par @MichaelFelt - voir l'architecture de mesure d'intégrité - mais l'impact sur les performances est plus élevé et le niveau d'intégrité réduit (car la vérification des signatures binaires ne vous aide pas avec les attaques via des non exécutables. contenu).
Charles Duffy

Réponses:

24

Au lieu de valider les binaires que vous allez exécuter, vous pouvez exécuter les bons binaires dès le départ. Par exemple, si vous voulez vous assurer de ne pas exécuter /tmp/surprise/tar, exécutez simplement /usr/bin/tarvotre script. Alternativement, définissez votre $PATHvaleur saine avant d'exécuter quoi que ce soit.

Si vous ne faites pas confiance aux fichiers /usr/bin/et aux autres répertoires système, il n'y a aucun moyen de reprendre confiance. Dans votre exemple, vous vérifiez auprès du propriétaire ls, mais comment savez-vous que vous pouvez faire confiance ls? Le même argument s'applique à d'autres solutions telles que md5sumet strace.

Lorsqu'une confiance élevée dans l'intégrité du système est requise, des solutions spécialisées comme IMA sont utilisées. Mais ce n'est pas quelque chose que vous pourriez utiliser à partir d'un script: l'ensemble du système doit être configuré de manière spéciale, avec le concept de fichiers immuables en place.

Dmitry Grigoryev
la source
Qui se casse lorsque différentes distributions choisissent de mettre des binaires à la /binplace de /usr/bin.
Damian Yerrick
IMA est l'une des deux approches prêtes pour la production à ce sujet - l'autre est l'approche dm-verity adoptée par ChromeOS pour effectuer la validation au niveau du bloc des rootfs.
Charles Duffy
@DamianYerrick Fair remarque. Définissez $PATHensuite ces deux chemins si la prise en charge de plusieurs distributions est nécessaire.
Dmitry Grigoryev,
AIX TE (avec ou sans RBAC) serait un troisième noyau intégré «prêt pour la production» qui accomplirait cela - peut-être plus. TE, une fois activé pour être plus que passif - empêchera l'ouverture de fichiers et / ou l'exécution de programmes. De plus, l'utilisation des applications et de la bibliothèque peut être définie pour être exclusivement sur TEP (chemin d'exécution approuvé) ou TLP (chemin de bibliothèque approuvé). Voir ibm.com/support/knowledgecenter/en/ssw_aix_61/… pour des informations de base
Michael Felt du
6

Si un intrus a accédé à votre système et est en mesure de modifier votre $PATH(ce qui ne devrait /tmpen aucun cas inclure ), il est trop tard pour commencer à vous soucier de la propriété des exécutables.

Au lieu de cela, vous devriez lire comment gérer une intrusion .

Mieux vaut se concentrer sur l'évitement des intrusions.

Si vous avez un système où ce genre de choses est important, il peut être judicieux d'isoler les parties qui doivent être publiques des parties qui doivent être privées, ainsi que d'effectuer un audit des modes de communication entre ceux-ci.

Kusalananda
la source
4

C'est possible dans une certaine mesure en vérifiant le md5sumfichier. Ainsi, sur les systèmes qui utilisent la aptgestion des packages - dans mon cas particulier, Ubuntu 16.04 - il y a le fichier /var/lib/dpkg/info/tar.md5sums, qui stocke les sommes md5 de tous les fichiers provenant de l' tarinstallation. Vous pouvez donc écrire une simple instruction if qui vérifie si la sortie de md5sum /bin/tarcorrespond à ce qui se trouve dans ce fichier.

Cela suppose bien sûr que le fichier lui-même n'a pas été falsifié. Bien sûr, cela ne peut se produire que si l'attaquant a obtenu un accès root / sudo, auquel cas tous les paris sont désactivés.

Sergiy Kolodyazhnyy
la source
8
Mais comment validez-vous /usr/bin/md5sum?
Dmitry Grigoryev
Si un attaquant est en mesure de remplacer /bin/tarou /usr/bin/tar, il est très probable qu'il puisse également simplement remplacer md5sumou /var/lib/dpkg/info/tar.md5sums. Ou $SHELL.
Jonas Schäfer
1
Je pense que j'ai déjà mentionné dans le dernier paragraphe, que pour qu'une telle chose se produise, un attaquant devrait avoir un accès root au système, et à ce stade, tout est possible. Dans les cas où l'attaquant n'a pas d'accès root, mais peut modifier la variable PATH pour un utilisateur ou créer un alias tarpointant vers différents binaires, cela fonctionnera. Lorsqu'un système est compromis au niveau racine, vous avez alors une option - le neutraliser depuis l'orbite
Sergiy Kolodyazhnyy
3

Oui, il existe une méthode: le builtin type. Contrairement à la whichcommande qui ne recherche que dans votre PATH, typevous dira si le nom de la commande est en fait un mot clé réservé, un builtin, un alias, une fonction ou un fichier disque.

$ type -t foobar || echo "Not found"
Not found

$ type -t echo
builtin

$ enable -n echo; type -t echo; type -p echo
file
/usr/bin/echo

$ echo() { printf "(echoing) %s\n" "$*"; }; type -t echo
function

$ alias echo="/bin/echo 'I say: ' "; type -t echo
alias

De plus type -avous donnera tous les candidats à votre commandement (du premier au dernier choix):

$ type -a echo
echo is aliased to `/bin/echo 'I say: ' '
echo is a function
echo () 
{ 
    printf "(echoing) %s\n" "$*"
}
echo is a shell builtin
echo is /usr/local/bin/echo
echo is /bin/echo

Enfin, si vous n'êtes concerné que par les binaires sur votre disque, vous pouvez utiliser type -Papour obtenir tous les binaires de votre PATH (même ordre que ci-dessus):

$ type -Pa tar
/home/me/bin/tar                <= oh oh, is this normal?
/bin/tar

Cela dit, typeseul ne vous dira pas exactement quelle commande sera appelée à la fin. Par exemple, si votre tarest un alias qui appelle un binaire (par exemple alias tar="/tmp/tar"), il typevous dira que c'est un alias.

xhienne
la source
type -ainclut tous les formulaires (par exemple, alias et programme externe)
dave_thompson_085
Merci @dave, c'est effectivement intéressant, j'ai mis à jour ma réponse
xhienne
1
typevous dira dans la mesure où bash le sait, mais si nous sommes sous le contrôle d'un attaquant malveillant, il n'y a aucune raison de croire que ce que bash pense qu'il sait reflète la vérité. Pour tout ce que vous savez, il existe un LD_PRELOADmodule interceptant chaque appel de bibliothèque C que vous effectuez.
Charles Duffy
1
@CharlesDuffy Vous avez bien sûr raison. Je ne voulais pas répondre du point de vue de la sécurité. Je propose simplement une réponse à la question du haut: "Existe-t-il des méthodes pour vérifier ce que vous exécutez réellement à partir d'un script bash" et j'ai proposé une alternative à which.
xhienne
Je n'en ai jamais vu enableauparavant. J'ai utilisé les conseils de ces réponses pour exécuter type enablepour découvrir qu'il s'agit d'un shell intégré, puis help enablepour voir ce qu'il fait.
Joe
3

Vous pouvez vérifier quelles commandes sont exactement exécutées par un script à l'aide de strace. Par exemple:

strace -f -e execve ./script.sh

Avec le script suivant:

#!/bin/bash
touch testfile.txt
echo "Hello" >> testfile.txt
cat testfile.txt
rm testfile.txt

stracevous indiquera le chemin exact des commandes exécutées lorsqu'il est utilisé avec le -e execveparamètre:

execve("./script.sh", ["./script.sh"], [/* 69 vars */]) = 0 
Process 8524 attached
[pid  8524] execve("/usr/bin/touch", ["touch", "testfile.txt"], [/* 68 vars */]) = 0 
[pid  8524] +++ exited with 0 +++
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=8524, si_status=0, si_utime=0, si_stime=0} --- 
Process 8525 attached [pid > 8525] execve("/bin/cat", ["cat", "testfile.txt"], [/* 68 vars */]) = 0
Hello [pid  8525] +++ exited with 0 +++
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=8525, si_status=0, si_utime=0, si_stime=0} --- 
Process 8526 attached [pid > 8526] execve("/bin/rm", ["rm", "testfile.txt"], [/* 68 vars */]) = 0
[pid  8526] +++ exited with 0 +++
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=8526, si_status=0, si_utime=0, si_stime=0} ---
+++ exited with 0 +++

Paramètres (de strace man):

-f: Trace les processus enfants tels qu'ils sont créés par les processus actuellement tracés à la suite des appels système fork (2), vfork (2) et clone (2). Notez que -p PID -fva attacher tous les threads du processus PID s'il est multi-thread, pas seulement le thread avec thread_id = PID.

-e trace=file: Trace tous les appels système qui prennent un nom de fichier comme argument. Vous pouvez considérer cela comme une abréviation pour -e trace=open,stat,chmod,unlink,...laquelle il est utile de voir à quels fichiers le processus fait référence. De plus, l'utilisation de l'abréviation garantira que vous n'oublierez pas accidentellement d'inclure un appel comme lstat dans la liste.

Zumo de Vidrio
la source
3
Ce n'est en aucun cas utilisable par un script pour effectuer des tests automatisés, et il n'y a aucune raison particulière de croire que cela stracen'a pas lui-même été renversé.
Charles Duffy
0

Le système d'exploitation Linux est basé sur des fichiers et de nombreuses commandes exécutées sur linux résoudront probablement certains changements dans les fichiers situés sur votre machine. À cause de cela, c'est peut - être la meilleure solution à votre problème. Vous pouvez tester vos commandes pour tout changement sur le système de fichiers avant qu'il ne soit exécuté.

entrez la description de l'image ici

Il y a la commande 'strace' qui décompile votre commande en plusieurs parties ...

entrez la description de l'image ici

Si vous voulez vraiment aller plus loin, vous devez vérifier les décompilateurs pour les scripts qui vont être exécutés. En d'autres termes, vous devez vérifier l'interprétation par l'assembleur de cette commande. Pour bash là-bas objdump -d. Les scripts bin Linux sont principalement créés avec Cun langage de programmation, utilisez donc un bon Cdécompilateur.


la source