通达OA最近悄咪咪的更新了一次,以下所发漏洞在新版基本已经失效
超全局变量覆盖导致SQL注入
首先是全局初始化参数:
if (0 < count($_GET)) {
foreach ($_GET as $s_key => $s_value ) {
if (!is_array($s_value)) {
$_GET[$s_key] = addslashes(strip_tags($s_value));
}
$s_key = $_GET[$s_key];
}
reset($_GET);
}
上面的代码会将GET所接受的参数自动注册为变量,如下demo所示:
php
foreach($_GET as $key => $v){
$$key=$v;
}
echo $admin;
?>
直接在GET中传递admin:
在查看如下代码:
php
if (0 < count($_GET)) {
foreach ($_GET as $s_key => $s_value ) {
if (!is_array($s_value)) {
$_GET[$s_key] = addslashes(strip_tags($s_value));
}
$$s_key = $_GET[$s_key];
}
reset($_GET);
}
echo $_GET['admin'];
?>
假如我们走通达OA正常的流程:
如果我们覆盖$_GET超全局变量:
可以轻而易举的绕过GPC,那么思路有了接下来就是找调用$GET或者$POST传参的地方:
这种地方很多,但是我们需要寻找未授权的地方,因为通达OA是面向过程的程序,所以只需要定位到验证权限文件,然后查找没有包含他的地方。
include_once "inc/auth.inc.php";
最后找到很多,拿一个比较简单的出来 retrieve_pwd.php:
include_once "inc/conn.php";
include_once "inc/utility_all.php";
$username = $_GET["username"];
$email = $_GET["email"];
$query = "SELECT UID,USER_ID,USER_NAME,USEING_KEY FROM USER WHERE BYNAME='$username'";
$cursor = exequery(TD::conn(), $query);
urldecode利用不当导致SQL注入:
go.php:
include_once "inc/session.php";
$OA_USER = str_replace(array(",", "\\\"", "\'", "\"", "'", "\t", "\\", "\\\\", "%27", "%22"), array("", "", "", "", "", "", "", "", "", ""), $OA_USER);
$APP_UNIT = str_replace(array(",", "\\\"", "\'", "\"", "'", "\t", "\\", "\\\\", "%27", "%22"), array("", "", "", "", "", "", "", "", "", ""), $APP_UNIT);
$OA_USER = urldecode($OA_USER);
$APP_UNIT = urldecode($APP_UNIT);
$query = "select MEMBER_ID from CONNECT_CONFIG where MEMBER_NAME='$APP_UNIT'";
$cursor = exequery(TD::conn(), $query);
首先使用str_replace绕过过滤危险字符:
$APP_UNIT = str_replace(array(",", "\\\"", "\'", "\"", "'", "\t", "\\", "\\\\", "%27", "%22"), array("", "", "", "", "", "", "", "", "", ""), $APP_UNIT);
然后使用urldecode解码:
$OA_USER = urldecode($OA_USER);
所以我们只需要传:
%25%252727
当然通达OA还有其他WAF,但是因为漏洞影响暂且不提。