1 x security it’s worse than it looks ilja van sprundel [email protected]

100
1 X Security it’s worse than it looks Ilja van Sprundel <[email protected] >

Upload: pamela-whitehead

Post on 16-Dec-2015

214 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

1

X Securityit’s worse than it looks

Ilja van Sprundel <[email protected]>

Page 2: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Who am I?

• IOActive• Director of Penetration Testing • Pentest • Code review • Break stuff for fun and profit

2

Page 3: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

agenda

• Intro• Client• Server• Solutions ?

3

Page 4: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

What this talk is about

• Implementation of X.org parsers• Client and server

• Identify some entrypoints • Show some bugs and trends of bugs that show up often• How bad is it really ?• What is it not about ?

• Network operational side• Yes, network X is bad (sniff, keylog, …) • Should tunnel over ssh if you want that

4

Page 5: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Intro

• I started this about a year ago • Looked at the client first, late last year (december)• Took about a week

• Grepping for entrypoints was easy • Reported ~80 bugs, all have been fixed (well, most)

• Been looking at the server on and off since may • A lot more tedious • Not finished (not by a long shot)• Reported ~120 bugs so far

5

Page 6: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

6

Client

Page 7: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Some observations

• X is a client/server protocol to be used for the gui in most unices

• It’s networked (can be tcp/ip, ipc, …)• Binary protocol

• The client protocol parsers become interesting when suids use X

• You can make them connect to arbitrary X servers using the DISPLAY variable • Who says these have to be well behaving X servers ?

7

Page 8: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

X network architecture

8

Page 9: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Some observations

9

Page 10: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Typical bugs

10

Status XAllocColorCells( register Display *dpy, Colormap cmap, Bool contig, unsigned long *masks, /* LISTofCARD32 */ /* RETURN */ unsigned int nplanes, /* CARD16 */ unsigned long *pixels, /* LISTofCARD32 */ /* RETURN */ unsigned int ncolors) /* CARD16 */{... xAllocColorCellsReply rep;... status = _XReply(dpy, (xReply *)&rep, 0, xFalse);

if (status) {_XRead32 (dpy, (long *) pixels, 4L * (long) (rep.nPixels)); _XRead32 (dpy, (long *) masks, 4L * (long) (rep.nMasks));

}...}

Page 11: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Typical bugs

11

XTimeCoord *XGetMotionEvents(register Display *dpy, Window w, Time start, Time stop, int *nEvents) /* RETURN */{ xGetMotionEventsReply rep;... if (!_XReply (dpy, (xReply *)&rep, 0, xFalse)) {…

}...

if (! (tc = (XTimeCoord *) Xmalloc( (unsigned)

(nbytes = (long) rep.nEvents * sizeof(XTimeCoord))))) { ...

}...

for (i = rep.nEvents, tcptr = tc; i > 0; i--, tcptr++) { _XRead (dpy, (char *) &xtc, nbytes); tcptr->time = xtc.time;

…}

...}

Page 12: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Typical bugs

12

_XkbReadGetDeviceInfoReply( Display * dpy,xkbGetDeviceInfoReply * rep, XkbDeviceInfoPtr devi)

{... if (rep->nBtnsWanted>0) {

act= &devi->btn_acts[rep->firstBtnWanted]; bzero((char *)act,(rep->nBtnsWanted*sizeof(XkbAction)));

}...

int size;act= &devi->btn_acts[rep->firstBtnRtrn];size= rep->nBtnsRtrn*SIZEOF(xkbActionWireDesc);if (!_XkbCopyFromReadBuffer(&buf,(char *)act,size)) goto BAILOUT;

...}

Page 13: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Typical bugs

13

Private Bool_XimXGetReadData( Xim im, char *buf, int buf_len, int *ret_len, XEvent *event){...

return_code = XGetWindowProperty(im->core.display,spec->lib_connect_wid, prop, 0L,(long)((length + 3)/ 4), True, AnyPropertyType,&type_ret, &format_ret, &nitems, &bytes_after_ret, &prop_ret);

...if (buf_len >= length) { (void)memcpy(buf, prop_ret, (int)nitems);

... }...}

Page 14: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Typical bugs

14

static char * ReadInFile(_Xconst char *filename){ register int fd, size;... if ( (fd = _XOpenFile (filename, O_RDONLY)) == -1 )

return (char *)NULL;...

if ( (fstat(fd, &status_buffer)) == -1 ) { close (fd); return (char *)NULL;} else size = status_buffer.st_size;

}

if (!(filebuf = Xmalloc(size + 1))) { /* leave room for '\0' */close(fd);return (char *)NULL;

} size = read (fd, filebuf, size); ...}

Page 15: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Typical bugs

15

static char*TransFileName(Xim im, char *name) { char *home = NULL, *lcCompose = NULL; char dir[XLC_BUFSIZE]; char *i = name, *ret, *j; int l = 0;

while (*i) { if (*i == '%') { i++; switch (*i) {

case 'H': home = getenv("HOME"); if (home) l += strlen(home); possible int overflow (long HOME and loads of %H's) break; case 'L': if (lcCompose == NULL) lcCompose = _XlcFileName(im->core.lcd, COMPOSE_FILE); if (lcCompose) l += strlen(lcCompose); possible integer overflow (long lcCompose and loads of %L's) break; case 'S': xlocaledir(dir, XLC_BUFSIZE); l += strlen(dir); possible integer overflow (long dir and loads of %S's) break; }

Page 16: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Typical bugs

16

j = ret = Xmalloc(l+1); integer overflow, alloc too short if any of the int overflows occured ... i = name; while (*i) { if (*i == '%') { i++; switch (*i) { case '%': *j++ = '%'; break; case 'H': if (home) { strcpy(j, home); buffer overflow if integer overflow occured j += strlen(home); } break; case 'L': if (lcCompose) { strcpy(j, lcCompose); buffer overflow if integer overflow occured j += strlen(lcCompose); } break; case 'S': strcpy(j, dir); buffer overflow if integer overflow occured j += strlen(dir); break; } ...

Page 17: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Typical bugs

17

XFixesCursorImage *XFixesGetCursorImage (Display *dpy) {... xXFixesGetCursorImageAndNameReply rep; int npixels;... if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {... }... npixels = rep.width * rep.height; ushort * ushort... rlength = (sizeof (XFixesCursorImage) +

npixels * sizeof (unsigned long) + nbytes_name + 1);

... image = (XFixesCursorImage *) Xmalloc (rlength); ... image->x = rep.x;...}

Page 18: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Typical bugs

18

Bool DMXGetScreenAttributes(Display *dpy, int physical_screen, DMXScreenAttributes *attr){... xDMXGetScreenAttributesReply rep;... if (!_XReply(dpy, (xReply *)&rep, (SIZEOF(xDMXGetScreenAttributesReply) - 32) >> 2, xFalse)) { UnlockDisplay(dpy); SyncHandle(); return False; } attr->displayName = Xmalloc(rep.displayNameLength + 1 + 4 /* for pad */); _XReadPad(dpy, attr->displayName, rep.displayNameLength); attr->displayName[rep.displayNameLength] = '\0'; ...}

Page 19: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Typical bugs

19

intXGetDeviceButtonMapping( register Display *dpy, XDevice *device, unsigned char map[], unsigned int nmap){ int status = 0; unsigned char mapping[256]; /* known fixed size */... xGetDeviceButtonMappingReply rep;... status = _XReply(dpy, (xReply *) & rep, 0, xFalse); if (status == 1) {

nbytes = (long)rep.length << 2; _XRead(dpy, (char *)mapping, nbytes);

... }...}

Page 20: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Typical bugs

20

XEventClass *XGetDeviceDontPropagateList( register Display *dpy, Window window, int *count){... xGetDeviceDontPropagateListReply rep;... if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {... }...

list = (XEventClass *) Xmalloc(rep.length * sizeof(XEventClass)); if (list) {

... for (i = 0; i < rep.length; i++) {

_XRead(dpy, (char *)(&ec), sizeof(CARD32));list[i] = (XEventClass) ec;

}}

...}

Page 21: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Typical bugs

21

static int_XIPassiveGrabDevice(Display* dpy, int deviceid, int grabtype, int detail, Window grab_window, Cursor cursor, int grab_mode, int paired_device_mode, Bool owner_events, XIEventMask *mask, int num_modifiers, XIGrabModifiers *modifiers_inout){... if (!_XReply(dpy, (xReply *)&reply, 0, xFalse)) {... }

failed_mods = calloc(reply.num_modifiers, sizeof(xXIGrabModifierInfo));... _XRead(dpy, (char*)failed_mods, reply.num_modifiers * sizeof(xXIGrabModifierInfo));

for (i = 0; i < reply.num_modifiers; i++) { modifiers_inout[i].status = failed_mods[i].status; … }...}

Page 22: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Typical bugs

22

XineramaScreenInfo *XineramaQueryScreens( Display *dpy, int *number){ XExtDisplayInfo *info = find_display (dpy); xXineramaQueryScreensReply rep;....

if((scrnInfo = Xmalloc(sizeof(XineramaScreenInfo) * rep.number))) { ... for(i = 0; i < rep.number; i++) {

_XRead(dpy, (char*)(&scratch), sz_XineramaScreenInfo);scrnInfo[i].screen_number = i;scrnInfo[i].x_org = scratch.x_org;scrnInfo[i].y_org = scratch.y_org;scrnInfo[i].width = scratch.width;scrnInfo[i].height = scratch.height;

}... }...}

Page 23: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Typical bugs

23

XvImageFormatValues * XvListImageFormats ( Display *dpy, XvPortID port, int *num){... xvListImageFormatsReply rep;... if (_XReply(dpy, (xReply *)&rep, 0, xFalse) == 0) {... }... int size = (rep.num_formats * sizeof(XvImageFormatValues));... if((ret = Xmalloc(size))) { ...

for(i = 0; i < rep.num_formats; i++) { ...

} }...}

Page 24: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Typical bugs

24

BoolXF86VidModeGetGammaRamp ( Display *dpy, int screen, int size, unsigned short *red, unsigned short *green, unsigned short *blue){... xXF86VidModeGetGammaRampReply rep;... if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {... } if(rep.size) {

_XRead(dpy, (char*)red, rep.size << 1); _XRead(dpy, (char*)green, rep.size << 1); _XRead(dpy, (char*)blue, rep.size << 1);

}... }

Page 25: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Typical bugs

25

BooluniDRIOpenConnection(dpy, screen, hSAREA, busIdString) Display *dpy; int screen; drm_handle_t *hSAREA; char **busIdString;{... xXF86DRIOpenConnectionReply rep;...

if (!(*busIdString = (char *)Xcalloc(rep.busIdStringLength + 1, 1))) { ...

}_XReadPad(dpy, *busIdString, rep.busIdStringLength);

...}

Page 26: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Typical bugs

26

static XcursorFileHeader *_XcursorReadFileHeader (XcursorFile *file){... if (!_XcursorReadUInt (file, &head.ntoc)) unsigned 32bit ntoc var read from file

return NULL;... fileHeader = _XcursorFileHeaderCreate (head.ntoc); passed on to allocate buffer ... for (n = 0; n < fileHeader->ntoc; n++) {

if (!_XcursorReadUInt (file, &fileHeader->tocs[n].type)) break;if (!_XcursorReadUInt (file, &fileHeader->tocs[n].subtype)) break;if (!_XcursorReadUInt (file, &fileHeader->tocs[n].position)) break;

}...}

Page 27: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Typical bugs

27

static XcursorFileHeader *_XcursorFileHeaderCreate (int ntoc){ XcursorFileHeader *fileHeader;

if (ntoc > 0x10000)return NULL;

fileHeader = malloc (sizeof (XcursorFileHeader) + ntoc * sizeof (XcursorFileToc));

if (!fileHeader)return NULL;

fileHeader->magic = XCURSOR_MAGIC; fileHeader->header = XCURSOR_FILE_HEADER_LEN; fileHeader->version = XCURSOR_FILE_VERSION; fileHeader->ntoc = ntoc; fileHeader->tocs = (XcursorFileToc *) (fileHeader + 1); return fileHeader;}

Page 28: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Typical bugs

28

static void ReqCleanup( Widget widget, XtPointer closure, XEvent *ev, Boolean *cont){... char *value;... (void) XGetWindowProperty(event->display, XtWindow(widget),

event->atom, 0L, 1000000, True, AnyPropertyType, &target, &format, &length, &bytesafter, (unsigned char **) &value); should check return

value.XFree(value);

...}

Page 29: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

More observations

• The X client libraries (Xlib)• All discovered X bugs are being fixed • The developer involved is actually quite good

• Amazing • Alan Coopersmith• Very deep understanding of X and the bugs involved • No pushback, no handholding• Worked tirelessly • 104 patches, with reviews and some tests in < 3 months

• And had some interesting comments 29

Page 30: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

30

“I don't know how many setuid X clients still exist these days (is xterm still setuid on any platforms, or did they all get grantpt() or similar calls to avoid needing root?), but since we know there's more X clients than we can keep track of (especially once you get to home grown apps in various companies they've been using for decades), we

have to assume there still may be some. It would be good to put a reminder in the security advisory that best

practice is to separate out the parts of an application that require elevated privileges from the GUI to avoid such

issues - GTK requires this, but not all toolkits do.”

More observations

Page 31: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

More observations

31

“Shoot me now. And then shoot daniels for not freeing us from XKB yet.And then shoot anyone who volunteers to try to fix XKB, before it's toolate for them too.”“Here's my initial analysis of the first part of the Xlib set, until I got so tired my head started spinning trying to figure them out”

“Really, if your window shape is anywhere near 2^32 rectangles, what are you doing?”

“Yes, these [bugs] all seem possible, and far more feasible now than when this code was written, back when disk sizes were still measured in megabytes.”

Page 32: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

More observations

• Comment on LWN from one of the people that introduced some of these bugs in the ‘80’s

32

Page 33: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

More observations

• Debian turn around on these bugs was ridiculously fast!

• 104 patches to merge in • 2 week embargo • Full releases and advisory on day embargo expired

• No one else managed to do this• I think Moritz Mühlenhoff deserves most of the

credit for that one

33

Page 34: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

More observations

• However, Raw X is rarely used nowadays • There’s stuff build on top• And they use raw X • gtk+ • KDE (which uses QT which uses raw X)• Rare direct calls to Xlib code • other

34

Page 35: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

More observations

• KDE / QT• Crappyness is about on par with Xlib• Trivial bugs!

35

Page 36: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

More observations

• Several instances of this

36

Qkeymapper_x11.cpp void QKeyMapperPrivate::clearMappings(){... uchar *data = 0; if (XGetWindowProperty(X11->display, RootWindow(X11->display, 0), ATOM(_XKB_RULES_NAMES), 0, 1024, false, XA_STRING, &type, &format, &nitems, &bytesAfter, &data) == Success && type == XA_STRING && format == 8 && nitems > 2) { ... char *names[5] = { 0, 0, 0, 0, 0 }; char *p = reinterpret_cast<char *>(data), *end = p + nitems; int i = 0; do { names[i++] = p; p += qstrlen(p) + 1; } while (p < end);...}

Page 37: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

More observations

• In QT init code (affects all QT applications)

37

Qapplication_x11.cppvoid qt_init(QApplicationPrivate *priv, int,

Display *display, Qt::HANDLE visual, Qt::HANDLE colormap){... } else if (arg == "-name") { if (++i < argc) appName = argv[i]; if it was previously new'ed, it isn't anymore. }...}

void qt_cleanup(){... if (X11->foreignDisplay) { delete [] (char *)appName; could delete [] a pointer that isn't new'ed and possibly corrupt memory appName = 0; }...}

Page 38: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

More observations

• So I reported these bugs• They didn’t seem to think it was a security issue• Quote from X developer (previous slide) is dead on

• Suid remark • QT does not seem to agree with this

38

Page 39: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

More observations

• "KDE has precisely one setuid application, kcheckpass, for this reason. I suspect that someone running an suid Qt application would fall into a huge number of problems, the most obvious one being a malicious style that would allow them to trivially execute arbitrary code“

• Wait, did we just get a free Code exec bug from the QT security team ?

39

Page 40: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

More observations

• I respond back, saying there are more KDE suid binaries, and specifically mention kppp, and question him on the styles thing

40

Page 41: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

More observations

41

“> I am aware of this, regardless, this is library code, as such, chances are, there are suid applications out there that will use it.

That would be a security hole in those applications rather than in Qt, there are many ways that people can abuse a library to create unsafe applications. > Do styles contain executable code ? Yes.”

Page 42: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

42

“> also, does kppp no longer run suid ? kppp should not be installed setuid. Here's a quote from its FAQ: "There is no need for the setuid bit, if you know a bit of UNIX® systems administration. Simply create a modem group, add all users that you want to give access to the modem to that group and make the modem device read/writable for that group." I doubt any modern distro would install it suid, in fact most are extremely careful about what they allow to be suid and are actively working to minimise what is.”

More observations

Page 43: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

More observations

• That kppp FAQ quote in incomplete, it goes on to say:

43

“… The KPPP team has lately done a lot of work to make KPPP setuid-safe. But it's up to you to decide if you install and how you install it.”

Page 44: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

More observations

• In fact, distros do still have it suid. • E.g. Ubuntu • This is library code! They should not set policy for

the apps that use them. • They’re sitting on the fence, because it’s easy

• you don’t actually have to do anything• Either defend it, and shut up • Or do a suid check and exit()

44

Page 45: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

More observations

• None of those bugs are fixed• Got the ok from QT security team to disclose:

45

“> Ok, since you guys don't consider this a security issue, you're ok with me talking about this publicly? Yes, that's fine”

Page 46: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

More observations

• So loaders have LD_PRELOAD • And has been made setuid safe years ago • KDE/QT

• QT_PLUGIN_PATH • Gnome

• GTK_MODULES• Neither are setuid safe !

46

Page 47: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

More observations

• The GTK+ people seem to be doing somewhat better.

• They do not allow suid GTK+ applications. • And clearly explain why on their webpage

47

Page 48: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

More observations (http://www.gtk.org/setuid.html)

Talking Radios born from taco trucks

48

Page 49: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

More observations

• This is beautiful, well though out and sane!• “Security of GTK+ requires the security of Xlib. The

GTK+ team is not prepared to make that guarantee”

• Or is it ?

49

Page 50: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

More observations

50

Gtkmain.c/* This checks to see if the process is running suid or sgid * at the current time. If so, we don't allow GTK+ to be initialized. * This is meant to be a mild check - we only error out if we * can prove the programmer is doing something wrong, not if * they could be doing something wrong. For this reason, we * don't use issetugid() on BSD or prctl (PR_GET_DUMPABLE). */static gbooleancheck_setugid (void)

Page 51: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

More observations

• What does that mean ? • Suid binaries can use GTK+, BUT …• … they must acquire the privileged resources they

want first • And then drop privileges • After that it’s ok to use GTK+• Want to have their cake and eat it too• Check should be stronger!

51

Page 52: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

More observations

• games are a great example • They are suid• Share a highscore database

• Once aquired, privs are dropped • Only thing an attacker would have access to is that db • assuming a bug was found and exploited

• That db is considered trusted. • Any security bug in db parsing allows for further escalation

• Any user now playing any of those games gets pwned52

Page 53: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

More observations

• By far the most common bug when using Xlib

• Check return values !• XLib defense in depth fixes. Now guarantees NULL

init of arguments on failure.53

void fn(){... SomeFormat *sf;... (void) XGetWindowProperty(dpy, w, property, 0L,

10000000, False, SomePropertyType, &type, &format, &length, &bytesafter, (unsigned char **) &sf);

... XFree((char*)sf);...}

Page 54: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

More observations

• Developers using Xlib don’t seem to realize that most of the api’s they use parse potentially untrusted network data

• _XReply

• _XRead32

• _XRead

• _XGetAsyncReply

• XGetWindowProperty

• XNextEvent

• XPeekEventXIfEvent

• XCheckIfEvent

• XPeekIfEvent

• XCheckTypedWindowEvent

• XSetErrorHandler

• XQueryFont

54

Page 55: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

More observations

• derived from XGetWindowProperty:• XFetchName

• XGetIconName

• XGetSizeHints

• XGetWMHints

• XGetWMSizeHints

• XGetIconSizes

• XGetTransientForHint

• XGetClassHint

• XGetRGBColormaps

• XGetTextProperty

• XGetWMName

• XGetWMIconName

• XGetWMClientMachine

• XGetCommand

• XGetWMColormapWindows

• XGetWMProtocols

55

• XScreenResourceString• XFetchBuffer• XFetchBytes• XkbRF_GetNamesProp

Page 56: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

More observations

• Conceptually there’s a couple of X suid apps around that you’ll see: • Config tools (e.g. kppp) • Games (e.g. swell foop)• Screen locking utils (e.g. Xlock, Xlockmore, Xscreensaver, …)

• Virtually all of these apps do drop privileges • Still holding on to privileged resources in most cases

56

Page 57: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Client summary

• Xlib in suids is a bad idea • GTK+ kinda sorta still allowed in suids • Very common sloppy misuse of Xlib api’s

57

Page 58: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

58

Server

Page 59: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

server

• Reviewing the X server code has been ongoing work since may-june

• Not finished • a LOT of code• I’m lazy• GLX is a horrible demotivator!

59

Page 60: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Server architecture

• Remember the X architecture layout ?

60

Page 61: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

X network architecture

61

Page 62: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

server• This is a lie!• X hasn’t looked like this in a very long time • Should watch Daniel Stone’s “The real story behind

wayland and X” talk (http://www.youtube.com/watch?v=RIctzAQOe44)

• X hasn’t been network transparant in a long time • Shared memory • DRI / DRM

• Direct rendering

• MMIO

• Kernel drivers / ioctl’s

62

Page 63: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

63

Page 64: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Server: core protocol

• Let’s start with the beginning • X server parses core X protocol • All straight c code • This is 30 years old

• If it was written in the early 90’s iso 80’s, it would’ve probably been written in C++.

• This code is actually pretty cool (from a security perspective)

• You can actually see where the bugs got patched over time (e.g. integer overflow checks)

64

Page 65: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Server: core protocol

• Dix/dispatch.c (dispatch())• This is where all connections for the X server come in• client calls

• initial connection (e.g. set up byte order) proc• Establish connection (e.g. authorization) proc

• Client now gets to send core X protocol requests to server

• Requests are limited to ~64k (~16mb with big requests enabled)

65

Page 66: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Server: core protocol

• Content of requests depends on the request (TLV)• All of them begin with a:

• CARD8 type; • CARD8 data;• CARD16 length;

• Anything < 4 bytes won’t make it through. • Type 0-127, core protocol • Type 128-255, extensions

• Extensions get to pick and choose how they want their (sub)type delivered • Will usually take data for (sub)type

66

Page 67: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Server: core protocol

• Procedures clients can call• Dix/tables.c

• ProcVector• SwappedProcVector (different byteorder)• Create/destroy/query

• Windows • Atoms • Properties• Image• Text• …

67

Page 68: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Server: Extensions

• This is how people have worked around X11s old age and brokenness (while leaving the core protocol in tact)

• Extensions for • Input• Output • Shared memory • OpenGL • DRI• …

68

Page 69: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Server: Extensions

• Extensions get registered by calling AddExtension()

• Will add MainProc to ProcVector (>128)• Will add SwappedMainProc to SwappedProcVector• MinorOpcodeProc decides how extension wants it’s

type delivered

69

Page 70: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Server: Extensions

• Extensions can also add new resources • Types of handles basically

• Done by calling CreateNewResourceType()• Takes two arguments

• Delete function • Name

• Delete logic can get very complicated • Possible source of bugs

70

Page 71: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Server: Extensions

• Rought list of Extensions• Core protocol

• ProcListExtensions proc• XListExtensions() xlib api• Shows list of loaded extension

71

$ grep AddExtension * -r | awk 'BEGIN{FS=":";} {print $1;}' | grep ".*\.c" | sort | uniq

composite/compext.cdamageext/damageext.c

dbe/dbe.cdix/extension.c

glx/glxext.chw/dmx/dmx.c

hw/dmx/glxProxy/glxext.chw/kdrive/ephyr/ephyrdriext.c

hw/xfree86/dixmods/extmod/xf86dga2.chw/xfree86/dixmods/extmod/xf86vmode.c

hw/xfree86/dri/xf86dri.chw/xfree86/dri2/dri2ext.c

hw/xquartz/applewm.chw/xquartz/pseudoramiX.chw/xquartz/xpr/appledri.chw/xwin/winwindowswm.c

randr/randr.crandr/rrxinerama.c

record/record.crender/render.c

Xext/bigreq.cXext/dpms.cXext/geext.c

Xext/panoramiX.cXext/saver.c

Xext/security.cXext/shape.c

Xext/shm.cXext/sync.c

Xext/xcmisc.cXext/xf86bigfont.c

Xext/xres.cXext/xselinux_ext.c

Xext/xtest.cXext/xvmain.c

Xext/xvmc.cxfixes/xfixes.cXi/exevents.c

Xi/extinit.cXi/selectev.c

xkb/xkb.c

int main() { Display *dpy = XOpenDisplay(NULL); int nextensions, i = 0; char **p, **extensionList = XListExtensions(dpy, &nextensions); for(p = extensionList; nextensions; nextensions--, p++){i++; printf("extension %d: %s\n", i, *p); }}

Page 72: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Server: Extensions

• Prime attack surface • Have reviewed most of these • Some are small, some are huge

• Some select few were HUMONGOUS• Varying level of quality

• Some good, some bad• GLX was sheer terror

72

Page 73: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Server: Request procedure

• So what does a general request Proc look like ?

• xTestReq is a structure describing the request • REQUEST() is a macro that defines a structure of type

xTestReq called stuff (and points it to the request buffer)

73

intProcTest(ClientPtr client) { REQUEST(xTestReq); REQUEST_SIZE_MATCH(xTestReq); useRequestData(stuff); return Success;}

Page 74: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Server: Request procedure

• REQUEST_SIZE_MATCH(type) • Indicates that the request has to be exactly as big as the

structure • REQUEST_AT_LEAST_SIZE(type)

• Indicates that the request has to be at least as big as the structure

• REQUEST_FIXED_SIZE(type, len)• Indicates that the request has to be exactly as big as the

structure + len • Has implicit integer overflow!

• Use of these macro’s prevent out of bound read/write 74

Page 75: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Server: Type of bugs

• There’s some typical bugs that keep showing up when looking at a bunch of these request Proc’s

75

Page 76: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Server: Type of bugs

• Memory allocation • Forgetting to check return values • In OOM cases, can return NULL • Would crash on NULL deref

76

Page 77: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Server: Type of bugs

• Integer overflows • when parsing large files

• > 4gig files • Read it all in one large buffer

• Buffer either dynamically grows (int overflow) • Loop over file to calculate size (int overflow)

• When parsing protocol data• out of bound reads (bypassing length checks) • Memory corruption (when doing buffer length calculations)

• Malloc wrappers • Implicit in REQUEST_FIXED_SIZE

77

Page 78: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Server: Type of bugs

• Cute realloc bugs • realloc() with size of 0 becomes free • Leads to use after free and double free bugs

78

Page 79: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Server: Type of bugs

• Unvalidated length fields / index (as part of the protocol)

• Leads to out of bound reads and writes

79

Page 80: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Server: Type of bugs

• Out of bound reads • No validation for this whatsoever when accessing data

in the request

80

Page 81: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Server: Type of bugs

• Byte order bugs when byte order swapping is • Basically need to create a swap wrapper before the

actual proc • This one needs to do proper calls to

• REQUEST_SIZE_MATCH• REQUEST_AT_LEAST_SIZE• REQUEST_FIXED_SIZE

• Often not written as careful as the actual proc • Dev forgot to use size macro’s • Or used them too late81

Page 82: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Server: Type of bugs

• Byte order bugs • Memory corruption If size macro’s are missing (or too

late)• Since in place byte swap happens

82

Page 83: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Server: Type of bugs

• Pretty standard memory leaks • Do alloc • Forgot to free in error corner cases

83

Page 84: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Server:…

• This is about as far as I’ve come • I had hoped to gotten further but

• There’s a ton of code really • GLX !@#$%^&^@#@!@!$$#$#• No seriously, GLX is horrible

• The rest of the slides will just be general entry points

84

Page 85: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Server: Drivers

• There’s a whole range of drivers that can be used in one way or the other

• font drivers • drawable drivers • gc rivers • Server display driver• opengl drivers • DRI drivers

85

Page 86: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Server: Server display Drivers

• Wanted to look at these • Haven’t gotten to it yet

86

Page 87: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Server: Font Drivers

• These get registered with RegisterFPEFunctions • Have actually looked at the one that contains the font

client code • This was horribly outdated code • Riddled with trivial bugs• Noone really uses font servers anymore

87

Page 88: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Server: OpenGL Drivers

• I was getting to these • GLX talks to OpenGL drivers • Figuring out the amount of control over data being

send back and forth is probably tedious work • Need to look at hundres of Proc functions • Drivers would call _glapi_set_dispatch

88

Page 89: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Server: Library dependancies

• pixman• mesa• SDL • DRMLib • FreeType• Gallium3d

89

Page 90: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Server: DRI

• Direct Rendering infrastructure • framework: allows for direct hardware access by

clients • Much more efficient • Requires DRI extensions in X server • Requires DRM drivers in kernel

• DRM: Direct Rendering Manager • Can talk to DRM and DRM drivers through IOCTL’s

90

Page 91: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Server: DRI

91

Page 92: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Server: DRM

• Looked at linux implementation of DRM • And DRM drivers • Drivers/gpu/drm/drm_drv.c• Exposes an ioctl interface • The drm itself has a number of ioctls • The drm drivers can expose a number of ioctls • Standard linux ioctl’s are just a number • BSD ioctl’s encode stuff in the ioctl number (in, out, len) • DRM ioctl’s are like BSD ioctls92

Page 93: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Server: DRM

• Also adds a bit more than just BSD ioctls• DRM Drivers expose their ioctls as follows

• 3rd argument are flags93

struct drm_ioctl_desc radeon_ioctls[] = { DRM_IOCTL_DEF_DRV(RADEON_CP_INIT, radeon_cp_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF_DRV(RADEON_CP_START, radeon_cp_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF_DRV(RADEON_CP_STOP, radeon_cp_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF_DRV(RADEON_CP_RESET, radeon_cp_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF_DRV(RADEON_CP_IDLE, radeon_cp_idle, DRM_AUTH), DRM_IOCTL_DEF_DRV(RADEON_CP_RESUME, radeon_cp_resume, DRM_AUTH), DRM_IOCTL_DEF_DRV(RADEON_RESET, radeon_engine_reset, DRM_AUTH), DRM_IOCTL_DEF_DRV(RADEON_FULLSCREEN, radeon_fullscreen, DRM_AUTH), DRM_IOCTL_DEF_DRV(RADEON_SWAP, radeon_cp_swap, DRM_AUTH),…};

Page 94: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Server: DRM

• Flag meaning / validation:

94

} else if (((ioctl->flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN)) || ((ioctl->flags & DRM_AUTH) && !drm_is_render_client(file_priv) && !file_priv->authenticated) || ((ioctl->flags & DRM_MASTER) && !file_priv->is_master) || (!(ioctl->flags & DRM_CONTROL_ALLOW) && (file_priv->minor->type == DRM_MINOR_CONTROL)) || (!(ioctl->flags & DRM_RENDER_ALLOW) && drm_is_render_client(file_priv))) {

Page 95: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Server: SHM

• X allows for sharing of images between client and server over shared memory

• Much faster than ipc/tcp• X Extension • Procs

• Version• Attach• Detach• Putimg• Get img• Create pixmap

95

Page 96: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Server: SHM

• Fonts can use shared memory too (xf86bigfont)• Number of other places

96

Page 97: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Server: SHM

• Would find typical shared memory bugs ??• Incorrect permissions (e.g. world read/write) • Race conditions ?

97

Page 98: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Server: Security

• The whole X server runs as root • There has been some talk of implementing priv sep / priv drop• Afaik noone has done this for xorg • OpenBSD did it!

• Xorg guys should steal that code!

• X Access Control Extension (XaceHooks)• Influenced by LSM • Allows drivers to implement a security model • E.g. which actions is allowed for which connection• Does anyone really use this ? • Comes from the NSA …98

Page 99: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

How bad is it? Can we do better?

• Trivial bugs in clientside fixed by now Yay!• Plenty of bugs left in the server / extensions / drivers • Maybe the load of bugs reported will scare people into

adopting wayland faster ?• Even with Wayland, Xorg is going to be around for a long

time• These bugs need to get fixed

• If clientside fix rate is any indication, this will happen fast.• Need driving force to go audit for more bugs

• Long and tedious work

• Should really implement priv sep / priv drop99

Page 100: 1 X Security it’s worse than it looks Ilja van Sprundel ivansprundel@ioactive.com

Questions ?

100