[英]Security vulnerabilities in fairly simple c code
我正在读我的最后一次考试(是的!),并遇到了一个我很难搞清楚的问题。 这是一个旧的考试问题,你应该找到至少两个可以在读取ppm图像文件的函数中利用的漏洞。 我可以识别的唯一问题是,如果cols和/或行被赋予意外值,或者太大(导致整数溢出)或者是负数,这会导致img-> raster的大小不正确,从而开启了基于堆的可能性缓冲区溢出攻击。
据我所知,未经检查的malloc不应被利用。
struct image *read_ppm(FILE *fp)
{
int version;
int rows, cols, maxval;
int pixBytes=0, rowBytes=0, rasterBytes;
uint8_t *p;
struct image *img;
/* Read the magic number from the file */
if ((fscanf(fp, " P%d ", &version) < 1) || (version != 6)) {
return NULL;
}
/* Read the image dimensions and color depth from the file */
if (fscanf(fp, " %d %d %d ", &cols, &rows, &maxval) < 3) {
return NULL;
}
/* Calculate some sizes */
pixBytes = (maxval > 255) ? 6 : 3; // Bytes per pixel
rowBytes = pixBytes * cols; // Bytes per row
rasterBytes = rowBytes * rows; // Bytes for the whole image
/* Allocate the image structure and initialize its fields */
img = malloc(sizeof(*img));
if (img == NULL) return NULL;
img->rows = rows;
img->cols = cols;
img->depth = (maxval > 255) ? 2 : 1;
img->raster = (void*)malloc(rasterBytes);
/* Get a pointer to the first pixel in the raster data. */
/* It is to this pointer that all image data will be written. */
p = img->raster;
/* Iterate over the rows in the file */
while (rows--) {
/* Iterate over the columns in the file */
cols = img->cols;
while (cols--) {
/* Try to read a single pixel from the file */
if (fread(p, pixBytes, 1, fp) < 1) {
/* If the read fails, free memory and return */
free(img->raster);
free(img);
return NULL;
}
/* Advance the pointer to the next location to which we
should read a single pixel. */
p += pixBytes;
}
}
/* Return the image */
return img;
}
原文(最后一个问题): http : //www.ida.liu.se/~TDDC90/exam/old/TDDC90%20TEN1%202009-12-22.pdf
谢谢你的帮助。
创建一个大的文件,例如,阅读row
和cols
均为阴性。 rasterBytes = pixBytes * rows * cols
是正数所以一切都会很好,直到p = img->raster;
。 但此时你有两个无限循环,程序可能会覆盖堆。
另一种攻击是建立row
和cols
使得它们具有不同的符号。 您可以选择任一值为-1
,而另一个值足以读取所需数据。 分配
img->raster = (void*)malloc(rasterBytes);
将失败,导致img-> raster指向NULL。 意思是
fread(p, pixBytes, 1, fp) < 1
将尝试将文件的内容读取到内核内存。 如果此代码在内核模式下执行,则取决于系统(假设使用不使用内存段的旧unix),那么您将使用文件内容覆盖内核内存的内容。 不使用内存段的内核不依赖于分段错误,而是依赖于页面错误(没有分配任何实际页面的虚拟地址)。 问题在于存在虚拟存储器设计,使得第一个真实页面被直接分配给内核页面。 即内核虚拟地址0x0对应于0x0处的实际内存,并且完全有效(在内核内)。
编辑:在这两种情况下,攻击者的目标是将输入文件的内容(完全由他控制)注入他不应该访问的内存区域,同时无法修改功能read_ppm()
。
还有一个事实是不会检查此分配是否成功。 可能导致DoS。
img->raster = (void*)malloc(rasterBytes);
如果分配失败:
img->raster = (void*)malloc(rasterBytes);
你可能正在写一些你不想要的记忆。
并且该分配的大小由该文件中的数据控制。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.