printerxpl-forge 6.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- nse/README.md +204 -0
- nse/__init__.py +6 -0
- nse/install_nse.py +412 -0
- nse/lib/printerxpl.lua +238 -0
- nse/scripts/cups-info.nse +74 -0
- nse/scripts/cups-queue-info.nse +43 -0
- nse/scripts/hp-printers-cve-2022-1026.nse +121 -0
- nse/scripts/http-device-mac.nse +107 -0
- nse/scripts/http-hp-ilo-info.nse +121 -0
- nse/scripts/http-info-xerox-enum.nse +101 -0
- nse/scripts/http-vuln-cve2022-1026.nse +158 -0
- nse/scripts/lexmark-config.nse +89 -0
- nse/scripts/pjl-ready-message.nse +106 -0
- nse/scripts/printer-banner.nse +217 -0
- nse/scripts/printer-cups-rce.nse +189 -0
- nse/scripts/printer-cve-detect.nse +279 -0
- nse/scripts/printer-discover.nse +205 -0
- nse/scripts/printer-firmware-exposed.nse +219 -0
- nse/scripts/printer-hp-pjl.nse +192 -0
- nse/scripts/printer-http-ews.nse +293 -0
- nse/scripts/printer-ipp-info.nse +235 -0
- nse/scripts/printer-lexmark-ipp.nse +203 -0
- nse/scripts/printer-passback.nse +204 -0
- nse/scripts/printer-pjl-info.nse +146 -0
- nse/scripts/printer-printnightmare.nse +211 -0
- nse/scripts/printer-snmp-info.nse +176 -0
- nse/scripts/printer-vuln-check.nse +256 -0
- nse/scripts/snmp-device-mac.nse +93 -0
- nse/scripts/snmp-info.nse +146 -0
- nse/scripts/snmp-sysdescr.nse +70 -0
- printerxpl_forge-6.2.0.dist-info/METADATA +919 -0
- printerxpl_forge-6.2.0.dist-info/RECORD +97 -0
- printerxpl_forge-6.2.0.dist-info/WHEEL +5 -0
- printerxpl_forge-6.2.0.dist-info/entry_points.txt +4 -0
- printerxpl_forge-6.2.0.dist-info/licenses/LICENSE +21 -0
- printerxpl_forge-6.2.0.dist-info/top_level.txt +4 -0
- src/assets/fonts/gunplay.pfa +1671 -0
- src/assets/fonts/kshandwrt.pfa +315 -0
- src/assets/fonts/laksoner.pfa +2402 -0
- src/assets/fonts/paintcans.pfa +9699 -0
- src/assets/fonts/stencilod.pfa +4076 -0
- src/assets/fonts/takecover.pfa +26138 -0
- src/assets/fonts/topsecret.pfa +6652 -0
- src/assets/fonts/whoa.pfa +773 -0
- src/assets/mibs/HOST-RESOURCES-MIB +1540 -0
- src/assets/mibs/Printer-MIB +4389 -0
- src/assets/mibs/README.md +9 -0
- src/assets/mibs/SNMPv2-MIB +854 -0
- src/assets/overlays/hacker.eps +596 -0
- src/assets/overlays/smiley.eps +214 -0
- src/assets/overlays/smiley2.eps +240 -0
- src/core/attack_orchestrator.py +1025 -0
- src/core/capabilities.py +323 -0
- src/core/destructive_audit.py +430 -0
- src/core/discovery.py +488 -0
- src/core/osdetect.py +74 -0
- src/core/poly_runner.py +579 -0
- src/core/printer.py +1426 -0
- src/main.py +2134 -0
- src/modules/install_printer.py +318 -0
- src/modules/login_bruteforce.py +852 -0
- src/modules/pcl.py +506 -0
- src/modules/pjl.py +3575 -0
- src/modules/print_job.py +1290 -0
- src/modules/ps.py +1102 -0
- src/payloads/__init__.py +98 -0
- src/payloads/assets/overlays/notice.eps +9 -0
- src/protocols/__init__.py +19 -0
- src/protocols/firmware.py +738 -0
- src/protocols/ipp.py +216 -0
- src/protocols/ipp_attacks.py +609 -0
- src/protocols/lpd.py +141 -0
- src/protocols/network_map.py +1004 -0
- src/protocols/raw.py +173 -0
- src/protocols/smb.py +359 -0
- src/protocols/ssrf_pivot.py +427 -0
- src/protocols/storage.py +587 -0
- src/ui/__init__.py +6 -0
- src/ui/interactive.py +742 -0
- src/ui/spinner.py +112 -0
- src/ui/tables.py +132 -0
- src/utils/banner_grabber.py +852 -0
- src/utils/codebook.py +456 -0
- src/utils/config.py +522 -0
- src/utils/cve_loader.py +158 -0
- src/utils/default_creds.py +134 -0
- src/utils/discovery_online.py +1327 -0
- src/utils/exploit_manager.py +805 -0
- src/utils/fuzzer.py +220 -0
- src/utils/helper.py +732 -0
- src/utils/local_printers.py +307 -0
- src/utils/ml_engine.py +491 -0
- src/utils/operators.py +474 -0
- src/utils/ports.py +234 -0
- src/utils/vuln_scanner.py +823 -0
- src/utils/wordlist_loader.py +412 -0
- src/version.py +36 -0
nse/lib/printerxpl.lua
ADDED
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
---
|
|
2
|
+
-- printerxpl.lua — Shared library for PrinterXPL-Forge NSE scripts
|
|
3
|
+
--
|
|
4
|
+
-- Provides: vendor detection, CVE cross-reference, severity formatting,
|
|
5
|
+
-- PrinterXPL-Forge / EmbedXPL-Forge exploit suggestions, and shared
|
|
6
|
+
-- protocol helpers (PJL, IPP, HTTP, SNMP).
|
|
7
|
+
--
|
|
8
|
+
-- Author: André Henrique (@mrhenrike) | União Geek
|
|
9
|
+
-- Repo : https://github.com/mrhenrike/PrinterXPL-Forge
|
|
10
|
+
-- Docs : https://github.com/mrhenrike/PrinterXPL-Forge/wiki/NSE
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
local stdnse = require "stdnse"
|
|
14
|
+
local string = require "string"
|
|
15
|
+
local table = require "table"
|
|
16
|
+
local math = require "math"
|
|
17
|
+
|
|
18
|
+
local _M = {}
|
|
19
|
+
|
|
20
|
+
-- ── Version ──────────────────────────────────────────────────────────────────
|
|
21
|
+
_M.VERSION = "5.0.0"
|
|
22
|
+
|
|
23
|
+
-- ── Severity colour tags (nmap output) ───────────────────────────────────────
|
|
24
|
+
_M.SEV = {
|
|
25
|
+
CRITICAL = "CRITICAL",
|
|
26
|
+
HIGH = "HIGH",
|
|
27
|
+
MEDIUM = "MEDIUM",
|
|
28
|
+
LOW = "LOW",
|
|
29
|
+
INFO = "INFO",
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
-- ── Verdict strings ──────────────────────────────────────────────────────────
|
|
33
|
+
_M.VERDICT = {
|
|
34
|
+
VULN = "VULNERABLE",
|
|
35
|
+
POSSIBLE = "POSSIBLY VULNERABLE",
|
|
36
|
+
NOT_VULN = "NOT VULNERABLE",
|
|
37
|
+
UNKNOWN = "UNKNOWN",
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
-- ── Vendor fingerprint table ─────────────────────────────────────────────────
|
|
41
|
+
-- Each entry: { pattern (case-insensitive), vendor, product_hint }
|
|
42
|
+
_M.VENDOR_PATTERNS = {
|
|
43
|
+
{ pat="hewlett.packard|hp laserjet|hp officejet|hp pagewide|jetdirect|hp enterprise",
|
|
44
|
+
vendor="HP", family="LaserJet/OfficeJet/PageWide" },
|
|
45
|
+
{ pat="canon imagerunner|canon imagepress|canon imageclass|canon lbp|canon mf",
|
|
46
|
+
vendor="Canon", family="imageCLASS/imageRUNNER/LBP" },
|
|
47
|
+
{ pat="ricoh aficio|ricoh mp|ricoh sp|ricoh im|savin|gestetner|lanier|nashuatec|nrg",
|
|
48
|
+
vendor="Ricoh", family="Aficio/MP/SP/IM" },
|
|
49
|
+
{ pat="lexmark",
|
|
50
|
+
vendor="Lexmark", family="MX/CX/XC/MB/MC series" },
|
|
51
|
+
{ pat="xerox workcentre|xerox versalink|xerox altalink|xerox phaser|xerox colorqube",
|
|
52
|
+
vendor="Xerox", family="WorkCentre/VersaLink/AltaLink" },
|
|
53
|
+
{ pat="brother mfc|brother dcp|brother hl|brother fax",
|
|
54
|
+
vendor="Brother", family="MFC/DCP/HL" },
|
|
55
|
+
{ pat="epson workforce|epson ecotank|epson expression|epson stylus",
|
|
56
|
+
vendor="Epson", family="WorkForce/EcoTank" },
|
|
57
|
+
{ pat="konica minolta|bizhub|konicaminolta",
|
|
58
|
+
vendor="Konica Minolta", family="bizhub" },
|
|
59
|
+
{ pat="kyocera ecosys|kyocera taskalfa|kyocera fs",
|
|
60
|
+
vendor="Kyocera", family="ECOSYS/TASKalfa" },
|
|
61
|
+
{ pat="sharp mx|sharp ar|sharp bp",
|
|
62
|
+
vendor="Sharp", family="MX/AR/BP" },
|
|
63
|
+
{ pat="toshiba e.studio|toshiba estudio",
|
|
64
|
+
vendor="Toshiba", family="e-STUDIO" },
|
|
65
|
+
{ pat="samsung multifunction|samsung clx|samsung scx|samsung ml",
|
|
66
|
+
vendor="Samsung", family="CLX/SCX/ML" },
|
|
67
|
+
{ pat="oki data|okidata|oki mc|oki es",
|
|
68
|
+
vendor="OKI", family="ES/MC" },
|
|
69
|
+
{ pat="dell multifunction|dell color",
|
|
70
|
+
vendor="Dell", family="Color MFP" },
|
|
71
|
+
{ pat="cups|openprinting",
|
|
72
|
+
vendor="Linux/CUPS", family="CUPS scheduler" },
|
|
73
|
+
{ pat="zebra technologies|zebra zpl|zpl ii",
|
|
74
|
+
vendor="Zebra", family="Label/Industrial" },
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
-- ── CVE quick-reference table ────────────────────────────────────────────────
|
|
78
|
+
-- Compact: { id, cvss, vendor_pat, desc, xpl_module, check_fn_name }
|
|
79
|
+
_M.CVE_DB = {
|
|
80
|
+
-- HP
|
|
81
|
+
{ id="CVE-2025-26506", cvss=9.8, sev=_M.SEV.CRITICAL, vendor="HP",
|
|
82
|
+
desc="HP LaserJet/OfficeJet Enterprise PostScript RCE — unauthenticated RCE via malformed PS job",
|
|
83
|
+
xpl="xpl/edb-cve-2025-26506", port=9100 },
|
|
84
|
+
{ id="CVE-2023-6018", cvss=9.8, sev=_M.SEV.CRITICAL, vendor="HP",
|
|
85
|
+
desc="HP LaserJet Enterprise firmware auth bypass — arbitrary firmware upload",
|
|
86
|
+
xpl="xpl/research/research-hp-fw-bypass", port=443 },
|
|
87
|
+
{ id="CVE-2023-1707", cvss=9.1, sev=_M.SEV.CRITICAL, vendor="HP",
|
|
88
|
+
desc="HP FutureSmart 5.6 scan job data disclosure when IPsec enabled",
|
|
89
|
+
xpl="xpl/research/research-hp-futuresmart-leak", port=443 },
|
|
90
|
+
{ id="CVE-2017-2741", cvss=9.8, sev=_M.SEV.CRITICAL, vendor="HP",
|
|
91
|
+
desc="HP PageWide/OfficeJet PJL path traversal to RCE",
|
|
92
|
+
xpl="xpl/edb-cve-2017-2741", port=9100 },
|
|
93
|
+
-- Canon
|
|
94
|
+
{ id="CVE-2022-24673", cvss=9.8, sev=_M.SEV.CRITICAL, vendor="Canon",
|
|
95
|
+
desc="Canon imageCLASS SLP pre-auth stack buffer overflow → root RCE (ZDI-22-515)",
|
|
96
|
+
xpl="xpl/edb-cve-2022-24673", port=427 },
|
|
97
|
+
{ id="CVE-2025-14235", cvss=9.8, sev=_M.SEV.CRITICAL, vendor="Canon",
|
|
98
|
+
desc="Canon imageCLASS PCL buffer overflow → RCE",
|
|
99
|
+
xpl="xpl/research/research-canon-pcl-bof", port=9100 },
|
|
100
|
+
-- Lexmark
|
|
101
|
+
{ id="CVE-2023-23560", cvss=9.0, sev=_M.SEV.CRITICAL, vendor="Lexmark",
|
|
102
|
+
desc="Lexmark SSRF-to-RCE via Web Services interface (Pwn2Own Toronto 2022)",
|
|
103
|
+
xpl="xpl/edb-51928", port=80 },
|
|
104
|
+
{ id="CVE-2023-50739", cvss=8.8, sev=_M.SEV.HIGH, vendor="Lexmark",
|
|
105
|
+
desc="Lexmark IPP heap buffer overflow → RCE (ZDI-CAN-22549) — 100+ models",
|
|
106
|
+
xpl="xpl/edb-cve-2023-50739", port=631 },
|
|
107
|
+
{ id="CVE-2023-50733", cvss=6.5, sev=_M.SEV.MEDIUM, vendor="Lexmark",
|
|
108
|
+
desc="Lexmark EWS SSRF — printer as pivot to internal network",
|
|
109
|
+
xpl="xpl/edb-cve-2023-50733", port=80 },
|
|
110
|
+
{ id="CVE-2023-26067", cvss=9.1, sev=_M.SEV.CRITICAL, vendor="Lexmark",
|
|
111
|
+
desc="Lexmark post-auth RCE via device configuration API",
|
|
112
|
+
xpl="xpl/edb-cve-2023-26067", port=80 },
|
|
113
|
+
-- Xerox
|
|
114
|
+
{ id="CVE-2024-6333", cvss=8.1, sev=_M.SEV.HIGH, vendor="Xerox",
|
|
115
|
+
desc="Xerox VersaLink OS command injection — authenticated RCE",
|
|
116
|
+
xpl="xpl/edb-cve-2024-6333", port=80 },
|
|
117
|
+
{ id="CVE-2021-27508", cvss=8.0, sev=_M.SEV.HIGH, vendor="Xerox",
|
|
118
|
+
desc="Xerox WorkCentre 78xx OS command injection via clone_group param",
|
|
119
|
+
xpl="xpl/research/research-xerox-workcentre-cmdinject", port=80 },
|
|
120
|
+
-- Ricoh
|
|
121
|
+
{ id="CVE-2024-34161", cvss=8.8, sev=_M.SEV.HIGH, vendor="Ricoh",
|
|
122
|
+
desc="Ricoh MP EWS malformed HTTP → RCE",
|
|
123
|
+
xpl="xpl/research/research-ricoh-ews-rce", port=80 },
|
|
124
|
+
{ id="CVE-2021-33945", cvss=7.5, sev=_M.SEV.HIGH, vendor="Ricoh",
|
|
125
|
+
desc="Ricoh SP wpa_supplicant stack overflow → DoS/RCE",
|
|
126
|
+
xpl="xpl/research/research-ricoh-wpa-bof", port=80 },
|
|
127
|
+
-- Brother
|
|
128
|
+
{ id="CVE-2024-51977", cvss=7.5, sev=_M.SEV.HIGH, vendor="Brother",
|
|
129
|
+
desc="Brother serial-based admin password derivation — info disclosure",
|
|
130
|
+
xpl="xpl/research/research-brother-serial-pwd", port=80 },
|
|
131
|
+
{ id="CVE-2024-51978", cvss=9.1, sev=_M.SEV.CRITICAL, vendor="Brother",
|
|
132
|
+
desc="Brother default credential auth bypass via serial derivation",
|
|
133
|
+
xpl="xpl/research/research-brother-serial-pwd", port=80 },
|
|
134
|
+
-- Sharp
|
|
135
|
+
{ id="CVE-2022-45796", cvss=9.8, sev=_M.SEV.CRITICAL, vendor="Sharp",
|
|
136
|
+
desc="Sharp MX OS command injection → RCE (no auth)",
|
|
137
|
+
xpl="xpl/research/research-sharp-rce", port=80 },
|
|
138
|
+
-- Toshiba
|
|
139
|
+
{ id="CVE-2024-21911", cvss=8.8, sev=_M.SEV.HIGH, vendor="Toshiba",
|
|
140
|
+
desc="Toshiba e-STUDIO TopAccess authentication bypass",
|
|
141
|
+
xpl="xpl/research/research-toshiba-auth-bypass", port=80 },
|
|
142
|
+
-- Kyocera
|
|
143
|
+
{ id="CVE-2022-1026", cvss=7.5, sev=_M.SEV.HIGH, vendor="Kyocera",
|
|
144
|
+
desc="Kyocera ECOSYS unauthenticated address book / credential dump",
|
|
145
|
+
xpl="xpl/edb-cve-2022-1026", port=9100 },
|
|
146
|
+
-- Windows Print Spooler
|
|
147
|
+
{ id="CVE-2021-1675", cvss=9.8, sev=_M.SEV.CRITICAL, vendor="Microsoft",
|
|
148
|
+
desc="PrintNightmare — Windows Print Spooler RCE/LPE (unauthenticated network)",
|
|
149
|
+
xpl="xpl/edb-50498", port=445 },
|
|
150
|
+
{ id="CVE-2022-38028", cvss=7.8, sev=_M.SEV.HIGH, vendor="Microsoft",
|
|
151
|
+
desc="GooseEgg — APT28 Windows Print Spooler LPE (CISA KEV)",
|
|
152
|
+
xpl="xpl/research/research-gooseegg-spooler", port=445 },
|
|
153
|
+
-- CUPS
|
|
154
|
+
{ id="CVE-2024-47176", cvss=9.9, sev=_M.SEV.CRITICAL, vendor="Linux/CUPS",
|
|
155
|
+
desc="CUPS cups-browsed unauthenticated RCE chain (2024)",
|
|
156
|
+
xpl="xpl/edb-cve-2024-47176", port=631 },
|
|
157
|
+
{ id="CVE-2026-34980", cvss=9.1, sev=_M.SEV.CRITICAL, vendor="Linux/CUPS",
|
|
158
|
+
desc="CUPS 2.4.16 unauthenticated RCE via PPD injection (2026)",
|
|
159
|
+
xpl="xpl/research/research-cups-chain-2026", port=631 },
|
|
160
|
+
-- HP fax
|
|
161
|
+
{ id="CVE-2018-5924", cvss=9.8, sev=_M.SEV.CRITICAL, vendor="HP",
|
|
162
|
+
desc="Faxploit — HP/Samsung fax stack overflow via malformed fax (port 9100 / PSTN)",
|
|
163
|
+
xpl="xpl/edb-cve-2018-5924", port=9100 },
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
-- ── Helper: detect vendor from banner string ──────────────────────────────────
|
|
167
|
+
function _M.detect_vendor(banner)
|
|
168
|
+
if not banner then return nil, nil end
|
|
169
|
+
local b = banner:lower()
|
|
170
|
+
for _, entry in ipairs(_M.VENDOR_PATTERNS) do
|
|
171
|
+
if b:match(entry.pat) then
|
|
172
|
+
return entry.vendor, entry.family
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
return nil, nil
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
-- ── Helper: match CVEs for a detected vendor (+ optional port filter) ────────
|
|
179
|
+
function _M.match_cves(vendor, port)
|
|
180
|
+
local matches = {}
|
|
181
|
+
if not vendor then return matches end
|
|
182
|
+
local v = vendor:lower()
|
|
183
|
+
for _, cve in ipairs(_M.CVE_DB) do
|
|
184
|
+
local cv = (cve.vendor or ""):lower()
|
|
185
|
+
if cv == v or cv == "generic" then
|
|
186
|
+
if (not port) or (cve.port == port) or (cve.port == 0) then
|
|
187
|
+
table.insert(matches, cve)
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
return matches
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
-- ── Helper: format a single CVE finding for nmap output ──────────────────────
|
|
195
|
+
function _M.fmt_cve(cve, verdict, details)
|
|
196
|
+
local lines = {}
|
|
197
|
+
table.insert(lines, string.format(" [%s] %s (CVSS %.1f — %s)",
|
|
198
|
+
verdict, cve.id, cve.cvss, cve.sev))
|
|
199
|
+
table.insert(lines, string.format(" Description : %s", cve.desc))
|
|
200
|
+
table.insert(lines, string.format(" PrinterXPL : printerxpl-forge run --module %s", cve.xpl))
|
|
201
|
+
table.insert(lines, string.format(" Reference : https://nvd.nist.gov/vuln/detail/%s", cve.id))
|
|
202
|
+
if details then
|
|
203
|
+
table.insert(lines, string.format(" Evidence : %s", details))
|
|
204
|
+
end
|
|
205
|
+
return table.concat(lines, "\n")
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
-- ── Helper: build a suggestion block when vendor is confirmed ─────────────────
|
|
209
|
+
function _M.suggest_xpl(vendor, family, cves)
|
|
210
|
+
local lines = {}
|
|
211
|
+
table.insert(lines, string.format("\n Detected: %s — %s", vendor, family or "Unknown model"))
|
|
212
|
+
table.insert(lines, " Full exploitation available via:")
|
|
213
|
+
table.insert(lines, " printerxpl-forge → pip install printerxpl-forge")
|
|
214
|
+
if vendor and vendor:lower():match("router|embedded|iot|zyxel|dlink|tplink|netgear|mikrotik") then
|
|
215
|
+
table.insert(lines, " embedxpl-forge → pip install embedxpl-forge")
|
|
216
|
+
end
|
|
217
|
+
if #cves > 0 then
|
|
218
|
+
table.insert(lines, string.format(" %d matching CVE module(s) available:", #cves))
|
|
219
|
+
for _, c in ipairs(cves) do
|
|
220
|
+
table.insert(lines, string.format(" printerxpl-forge run --module %s --target <IP>", c.xpl))
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
return table.concat(lines, "\n")
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
-- ── PJL helper: build PJL command with UEL wrapper ───────────────────────────
|
|
227
|
+
function _M.pjl_cmd(cmd)
|
|
228
|
+
return "\x1b%-12345X@PJL\r\n" .. cmd .. "\r\n\x1b%-12345X"
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
-- ── Verdict helper ────────────────────────────────────────────────────────────
|
|
232
|
+
function _M.verdict(is_vuln, is_possible)
|
|
233
|
+
if is_vuln then return _M.VERDICT.VULN end
|
|
234
|
+
if is_possible then return _M.VERDICT.POSSIBLE end
|
|
235
|
+
return _M.VERDICT.NOT_VULN
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
return _M
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
local ipp = require "ipp"
|
|
2
|
+
local shortport = require "shortport"
|
|
3
|
+
local stdnse = require "stdnse"
|
|
4
|
+
local table = require "table"
|
|
5
|
+
|
|
6
|
+
description = [[
|
|
7
|
+
Lists printers managed by the CUPS printing service.
|
|
8
|
+
]]
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
-- @usage
|
|
12
|
+
-- nmap -p 631 <ip> --script cups-info
|
|
13
|
+
--
|
|
14
|
+
-- @output
|
|
15
|
+
-- PORT STATE SERVICE
|
|
16
|
+
-- 631/tcp open ipp
|
|
17
|
+
-- | cups-info:
|
|
18
|
+
-- | Generic-PostScript-Printer
|
|
19
|
+
-- | DNS-SD Name: Lexmark S300-S400 Series @ ubu1110
|
|
20
|
+
-- | Location:
|
|
21
|
+
-- | Model: Local Raw Printer
|
|
22
|
+
-- | State: Processing
|
|
23
|
+
-- | Queue: 0 print jobs
|
|
24
|
+
-- | Lexmark-S300-S400-Series
|
|
25
|
+
-- | DNS-SD Name: Lexmark S300-S400 Series @ ubu1110
|
|
26
|
+
-- | Location:
|
|
27
|
+
-- | Model: Local Raw Printer
|
|
28
|
+
-- | State: Stopped
|
|
29
|
+
-- | Queue: 0 print jobs
|
|
30
|
+
-- | PDF
|
|
31
|
+
-- | DNS-SD Name: PDF @ ubu1110
|
|
32
|
+
-- | Location:
|
|
33
|
+
-- | Model: Generic CUPS-PDF Printer
|
|
34
|
+
-- | State: Idle
|
|
35
|
+
-- |_ Queue: 0 print jobs
|
|
36
|
+
--
|
|
37
|
+
|
|
38
|
+
author = "Patrik Karlsson"
|
|
39
|
+
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
|
|
40
|
+
categories = {"safe", "discovery"}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
portrule = shortport.port_or_service(631, "ipp", "tcp", "open")
|
|
44
|
+
|
|
45
|
+
local verbose_states = {
|
|
46
|
+
[ipp.IPP.PrinterState.IPP_PRINTER_IDLE] = "Idle",
|
|
47
|
+
[ipp.IPP.PrinterState.IPP_PRINTER_PROCESSING] = "Processing",
|
|
48
|
+
[ipp.IPP.PrinterState.IPP_PRINTER_STOPPED] = "Stopped",
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
action = function(host, port)
|
|
52
|
+
|
|
53
|
+
local status, printers = ipp.Helper:new(host, port):getPrinters()
|
|
54
|
+
if not status then
|
|
55
|
+
return
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
local output = {}
|
|
59
|
+
for _, printer in ipairs(printers) do
|
|
60
|
+
table.insert(output, {
|
|
61
|
+
name = printer.name,
|
|
62
|
+
("DNS-SD Name: %s"):format(printer.dns_sd_name or ""),
|
|
63
|
+
("Location: %s"):format(printer.location or ""),
|
|
64
|
+
("Model: %s"):format(printer.model or ""),
|
|
65
|
+
("State: %s"):format(verbose_states[printer.state] or ""),
|
|
66
|
+
("Queue: %s print jobs"):format(tonumber(printer.queue_count) or 0),
|
|
67
|
+
} )
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
if ( 0 ~= #output ) then
|
|
71
|
+
return stdnse.format_output(true, output)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
local ipp = require "ipp"
|
|
2
|
+
local shortport = require "shortport"
|
|
3
|
+
local stdnse = require "stdnse"
|
|
4
|
+
|
|
5
|
+
description = [[
|
|
6
|
+
Lists currently queued print jobs of the remote CUPS service grouped by
|
|
7
|
+
printer.
|
|
8
|
+
]]
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
-- @usage
|
|
12
|
+
-- nmap -p 631 <ip> --script cups-queue-info
|
|
13
|
+
--
|
|
14
|
+
-- @output
|
|
15
|
+
-- PORT STATE SERVICE
|
|
16
|
+
-- 631/tcp open ipp
|
|
17
|
+
-- | cups-queue-info:
|
|
18
|
+
-- | HP Laserjet
|
|
19
|
+
-- | id time state size (kb) owner jobname
|
|
20
|
+
-- | 14 2012-04-26 22:01:19 Held 2071k Patrik Karlsson Print - CUPS Implementation of IPP - Documentation - CUPS
|
|
21
|
+
-- | Generic-PostScript-Printer
|
|
22
|
+
-- | id time state size (kb) owner jobname
|
|
23
|
+
-- | 3 2012-04-16 23:25:47 Pending 11k Unknown Unknown
|
|
24
|
+
-- | 4 2012-04-16 23:33:21 Pending 11k Unknown Unknown
|
|
25
|
+
-- |_ 11 2012-04-24 08:15:14 Pending 13k Unknown Unknown
|
|
26
|
+
--
|
|
27
|
+
|
|
28
|
+
categories = {"safe", "discovery"}
|
|
29
|
+
|
|
30
|
+
author = "Patrik Karlsson"
|
|
31
|
+
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
|
|
32
|
+
categories = {"safe", "discovery"}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
portrule = shortport.port_or_service(631, "ipp", "tcp", "open")
|
|
36
|
+
|
|
37
|
+
action = function(host, port)
|
|
38
|
+
local output = ipp.Helper:new(host, port):getQueueInfo()
|
|
39
|
+
if output then
|
|
40
|
+
return stdnse.format_output(true, output)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
description = [[
|
|
2
|
+
Identifies HP printers using SNMP, HTTP(S), and JetDirect (PJL).
|
|
3
|
+
Extracts make/model information for reliable identification.
|
|
4
|
+
]]
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
-- @usage
|
|
8
|
+
-- nmap -p 161,80,443,9100 --script hp-printers <target>
|
|
9
|
+
--
|
|
10
|
+
-- @output
|
|
11
|
+
-- | hp-printers:
|
|
12
|
+
-- | Make: HP
|
|
13
|
+
-- | Model: HP LaserJet Pro M404dn
|
|
14
|
+
--
|
|
15
|
+
|
|
16
|
+
author = "ThreatWorx"
|
|
17
|
+
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
|
|
18
|
+
categories = {"discovery", "safe"}
|
|
19
|
+
|
|
20
|
+
local http = require "http"
|
|
21
|
+
local json = require "json"
|
|
22
|
+
local shortport = require "shortport"
|
|
23
|
+
local stdnse = require "stdnse"
|
|
24
|
+
local comm = require "comm"
|
|
25
|
+
local snmp = require "snmp"
|
|
26
|
+
|
|
27
|
+
portrule = function(host, port)
|
|
28
|
+
-- Run if any of these ports are open
|
|
29
|
+
return port.number == 161 or port.number == 80 or port.number == 443 or port.number == 9100
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
-- SNMP
|
|
33
|
+
local function try_snmp(host)
|
|
34
|
+
local ok, session = snmp.Helper:new(host, {number = 161, protocol = "udp"}, "public")
|
|
35
|
+
if not ok or not session then return nil end
|
|
36
|
+
|
|
37
|
+
local sysDescrOID = "1.3.6.1.2.1.1.1.0"
|
|
38
|
+
local hpModelOID = "1.3.6.1.2.1.43.5.1.1.16.1"
|
|
39
|
+
|
|
40
|
+
local sysDescr = session:get(sysDescrOID)
|
|
41
|
+
local model = session:get(hpModelOID)
|
|
42
|
+
|
|
43
|
+
if sysDescr and sysDescr.value and sysDescr.value:match("HP") then
|
|
44
|
+
model = model.value or sysDescr.value
|
|
45
|
+
return model
|
|
46
|
+
end
|
|
47
|
+
return nil
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
-- HTTP(S)
|
|
51
|
+
local function try_http(host, port)
|
|
52
|
+
local paths = { "/hp/device/DeviceInformation.xml", "/hp/device/this.LCDispatcher?nav=hp.DeviceInfo" }
|
|
53
|
+
for _, path in ipairs(paths) do
|
|
54
|
+
local ok, response = http.get(host, port, path)
|
|
55
|
+
if ok and response and response.body then
|
|
56
|
+
-- Try <ProductName> first
|
|
57
|
+
local model = response.body:match("<ProductName>(.-)</ProductName>")
|
|
58
|
+
if not model then
|
|
59
|
+
-- Fallback: first <dd> (used on older printer UIs)
|
|
60
|
+
model = response.body:match("<dd>(.-)</dd>")
|
|
61
|
+
end
|
|
62
|
+
if model then
|
|
63
|
+
model = model:match("^%s*(.-)%s*$")
|
|
64
|
+
model = model:gsub("^@PJL INFO ID%s*\"?", ""):gsub("\"?$", ""):gsub("[\r\n]", "")
|
|
65
|
+
return model
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
return nil
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
-- JetDirect (PJL)
|
|
73
|
+
local function try_jetdirect(host)
|
|
74
|
+
local socket = nmap.new_socket()
|
|
75
|
+
socket:set_timeout(3000)
|
|
76
|
+
local ok, err = socket:connect(host, 9100)
|
|
77
|
+
if not ok then return nil end
|
|
78
|
+
socket:send("\027%-12345X@PJL INFO ID\r\n")
|
|
79
|
+
local status, response = socket:receive_lines(1)
|
|
80
|
+
socket:close()
|
|
81
|
+
|
|
82
|
+
if status and response and response:match("HP") then
|
|
83
|
+
response = response:match("^%s*(.-)%s*$")
|
|
84
|
+
response = response:gsub("^@PJL INFO ID%s*\"?", ""):gsub("\"?$", ""):gsub("[\r\n]", "")
|
|
85
|
+
return response
|
|
86
|
+
end
|
|
87
|
+
return nil
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
-- Combined action: try all protocols
|
|
91
|
+
action = function(host, port)
|
|
92
|
+
-- 1. SNMP first
|
|
93
|
+
local snmp_data = try_snmp(host)
|
|
94
|
+
if snmp_data then
|
|
95
|
+
result = stdnse.output_table()
|
|
96
|
+
result["hp printer"] = snmp_data
|
|
97
|
+
return result
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
-- 2. HTTP & HTTPS
|
|
101
|
+
for _, p in ipairs({80, 443}) do
|
|
102
|
+
local http_data = try_http(host, {number=p, protocol=(p==443 and "https" or "http")})
|
|
103
|
+
if http_data then
|
|
104
|
+
result = stdnse.output_table()
|
|
105
|
+
result["hp printer"] = http_data
|
|
106
|
+
return result
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
-- 3. JetDirect
|
|
111
|
+
local jet_data = try_jetdirect(host)
|
|
112
|
+
if jet_data then
|
|
113
|
+
result = stdnse.output_table()
|
|
114
|
+
result["hp printer"] = jet_data
|
|
115
|
+
return result
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
return nil
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
local shortport = require "shortport"
|
|
2
|
+
local http = require "http"
|
|
3
|
+
|
|
4
|
+
description = [[
|
|
5
|
+
Get MAC address from network devices such printers and scanners
|
|
6
|
+
]]
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
-- @usage
|
|
10
|
+
-- nmap -sS -p 9100 --script http-device-mac <target>
|
|
11
|
+
--
|
|
12
|
+
-- @output
|
|
13
|
+
-- |_http-device-mac: 00:01:02:03:04:AB
|
|
14
|
+
-- <snip>
|
|
15
|
+
--
|
|
16
|
+
|
|
17
|
+
author = "Esteban Dauksis"
|
|
18
|
+
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
|
|
19
|
+
categories = {"discovery", "safe"}
|
|
20
|
+
|
|
21
|
+
portrule = shortport.http
|
|
22
|
+
|
|
23
|
+
action = function(host,port)
|
|
24
|
+
|
|
25
|
+
local socket = nmap.new_socket()
|
|
26
|
+
|
|
27
|
+
socket:set_timeout(5000)
|
|
28
|
+
|
|
29
|
+
local catch = function()
|
|
30
|
+
socket:close()
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
local try = nmap.new_try(catch)
|
|
34
|
+
|
|
35
|
+
-- I have identified some useful config urls
|
|
36
|
+
local answer1 = http.get(host, port, "/en/mnt/sysinfo.htm" )
|
|
37
|
+
local answer2 = http.get(host, port, "/hp/jetdirect/configpage.htm" )
|
|
38
|
+
local answer3 = http.get(host, port, "/configpage.htm" )
|
|
39
|
+
local answer4 = http.get(host, port, "/card.asp?Lang=en" )
|
|
40
|
+
local answer5 = http.get(host, port, "/cgi-bin/admin/management.cgi?_la=4")
|
|
41
|
+
local answer6 = http.get(host, port, "/web/guest/es/websys/netw/getInterface.cgi")
|
|
42
|
+
local answer7 = http.get(host, port, "/info_config_network.html?tab=Status&menu=NetConfig")
|
|
43
|
+
local answer8 = http.get(host, port, "/hp/device/info_configuration.htm")
|
|
44
|
+
local answer9 = http.get(host, port, "/start/start.htm")
|
|
45
|
+
local answer10 = http.get(host, port, "/Istatus.htm")
|
|
46
|
+
|
|
47
|
+
if answer1.status ~= 200
|
|
48
|
+
and answer2.status ~= 200
|
|
49
|
+
and answer3.status ~= 200
|
|
50
|
+
and answer4.status ~= 200
|
|
51
|
+
and answer5.status ~= 200
|
|
52
|
+
and answer6.status ~= 200
|
|
53
|
+
and answer7.status ~= 200
|
|
54
|
+
and answer8.status ~= 200
|
|
55
|
+
and answer9.status ~= 200
|
|
56
|
+
and answer10.status ~= 200
|
|
57
|
+
then
|
|
58
|
+
return nil
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
-- Regex for each url
|
|
62
|
+
if answer1.status == 200 then
|
|
63
|
+
return answer1.body:match("%x%x:%x%x:%x%x:%x%x:%x%x:%x%x")
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
if answer2.status == 200 then
|
|
67
|
+
mac = answer2.body:match("%x%x%x%x%x%x%x%x%x%x%x%x")
|
|
68
|
+
return string.format("%s:%s:%s:%s:%s:%s",mac:sub(1,2),mac:sub(3,4),mac:sub(5,6),mac:sub(7,8),mac:sub(9,10),mac:sub(11,12))
|
|
69
|
+
-- return answer2.body:match("%x%x%x%x%x%x%x%x%x%x%x%x")
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
if answer3.status == 200 then
|
|
73
|
+
mac = answer3.body:match("%x%x%x%x%x%x%x%x%x%x%x%x")
|
|
74
|
+
return string.format("%s:%s:%s:%s:%s:%s",mac:sub(1,2),mac:sub(3,4),mac:sub(5,6),mac:sub(7,8),mac:sub(9,10),mac:sub(11,12))
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
if answer4.status == 200 then
|
|
78
|
+
return answer4.body:match("%x%x:%x%x:%x%x:%x%x:%x%x:%x%x")
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
if answer5.status == 200 then
|
|
82
|
+
return answer5.body:match("%x%x:%x%x:%x%x:%x%x:%x%x:%x%x")
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
if answer6.status == 200 then
|
|
86
|
+
return answer6.body:match("%x%x:%x%x:%x%x:%x%x:%x%x:%x%x")
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
if answer7.status == 200 then
|
|
90
|
+
return answer7.body:match("%x%x:%x%x:%x%x:%x%x:%x%x:%x%x")
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
if answer8.status == 200 then
|
|
94
|
+
mac = answer8.body:match("%x%x%x%x%x%x%x%x%x%x%x%x")
|
|
95
|
+
return string.format("%s:%s:%s:%s:%s:%s",mac:sub(1,2),mac:sub(3,4),mac:sub(5,6),mac:sub(7,8),mac:sub(9,10),mac:sub(11,12))
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
if answer9.status == 200 then
|
|
99
|
+
return answer9.body:match("%x%x:%x%x:%x%x:%x%x:%x%x:%x%x")
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
if answer10.status == 200 then
|
|
103
|
+
return answer10.body:match("%x%x:%x%x:%x%x:%x%x:%x%x:%x%x")
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
end
|
|
107
|
+
|