Insecure shelling via netcat
For a typical Linux system, putting this script in the PATH variable should be enough.
curl -L https://git.io/JBWnf > /usr/local/bin/issh && chmod +x /usr/local/bin/issh
- Support embedded systems that lack OpenSSL/OpenSSH
- Upwards of 10x faster (see benchmarks)
- Android support
- Relies almost exclusively on toybox
- Acts as both a server and client
- Supports fully interactive clients
- Supports filtering of external connections
Since we do not rely on OpenSSL, we are able to get a reply from a server in significantly less time using issh. In this benchmark, we compare sshpass -p <PASSWORD> ssh host@localhost <COMMAND>
against ./issh -c "sh"
and ./issh -C localhost
.
- OpenSSH: ~150ms avg latency
- issh: ~15ms avg latency
You can use issh for a variety of tasks. Here's a few examples to get you started.
- Server:
./issh -d
(-d
forks our server to the background) - Client:
echo "whoami" | ./issh -C localhost
Note that for interactive shells, we should do a few things:
- Use a login shell, so we source our profile dotfile
- Use an interactive shell to handle TTY commands
- Redirect STDERR to STDOUT, so our client can see it
- Server:
./issh -d -c "sh -li 2>&1"
- Client:
./issh -C localhost -t
(connects as an interactive tty)
- Server:
./issh -d -c "su -c 'sh -li' - username 2>&1"
- Client:
./issh -C localhost -t
(greeted with su asking for password; if success, dropped intosh -li
)
- Server:
./issh -d -c "./auth.sh"
- Server: Create an authentication script that should be presented to the client on connect. Here's an example. Ideally, your password would not be stored in plaintext in the script. Other authentication ideas could be to use SSL or GPG keys. Authentication is not provided by issh.
#!/usr/bin/env bash
echo -n "Enter secret key: "
read -r key
[[ "$key" == "password123" ]] && bash -li 2>&1
- Client:
./issh -C localhost -t
(connects as an interactive tty) - Client:
Enter secret key: password123
- Server:
./issh -d -c "cat /proc/loadavg"
- Client:
SERVER_LOADAVG="$(./issh -C localhost)"
You can start issh on bootup using systemd. The default configuration creates an interactive bash session.
cp systemd/isshd.service /etc/systemd/system/
chmod +x /etc/systemd/system/isshd.service
systemctl enable --now isshd
Since issh is built on top of toybox instead of typical GNU tools, we can support a wider variety of devices, including Android.
A useful concept is allowing a regular user to gain ADB-level access without needing to be constantly connected to a computer, nor needing wireless debugging or an ADB binary of any kind.
- Using a computer, start an
adb shell
- Pull the
issh
script somewhere local (i.e., /sdcard/Download/) sh issh -d -c "sh -li 2>&1"
Now, on a client (which can be the device itself via a standard terminal emulator), we can connect to this session locally.
sh issh -C localhost -t
pm grant com.example.app android.permission.PRIVILEDGED_PERMISSION_EXAMPLE
In this case, our client does not need to use a computer to gain ADB-level access since we have an open issh session.
- Avoiding ADB protocol entirely
- Avoiding cross-compiling ADB binary
- Avoiding external programs that rely on binary executables
- Compatibility with Android 6+ (instead of Android 10+)
- Wireless debugging is no longer necessary
You can launch an issh session in Termux as well. However, Termux lacks toybox, so we must add it to our PATH variable from the Android system. Use the built-in Termux issh wrapper to automate the process:
./issh.termux.sh