Difference between revisions of "PostScript"

From Hacking Printers
Jump to: navigation, search
 
(6 intermediate revisions by 2 users not shown)
Line 1: Line 1:
The PostScript (PS) language was invented by Adobe Systems between 1982 and 1984. It has been standardized as PostScript Level 1 <ref>''PostScript Language Reference Manual'', Adobe Systems Inc., 1985</ref>, PostScript Level 2 <ref>''[https://www-cdf.fnal.gov/offline/PostScript/PLRM2.pdf PostScript Language Reference Manual, 2nd Edition]'', Adobe Systems Inc., 1992</ref>, PostScript 3 <ref>''[https://www.adobe.com/products/postscript/pdfs/PLRM.pdf PostScript Language Reference Manual, 3rd Edition]'', Adobe Systems Inc., 1999</ref> and in various language supplements. While PostScript has lost popularity in desktop publishing and as a document exchange format to [[PDF]], it is still the preferred page description language for laser printers. The term `page description' may be misleading though, as PostScript is capable of much more than just creating vector graphics. PostScript is a stack-based, Turing-complete programming language consisting of almost 400 operators for arithmetics, stack and graphic manipulation and various data types such as arrays or dictionaries. Technically spoken, access to a PostScript interpreter can already be classified as code execution because any algorithmic function can theoretically be implemented in PostScript. Certainly, without access to the network stack or additional operating system libraries, possibilities are limited to arbitrary mathematical calculations like mining bitcoins. However, PostScript is capable of basic file system I/O to store frequently used code, graphics or font files. Originally designed as a feature, the dangers of such functionality were limited before printers got interconnected and risks were mainly discussed in the context of host-based PostScript interpreters. In this regard, Encapsulated PostScript (EPS) is also noteworthy as it can be included in other file formats to be interpreted on the host such as [https://en.wikipedia.org/wiki/LaTeX LaTeX] documents. Like [[PJL]] and [[PCL]], PostScript supports bidirectional communication been host and printer. Example PostScript code to echo ''Hello world'' to ''stdout'' is given below:
+
The PostScript (PS) language was invented by Adobe Systems between 1982 and 1984. It has been standardized as PostScript Level 1 <ref>''PostScript Language Reference Manual'', Adobe Systems Inc., 1985</ref>, PostScript Level 2 <ref>''[https://www-cdf.fnal.gov/offline/PostScript/PLRM2.pdf PostScript Language Reference Manual, 2nd Edition]'', Adobe Systems Inc., 1992</ref>, PostScript 3 <ref>''[https://www.adobe.com/products/postscript/pdfs/PLRM.pdf PostScript Language Reference Manual, 3rd Edition]'', Adobe Systems Inc., 1999</ref> and in various language supplements. While PostScript has lost popularity in desktop publishing and as a document exchange format to [[PDF]], it is still the preferred page description language for laser printers. The term ‘page description’ may be misleading though, as PostScript is capable of much more than just creating vector graphics. PostScript is a stack-based, Turing-complete programming language consisting of almost 400 operators for arithmetics, stack and graphic manipulation and various data types such as arrays or dictionaries. Technically spoken, access to a PostScript interpreter can already be classified as code execution because any algorithmic function can theoretically be implemented in PostScript. Certainly, without access to the network stack or additional operating system libraries, possibilities are limited to arbitrary mathematical calculations like mining bitcoins. However, PostScript is capable of basic file system I/O to store frequently used code, graphics or font files. Originally designed as a feature, the dangers of such functionality were limited before printers got interconnected and risks were mainly discussed in the context of host-based PostScript interpreters. In this regard, Encapsulated PostScript (EPS) is also noteworthy as it can be included in other file formats to be interpreted on the host such as [https://en.wikipedia.org/wiki/LaTeX LaTeX] documents. Like [[PJL]] and [[PCL]], PostScript supports bidirectional communication been host and printer. Example PostScript code to echo ''Hello world'' to ''stdout'' is given below:
  
 
<syntaxhighlight lang=postscript>
 
<syntaxhighlight lang=postscript>
Line 12: Line 12:
 
=== Exiting the server loop ===
 
=== Exiting the server loop ===
  
One intersting fact about PostScript when running in a printer is that the separtion of print ... can be bypassed
+
Normally, each print job is encapsulated in its own, separate environment. One interesting feature of PostScript is that a program can circumvent print job encapsulation and alter the initial VM for subsequent jobs <ref>''[https://www.adobe.com/products/postscript/pdfs/PLRM.pdf PostScript Language Reference Manual, 3rd Edition]'', Adobe Systems Inc., 1999, p. 68-72</ref>. To do so, it can use either ''startjob'', a Level 2 feature:
 
+
 
+
‘The conventional model of a PostScript interpreter is a “print server” — a single-threaded process that consumes and executes a sequence of “print jobs”, each of which is a complete, independent PostScript program. [...] A program can circumvent job encapsulation and alter the initial VM for subsequent jobs. To do so, it can use either ''startjob'' (LanguageLevel 2) or ''exitserver'' (available in all implementations that include a job server). This capability is controlled by a password.’ <ref>''[https://www.adobe.com/products/postscript/pdfs/PLRM.pdf PostScript Language Reference Manual, 3rd Edition]'', Adobe Systems Inc., 1999, p. 68-72</ref>
+
 
+
To exit the server loop using the default ''StartJobPassword'' (<code>0</code>, compare [[Credential disclosure#PostScript|credential disclosure]]),
+
  
 
<syntaxhighlight lang=postscript>
 
<syntaxhighlight lang=postscript>
 
true 0 startjob
 
true 0 startjob
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 +
or ''exitserver'' (available in all implementations that include a job server):
  
 
<syntaxhighlight lang=postscript>
 
<syntaxhighlight lang=postscript>
Line 27: Line 24:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
‘Since the job server loop is generally responsible for cleaning up the state of the interpreter between jobs, any changes that are made outside the server loop by using exitserver will remain as part of the permanent state of the interpreter for all subsequent jobs. This only applies to changes to VM (like procedure definitions), since the stacks and graphics state are cleared after each job.’ <ref>''[https://www-cdf.fnal.gov/offline/PostScript/GREENBK.PDF PostScript Language Program Design (‘Green Book’),]'', Adobe Systems Inc., 1988, p. 176</ref>
+
This capability is controlled by the ''StartJobPassword'' which defaults to <code>0</code> (compare [[Credential disclosure#PostScript|credential disclosure]]). Since the job server loop is generally responsible for cleaning up the state of the interpreter between jobs, any changes that are made outside the server loop will remain as part of the permanent state of the interpreter for all subsequent jobs <ref>''[https://www-cdf.fnal.gov/offline/PostScript/GREENBK.PDF PostScript Language Program Design (Green Book),]'', Adobe Systems Inc., 1988, p. 176</ref>. In other words, a print job can access and alter further jobs. Bingo!
 
+
 
+
 
+
 
+
  
 
=== Operator redefinition ===
 
=== Operator redefinition ===
Line 43: Line 36:
 
The potential impact of redefining operators is only limited by creativity. When further legitimate documents are printed and call a redefined operator, the attackers version will be executed. This can lead to a various attacks such as [[Document processing#Showpage redefinition|denial of service]], print job [[Print job retention|retention]] and [[Print job manipulation|manipulation]]. Note however that this is not necessarily a security bug, but a 32 years old language feature, available in almost any PostScript printer and [https://en.wikipedia.org/wiki/Raster_image_processor RIP].
 
The potential impact of redefining operators is only limited by creativity. When further legitimate documents are printed and call a redefined operator, the attackers version will be executed. This can lead to a various attacks such as [[Document processing#Showpage redefinition|denial of service]], print job [[Print job retention|retention]] and [[Print job manipulation|manipulation]]. Note however that this is not necessarily a security bug, but a 32 years old language feature, available in almost any PostScript printer and [https://en.wikipedia.org/wiki/Raster_image_processor RIP].
  
→ ''Related aricles:'' [[Fundamentals#Printer Control Languages|Page Description Languages]], [[Denial of service]], [[Print job manipulation]], [[Print job retention]], [[File system access]]
+
→ ''Related articles:'' [[Fundamentals#Printer Control Languages|Page Description Languages]], [[Denial of service]], [[Print job manipulation]], [[Print job retention]], [[File system access]]
  
 
<!-- what about Configurable PostScript Interpreter (CPSI) technology? -->
 
<!-- what about Configurable PostScript Interpreter (CPSI) technology? -->
  
 
-----
 
-----

Latest revision as of 16:49, 31 January 2017

The PostScript (PS) language was invented by Adobe Systems between 1982 and 1984. It has been standardized as PostScript Level 1 [1], PostScript Level 2 [2], PostScript 3 [3] and in various language supplements. While PostScript has lost popularity in desktop publishing and as a document exchange format to PDF, it is still the preferred page description language for laser printers. The term ‘page description’ may be misleading though, as PostScript is capable of much more than just creating vector graphics. PostScript is a stack-based, Turing-complete programming language consisting of almost 400 operators for arithmetics, stack and graphic manipulation and various data types such as arrays or dictionaries. Technically spoken, access to a PostScript interpreter can already be classified as code execution because any algorithmic function can theoretically be implemented in PostScript. Certainly, without access to the network stack or additional operating system libraries, possibilities are limited to arbitrary mathematical calculations like mining bitcoins. However, PostScript is capable of basic file system I/O to store frequently used code, graphics or font files. Originally designed as a feature, the dangers of such functionality were limited before printers got interconnected and risks were mainly discussed in the context of host-based PostScript interpreters. In this regard, Encapsulated PostScript (EPS) is also noteworthy as it can be included in other file formats to be interpreted on the host such as LaTeX documents. Like PJL and PCL, PostScript supports bidirectional communication been host and printer. Example PostScript code to echo Hello world to stdout is given below:

%!
(Hello world) print

While most printer manufacturers have implemented (as hardware modules or in software) and licensed original ‘Adobe PostScript’, Brother and Kyocera use their own PostScript clones: Br-Script and KPDL. Such flavours of the PostScript language are not 100% compatible, especially concerning security features like exiting the server loop. PostScript can be used for a variety of attacks such as denial of service (for example, through infinite loops), print job manipulation and retention as well as gaining access to the printer's file system.

Security features

Exiting the server loop

Normally, each print job is encapsulated in its own, separate environment. One interesting feature of PostScript is that a program can circumvent print job encapsulation and alter the initial VM for subsequent jobs [4]. To do so, it can use either startjob, a Level 2 feature:

true 0 startjob

or exitserver (available in all implementations that include a job server):

serverdict begin 0 exitserver

This capability is controlled by the StartJobPassword which defaults to 0 (compare credential disclosure). Since the job server loop is generally responsible for cleaning up the state of the interpreter between jobs, any changes that are made outside the server loop will remain as part of the permanent state of the interpreter for all subsequent jobs [5]. In other words, a print job can access and alter further jobs. Bingo!

Operator redefinition

When a PostScript document calls an operator, the first version found on the dictionary stack is used. Operators usually reside in the systemdict dictionary, however by placing a new version into the userdict dictionary, operators can be practically overwritten because the user-defined version is the first one found on the dictionary stack. Using the startjob/exitserver operators, such changes can be made permanent – at least until the printer is restarted. A scheme of the PostScript dictionary stack is given below:


The PostScript dictionary stack


The potential impact of redefining operators is only limited by creativity. When further legitimate documents are printed and call a redefined operator, the attackers version will be executed. This can lead to a various attacks such as denial of service, print job retention and manipulation. Note however that this is not necessarily a security bug, but a 32 years old language feature, available in almost any PostScript printer and RIP.

Related articles: Page Description Languages, Denial of service, Print job manipulation, Print job retention, File system access



  1. PostScript Language Reference Manual, Adobe Systems Inc., 1985
  2. PostScript Language Reference Manual, 2nd Edition, Adobe Systems Inc., 1992
  3. PostScript Language Reference Manual, 3rd Edition, Adobe Systems Inc., 1999
  4. PostScript Language Reference Manual, 3rd Edition, Adobe Systems Inc., 1999, p. 68-72
  5. PostScript Language Program Design (Green Book),, Adobe Systems Inc., 1988, p. 176