Posted on by & filed under programming, security.

Like many nerds, I participate in the MIT Mystery Hunt every January. This is not a post about the hunt, or about the puzzles at the hunt, or about the tools used to solve those puzzles. This is a post about nametags.

My team uses nametags to help us keep track of people, and because it’s fun to make nametags. Because we have the fictional persona of a law firm called “Immoral, Illegal, and Fattening” every person’s nametag contains something immoral, illegal, or fattening that they are defending. This has led, as intended, to some hilarity in this part of the nametag. Two years ago, my housemate Deborah Kaplan defended “a’;DROP TABLE puzzles;” a classic SQL Injection attack. But our nametags aren’t assembled using SQL. They’re assembled by parsing the team roster with Perl and creating a PostScript document that is sent to a printer. So this year, Deborah, my colleague Joy Nicholson, and I wrote a PostScript injection attack.


PostScript is a language created in the 1980’s by Adobe to allow simple creation of files that are sent to printers. It is generally used as a communications protocol between computers and printers. But it’s a full programming language, written in ASCII, and as such can be very useful as a scriptable language format for producing printed material. Our nametag code, written by my brother Denis Moskowitz, is an example. It produces a single PostScript file that contains a nametag for every team member, with all of their information included. The resulting file looks something like this:

Nametag: Immoral, Illegal, and Fattening. Name: Marc Moskowitz. Defending Sloth

So what did my injection attack look like? It’s simply:

How does this work? It relies on three of the language commands (pop, show, and def) and three language syntax elements, strings, names, and procedures.

PS uses parentheses to delimit strings, so the close-parenthesis at the beginning simply closes the string that the program has started to contain the item. Similarly, the final open-parenthesis gives the program a new string to end with the close-parenthesis that is expecting to close its open parenthesis. So the two parentheses are giving us a little space to work some mischief. PS is a stack-based language. All literal elements simply put an item on the stack. A stack-based language needs stack manipulation commands, and pop is the simplest. It just removes the item on the top of the stack and discards it. So the first pop just gets rid of the string we just created. PS sets off items that are used as names of functions and variables with slashes. So “/show” puts the name “show” on the stack for definition by later commands. PS delimits procedures, groups of commands for later use, in functions with braces, which can then be used by other commands. In this case, we’ve created a procedure that simply calls “pop” (which removes the top of the stack) and completes. As you may have guessed, def takes a name and a procedure off the stack and defines a function with that name. So when the processor reads “/show { pop } def” it defines “show” as a function that does the same thing as “pop”. But “show” already had a definition, which we’ve just overridden. The show command is used by the language to take a string and display it on the printed page. So in 24 characters, we’ve disabled the ability of the program to print text.

Did it work? Technically, yes. The day my brother ran the code to produce the badges, he sent me mail with the subject “Curse you Bobby Tables!” containing a PDF that was multiple pages that looked like:
Multiple nametags with all text missing
So I did pull it off. What I didn’t do is surprise him or inconvenience him. He had noticed the code when I entered it, and after producing this image, he made an easy change to escape parentheses in string literals. But as a fun hack, it definitely passes, and it’s a useful warning that any unsecured system can be affected contrary to the designer’s intentions.


Comments are closed.