7

CVE-2022-36923 ManageEngine OpManager getUserAPIKey Authentication Bypass

 1 year ago
source link: https://y4er.com/posts/cve-2022-36923-manageengine-opmanager-getuserapikey-authentication-bypass/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

CVE-2022-36923 ManageEngine OpManager getUserAPIKey Authentication Bypass

 2022-09-01  2022-09-01  约 1473 字   预计阅读 3 分钟 

根据ZDI的公告来看,漏洞点存在于com.adventnet.me.opmanager.server.util.RMMUtil#getUserAPIKey

关键点在于怎么走到这个位置。

搜索xml配置文件发现

路由为/RestAPI/getAPIKey,尝试构造请求包

提示缺失参数,看日志报错

IAMSecurityException 断点打在其构造函数上向上追溯,最终在com.adventnet.iam.security.ParameterRule#checkForAllowedValueRegex发现是由于参数正则匹配不对导致抛出异常。

最终构造参数成功返回200

此时回头来看com.adventnet.me.opmanager.server.util.RMMUtil#getUserAPIKey

    public String getUserAPIKey(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String userName = request.getParameter("username");
        String domainName = request.getParameter("domainname");
        if (userName != null && domainName != null) {
            try {
                Long userId = MickeyLiteUtil.getUserId(userName, domainName);
                String apiKey = (new APIKeyGenerator()).checkAndGenerateApiKey(userId, -1L);
                response.setContentType("text/plain");
                PrintWriter out = response.getWriter();
                out.println(apiKey);
                out.flush();
                return null;
            } catch (Exception var8) {
                var8.printStackTrace();
                return null;
            }
        } else {
            return null;
        }
    }

MickeyLiteUtil.getUserId()需要给一个正确的domainName才行,得看数据库AaaLogin表中有什么值。

查看数据库jdbc链接C:\Program Files\ManageEngine\OpManager\conf\database_params.conf

密码被加密,在bin目录中发现bin\encrypt.bat

call .\setCommonEnv.bat

set CLASS_PATH="%SERVER_HOME%\lib\framework-tools.jar"

IF "%1"=="" GOTO SHOW_SYNTAX

"%JAVA%"  -Dserver.home="%SERVER_HOME%" -cp %CLASS_PATH% com.zoho.framework.utils.crypto.CryptoUtil %*
GOTO END_ENCRYPT

:SHOW_SYNTAX 
"%JAVA%" -Dserver.home="%SERVER_HOME%" -cp %CLASS_PATH% com.zoho.framework.utils.crypto.CryptoUtil "showUsage"

:END_ENCRYPT

调用CryptoUtil类进行加密

直接写一个类调用decrypt函数即可

cryptTag由EnDecryptUtil.getCryptTag()获得

解析persistence-configurations.xml文件拿到CryptTag属性,查看文件内容

尝试用MLITE_ENCRYPT_DECRYPT解密不成功,然后发现这个xml文件最上方引入了外部实体

最终在conf\customer-config.xml文件中找到了CryptTag

算法为AES256,解密后链接数据库,查看AaaLogin表

得到domainName为-,最终请求包如下

由此拿到restapi

rce的方式看了看restapi文档,有一个workflow可以rce,但是通过restapi访问有问题,在OpManagerServerClasses.jar!/com/adventnet/me/opmanager/server/api/OpManagerAPIServlet.class:354

如果你的api是APIUtil.getInstance().isInternalAPI()内部api,那么在session中isAPIClient只有在login的时候才会被赋值,所以这个地方isApiclient为false,而NmsUtil.isRMMEdition为false,导致抛出异常APIError.internalAPI(request, response)那么所有的内部api都不能被调用。

conf\OpManager\do\RestApi.xml定义了workflow关键的api都是EXPOSED_API=TRUE,也就是内部API

到这rce就断了,回溯了一下isInternalAPI()函数,发现所有的api在数据库OpManagerDB.public.restapioperation表中,过滤一下exposed_api='true',一共955个api可以通过restapi访问。

看了看没啥都是增删改查,希望有缘人能挖出来一个rce把。

文笔垃圾,措辞轻浮,内容浅显,操作生疏。不足之处欢迎大师傅们指点和纠正,感激不尽。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK