Moin Matthias,

regarding this bit with screen-4.9.1:

Am Mon, 12 May 2025 17:24:26 +0200
schrieb Matthias Gerstner <mgerst...@suse.de>:

> 3.c) Screen by Default Creates World Writable PTYs (CVE-2025-46803)
> -------------------------------------------------------------------
> 
> In Screen version 5.0.0 the default mode of pseudo terminals (PTYs)
> allocated by Screen was changed from 0620 to 0622, thereby allowing
> anyone to write to any Screen PTYs in the system. Security-wise this
> results in some of the issues that have been outlined in issue 3.b),
> without the information leak aspects, however.
> 
> The history of the default PTY mode in Screen is rather complex. Let's
> have a look at the situation in version 4.9.1 (and a lot of older
> versions):
> 
> - There is a 0622 default mode in the code in process.c line 207 [14].
>   This is only a fallback that should not become active unless the code
>   is compiled in unusual ways.
> - A default mode of 0620 is applied in configure.ac line 811 [15], which
>   results in a safe default when compiling Screen using autotools.
> - In acconfig.h line 81 [16] the following is stated:
>   
>   > define PTYMODE if you do not like the default of 0622, which allows 
> public write to your pty.  
>   
>   Thus in this version there is an inconsistency between the default
>   mode on autoconf level and the default on source code level, but in
>   the end the (safe) autoconf default wins.

Are you sure the safe default wins? I also read configure.ac as such,
at a first glance … but running plain configure results in

$ grep PTYMODE config.h
 * define PTYMODE if you do not like the default of 0622, which allows 
/* #undef PTYMODE */

on a Debian 12 machine with perhaps a specific setup because of
multiuser access — exactly the situation where the world-writable ptys
are of most concern.  Configure messages:

configure: checking for ptyranges...
configure: checking default tty permissions/group...
checking for write... /usr/bin/write
checking for xterm... no
- ptys are world accessable

This system does not have xterm installed in /usr/. It is a headless
shell server. But also running the configure code on an Ubntu 22.04.5
box, with write and xterm shows this:

~$ sh -x  /dev/shm/ttygrp.sh "$(command -v write)" "$(command -v xterm)"
+ AWK=awk
+ WRITEPATH=/usr/bin/write
+ XTERMPATH=/usr/bin/xterm
+ found=
+ test -n /usr/bin/write/usr/bin/xterm
+ findfollow=
+ lsfollow=
+ find /usr/bin/write /usr/bin/xterm -follow -print
+ found=/usr/bin/write
/usr/bin/xterm
+ test -n /usr/bin/write
/usr/bin/xterm
+ findfollow=-follow
+ lsfollow=L
+ test -n /usr/bin/xterm
+ ls -lL /usr/bin/xterm
+ sed -n -e 1p
+ awk {print $4}
+ ptygrpn=root
+ test tty != root
+ XTERMPATH=
+ test -n /usr/bin/write
+ find /usr/bin/write -follow -perm -2000 -print
+ found=
+ test -n 
+ echo - ptys are world accessable
- ptys are world accessable

So the code sees

-rwxr-xr-x 1 root root 22920 Apr  9  2024 /usr/bin/write.ul
-rwxr-xr-x 1 root root 852552 Mär 11  2022 /usr/bin/xterm

and deduces that ptys should be world-accessible (see typo, btw.). Why
does it enter that code path at all? This test program fails on the
Debian 12 multiuser server, and probably everywhere:

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int
main()
{
  struct stat sb;
  char *x,*ttyname();
  int om, m;
  FILE *fp;

  if (!(x = ttyname(0))) return 1;
  if (stat(x, &sb)) return 2;
  om = sb.st_mode;
  if (om & 002) return 0;
  m = system("mesg y");
  if (m == -1 || m == 127) return 3;
  if (stat(x, &sb)) return 4;
  m = sb.st_mode;
  if (chmod(x, om)) return 5;
  if (m & 002) return 0;
  if (sb.st_gid == getgid()) return 6;
  if (!(fp=fopen("conftest_grp", "w")))
    return 7;
  fprintf(fp, "%d\n", sb.st_gid);
  fclose(fp);
  return 0;
}

Why? Because stdin is no terminal for configure tests.* The much
simplified logic in the screen-5.0.0 configure (which is also really
small and fast, to name an improvement) does not suffer from these
quirks and just uses sane defaults.

So screens opened with screen-4.9.1 are world-writable basically
everywhere without setgid xterm or write binaries, which is rather
counter-intuitive for admins who might even remove these bits to
enhance security.

So a better workaround is to supply _both_ mode and groups, to avoid
the wonky group detection logic:

$ ./configure --with-pty-mode=0620 --with-pty-group=tty
[…]
$ grep -e PTYMODE -e PTYGROUP config.h
 * define PTYMODE if you do not like the default of 0622, which allows 
 * define PTYGROUP to some numerical group-id if you do not want the
#define PTYMODE 0620
#define PTYGROUP tty

Still, I'd rather expect, in the absence of requested group write
permissions to have the terminals as 0600, not 0622. This is really not
secure-by-default.


Alrighty then,

Thomas

* I admit that I was not sure of that, but rather hope that this would
  be ensured by autoconf, as it would introduce horrible inconsistency
  between automated and interactive builds.

-- 
Dr. Thomas Orgis
HPC @ Universität Hamburg

Reply via email to