
Hello. I hope you can hear me because I'm wearing this mic. Nice. Okay, cool. Welcome. Uh, good morning. We're going to be playing Peekaboo with runtime. the the title. Okay, I admit it's a little bit of a stretch of imagination, but what we're actually going to be doing, right, is looking at these really traditional security things of the runtime, you know, malware and processes that might be running, uh, privilege escalation, all that, but in the context of CICD. So, I'm Patricia. I am a cloud security engineer. I really like to talk and write about pipelines and CI/CD security. You so much you can you can see that I've been here before. Just last year I was in this uh exact stage
um talking about CI/CD security and today slightly uh on the same uh vibes of CI/CD security. We're going to be talking about anything that you can do uh automated. So developer uh development workflows or engineering workflows that you might be doing within your pipelines with pipelines uh within your CI/CD platforms. What's CI/CD? What do I mean by CI/CD platforms? I mean things like Azure DevOps. Some people here might be using Azure DevOps. Some people might be using GitHub um stuff and workflows actions all of that good stuff. Some people might even be using Atlassian and Bitbucket. In case you didn't know, you can also do pipelines there. So, we're going to try to understand where runtime fits in the
CI/CD uh platforms in these CI/CD platforms. And once we understand that, we can start poking holes on them and attacking them and then um defending them. So, why am I back? uh because as I said I was talking about CI/CD security just last year and uh in that screenshot there you can see that I am explaining what a pipeline is and we're going to touch on this just in a few minutes but there essentially I'm saying this is a pipeline these are the instructions of the pipeline and uh these are the resources the pipeline is accessing so the pipeline is saying oh get some repos uh files and credentials from somewhere. But today we're going to be focusing on
that first uh resource, the compute resource. And the the reason we're going to be focusing on this compute resource is because it's just a build server. It's runtime and it's a runtime that's going to be running your pipeline, your set of instructions. So the agenda for today is a quick recap around what is a pipeline and what's a pipeline resource just to ensure that we all understand when I say a pipeline what when I what what I'm am I talking about when I say resource then we're going to see exactly where runtime fits within the uh SDLC and CI/CD context once we understand where that runtime is we kind of realize okay that runtime is my build server
uh and we're going to try to understand build servers. We're going to then uh because we understand them, we can attack them. And because we attack we can attack them, we can think about how to better secure them. So pipelines, what what's a pipeline and what's a resource? A pipeline is just a set of instructions, a set of tasks that um uh that will be run by by something. Uh and so the pipeline is the set of instructions and it also declares the access to pipeline resources. A resource is really uh anything from a code code of uh code repository files credentials even build server. Build server a build server is a very special kind of
resource. And it's a very special kind of resource because it's what's going to execute your pipeline. Now this is just X. I like a bit of a a mind map. So a pipeline, we know that a pipeline is a set of instructions. Those instructions specify tasks. Think of them as scripts, commands that are going to be run somewhere. Those instructions, more than just specifying um specifying tasks and scripts, they also declare access to resources. These resources as we've seen are things like code, files, credentials, even com uh it even declares access to compute resources and those resources represent access to some target service. So some target environment. It might be a credential to access your development or production
environment, your database, your local VM. The tasks that the instructions specify. So those tasks there they use resources and so far you have actually done nothing like all of this is done in maybe a YAML file and nothing is really happening. What you need to uh what you need to make happen is uh you need those tasks that you're specifying in your pipeline to be executed somewhere. That somewhere is our star of the show, the build server. And don't forget that the the tasks and the scripts use resources and uh for that when they are being executed those resources need to flow down to the build server and that happens as long as the pipeline h is
authorized to use those resources. Okay, so a build server is really just a special kind of resource and it's a special kind of resource because it allows you to run those pipeline tasks. So this is uh the that first point around okay what do we mean when we talk about the pipeline a resource and a build server. Let's understand where these build servers sit within our SDLC or CI/CD context. Okay. All diagrams around the SDLC's uh start on the left with developer workstations user endpoints. It's you running your code uh in your favorite IDE and doing your scripts. At the end of the day, what you do is you you deploy uh you push something into a Git repository
that sits again either in your Azure DevOps environment with Azure repos or maybe it sits in GitHub in the GitHub repos. when you're happy with it, you might be doing you might be running some CI/CD pipelines on the the the code that you've done and that might be um uh building an image for example container image and then deploying it to somewhere and to that somewhere might be one of your apps and services right like you might have a container registry you might have a Google cloud function that is using your uh just built uh image. Now both ends of these diagram are really well understood when it comes to runtime security. It's fairly well understood
that a script running uh that uh a script running in the developers workstations that might be uh coming from a a malicious source or um is excfiltrating data. It's fairly well understood that we have to have controls around them. That's why we have things like endpoint detection and response and uh vulnerability scanning. Same thing on the side on the the side of your apps and services. It's very natural to have good network controls around your um your services that are deployed there, your servers, your databases, you have database activity monitoring. However, something that is somewhat overlooked is this bit here, right? the that pipeline magic that you can see there that goes on with your CI/CD pipelines. My goal
today is to convince you that that uh pipeline magic is not really a thing and actually we need to really be assessing the security of our build servers which is essentially what's executing those CI/CD pipelines. Okay, let's understand a little bit more about uh the these build servers. Okay, so we have a build server. We already know that we can schedule tasks on it and those tasks come from the pipeline. How does uh how is it that those tasks get to the build server? Well, you have many users that have the ability to create a pipeline to edit the pipeline file and schedule uh schedule those pipelines in the build servers. Obviously, you also have some users that
might have the ability to directly access VSSsh the build server, but that's not really what we're talking about today. We're really talking about your ability to edit a file. And because of that, you can schedule something on the build server. When you do that, what that build server might be executing and doing is things like pulling some artifacts from uh external sources. That can be an npm repo, uh Maven repo, uh it can be your Azure container registry. It can do uh essentially it's pulling some artifacts more than just pulling the artifacts. After doing that, it might build a new artifact. You might build a new container image or you might build a new um a new artifact of other kinds and you
didn't need to store it somewhere. So, we're going to store it back in one of those artifact stores. The real server is also um uh a point where you can say oh um deploy something to my target environment. So think of uh your Azures, your cloud service providers that you're using and you might have a cluster running there or a server or a database and you are configuring these uh these infrastructure elements there and many times actually what those services are doing there those servers those applications they they are using the artifacts up there. So you can see that sometimes you might be pushing artifacts and those artifacts are being used um in in your in your environment.
Funnily enough, uh build servers can also uh be there because if you're self-hosting your build servers, which happens a lot, um they they kind of become part of your target environment. This kind of a mirror thing there. Um okay, so why should we care? Why should we care about build servers? You can see kind of this pattern that that um everything seems to go into and go out of build servers. And and that really means that at some point you all the access that you need, all those credentials, all those identities that you need to impersonate, they're going to be accessible from that build server. And you need that to happen because you need to do your
continuous integration, continuous deployments, workflows. And the the thing is even though the build servers have these um this amount of access, sometimes they are they feel a little bit under appreciated. So we're going to try and see why we should appreciate them more. And we're going to do that by uh attacking them first. Okay. Um so let's take the the diagram from before and let's think about two things. Number one, how would anyone would even access these build servers? And number two is okay, even if they do, what could you go wrong? So we already kind of touched on how you can access these build servers. Just the fact that you have the ability to edit the pipeline
file means you can uh schedule something there. And humans might make mistakes. So it could happen that they accidentally are uh pushing some u malicious uh jobs, malicious task, pipeline tasks. It could also happen that you have an insider threat or that uh someone um uh that that attacker can compromise your user's credentials. And what this translates to is you now have tasks that are being scheduled and uh but these tasks are potentially malicious and they might be pulling potentially malicious artifacts from those those registries do something bad to the build server. uh they also might be pushing malicious artifacts back to those uh registries and artifact stores and again they can be uh directly
affecting your target environments which will maybe uh also pull the malicious artifacts that maybe you overrote right um so this is how you can uh start to to attack and that's what can can go wrong again we're not solely talking about the SSH access that the you might think we're talking about just the ability to schedule a pipeline, a job, a task means you can um you can affect the build server. Let's let's prove it right. We can choose any one of these uh platforms and I'm going to choose Azure DevOps uh to show this uh happening. So what I'm showing here, what I'm going about to play is uh a single pipeline that has
two jobs. One of the jobs, the first job, just as an example, I'm scheduling it in a Microsoft hosted build agent. That's uh a VM that runs in Microsoft. Okay. Um it runs and then it gets deleted according to them. So that's all good. Uh the second job is run in my self-hosted build server. This is a machine in my environment. Okay. So uh we can see here that's what I'm doing. I'm the first job Microsoft build agent uh build server and the second job I'm running it on my machine and I'm actually just running some Linux commands including I'm creating a chrome tab entry. So, chronabs uh are ways of you scheduling kind of automated tasks.
And I just created uh chronab entry to sleep for 300 seconds. It doesn't matter. You could do like a bunch of things. I just chose a very easy way of uh now showing you what I want to show. Okay. So, my self-hosted build server was listening for pipelines. Uh then it when it got that pipeline uh that job that was scheduled on it, it ran it and by the end I had a chrome top entry for sleeping with 300 seconds like sleep 300. It's just a Linux environment. Okay. So and I essentially with a job ran commands on it. Now I want to show you what happens if I ran another job from another pipeline in that um in that
build server again. And uh here I'm running that second job. And the first thing that we can notice is that the sleep 300 is still there because it's still my build server. And what I did I added another prompt app entry this time to sleep 150. And uh what what we can see then is that those uh process files and processes from uh the previous executions of the pipeline of previous executions of the the jobs um persist across jobs. So this breaks pipeline job isolation. So that means if I run a pipeline and then someone else runs a another pipeline, my the first pipeline that run can influence the the second pipeline's execution and you can be very creative
in the kinds of attacks that you that you can have there. Okay, so recap, I was listening for and running that second pipeline job and then when it ran, I got a a sleep 150. So now I have a sleep 300 and a sleep 150. Let's do another scenario just really to to pin this down. Let's now schedule pipeline from another Azure DevOps project just uh to to to brief you on Azure DevOps projects. There are usually quite a good boundary in terms of isolation. the um I Microsoft doesn't even allow you to share things like variable groups across project because there's supposed to be that good boundary. I have my project, you have my
project, they should not be uh crossing over. However, if you're using that same build uh server, what I'm showing here is that from another not my project, I'm scheduling a pipeline on that same build server. And what we can see then is, oh, I can still see sleep 300, sleep 150, and I'm going to schedule yet another sleep, a sleep 75. Um, and this really what shows us is it that it's possible to break the project isolation. That concept that you might have thought that you had, oh, my project is completely isolated from yours is not really true because again the build server is that one funnel thing where everything ends up ends up with. Okay. Uh well then uh
that was probably the the longest demo. Um and what it showed is that you can really access the host um but just by scheduling a task. And uh believe me when I tell you that more often than not you're going to be rude. Okay? Uh so don't be shocked when when when you find that and you try to do that. Couple bonus bonus tips. Okay. Really quickly um I just want to say try to reduce your attack surface when it comes to having credentials present in your um in your jobs when you're executing something. there's ways that you can reduce the time where for example your environment variables have a docker credential and the other um the other tip here that I
have is when you're using a service for example if you're using Azure container registry services um if you set it up like two years ago just revisit them because what happens is as time moves on there's new security settings that you uh you should be looking at. Okay. Um, don't ask me how I know that. Well, maybe uh I wasn't really using the uh the right security settings. Um, this is a little bit of the why you should reduce the scope. There's ways you can do schedule jobs that uh one of them u essentially means that your Docker credentials are only available for doing the specified tasks. But the other way uh means it's going to be available
through all of your pipeline. So just yeah I'll I'll share the slides later. You can you can have a look. Uh now you're going to be challenged if you're presenting something like this like you may be presenting uh a project to improve your CI/CD security. Uh you're going to get told inside a threat really I mean we that's a risk we need to live with it. Or uh if it's about the count of compromise, you can also um have there's the argument that says well we have a bunch of um extra controls that that's really not a a thing we we are worried about. So that's when you need to explain that there's things running
in your pipeline that were not written by you. So you need to think about what tools and packages you are using, where are you pulling them from, and how are you using them. So I'm going to I'm going to show you um how you can seemingly use a trusted tool uh called check off, which is a policy code tool that that's a tool that is many times just expected for you to use. Okay. So, nothing nothing wrong with it, but you can use it in a uh in a way that is sort of insecure. Um, and I'm going to show you this using Bitbucket this time because no one uses Bitbucket. I feel like we we needed to see it. Um, so, uh,
Tesl I I really like this scenario cuz u that's kind of what I can do um when I'm pretending to be a hacker. Um, what I'm doing here, right, is this is a pipeline file. It's really small, but all I'm doing is running check off, but I'm running check off with an extra check there. And that all that does is pull someone else's file of custom checks, custom compliance checks, and uh just runs it. And this actually does what I wanted it to do. So what the developer that created this pipeline wanted to do was oh I want to ensure that my um that my uh docker image when I created has the right labels the docker labels and it
has okay that's fine but what the developer didn't realize is at the same time as the checks were running um the attacker was able to exfiltrate all the context from that build server all those environment variables, all those files into a g a private GitHub um uh repo that they own. Okay. And all of that with I know I don't know how many lines that is, but you probably can get it really condensed. That's like that's Python codes just running the commands I need. The the point here is like you never know actually pretty sure some of there are some people that have or had this kind of uh situation happening they just don't know that it has happened
because you never know you're never going to check. Okay. Uh that was the the second hardest bit uh and we got it got through it. So just remember that when you're executing anything in your pipeline um trusted on trusted you might be running code and that code is going to inherit all the access your pipeline has. Okay the last kind of uh little u section that I have here is about sharing. We've talked about sharing packages and tools and open source stuff that that's um that's where most of the supply chain um security uh bits come from. But there's another kind of sharing um that I wanted to to to highlight here which is when you have
things like extensions or templated pipelines, right? So these templates these are just extensions of uh capabil. So if you have your pipeline and you use an uh an extension or a templated pipeline by someone else, you are just importing their code into your own pipeline. I'm going to show you an example with GitHub this time. Um that should really make you think should I trust these uh templates uh by default? The answer is probably not. Okay, but I do say that it's very much easier said than done. uh it's really hard to to balance here. Okay. Uh so let's talk a little bit about GitHub actions which are the these templates. Uh we so GitHub
actions are kind of pipelines but many times um they are frequently shared. Okay. Uh it's a very communitydriven environment. Uh they're quite simple to sh to share more uh more so than Azure DevOps templates pipeline templates. they are also a little bit underestimated. So there's a really good blog post by Eigor there and he calls out a few common security risks from from these GitHub actions. One example that that he gives is u just by using a seemingly innocent uh GitHub action. What you don't realize is that you might be pulling codes that you're not expecting. that GitHub action that you're pulling. You might say, "Okay, no, I've reviewed it. It's fine." But do you know if that GitHub action there is
calling other GitHub actions that you have no idea? Is it using dependency pinning? Uh is it a hash commit or a commit of a hash or um uh overwritable tags? What this kind of translates to is look, when you're using templates and code that you haven't written yourself, it it's a little bit of a supply chain hell. And if you decide to ignore that completely, something like that is going to happen to you, right? Uh we had TJ actions in the beginning of the year. Uh which was again a very used very widely used um GitHub action. It got compromised. It got malicious code that essentially was um leaking your credentials into uh repositories in this
case public repositories. So uh mental note number four uh conven con convenience helpful uh but it can become a vulnerability if you uh if you don't put the right controls around it okay that was attacking now uh let's talk a little bit about how can we defend these build servers there's a few things that I want you to keep in mind keep in mind isolation u the performance of your build servers uh and the blast radius when when then considering these um considerations these key considerations. Okay. So number one thing that I would think if I was to improve the security of my build agents is am I sharing my build my build servers. So these build servers can be
shared maybe across teams and across environments and across projects. It's easy to get overwhelmed and be like, "Oh my gosh, this is so hard to um to to separate." Uh so what you can do is uh just go for a simple approach. Okay? Don't let don't let uh the perfect be enemy of the the good enough. A good start is just separate stuff that you trust from stuff that you don't trust. for example, production uh where you run production workloads where production credentials end up there versus everything else. I mean that's be already better, miles better than what you if you're not doing any kind of segregation. The second thing here that I'm talking about is about this build server reuse.
Are you reusing build servers across pipelines? Uh we've seen that um different pipelines can uh influence following pipelines, right? So are you um are you discarding the build server every time? Are you cleaning it up? It's it's a really hard balance there because if you're cleaning the the whole build server, you might lose some benefits and it might affect your performance and that's going to show uh in the the faces of the developers and engineers that need to wait for that pipeline to run. Um, so because that's a hard balance while you're kind of deciding what to do, I'll just what I would say to you is just ensure that you have good endpoint detection um
and response there. Okay, just really focus on that uh on what you can do now to uh at least detect if something is going on. And lastly, but definitely not least, okay, it's one of my favorite uh controls is uh network access control uh from these build servers. So, and you need to think about what are my build servers accessing and do they really need access to uh I YouTube and Facebook? Maybe not. So, one thing that you by the way, it's really hard. Um, I've done this. Uh, I' I've spent a lot of time looking at what are my build servers accessing. It's really hard to pin down. So, what I my suggestion to
you is just start by discovering what are they accessing and uh try to transition into a allow based model. Okay. Um, maybe to put this all together, just remember that engineers are your best friends here. It's not security that's going to help you uh balance security and performance. Engineers understand the security risks that build servers bring and uh they they will help you get to that balance um if if you work with them. Okay, it's perfectly reasonable to ask, okay, what if I don't host my own build servers? Uh, there's some potential benefits for sure. You are outsourcing the management of these really complex machines. Um, you're also getting some security best practices by default. Um
and obviously it's less likely that you actually get uh persistence in your environment because well you're not using your environment you're using using someone else's. Um but please do consider the potential concerns that you might have things like do you have the appropriate egress controls or can I use those um so do you have the ability to restrict where those build servers that are not managed by you are accessing? Um, do you have the right monitoring? And again, you can say to me, well, I'm not doing monitoring now on my self-hosted build servers. So, I mean, it's a good point then, but uh, just consider that. Uh, obviously, there's a cost and in red right there, don't
forget that at some point your credential are still going to be there. So, there's no running away from the fact that that build server at some point will have your credentials. So mental note there is that um there's definitely a place for not self-hosted build servers. Um just understand you uh understand the the the trade-offs. Okay, this is a final slide as you can see there with a smiley face. Um some some conclusions. Okay, you can use CI/CD build servers uh for um uh lots of abuse. Okay. Uh things like bypassing endpoint controls uh running unauthorized uh workflows, things like crypto crypto miners and stuff. Um persisting your environment and silently exfiltrate uh credentials. That's
something cool that you can do. You can just put a listener there. Um you can even temper with security tooling as in you can turn off security tooling and yeah because don't forget most of times you are root. um focus on what can make things worse and at the same time if you fix them can make it a lot better. Uh things like if you have unrestrict unrestricted internet access that's a no no. Uh it's really hard to fix but try. Um how long lived are your build servers or are they super ephemeral like they run one job and just get deleted. um try to segregate at least production and non-production. That's kind of my go-to
usually. Um and also have some um considerations around the governance of the credentials of what your pipeline can access, right? Cuz don't forget that your pipeline needs to be authorized in order for the those credentials to go and to flow down to the build server. and just yeah keep calm and treat CI/CD runtime um kind of as production cuz it is production and yeah that's that's all I have for you today
fantastic I think we've got time for a few questions if that's okay Patricia right who would like to go
Thank you. Really good talk. Um the the delivery spoke to very much is one way or the other especially with regards to self-hosted versus uh ephemeral. Um, how much do you consider breaking down the pipelines, say CI versus CD, you know, having your code compile and unit test run in an ephemeral agent and then a bit more rigor and internal, you know, structure for deploying the code that has gone through a promotion pipeline that might also yeah be running internally. So, >> uh, yeah. So that that's a a a great uh question and it's it's about maturity, right? Like if you're just if you don't have a big team and or or maybe you have
a two too many uh pipelines running already, it's a huge amount of work. Yeah, just try to separate them like one way or the other. But uh something to to do you talked about CI you talked about CD there's also things like uh that um in my company we're looking at now which is things like are you running tests on this CIC pipeline so the test pipelines those things we are going to need have different requirements in terms of network access in terms of packages that I need to access and they probably don't need a lot of uh production credentials so that's even another group of things. I I do think that um for a
idealistically you would be separating those CI from then the CD part which is kind of probably what you really need to care about because you're going to have the credentials for production for uh development etc. And then the tests and I think those are like kind of three groups that you can separate them on. So yeah, >> any more questions >> over here? testing. There we go. Hey, thanks for your talk. For nonhosted build servers, when it comes to logging, what are your priorities in what you would like in your logging? I know it might depend on where things are self-hosted, but I've come into the, you know, problem that I need more verbose logging or less
verbose logging. So, knowing what your priorities are, what you're interested in, um, I'd love to know more about. So uh right now um uh I I do feel like uh whatever logging there is it's not being you need to have those detection kind of use cases on top of that logging else it's just going to be very verbose but if your sock doesn't doesn't understand how to connect those those logs to the u to a potential like kind of uh exploitation. uh it doesn't matter how much logging you do have. Uh something that can help uh uh that we're looking at now is things like if you're using an agent like a runtime agent uh
that already allows you to so you deploy that go that runtime agent. I don't know if you're using I know Microsoft Defender like runtime stuff. Um it it it's just runtime as normal runtime. It's going to require you to do some quite custom potentially custom detections uh based on the logs. Uh because it's such a wild west uh environment, right? because you are literally allowing people to sometimes uh escalate. Uh but it's for a a good reason. Um so um in terms of the level of logging, I just obviously some I don't have like a an actual answer for that. Uh but I would say just just think about the use cases and think about what you want to um to
detect. Thanks. Thank you. Any more up front here? Um, great talk. Thanks very much. Um, so in kind of relation to the salt component and maybe businesses have had CI/CD set up historically, but maybe haven't had a security focus in mind when developing it. what would be your kind of starting point in terms of doing a threat model and threat hunting assessment to try and gain an understanding especially to try and identify where CI/CD could be abused and particularly um cause then I guess an exploitation point and then yeah go from there. >> Uh sure. So uh the first thing that I would that I would say is um arrange internal calls and kind of just explain
how these things work because um it's sometimes the lack of context that these machines when you're running a pipeline. Oh, it's just a pipeline. It's not just a pipeline. You're actually pulling all those credentials. So just sitting down and explaining as a like initial kind of call, initial meeting uh and then showing uh things going wrong. showing how you can exploit these things because that will uh motivate people to uh learn more about about how to to attack them especially if if security people like to hack stuff. So they're they're going to be motivated um and then start talk to talk about how okay what do we need to do to in order so those use cases around
okay this can happen how can we detect these things um one other thing is do include your engineering functions if you have uh engineers that are working on u setting up pipelines do include them because they they still kind of oh they realize okay I see how I see how that's a threat and why we need to be careful here >> anymore oh one more okay
thank you for the talk was really good um I've heard the argument that as soon as you open up the developer to putting whatever they want in the pipeline whether that's going to be applied to something that's self uh self self-hosted or hosted as a service, you're opening the attack window too much. Have you got any recommendations on controlling what an attacker, whether that's internal or external, can put in the pipeline to prevent them running something? If I put forward a scenario, let's say you allow developers to request and run commands on containers, which is quite common in in your build pipeline, how do you enable them to run a container, but stop them running a
container with a privileged flag or something that would give them access to the underlying host's memory? >> Uh, okay. So, uh, that's a challenging question, but so the there's two things, right? There's the the fact that people can just run uh there's ways and ways that you can run pipeline jobs for example. So you can run them directly on the host or maybe you can force people uh to run them in a a container inside a container an isolated environment. So that's already helping right but I say that again you probably can escalate from inside that container though it is about adding layers of uh barriers right uh to in order to do that. Um so um and
but that really just helps kind of containing and isolating that run to to the that special job. Um, when it comes to the job itself and what the the user is doing while that's running, that's what to me that's where you need that detection and response really tuned down to to the to to the to the build servers. And that's hard. >> It's not an easy one. >> It's not an easy one. >> No, it's not it's not an easy one. uh but that's why it's it's a bit of a you need to collaborate with your and if you have detection engineers uh your sock and everyone needs to understand what are we trying to do here but also uh and
I keep coming back to the engineers because if you just go and explain CI/CD to uh socks uh sock analysts and um detection they'll be like what you can run whatever you want I'm like yes but but it's not that simple because you need to cuz it's CI/CD and it's supposed you're supposed to allow your engineers to to do stuff. Um, it's just a hard one. >> Thank you so much. I think that's it. Yep. Okay. Listen, thank you very much. Excellent talk. Cheers.