zoukankan      html  css  js  c++  java
  • 通达OA前台任意用户登录分析

    最近爆了个通达 OA 任意用户登录漏洞,正好分析分析,顺便师傅一起学习。

    漏洞分析

    第一处

    首先我们找到文件根目录的文件 logincheck_code.php,这个文件是没有权限验证的。

    我们会发现在 180 行附近有两行代码:

    $LOGIN_UID = $UID;
    $LOGIN_USER_ID = $USER_ID;
    ...
    $_SESSION["LOGIN_UID"] = $LOGIN_UID;
    $_SESSION["LOGIN_USER_ID"] = $LOGIN_USER_ID;

    验证登录时就是判断的这两个 SESSION

    往上翻翻 $UID 哪来的:

    可以发现是直接从 $_POST 中获取的,也就是任意控制即可。

    但是 15 行附近有个判断,如果缓存里没有 CODE_LOGIN.$CODEUID$CODEUID 也是可以任意控制的) 就退出程序了,我们可以全局搜索一下这个缓存在哪里设置了。

    很快找到一处: ispiritlogin_code.php

    <?php
    
    include_once "inc/utility_all.php";
    include_once "inc/utility_cache.php";
    include_once "inc/phpqrcode.php";
    $codeuid = $_GET["codeuid"];
    $login_codeuid = TD::get_cache("CODE_LOGIN_PC" . $codeuid);
    
    if (empty($login_codeuid)) {
        // 给 codeuid 设置个随机值
        $login_codeuid = getUniqid();
    }
    
    $databack = array("codeuid" => $login_codeuid, "source" => "pc", "codetime" => time());
    $dataStr = td_authcode(json_encode($databack), "ENCODE");
    $dataStr = "LOGIN_CODE" . $dataStr;
    $databacks = array("codeuid" => $login_codeuid, "authcode" => $dataStr);
    
    //将 codeuid 存入缓存
    TD::set_cache("CODE_LOGIN_PC" . $login_codeuid, $login_codeuid, 120);
    
    //输出 codeuid
    echo json_encode(td_iconv($databacks, MYOA_CHARSET, "utf-8"));
    echo "
    
    
    ";
    
    ?>

    这里给重要的三句话写了注释。我们只要直接访问一次这个文件就可以伪造了。

    复现测试

    首先访问一次 /ispirit/login_code.php

    存下这个 codeuid。然后访问 /logincheck_code.php

    UID 设置成 1,这个 ID 默认是管理员。然后 CODEUID 设置成: _PC+codeuid

    随便访问个需要验证的 url/pda/main.php

    第二处任意登录

    一样的思路,我们全局搜索会找到在文件 ispiritlogin_code_check.php 处有类似的代码:

    我们往上翻:

    会发现 $UID 来自 $code_info$code_info 又来自缓存 CODE_INFO_PC+$login_codeuid

    这里的 $code_info[type] 需要等于 confirm.

    再上面一点有这样的代码:

    //$codeuid 可控
    $login_codeuid = TD::get_cache("CODE_LOGIN_PC" . $codeuid);

    这里和之前一样得。

    然后我找找哪里有设置 CODE_INFO_PC 的代码,在文件 generallogin_code_scan.php

    可以发现这里的 codeuid 和 type 都是可控的。现在就可以利用了。

    漏洞复现

    1. 首先访问 /ispirit/login_code.php 获取 codeuid
    2. 访问 /general/login_code_scan.php 提交 post 参数:

    source=pc&type=confirm&codeuid={5D9B864F-07AD-519C-13D1-E573E226302A}&uid=1&

    1. 最后访问 /ispirit/login_code_check.php?codeuid=xxx

    这样 $_SESSION 里就有了登录的信息了。

    补丁分析

    第一处修复 logincheck_code.php

    这里从 redis 中获取了数据,判断了 $UID 不等于 0 的话才能下一步,相当于做了个权限验证吧。

    如果我们能找到一处设置 OA:authcode:token:XXX 的地方,或者找到一处可以控制键值的缓存,即可绕过。

    第二处修复 generallogin_code_scan.php

    在设置 CODE_INFO_PC前进行了权限验证,这里根据传入的 session 查询此 session 是否登陆过,如果没登陆过就退出程序

    思考及总结

    这个漏洞其实挺简单的,但是到现在才发现,看来挖掘这样的洞更需要一些耐心和细心。由于这个程序用了全局覆盖,我们可以直接覆盖 _SESSION 里的数据,但是 _SESSION 是存在 redis 中的。所以如果有一处先开启 session_start 然后引入了 session.php 文件,即可直接覆盖 _SESSION 里的数据。

  • 相关阅读:
    spring相关资源
    spring mvc获取request HttpServletRequest
    spring中文乱码问题
    haskell读写文件相关(含二进制)
    grade web的构建约定 convention
    李洪强iOS开发之-实现点击单行View显示和隐藏Cell
    Animated progress view with CAGradientLayer(带翻译)
    关于CAShapeLayer
    CAShapeLayer的使用
    用缓动函数模拟物理动画
  • 原文地址:https://www.cnblogs.com/0daybug/p/12866884.html
Copyright © 2011-2022 走看看