CVSS 6.8 CVE-2019-6109

CVSS 6.8 CVSS:3.0/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N

An issue was discovered in OpenSSH 7.9. Due to missing character encoding in the progress display, a malicious server (or Man-in-The-Middle attacker) can employ crafted object names to manipulate the client output, e.g., by using ANSI control codes to hide additional files being transferred. This affects refresh_progress_meter() in progressmeter.c.

SCP Protocol Background

The SCP protocol is not an official standard — it is a de-facto protocol derived from the 1983 BSD rcp (remote copy) utility and was never formally documented. SCP runs over an SSH channel: the client SSH-connects to the server and executes the remote scp binary in file-sending mode (scp -f <file>). The two scp processes then communicate over that channel using a simple line-oriented text protocol.

For each file the server sends, it first transmits a C-message (copy message):

C<mode> <size> <filename>\n

For example:

C0644 14295 document.txt\n

The client parses this line, extracts the filename, opens a local file with that name, and then receives the file data. Once the transfer is complete the server sends a zero-byte confirmation. The filename is taken verbatim from the C-message — the client performs no control-character filtering.

Vulnerable Code Path

After parsing the C-message, OpenSSH stores the server-supplied filename in curfile and immediately begins rendering the progress meter via refresh_progress_meter() in progressmeter.c. The progress display is written directly to the user’s terminal (stderr) using atomicio():

/* progressmeter.c (simplified) */
snprintf(buf, sizeof(buf), "\r%-*s", win_size - 36, curfile);
atomicio(vwrite, STDERR_FILENO, buf, strlen(buf));

The \r at the beginning of buf moves the cursor to the start of the current line (standard progress-meter behavior to overwrite the previous status line). If ``curfile`` itself contains ANSI escape sequences, they are written to the terminal along with the filename — no sanitization takes place.

ANSI Escape Sequences used in the Attack

A malicious server can embed any of the following terminal control sequences in the filename portion of the C-message:

Sequence

Effect

\r (0x0D)

Moves cursor to column 0 of the current line

\x1b[2K

Erases the entire current line (cursor position unchanged)

\x1b[1A

Moves cursor up one line

\x1b[1A\x1b[2K

Moves up one line and erases it completely

The only byte that cannot appear in a filename (and therefore cannot be injected) is \n (0x0A), because it terminates the C-message line.

Attack Chain

The attack combines this vulnerability with CVE-2019-6111 (file injection) and CVE-2019-6110 (stderr erasure):

Step 1 — Legitimate transfer begins

The client runs scp user@server:document.txt .. The server sends the expected C-message:

C0644 14295 document.txt\n

The client renders: document.txt   100%  13 KB   1.3 MB/s   00:00

Step 2 — Server injects an additional file (CVE-2019-6111)

Before the client sends its final acknowledgement, the server sends a second, injected C-message. Per CVE-2019-6111 the client accepts arbitrary files from the server because the SCP client-side validation only blocks ../ directory traversal — not arbitrary target filenames.

The injected C-message uses a crafted filename containing ANSI codes:

C0600 444 \x1b[2K\rauthorized_keys\n

Broken down:

  • \x1b[2K — immediately erases the current terminal line (where the progress for the injected file would appear)

  • \r — moves cursor back to column 0

  • authorized_keys — the actual local filename the content is written to

Step 3 — Progress meter renders the crafted filename

refresh_progress_meter() writes the crafted filename to the terminal. The terminal processes it as:

  1. \x1b[2K → erase the line

  2. \r → move cursor to column 0

  3. authorized_keys → rendered at the start of a blank line — but is immediately overwritten by the next progress update for document.txt

From the user’s perspective, the terminal shows only document.txt completing normally. The injected transfer of ~/.ssh/authorized_keys is invisible.

Step 4 — Result

The client has silently written attacker-controlled content to authorized_keys (or any other target file). The user’s terminal output shows no indication that a second file was received.

Test with SSH-MITM

A proof of concept exploit is integrated in SSH-MITM. This exploit also uses CVE-2019-6111 to inject additional files.

To inject a file during a download from the server to the client:

$ ssh-mitm server --scp-forwarder inject_file --scp-inject /path/to/additional/file

The injected file transfer is hidden using this vulnerability and CVE-2019-6110.

References