Ots安全
CVE-2023-43786 漏洞本质上是由于递归停止条件计算不正确而导致的无限循环。
修复提交:
https://gitlab.freedesktop.org/xorg/lib/libx11/-/commit/204c3393c4c90a29ed6bef64e43849536e863a86
XPutImage是 libX11 中的一个函数,可让您将图像放置到 X Drawable(通常是 X Window)上。使用此函数,可以将像素信息从 XImage 结构传输到指定的可绘制对象(如窗口或像素图),并根据需要对其进行定位。
xpmCreatePixmapFromImage
libXpm函数xpmCreatePixmapFromImage调用此XPutImage函数:
voidxpmCreatePixmapFromImage(Display *display,Drawable d,XImage *ximage,Pixmap *pixmap_return){GC gc;XGCValues values;*pixmap_return = XCreatePixmap(display, d, ximage->width,ximage->height, ximage->depth);/* set fg and bg in case we have an XYBitmap */values.foreground = 1;values.background = 0;gc = XCreateGC(display, *pixmap_return,GCForeground | GCBackground, &values);XPutImage(display, *pixmap_return, gc, ximage, 0, 0, 0, 0,ximage->width, ximage->height);XFreeGC(display, gc);}
在此函数中,ximage是要显示的源图像像素数据,并将其复制到X Drawable对象(在本例中为pixmap_return)。
XPutImage
这是XPutImagelibX11 函数:
intXPutImage (register Display *dpy,Drawable d,GC gc,register XImage *image,int req_xoffset,int req_yoffset,int x,int y,unsigned int req_width,unsigned int req_height){.....PutSubImage(dpy, d, gc, &img, 0, 0, x, y,(unsigned int) width, (unsigned int) height,dest_bits_per_pixel, dest_scanline_pad);UnlockDisplay(dpy);SyncHandle();Xfree(img.data);return 0;}}LockDisplay(dpy);FlushGC(dpy, gc);PutSubImage(dpy, d, gc, image, req_xoffset, req_yoffset, x, y,(unsigned int) width, (unsigned int) height,dest_bits_per_pixel, dest_scanline_pad);.........}
它调用该PutSubImage函数:
static voidPutSubImage (register Display *dpy,Drawable d,GC gc,register XImage *image,int req_xoffset,int req_yoffset,int x, int y,unsigned int req_width,unsigned int req_height,int dest_bits_per_pixel,int dest_scanline_pad){int left_pad, BytesPerRow, Available;if ((req_width == 0) || (req_height == 0))return;Available = ((65536 < dpy->max_request_size) ? (65536 << 2) : (dpy->max_request_size << 2)) - SIZEOF(xPutImageReq); if ((image->bits_per_pixel == 1) || (image->format != ZPixmap)) { [1]left_pad = (image->xoffset + req_xoffset) & (dpy->bitmap_unit - 1);BytesPerRow = (ROUNDUP((long)req_width + left_pad,dpy->bitmap_pad) >> 3) * image->depth;} else { [2]left_pad = 0;BytesPerRow = ROUNDUP((long)req_width * dest_bits_per_pixel, [3]dest_scanline_pad) >> 3;}if ((BytesPerRow * req_height) <= Available) { [4] PutImageRequest(dpy, d, gc, image, req_xoffset, req_yoffset, x, y, req_width, req_height, dest_bits_per_pixel, dest_scanline_pad); } else if (req_height > 1) {int SubImageHeight = Available / BytesPerRow;if (SubImageHeight == 0)SubImageHeight = 1;PutSubImage(dpy, d, gc, image, req_xoffset, req_yoffset, x, y,req_width, (unsigned int) SubImageHeight,dest_bits_per_pixel, dest_scanline_pad);PutSubImage(dpy, d, gc, image, req_xoffset,req_yoffset + SubImageHeight, x, y + SubImageHeight,req_width, req_height - SubImageHeight,dest_bits_per_pixel, dest_scanline_pad);} else { [5]int SubImageWidth = (((Available << 3) / dest_scanline_pad) [6]* dest_scanline_pad) - left_pad;PutSubImage(dpy, d, gc, image, req_xoffset, req_yoffset, x, y,(unsigned int) SubImageWidth, 1,dest_bits_per_pixel, dest_scanline_pad);PutSubImage(dpy, d, gc, image, req_xoffset + SubImageWidth,req_yoffset, x + SubImageWidth, y,req_width - SubImageWidth, 1,dest_bits_per_pixel, dest_scanline_pad);}}
技术漏洞详细信息
让我们看下面的示例图像:
Available [the requested size] = (65,536 * 4) - 28 = 262,116bits_per_pixel = 32width = 90,000 pixelsheight = 1 pixel
由于图像bits_per_pixel是 32,[1] 中的条件语句将不会通过,导致我们进入 [2] 中定义的替代代码块。
然后计算BytesPerRowon [3],然后除以 8。在我们的示例中:BytesPerRow = 90000 * 32 / 8 = 360,000
在示例中,对 [4] 的检查不会通过,因为 360000 不小于请求的大小 262116,并且无法将请求宽度的单行放入单个请求中 – 这会启动对 [5] 的else检查。
这决定了单个请求中可以包含的像素数量。然后,它启动对该函数的递归调用PutSubImage以仅传递该子集,然后进行后续递归调用以管理该行的其余部分。如果需要,还可以通过额外的递归调用进一步划分剩余部分。
然而,[6] 的计算未能考虑每像素的位数,并且递归调用使请求发送 2096928 像素而不是 2096928 位——这比单个请求所能容纳的要大。
这会导致尝试分割像素线的无限循环,始终导致数字太大而无法容纳,并再次尝试该过程以使用相同的值重试。这种递归一直持续到调用堆栈耗尽为止。
该错误修复更改了 [6] 的计算并考虑了bits_per_pixel. 在示例中,这将导致递归调用请求仅发送 65529 个像素,从而导致 BytesPerRow 为 262116,完全适合可用空间,从而允许递归向前推进并只需 2 次调用即可完成。
触发错误的概念验证图像示例:https://github.com/jfrog/jfrog-CVE-2023-43786-libX11_DoS/blob/main/cve-2023-43786.xpm
如何触发该错误
调用易受攻击的 libXpm 库函数的应用程序的一个示例是 CLI 实用程序sxpm,它用于在屏幕上显示 Xpm 图像。
它调用易受攻击的xpmCreatePixmapFromImageXpm 函数,然后该函数又调用易受攻击的 libX11XPutImage函数PutSubImage。
感谢您抽出
.
.
来阅读本文
点它,分享点赞在看都在这里