
hello everybody um today we're going to learn how to write a worm for gab actions This research was a result of about three months of work in which my goal was to find a new attack Vector to attack CCD pipelines now before we begin how many of you use GitHub actions by a raise of hand okay I see a lot of people good so it's relevant for you everybody else maybe you'll learn about a new attack Vector so let me introduce myself my name is as Greeno I'm a security researcher I have about 8 years of experience in cyber security for the last 3 years I've been researching CCD security uh first at cider security
which was later acquired by pal Alto networks here are some notable projects uh projects have been a part of so first one is the top 10 CCD security risks by oasp after that we have the CCD goat which is a deliber vulnerable CCD environment if you want to learn how to attack CCD pipelines and um project I released a month ago which is called awesome CCD attacks you can also find it on GitHub the best resources I've read about CCD offive Security in the last three years let's begin So today we're going to learn how to build a gab Backes worm in order to build a warm we have few parts of the puzzle H maybe at first
everything won't seem related but when we get to the worm itself everything will eventually connect and you'll learn how to write a gab actions worm so we're going to talk about initial attack Vector action dependencies action to infect actions how actions can infect other actions and eventually we'll see how to find attack graphs at scale and I'll show you some uh real cases from The Real World so let's begin by an initial an by learning about initial attack vectors so our first goal is to compromise a single GitHub repository so we're able to maybe push code to the repository or or abuse it uh somehow let's see one example of a non attack Vector to compromise a gab
repository that's called reprojecting so on the on the left we have our repository and it uses a dependency repository in the middle which is part of an organization when we try when uh the developer let's say wakes up one day and decides to move the dependency repository to a new organization gab automatically creates a redirect and when we try to fetch the old name it redirects us to the new name of the repository in the new GitHub organization now let's say that developer decided to delete the old organization now anyone can reclaim that name and for example a malicious attacker can create the old organization with the same name what they can also do is create the same repository name next
thing will happen when we'll try to fetch the repository again the redirection will be cancelled and we will actually fetch a malicious repository now GitHub knows this issue and they've implemented a partial fix let's say it h they retire the name spaces basically organization names or usernames of projects that had more than 100 clones in the week leading up to the owner's account uh being renamed or deleted I won't get into the details but this is still uh possible to exploit this attack for many reasons uh just keep notice of that and know that it's still possible to exploit this attack now there are more known attack vectors I've implemented in my research uh three
more uh attack vectors that have automated the discovery of uh these are npm email hijacking and giab actions command injection I won't get into the details but just know that they exist you can later read on those attack vectors if you want so we now know how to compromise a single repository but how can we further reach and get to more and more repositories basically we want to write a warm right so let's talk about action dependencies how actions are dependent on other actions and in this part our goal is to create a dependency tree of actions Now actions depend on other actions in two ways the first way uh before we get to the first way let's
learn a bit about uh what actions are so actions are individual tasks that you can uh combine to create jobs and customize your workflows here you see a high level architecture of Gab back C basically you have some event that triggers a workflow workflow contains multiple jobs each job can contain multiple steps and each step can contain an action or a script so action is basically some code package you can write and you can use it as uh modular parts of your pipeline to uh easily and fast to easily write pipelines and uh you can also uh use actions that are written by the community so if someone publishes uh a repository with an action
you can use it and you can uh find it on the gab Marketplace and you can you can directly find the repository itself so everybody can share uh their code now let's talk about the dependency the ways that actions depend on other actions here we have the action yo file which defines an action now in the bottom of the file we can see that this is action of type composite we have other types of actions but they're not relevant for uh this part and composite action can do two things they can run other actions they can also run scripts in this example we see that this action runs another action that's called actions checkout so when someone runs the
repository that this action yaml uh is inside it basically it runs the H checkout H action so this is one dependency type the other dependency type is through cacd actions also have their own GitHub action cacd workflows and they probably use other actions in their cicd pipelines to build or test their code in this example we can see uh few actions but on the red box you can see the setup node action which sets up node environment which can then uh be used to install the project and test it and so on so what we can do is we can take both of these files pass them and if we pass the files and then do it
recursively basically passing all the actions that depend on other actions and and so on and so on we can create a beautiful tree of dependencies that looks like this this uh beautiful flower of dependencies you can see here uh on the purple nodes you have repositories each repository is connected to Orange nodes which represent usage of an action inside a file and each orange node is connected to a repository that host that hosts the action that's being used so we have a recursion here that creates this a beautiful action actions dependency tree now this is the same Tree in a different representation let's say we have a Target repository on the left that we want to attack how can we do it
we have an initial action that we can try to compromise then we climb up the tree by infecting all actions that are all the actions that are using it basically creating a worm and uh affecting the target repository how do we initially uh compr romise the first repository using the initial attack vectors we talked about earlier like reprojecting npm email highjacking or command injection that's it for this part next part is how do we do the actual infection in the chain we need to climb up the tree how can one action infect other actions this part is more complicated so I hope I won't lose you so we need to learn few things we have here an examp example of a workflow
file H you can see that we have two jobs the first job and the second job the first job has the first secret the second job has the second secret and also the second job has an interesting code here that what it does it basically dumps the memory of the runner and grabs for secrets in memory because in gab actions the secrets are stored in the memory in clear text now I know this thanks to a research done by Karim Rahal you can see the link to the research uh below and when we execute this code we get the following decoded Bas 64 text we see here we have the second secret and the GitHub token now we don't see the first
secret because as I told you earlier each job runs on a different Runner so we only have the second uh secret from the uh second job and we have the GitHub token which wasn't referenced at all in the file but it still exists in the memory of the runner so so far we know that all secrets are accessible to all steps in a job because the uh dumping of the memory was done before the secret was actually being used and if you want to know why you can read more in the research that I've referenced below uh and another thing we know is that GitHub token is accessible even though it's not referenced at all now what is the GitHub
token the gab token is a token generated at the start of each workflow and it can be used by the workflow itself self to communicate uh to the repository to GitHub and to perform actions on it we can create pull request comment on pull request and one interesting thing we can push code H back to the repository if we have permissions now what about permissions so not too long ago about a year ago the default uh GitHub token permissions for repository for repositories was read and write GitHub changed it a year ago to be a default read but all the repositories in the worldall that were created more than a year ago have a default right permission
if it wasn't changed by anyone another thing we need to know is how to use actions so to use actions we have three ways we can use a commit Hash a branch reference and a git tag reference now in our special case we want to infect a repository by pushing malicious code to the repository and we need to override a reference we can't overwrite a g a git commit hash because it's Unique but we can overwrite a git tag and we can push a new commit to a branch basically to override the new the newest uh commit now how the attack actually looks like is as follows we have on the left our repository an
action repository which has a CD workflow that uses the compromis action using the main branch uh reference when the uh workflow triggers a giab talking is being generated and our compromise action can use it to push code back to the repository and affect the repository if it has uh the right permissions now let's summarize what we know so far this is the full attack the whole story together just to so we understand before we see the real cases so the first step is to compromise an initial action repository using one of the methods I've showing you earlier like reprojecting the second step is to infect dependent repositories by pushing code to the back to the repositories when the actions or
the comp ised actions is being used and the next step is just climbing up the tree and reaching our Target repositories in which we can execute whatever code we want we can steal secrets we can modify it source code and so one may be infecting more and more targets even outside of the GitHub platform the next part I'll going I'm going to show you how how I found vulnerable attack graphs that scale on the internet real cases uh I used neo4j database as you've seen earlier H to create a huge graph later after I created the huge graph of dependencies I queried uh for a start of an attack node initial attack node and an end of the
tree that ends in one of the target repositories I tried to attack so the process was as follows first I collected targets so I defined the 10K top repositories on GitHub I also used Kos DB as you can see on the right to H create a list of 32k repositories of companies that have bug Bounty next thing I did was to filter out all the repositories that didn't use GitHub actions and then I cloned each repository and then I checked for the three initial attack vectors automatically if uh any one of them was possible I connected an attack node to that uh repository after that I collected metadata about the action itself to see if it can actually propagate up the tree
and infect other actions using it so I collected if it has content right permissions I was able to do that by uh passing the log files of workflows in GitHub they show you the permissions of the GitHub actions token even in public repositories you can see the permissions that are being used it sounds simple turns out it's really complicated to actually gather this data efficiently and reliably but uh eventually it worked and I also uh collected What secrets are accessible by the action because I needed to collect all the secrets that are used in the same job that the action is using because in addition to the GitHub token the job might use a GitHub
access token which we can also use to infect uh a dependent repository if that access token has uh right permissions and many other uh parameters you can see here in the image and I did so recursively for everything so I built this huge dependency of about I think 100,000 nodes uh something like that and here's example from a real world case that have publicly disclosed and they already fixed everything H so we'll use this case to understand the real impact of uh this attack so on the right we have us as the attacker and I found the action Z repository which is an action vulnerable to reprojecting so I claimed the organization I'm now the owner of the
old organization of this repository and I validated that that I can actually compromise the repository and reproject it and this repository is being used by two other repositories hangfire repository which is a very popular open source and verac code repository which has a very long name it's another action by verac code so I can see that by compromising the action Z repository I can compromise two other repositories now now that's not enough to like getting times two vulnerable repositories that's not uh not everything I want as as a attacker I want a warm that spreads all over the internet but that's not the whole picture because the verac code repository has about 1.6k dependence so
I can also infect all of them and all of the repositories that depend on them and so on recursively and the action zip repository also has has about 600 uh uh dependence but that's still not the full picture because the hangfire repository actually creates a nugget package that is being downloaded 99.4k times a day each day it has about 10K downloads which also by infecting the hangfire repository and hoping it will release its code as a package as a nugget package we can infect all of its uh users but that is still not the whole picture of this attack this is only public data we have what about all the private repositories that are also
depending on those repositories probably much much much more and you probably think to yourself okay so that's a huge impact blast that's crazy amazing but that's still not the uh representation of the real world the real world looks something like this I found many many cases like this much much bigger attack trees much more complicated and I can tell you that I found very H ER popular open sources that were able that I was able to or directly compromise or indirectly by infecting their dependence and also I found uh many many uh huge companies that all of you probably use their products that are vulnerable to this attack and I could uh execute code in their repositories and infect them by
infecting the weakest link in the chain basically of uh repositories that they depend on and so on so this is the full scale of the attack itself now let me show you and let me introduce to you the dendro worm the actual worm uh that implements this I'll show you a short PC the word dendro comes from the word dendrology which is the science and study of Woody plants now let's get to the demo itself before we get to the demo I'll show you a quick overview of what you're going to see so we have this environment we have a Target repository on the left we want to attack it has a CCD pipeline that uses the random action V1 tag and
it also has a CCD pipeline which uses the uh rev dat action uh repository using a main branch reference and the Rev date action is a composite action which directly depends on the uh rev action repository now as attackers we start with the uh initial ability to push code to the repository and what you'll see in the demo is that the attacker infects the repository with the warm code which means instantly that the Rev date action repository is compromised because it directly depends on the Rev action repository after that we will simulate uh commit to the uh random action repository to trigger its CD pipeline in which our warm will run and it will try to override
the V1 tag of the random action repository and the V1 tag is used by the Target repository and which will also simulate uh commit by the maintainer which will trigger its CCD Pipeline and our warm will run on the C CD pipeline of the target repository and will be able to steal one of its uh secrets so let's see the demo
wa done
okay thank you okay so we have the first repository you can see a graph on the bottom right that shows you the progress of the attack here we infect the repository with malicious code this is just a PC in Python we can obviously make this code much more hidden but this code downloads the malware installs it and executes it from a remote server
okay so now we see the second uh wait I'll just go back a
bit okay so we commit those changes and we go to the second repository we can see it's action yaml that is directly using the action that we've just infected so no no need to do anything here it directly uses
it now we go to the third repository we can see that all this action does is uh generate some random numbers and we can look at its CD workflow file in which we see that it uses the second action another thing we can see uh in this repository is that it has a tag which was created yesterday V1 tag as you can see now we simulate a push by the maintainer to the repository to trigger the
pipeline this will trigger uh the uh gab action workflow and now the malware will be downloaded from uh the compromis repos from the server by a compromised action and you'll be able to see on the server on the right we see the download request and you'll see that uh it also sent its GitHub token to the server on the right and it over it overwrote the uh V1 tag of the repository you can see now the tag is dated to now and we can see it's commit which contains the worm code again the simp the again the download and execution of the worm and now we are in the last repository the target repository we can
see that it has a secret and it uses the action repository that we've just infected its tag and we'll again simulate a push to the commit by the maintainer push to the Ripple and now the workflow will trigger and you'll be able to see on the right that we've successfully stolen a the secret and sent it to the server here's the download request and you can see in the red box the secret that was stolen woo yeah [Applause]
okay so that was the demo this is that is an actual PC of the war H I reported this uh issue to many organizations I got some bounties uh most of the organizations I reported it to didn't consider it as an issue because it's an issue maybe in a dependency of a dependency of a dependency some of them recognize it some of them not but still it pro it's probably possible to uh uh execute this attack today on many repositories because of the interc connectability of the whole H GitHub actions ecosystem now how can you uh protect yourselves so you can set the GitHub token and any personal access token you use uh and you
can set the permissions to uh read you can configure Branch protection rules you can use protected tags limit outbound uh network connections from the runners to uh prevent download of malicious uh components pin actions by using hash and you can use also this repository by github's security team and you can also read if you want to understand the attack more and get more details I've published a Blog on paloalto Network's uh uh website uh which you can read more details and more examples about the uh the worm itself and that is everything today about G WM thank you