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.
Files changed (97) hide show
  1. nse/README.md +204 -0
  2. nse/__init__.py +6 -0
  3. nse/install_nse.py +412 -0
  4. nse/lib/printerxpl.lua +238 -0
  5. nse/scripts/cups-info.nse +74 -0
  6. nse/scripts/cups-queue-info.nse +43 -0
  7. nse/scripts/hp-printers-cve-2022-1026.nse +121 -0
  8. nse/scripts/http-device-mac.nse +107 -0
  9. nse/scripts/http-hp-ilo-info.nse +121 -0
  10. nse/scripts/http-info-xerox-enum.nse +101 -0
  11. nse/scripts/http-vuln-cve2022-1026.nse +158 -0
  12. nse/scripts/lexmark-config.nse +89 -0
  13. nse/scripts/pjl-ready-message.nse +106 -0
  14. nse/scripts/printer-banner.nse +217 -0
  15. nse/scripts/printer-cups-rce.nse +189 -0
  16. nse/scripts/printer-cve-detect.nse +279 -0
  17. nse/scripts/printer-discover.nse +205 -0
  18. nse/scripts/printer-firmware-exposed.nse +219 -0
  19. nse/scripts/printer-hp-pjl.nse +192 -0
  20. nse/scripts/printer-http-ews.nse +293 -0
  21. nse/scripts/printer-ipp-info.nse +235 -0
  22. nse/scripts/printer-lexmark-ipp.nse +203 -0
  23. nse/scripts/printer-passback.nse +204 -0
  24. nse/scripts/printer-pjl-info.nse +146 -0
  25. nse/scripts/printer-printnightmare.nse +211 -0
  26. nse/scripts/printer-snmp-info.nse +176 -0
  27. nse/scripts/printer-vuln-check.nse +256 -0
  28. nse/scripts/snmp-device-mac.nse +93 -0
  29. nse/scripts/snmp-info.nse +146 -0
  30. nse/scripts/snmp-sysdescr.nse +70 -0
  31. printerxpl_forge-6.2.0.dist-info/METADATA +919 -0
  32. printerxpl_forge-6.2.0.dist-info/RECORD +97 -0
  33. printerxpl_forge-6.2.0.dist-info/WHEEL +5 -0
  34. printerxpl_forge-6.2.0.dist-info/entry_points.txt +4 -0
  35. printerxpl_forge-6.2.0.dist-info/licenses/LICENSE +21 -0
  36. printerxpl_forge-6.2.0.dist-info/top_level.txt +4 -0
  37. src/assets/fonts/gunplay.pfa +1671 -0
  38. src/assets/fonts/kshandwrt.pfa +315 -0
  39. src/assets/fonts/laksoner.pfa +2402 -0
  40. src/assets/fonts/paintcans.pfa +9699 -0
  41. src/assets/fonts/stencilod.pfa +4076 -0
  42. src/assets/fonts/takecover.pfa +26138 -0
  43. src/assets/fonts/topsecret.pfa +6652 -0
  44. src/assets/fonts/whoa.pfa +773 -0
  45. src/assets/mibs/HOST-RESOURCES-MIB +1540 -0
  46. src/assets/mibs/Printer-MIB +4389 -0
  47. src/assets/mibs/README.md +9 -0
  48. src/assets/mibs/SNMPv2-MIB +854 -0
  49. src/assets/overlays/hacker.eps +596 -0
  50. src/assets/overlays/smiley.eps +214 -0
  51. src/assets/overlays/smiley2.eps +240 -0
  52. src/core/attack_orchestrator.py +1025 -0
  53. src/core/capabilities.py +323 -0
  54. src/core/destructive_audit.py +430 -0
  55. src/core/discovery.py +488 -0
  56. src/core/osdetect.py +74 -0
  57. src/core/poly_runner.py +579 -0
  58. src/core/printer.py +1426 -0
  59. src/main.py +2134 -0
  60. src/modules/install_printer.py +318 -0
  61. src/modules/login_bruteforce.py +852 -0
  62. src/modules/pcl.py +506 -0
  63. src/modules/pjl.py +3575 -0
  64. src/modules/print_job.py +1290 -0
  65. src/modules/ps.py +1102 -0
  66. src/payloads/__init__.py +98 -0
  67. src/payloads/assets/overlays/notice.eps +9 -0
  68. src/protocols/__init__.py +19 -0
  69. src/protocols/firmware.py +738 -0
  70. src/protocols/ipp.py +216 -0
  71. src/protocols/ipp_attacks.py +609 -0
  72. src/protocols/lpd.py +141 -0
  73. src/protocols/network_map.py +1004 -0
  74. src/protocols/raw.py +173 -0
  75. src/protocols/smb.py +359 -0
  76. src/protocols/ssrf_pivot.py +427 -0
  77. src/protocols/storage.py +587 -0
  78. src/ui/__init__.py +6 -0
  79. src/ui/interactive.py +742 -0
  80. src/ui/spinner.py +112 -0
  81. src/ui/tables.py +132 -0
  82. src/utils/banner_grabber.py +852 -0
  83. src/utils/codebook.py +456 -0
  84. src/utils/config.py +522 -0
  85. src/utils/cve_loader.py +158 -0
  86. src/utils/default_creds.py +134 -0
  87. src/utils/discovery_online.py +1327 -0
  88. src/utils/exploit_manager.py +805 -0
  89. src/utils/fuzzer.py +220 -0
  90. src/utils/helper.py +732 -0
  91. src/utils/local_printers.py +307 -0
  92. src/utils/ml_engine.py +491 -0
  93. src/utils/operators.py +474 -0
  94. src/utils/ports.py +234 -0
  95. src/utils/vuln_scanner.py +823 -0
  96. src/utils/wordlist_loader.py +412 -0
  97. 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
+