GitHub Actions 介绍
GitHub Actions 是微软于 2018 年秋季推出的一个平台。这一平台可以让开发者实现定制化的程序逻辑,而不需要专门创建一个应用去完成需要的任务。开发者可以借助 Actions 平台建立工作流,使用他们代码repo中定义好的 action、或者 GitHub 公开代码库中的 action,甚至是一个公开的 Docker 容器镜像。action 在这里指的是开发、测试、部署和发布代码中的各种流程,举个例子,一个 action 可以是公开发布某个 npm 模块,在创建紧急 issue 时为开发者发送 SMS 警告,或者部署生产流程中的代码的过程。这些工作流程过去需要开发者自己去手动实现。现在有了 Actions 平台后,借助 Actions 平台和 GitHub 中百万级别的公开库,任何一个开发者都可以直接建立上述工作流程,不需要专门去创建实现这些 action 的应用了。此外,开发者创建的工作流也可以分享给 GitHub 社区供其他人使用。
简而言之,GitHub Actions 是 GitHub 的持续集成服务。大家知道,持续集成由很多操作组成,比如抓取代码、运行测试、登录远程服务器,发布到第三方服务等等,GitHub 把这些操作就称为 actions。在 2018 年 Actions 平台刚建立的时候,就已经有很多 action保存在 GitHub 上了,总数已超过 9600 万个。海量的公开代码库是 GitHub 开源这一平台的技术基础。
Actions是一个CI/CD管道,内置于GitHub中,该管道于2019年11月全面投入使用。Actions允许我们基于诸如签入、拉请求等触发器来构建、测试和部署我们的代码。
在开源之初,Actions 平台的功能相对有限。首先,最初的公开的 Actions 只能在 Linux 平台上使用,而且只支持 Docker 容器。但在最新版本中,Actions 支持基本上所有的编程语言,因此也可以在多个平台上使用,如 Linux、Linux Container、Windows 和 macOS 等。此外,开发者也可以使用 Javascript 语言编写 action 的代码。这样一来,受益的开发者更多了。此外,和 2018 年公开的版本相比,Actions 支持了更多的编程语言,包括主流的开发语言,如 Node.js、Python、Java、PHP、Ruby、C/C++、.NET,以及 Android 和 iOS 设备上的开发语言。现在开发者可以在任何平台上构建、测试和发布代码并在容器或虚拟机上运行他们的工作流。比如,基于“矩阵构建(matrix builds)”功能,开发者可以同时在多个平台测试多个版本的项目,例如,可以同时在 Linux、macOS 和 windows 平台上测试三个不同版本的 Node.js 项目。因为 GitHub Actions 是基于 YAML 文件构建的,开发者只需要在文件中添加几行代码就可以完成设置,而 Actions 平台会完成剩下的工作。
如果你感兴趣,可以点此,本文详细介绍了如何设置Actions以构建工具,并展示了如何将混淆功能集成到CI工作流中。当时,无法在GitHub UI之外与Actions集成。
开发准备
在这篇文章中,我们将研究如何使用Actions API在Cobalt Strike中下载和执行工具,并发布附带的攻击者脚本,这样你就可以在看完本文时开始使用这些攻击特性。
不过我要强调的是,这是一个概念证明的例子,我们建议你手动检查已经下载的所有代码,并定期跟踪更改和更新。
在深入研究API之前,有必要快速回顾一下如何配置操作。在这篇文章中,我使用了一个私有的repo,它包含了一些常用的工具,比如GhostPack和SharpHound。为此,我在GitHub上创建了一个私有的repo,并使用以下命令将这些工具添加为子模块:
git submodule add https://github.com/BloodHoundAD/SharpHound3.git
Ghostpack是以前 PowerShell 功能的各种 C# 实现的集合,包括六个独立的工具集:Seatbelt, SharpUp, SharpRoast, SharpDump, SafetyKatz, 和 SharpWMI。 所有这些项目都将托管在 GhostPack 的 GitHub 代码repo中,每个项目作为一个独立的repo分离出来。
SharpHound是针对.Net 4.5设计的。 Sharphound必须从域用户的上下文中运行,或者直接通过登录或通过其他方法(例如RUNAS)运行。SharpHound是使用C#9.0功能编写的,若要轻松编译此项目,请使用Visual Studio 2019。如果要在Visual Studio的早期版本上进行编译,则可以安装Microsoft.Net.Compilers nuget包。构建项目将生成可执行文件以及封装可执行文件的PowerShell脚本。此时,所有的依赖关系都被滚动到二进制文件中。
添加repo并进行提交和推送之后,我们得到一个私有repo,其中包含对我们要构建的工具的引用。这些都与链接的repo的特定版本相关联,如果你要进行新更改,则可以稍后对其进行更新。
使用子模块而不是复制repo意味着我们可以轻松利用对我们引用的repo所做的任何更新。如果愿意,我们还可以将我们的repo设为私有。
接下来,我们需要配置工作流程,通过“操作”选项卡配置工作流程。
攻击性行为的开发
有许多预先配置的操作可供选择,但是在这篇文章的示例中,我们将自己完全从头构建工作流。选择此选项将创建一个支架yml文件,我们可以在GitHub UI中进行编辑。
在这里,我们既可以访问一系列的操作,也可以将这些操作合并到我们的工作流中。在这篇文章中,我们将坚持使用一些非常简单的方法来构建工具和发布工件。
为了实现这一点,我们需要检查我们的repo,包括子模块,恢复我们需要的任何包,然后以发布模式执行MSBuild。
我们会将其设置为在每次repo请求被推送时发生:
name: Buildon: [push] jobs: build: runs-on: windows-latest steps: - uses: actions/checkout@v2 - uses: actions/checkout@v2 - name: Checkout submodules shell: bash run: | # If your submodules are configured to use SSH instead of HTTPS please uncomment the following line # git config --global url."https://github.com/".insteadOf "[email protected]:" auth_header="$(git config --local --get http.https://github.com/.extraheader)" git submodule sync --recursive git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1- name: Setup Nuget.exe uses: warrenbuckley/Setup-Nuget@v1 - name: Nuget Restore run: nuget restore $Env:GITHUB_WORKSPACE\SharpHound3\SharpHound3.sln - name: Build SharpHound3 run: | cd "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\" .\MSBuild.exe $Env:GITHUB_WORKSPACE\SharpHound3\SharpHound3\SharpHound3.csproj /property:Configuration=Release - uses: actions/upload-artifact@master with: name: SharpHound3 path: SharpHound3\SharpHound3\bin\Release\SharpHound.exe
它的语法可能有点混乱,所以了解它的后台是有帮助的。每个构建都在临时容器上运行,该容器具有运行git命令和执行构建所需的工具链。对于这个构建,由于我们的目标是. net代码,所以我们使用了一个windows容器(即 runs-on: tag)。
我们的第一步只是检验我们的repo,然后,恢复子模块。虽然这个命令稍微复杂一些,但是我们所做的只是进入shell并直接运行一个git命令。
现在,我们就可以执行setup-nuget操作,它允许我们在SharpHound3上运行nuget还原,该命令获取构建SharpHound所需的依赖关系。
完成该步骤后,我们通过shell调用MSBuild,将路径传递到SharpHound csproj文件并指定发布构建。这将运行MSBuild,它将编译后的EXE放到容器中的磁盘上。
要访问编译后的结果,我们首先需要上传它。这使得它可以通过GitHub UI和Actions API访问。如果没有上传这个步骤,编译后的结果将与构建容器一起被破坏。为每个工具添加适当的构建步骤,并通过提交触发构建,应该会产生可用工件的列表。
配置了构建操作后,我们就可以开始查看API。要访问API,就需要凭据。 GitHub支持多种身份验证方法,但是个人访问令牌可满足我们的需求。我们可以使用PAT来代替密码,同时仍然允许它在任何时候被撤销。执行操作时,我们需要repo范围。
创建令牌后,我们可以开始通过cURL发出API请求:
curl -u two06:TryHarder 'https://api.github.com/repos/two06/redteam-tooling/actions/artifacts'
这应该返回我们repo中可用工件的详细信息。
这为我们提供了在其他工具中开始使用这些工件所需的所有信息,不过,关于如何编写攻击脚本,我不会讲太多细节。你可以在这里查看官方文档,或者查看本文附带的代码。重要的是我们可以使用Exec方法调用GitHub API,如下所示:
sub make_API_request{ $cmd = @('curl', '-u ' . $username . ':' . $access_token, $api_url . $repo_url . $endpoint); $curl_command = exec($cmd); $data = readAll($curl_command); closef($curl_command); return $data; }
现在,我们就可以上传用户名、访问令牌并构建要调用的URL。然后,我们读取数据并将其返回进行处理。
完成了这些操作后,我们就可以访问Cobalt Strike的可用工件列表。
在后台,它是调用actions API并获取可用的工件名称的唯一列表。 该API会返回所有工件,包括旧的构建,这样我们就获取了最新版本。
然后,使用已经编译的名称,我们就可以查找下载URL并获取包含已经编译的压缩文件。 然后,我们可以提取压缩文件并使用Beacons执行程序集命令执行编译。
以下就是我们得到的最终结果:
总结
这篇文章介绍了如何在GitHub上为我们的代码创建CI / CD管道,并直接从cobalt strike访问编译后的工件,文中介绍的攻击脚本可在此处找到。
本文翻译自:https://www.mdsec.co.uk/2020/03/offensive-development-with-github-actions/如若转载,请注明原文地址: