Presentation is loading. Please wait.

Presentation is loading. Please wait.

1 X Security it’s worse than it looks Ilja van Sprundel

Similar presentations

Presentation on theme: "1 X Security it’s worse than it looks Ilja van Sprundel"— Presentation transcript:

1 1 X Security it’s worse than it looks Ilja van Sprundel

2 Who am I? IOActive Director of Penetration Testing Pentest Code review Break stuff for fun and profit 2

3 agenda Intro Client Server Solutions ? 3

4 What this talk is about Implementation of 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

5 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

6 6 Client

7 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

8 X network architecture 8

9 Some observations The X client libraries (Xlib) are clear attack surface Spend about a week looking at the network parsing code in Xlib Have not looked at xcb yet. Things are were really really bad Binary protocol parsers in C. A lot of them written in the 80’s Server data appears to be trusted. Very little validation > 60 trivial bugs It’s clear that code was not written with trust boundaries in mind at all. 9

10 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)); }... }

11 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; … }...}

12 Typical bugs 12 _XkbReadGetDeviceInfoReply(Display *dpy, xkbGetDeviceInfoReply *rep, XkbDeviceInfoPtrdevi) {... 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;... }

13 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);... }... }

14 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);... }

15 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; }

16 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; }...

17 Typical bugs 17 XFixesCursorImage *XFixesGetCursorImage (Display *dpy) {... xXFixesGetCursorImageAndNameReplyrep; intnpixels;... 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;... }

18 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 /* for pad */); _XReadPad(dpy, attr->displayName, rep.displayNameLength); attr->displayName[rep.displayNameLength] = '\0';... }

19 Typical bugs 19 int XGetDeviceButtonMapping( 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);... }... }

20 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; }... }

21 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; … }... }

22 Typical bugs 22 XineramaScreenInfo * XineramaQueryScreens( Display *dpy, int *number ) { XExtDisplayInfo*info = find_display (dpy); xXineramaQueryScreensReplyrep;.... 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; }... }... }

23 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++) {... }... }

24 Typical bugs 24 Bool XF86VidModeGetGammaRamp ( 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); }... }

25 Typical bugs 25 Bool uniDRIOpenConnection(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);... }

26 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 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; }... }

27 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; }

28 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, , True, AnyPropertyType, &target, &format, &length, &bytesafter, (unsigned char **) &value);  should check return value. XFree(value);... }

29 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

30 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

31 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 too late 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.”

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

33 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

34 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

35 More observations KDE / QT Crappyness is about on par with Xlib Trivial bugs! 35

36 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 (data), *end = p + nitems; int i = 0; do { names[i++] = p; p += qstrlen(p) + 1; } while (p < end);... }

37 More observations In QT init code (affects all QT applications) 37 Qapplication_x11.cpp void 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; }... }

38 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

39 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

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

41 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.”

42 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

43 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.”

44 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

45 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”

46 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

47 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

48 More observations ( Talking Radios born from taco trucks 48

49 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

50 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 gboolean check_setugid (void)

51 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

52 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 pwned 52

53 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, , False, SomePropertyType, &type, &format, &length, &bytesafter, (unsigned char **) &sf);... XFree((char*)sf);... }

54 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

55 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

56 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

57 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

58 58 Server

59 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

60 Server architecture Remember the X architecture layout ? 60

61 X network architecture 61

62 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 ( ) X hasn’t been network transparant in a long time Shared memory DRI / DRM Direct rendering MMIO Kernel drivers / ioctl’s 62

63 63

64 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

65 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

66 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 , extensions Extensions get to pick and choose how they want their (sub)type delivered Will usually take data for (sub)type 66

67 Server: core protocol Procedures clients can call Dix/tables.c ProcVector SwappedProcVector (different byteorder) Create/destroy/query Windows Atoms Properties Image Text … 67

68 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

69 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

70 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

71 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.c damageext/damageext.c dbe/dbe.c dix/extension.c glx/glxext.c hw/dmx/dmx.c hw/dmx/glxProxy/glxext.c hw/kdrive/ephyr/ephyrdriext.c hw/xfree86/dixmods/extmod/xf86dga2.c hw/xfree86/dixmods/extmod/xf86vmode.c hw/xfree86/dri/xf86dri.c hw/xfree86/dri2/dri2ext.c hw/xquartz/applewm.c hw/xquartz/pseudoramiX.c hw/xquartz/xpr/appledri.c hw/xwin/winwindowswm.c randr/randr.c randr/rrxinerama.c record/record.c render/render.c Xext/bigreq.c Xext/dpms.c Xext/geext.c Xext/panoramiX.c Xext/saver.c Xext/security.c Xext/shape.c Xext/shm.c Xext/sync.c Xext/xcmisc.c Xext/xf86bigfont.c Xext/xres.c Xext/xselinux_ext.c Xext/xtest.c Xext/xvmain.c Xext/xvmc.c xfixes/xfixes.c Xi/exevents.c Xi/extinit.c Xi/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); }

72 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

73 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 int ProcTest(ClientPtr client) { REQUEST(xTestReq); REQUEST_SIZE_MATCH(xTest Req); useRequestData(stuff); return Success; }

74 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

75 Server: Type of bugs There’s some typical bugs that keep showing up when looking at a bunch of these request Proc’s 75

76 Server: Type of bugs Memory allocation Forgetting to check return values In OOM cases, can return NULL Would crash on NULL deref 76

77 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

78 Server: Type of bugs Cute realloc bugs realloc() with size of 0 becomes free Leads to use after free and double free bugs 78

79 Server: Type of bugs Unvalidated length fields / index (as part of the protocol) Leads to out of bound reads and writes 79

80 Server: Type of bugs Out of bound reads No validation for this whatsoever when accessing data in the request 80

81 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 late 81

82 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

83 Server: Type of bugs Pretty standard memory leaks Do alloc Forgot to free in error corner cases 83

84 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

85 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

86 Server: Server display Drivers Wanted to look at these Haven’t gotten to it yet 86

87 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

88 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

89 Server: Library dependancies pixman mesa SDL DRMLib FreeType Gallium3d 89

90 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

91 Server: DRI 91

92 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 ioctls 92

93 Server: DRM Also adds a bit more than just BSD ioctls DRM Drivers expose their ioctls as follows 3 rd argument are flags 93 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), … };

94 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))) {

95 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

96 Server: SHM Fonts can use shared memory too (xf86bigfont) Number of other places 96

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

98 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

99 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 drop 99

100 Questions ? 100

Download ppt "1 X Security it’s worse than it looks Ilja van Sprundel"

Similar presentations

Ads by Google