Giter VIP home page Giter VIP logo

arghsh's Introduction

ARGHSH

What is this

A login shell for SSH RPC that safely passes through your argument vector. For Posix-y systems that have execv.

Why is this

When we use SSH as an RPC transport mechanism, like so (trivialised case, Python):

from subprocess import run
run(['ssh', 'somewhere', 'ls' '-la', 'a filename with spaces'])

then sooner or later we will find out that the OpenSSH server on the remote side doesn't execute ls directly — rather, it starts the login shell (as referenced from /etc/passwd or from some other source) with two arguments:

  1. -c
  2. ls -la a filename with spaces.

It does that even when you use ForceCommand. In other words, the argument vector framing we so neatly passed to ssh was lost; it's been string-joined and passed on as a single argument to the login shell >:(.

The invoked login shell (say, bash) will then proceed to tokenize its second argument, in the same way as it does when you use the shell interactively. Sadly for us, it will not simply reconstruct the original three-member argument vector of ['ls', '-la', 'a filename with spaces']. It turns out that we'll need to escape the spaces in a filename with spaces. Or we could quote the filename part of the command. That would indeed suffice for this trivial case, but to handle arbitrary inputs we'll also need to escape any quoting and escaping characters already present in those inputs. And take care of all the shell metacharacters that might occur. Going down this rabbit hole is not necessarily pretty, pleasant, or easy. It may even be ű͚̥̼̩̳̭̫́ͯ̍͢n̓͗̈́̈s̘͈̠̠̲̾͐͊ͦa̡̱̯̖̋́̋ͥͣḟ̸̹͎͇̠̫̃ͫ̑ͦḛ̯͍̰ͣ͋̋͑ͅ, exposing you to injection if parts of the argument vector are unsafe inputs. The misery grows with every round of tokenization (as when your RPCd command does RPC in turn — as in ssh somewhere ssh somewhere_else ls -la a filename with spaces). ARGH!

So. It would have been much better if the original argument vector element boundaries had been preserved, using well-understood and simple framing and escaping. A JSON array of strings is a vehicle approachable from many programming languages, so we'll use that, and we will simply avoid having any shells in the loop. In such a setup, arghsh takes the role of login shell.

Usage

Build arghsh. For creating a statically linked executable, read onwards. Then use chsh to set arghsh as a login shell. You'll probably want a dedicated user for SSH RPC through arghsh, as this shell is a bit *cough* awkward to use as a day-to-day login shell. If for some reason you don't want a completely distinct user, then a neat trick is to create another username for an existing user by creating a copy of a passwd entry, modifying just the username and login shell. Then you can invoke either the "normal" login shell or arghsh by passing the appropriate username to SSH.

Once installed on a remote system, you should be able to do tidy and worry-free SSH RPC with it like so (trivial Python example):

from json import dumps
from subprocess import run

cmd = dumps(["/bin/ls", "-la", r"a file with spaces and !horrib;le$ shell meta\ charac'ters"])
run(['ssh', 'somewhere_with_arghsh', cmd])

Splendid.

Creating a statically linked executable (Linux)

For Linux, Rust supports statically linking, but using musl rather than glibc. So, install that platform:

rustup target add x86_64-unknown-linux-musl

Then compile:

cargo build --release --target=x86_64-unknown-linux-musl

And there it is:

$  ldd target/x86_64-unknown-linux-musl/release/arghsh     
	statically linked

arghsh's People

Contributors

blinkingtwelve avatar nsauzede avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.