En quoi SFTP n'est-il pas basé sur SSH?

9

Je viens de terminer le jeu de guerre OverTheWire Bandit, niveau 18 .

Ce fut une surprise. Voici les instructions pour ce niveau.

Le mot de passe pour le niveau suivant est stocké dans un fichier lisez -moi dans le répertoire principal. Malheureusement, quelqu'un a modifié .bashrc pour vous déconnecter lorsque vous vous connectez avec SSH.

Je réfléchissais à un moyen de faire en sorte que le shell saute l'approvisionnement .bashrc. Mais avant de trouver une solution, j'ai été tenté de simplement démarrer une connexion SFTP avec le serveur. Je ne m'attendais pas à ce que ça marche. Mais ça l'a fait. Et j'aimerais savoir pourquoi. Je pensais que SFTP fonctionne sur SSH.

Pour plus de clarté, lorsque je SSH sur le serveur, je suis expulsé, comme prévu.


la source
1
SFTP s'exécute sur SSH. bash peut également s'exécuter sur SSH. Mais SFTP ne s'exécute pas sur bash. (notez que j'utilise vaguement "
écraser

Réponses:

13

Sur bash en général

La conception de Bash en ce qui concerne les fichiers de démarrage est plutôt particulière. Bash charges .bashrcdans deux circonstances indépendantes:

  • Lorsqu'il s'agit d'un shell interactif, sauf lorsqu'il s'agit d'un shell de connexion (et sauf lorsqu'il est appelé en tant que sh). C'est pourquoi .bash_profilese charge généralement.bashrc .
  • Lorsque bash n'est pas interactif ni un shell de connexion ni invoqué en tant que shmais donné une commande à exécuter avec -cet SHLVLest non défini ou inférieur ou égal à 1, et l'une des conditions suivantes est vraie:

    • Si l'entrée standard est une prise. En pratique, cela se produit principalement lorsque bash est invoqué par rshd, c'est-à-dire lors de l'exécution rsh remotehost.example.com somecommand.
    • Si activé au moment de la compilation (ce qui est le cas sur certaines distributions, telles que Debian et dérivés), si l'une des variables d'environnement SSH_CLIENTou SSH2_CLIENTest définie. En pratique, cela signifie que bash est invoqué par sshd, c'est-à-dire ssh remotehost.example.com somecommand.
      Si vous ne savez pas comment bash a été compilé, vous pouvez savoir si cette option a été définie en vérifiant si le binaire contient la chaîne SSH_CLIENT:

      strings /bin/bash | grep SSH_CLIENT
      

Sur SSH en général

Lorsque vous exécutez une commande via le protocole SSH, la commande est transmise sur le câble sous forme de chaîne. La chaîne est exécutée par le shell distant. Lorsque vous exécutez ssh example.com somecommand, si le shell de connexion de l'utilisateur distant est /bin/bash, le serveur SSH s'exécute /bin/bash -c somecommand. Il n'y a aucun moyen de contourner le shell de connexion. Cela permet des shells de connexion restreints, par exemple pour autoriser uniquement la copie de fichiers et non l'exécution générale de commandes.

Il existe une exception: le protocole SSH permet au client de demander un sous-système spécifique. Si le client demande le sftpsous - système, par défaut, le serveur OpenSSH invoque le programme /usr/lib/openssh/sftp-server(l'emplacement peut varier) via le shell de connexion de l'utilisateur. Mais il peut également être configuré pour exécuter un serveur SFTP interne via la ligne

Subsystem sftp internal-sftp

dans le sshd_configfichier. Dans le cas du serveur SFTP interne, et seulement dans ce cas, le shell de connexion de l'utilisateur est contourné.

Pour ce défi

Dans le cas d'OverTheWire Bandit 18, .bashrccontient

…
# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac
…
echo 'Byebye !'
exit 0

Vous pouvez donc résoudre ce niveau en faisant tout ce qui empêche bash d'être interactif.

Comme vous l'avez découvert, SFTP fonctionne.
Mais ssh [email protected] cat readmecela fonctionnerait aussi.
Comme ça echo 'cat readme' | ssh [email protected].
Et appuyer sur Ctrl + C au bon moment lors d'une connexion interactive fonctionnerait également: cela interromprait bash, donc le .bashrcne serait pas complètement exécuté. Bash prend du temps macroscopique pour démarrer, donc bien que cela ne fonctionne pas de manière fiable, cela peut être fait dans la pratique.

Gilles 'SO- arrête d'être méchant'
la source
2
Je ne pense pas que SFTP exécute bash du tout , pas seulement de manière non interactive.
user253751
@immibis Je pense que vous avez raison à ce sujet. J'ai utilisé SFTP pour échanger des fichiers sur un compte d'utilisateur qui a été configuré avec une application comme shell de connexion plutôt que comme un "vrai" shell.
kasperd
@immibis SFTP ne lance pas bash. Mais à moins que le serveur SFTP ne soit interne, sshdexécute le shell de connexion de l'utilisateur qui s'exécute sftp-server. Par conséquent, si le shell de connexion n'interprète pas la chaîne /usr/lib/openssh/sftp-servercomme «exécutez la commande /usr/lib/openssh/sftp-server», vous ne pouvez pas utiliser SFTP.
Gilles 'SO- arrête d'être méchant'
5

Le .bashrcn'est exécuté que lorsque vous démarrez un shell.

Le serveur SSH peut être configuré pour ne pas démarrer un shell pour le protocole SFTP en fournissant la commande Subsystem internal-sftpdans le sshd_configfichier du serveur .

Conjecture: il est probable que c'est ainsi que le wargame OverTheWire Bandit est réellement configuré plutôt qu'un ajustement .bashrccar sinon la même restriction pour sshbloquerait également la sftpcommande du serveur.

roaima
la source
2
Exécution SFTP ne lancer un shell. Le démon SSH s'exécute /path/to/shell -c /path/to/sftp-serveroù se /path/to/shelltrouve le shell de connexion de l'utilisateur. Si le shell de connexion de l'utilisateur est bash, il .bashrcpeut être exécuté selon la façon dont bash a été compilé. Il est toujours exécuté lorsque bash est exécuté par rshd(oui, même pour un shell non interactif, le démarrage de bash est bizarre) et une option de compilation étend cela à sshd.
Gilles 'SO- arrête d'être méchant'
Je suis allé vérifier. Bonne supposition, mais en fait ce n'est pas si subtil. L' exiten .bashrcest exécutée seulement si bash est interactif.
Gilles 'SO- arrête d'être méchant'
@ Gilles, avec Subsystem sftp internal-sftpet echo No.; exit 1dans mon .bashrcje n'ai pas sshaccès au serveur mais ça sftpmarche toujours. (Et bien sûr, il est potentiellement possible d'écraser ou de supprimer les .bashrcautorisations. Nonobstant.) La sshtentative de connexion échoue, qu'elle soit interactive ou non. D'un autre côté, si je l'ai, Subsystem sftp /usr/lib/openssh/sftp-serverle service SFTP échoue également lorsqu'il .bashrcest modifié.
roaima