某光猫的漏洞
1、目录穿越:
在这个设备的web界面可以通过usb设备的链接调用自定义函数或者更改请求包可以实现目录穿越。
2、目录穿越
可以通过usb设备实现目录穿越下载文件
3、信息泄露
可以通过下载相关文件可以对拿到明文密码。
1、前期准备
串口调试器
杜邦线
一个U盘(确保有足够的内存)
一根网线
一台电脑
一个该品牌的实体设备
2、提取固件
2.1、第一种方法:web界面提取这个文件系统
首先我们把设备通电,通过网线与我们的电脑连接,把U盘插到该设备的usb接口,然后通过账号密码进入该页面。
然后我们F12打开控制台,切换目录进二级目录[storage iframe(settings)]
我们通过对该页面的代码分析,发现这个函数get_path_files是用来实现目录跳转的。
然后我们通过函数get_path_files("/mnt/usb1_1/../../../../../")进入到固件的根目录
ps:因为linux系统目录在跳转目录时,如果目标文件目录不存在,会直接跳转到根目录。
关于这个函数的分析见本文章的2.1.2:关于一些细节的解释。
然后我们选择这些文件夹,复制到我们的U盘里面的【新建文件1夹】目录下
我们把u盘拔下来,放到电脑上看一下是提取成功。
所以,我们就可以通过这个步骤,把这个设备的文件系统全部提取出来,然后再做分析。
2.1.1、抓包改包
除了上述的通过分析页面的源码调用自定函数来实现目录穿越的方法以外,我们还可以通过抓包的方式来分析他是怎么实现目录的跳转的。
我们点击这个u盘的文件夹,进行抓包。
我们发现这个path的值就是我们的索要进入的目录,并且这个值进行了URL编码,我们上面知道了linux的目录的目录穿越的原理,所以我们在这里对path的值进行更改
我么在原本path的值后面加了几个'..%2F'这个是'../'的URL编码,我们发现改值以后的返回包是关于根目录的文件目录信息,接下来我我们放包来让web界面显示出来,看我们的想法是否正确。
我们发现确实跳转到了文件的根目录,这样我们在不去审计网页的源代码也能实现目录的穿越去拿到我们想要拿到的信息了。
2.1.2、关于一些细节的解释
关于二级目录[storage iframe(settings)]
在控制台来看;这个top是真个web页面的目录,切换目录[storage iframe(settings)]下再调用这个目录下的函数get_path_files
关于函数get_path_files
源码:
function get_path_files(getpath) {
// 清除当前活动的定时器
clearTimeout(activeTimeout);
// 设置一个新的定时器,5分钟后调用 Timeout() 函数
activeTimeout = setTimeout("Timeout()", 300000);
// 创建一个新的 XMLHttpRequest 对象,发送 POST 请求
(new XHR()).post('/cgi-bin/luci/admin/storage/openFolder',
{
token: '9e5aa94517c7475794822ea152f5a724', // 认证令牌
path: getpath // 要访问的路径
},
function(x) {
// 检查响应文本是否为文档类型,如果是则重定向到登录页面
if (x.responseText.substr(2, 7) == "DOCTYPE")
parent.location = "/cgi-bin/luci";
else {
// 清空当前文件列表
removeAllFiles();
// 解析响应文本为 JSON 对象
var json = eval("(" + x.responseText + ")");
// 获取当前路径和文件数据
path = json.filePath;
jdata = json;
// 遍历文件数量,添加文件到列表
for (var i = 0; i < json.fileNum; i++) {
eval("fileList = json.file" + (i + 1)); // 动态获取文件信息
addFileList(fileList.name, fileList.size, fileList.isFolder, fileList.time); // 添加文件到列表
}
// 对文件列表进行排序
sortFiles();
// 根据当前路径显示或隐藏返回按钮
if (path != rootpath)
$("#backShowOr").show(); // 显示返回按钮
else
$("#backShowOr").hide(); // 隐藏返回按钮
// 处理当前路径的显示格式
if (path.length > 36) {
var path_item = path.split('/'); // 分割路径
if (path_item[path_item.length - 1].length > 24) {
// 如果文件名过长,显示简化路径
var str_after = path_item[path_item.length - 1].substring(path_item[path_item.length - 1].length - 15, path_item[path_item.length - 1].length);
var pathway = "/" + path_item[1] + "/..." + str_after;
} else {
// 显示完整路径
var pathway = "/" + path_item[1] + "/.../" + path_item[path_item.length - 1];
}
$("#curpath").html(pathway); // 更新当前路径显示
} else {
$("#curpath").html(path); // 更新当前路径显示
}
}
});
}
这个函数的主要任务是:
- 从指定路径获取文件列表。
- 更新网页上的文件显示和当前路径。
- 处理用户界面的交互,确保在不同情况下正确显示信息。
这个 get_path_files 函数的功能是从服务器获取指定路径下的文件列表,并在网页上更新相应的内容。
所以我们可以跳转的一个不存在的目录来使得它直接跳转到根目录。
在不同的编译环境中的实现这一功能的方法也不一样:
- Python 中的 get_path_files 使用了 os.listdir() 或 glob.glob() 来实现。
- JavaScript 中的 getPathFiles 使用了 fs.readdirSync() 和 fs.statSync()。
- Bash 中的 get_path_files 使用了 ls 或 find 命令来实现。
2.2、第二种方法:urt串口提取
首先我们确定这个设备对应的UART串口的具体对应接口
在《物联网安全漏洞挖掘实战》这本书中第20页提到相关串口知识。
按照上面的我们对应我们FT232上的接线方式进行对应连接。
我们通过SecureCRT软件进行链接并设置波特率为115200
我们可以通过上面的web界面漏洞进行目录穿越和文件的越权下载romfile.cfg配置文件,我们可以拿到很多账号密码,通过尝试我们发现账号密码为:admin:1234
连接成功后我们看到这个设备的根目录系统。接下来我们就可以通过cp命令把我们想要的文件拷贝到mnt/usb1_1,也就是我们的u盘里面,这里以/etc/passwd为例
打开telnet的方法
除了上面的uart串口提取,也可以通过telnet进shell 然后拷贝文件目录。
通过我们上面提取到的固件分析,我们发现一个文件getGateWay.cgi ,通过对源码的分析,我们发现这个网页可以打开telnet服务。那么我们直接访问
192.168.1.1:8080/cgi-bin/getGateWay.cgi
因为这个光猫有两个web端口,8080端口是维护的web界面,80端口是用户访问的界面。
我们可以通过上面的web界面漏洞进行目录穿越和文件的越权下载romfile.cfg配置文件,从而拿到超级用户密码。
我们需要在8080端口进行登录访问
这个脚本用于在 Web 界面上显示系统网关、Telnet 用户名、密码和 Telnet 状态。它首先获取相关信息,检查 Telnet 状态,并确保输出的内容是安全的,第一次访问是显示'NO'表示没有打开,第二次访问显示'YES',表示打开。
当他检查到'NO'
我们通过上面的romfile.cfg配置文件可以知道telnet的账号和密码。
这里我们同样以/etc/passwd为例
3、漏洞实现及解释
3.1、目录穿越
正如前面2.1随描述的,插上U盘后,我们可以通过调用自定义函数或者抓包的方式来实现目录穿越。
3.2、文件越权下载
在我们2.1的描述里面提到,这个U盘插上以后页面是会对能访问到的目录进行限制的,要求用户只能访问/tmp/mnt/usb1_1/目录下的文件。
但是通过目录穿越的漏洞,访问到了其他目录下的文件,我们仍可以进行下载,也就是说,对于文件的下载,并没有进行权限的限制。
3.3、信息泄露x
通过上面的漏洞,我们可以通过网页的目录穿越,下载到romfile.cfg文件,这是一个配置文件,我们可以在这个文件里面查找到明文账号密码