Abstract
The minimum viable security (MVS) approach, enables us to easily bake security into our config files, apps, and CI/CD processes with a few simple controls built for Python applications.
In this talk we will focus on five critical security controls that will be integrated as part of the CI/CD pipeline: Bandit for static application security (SAST), Gitleaks to detect hard-coded or insufficiently secured secrets, Python dependency checks (SCA), infrastructure as code (IaC) and ZAP for API and dynamic application security (DAST), in addition to custom controls to ensure proper enforcement of MFA via Github Security. These controls will provide a foundational framework for securing Python applications, from the first line of code, that will make it possible to continuously iterate and evolve our security maturity, for advanced layers of security that often comes with time, as well as increased experience.
Code examples will be showcased as part of this session.
Transcript
This transcript was autogenerated. To make changes, submit a PR.
Hello everyone, and thank you for attending my talk about minimal viable
securing for Python applications. The goal of this talk is
to share with you an iterative approach to security called minimal viable
security and how to practically implement it, taking as
an example a fast API based application that
I want to secure by adding a few critical security controls.
So let's get started. But first of all, let me thank the
42 organizers for a carefully planned event full of excellent
topics and speakers. In these challenging times, it's far
from being granted. So well done. Let me now briefly introduce
myself. I'm David Melamed, one of the
cofounder CTO CTO at JIT, a dev first cybersecurity company.
I have a phd in bioinformatics and I'm passionate about technology and
security. For a few years previously I worked as a
senior technical leader in the city office at Cisco and before that
at Cloudlock, where I have built cloud applications at scale
and led some strategic projects. I love to share my
knowledge and experience, and in the past I was also involved in a few
communities like Python and AWS in Israel.
So when you should start to
care about security, I'm sure that's usually not the first thing that
comes to mind when you start building a new application.
If I ask an engineer what is his main concern while writing
his application, he probably would mention functional bugs and performance
way before security. And that's also the way startups are picking up
their priority. You need to deliver business value to survive
accepting the risk of security, at least until your customers start
asking about it, or when you face your first security incident.
That's mainly because security is hard and yet it's an ongoing
concern. It's not something you can deal with once
and tick a checkbox. It's a journey and a continuous investment,
but its cost is lower if you start managing it on your first day,
not necessarily handling everything, but at least be aware
of what needs to be done so that you don't spend your time catching up.
But don't try to bowl the ocean on your first day.
Start minimal and add security iteratively.
Let's take an example. This is a typical cloud application
starts with the manager granting the developer access to committee's code.
The code is stored into some SCM like GitHub or GitLab.
Upon commits, the CI pipeline is triggered and after
merging the code, the application is deployed in the cloud
provider. In our case, the application is containerized,
so the CI pipeline builds the docker image and stores it
into the container registry, which is pulled by the microservice at
runtime. Microservices states are
then persisted in database and are committing with third party
services and between each other and are exposing
through an API gateway some external endpoint for external
users. Now this environment has
multiple risks in each area, and I want to mention
a few. One. So first of all, if you're looking at the
grant access to the manager, well let's say that
right now he granted access to the developer, but let's say the
developer is leaving the company, he may forget
to remove his access and therefore there may be some
unauthorized access for the developer itself.
Well, you have the risk of credential theft of
course, but also the dependency type was quoting
if he mistyped name of a package and now
he got some malicious package inside his code.
For the code itself you have code vulnerabilities that are
really common and infrastructure misconfiguration
that are part of infrastructure as code. In the
CI CD pipeline you have supply chain attack and credential
steps as well. And in the cloud provider
and the runtime you have a lot of different risks,
ranging from data leakage to corrupted
data for multitenancy cases and data loss
and leakage also, and finally for
the users you have unauthorized access and mainly middle attacks. So a
wide range of risks and those areas
that are showing the different risk can actually be grouped in
different layers. So you have the layers of the code,
the pipeline, the runtime, the third party and
the operations. Now look
at the chart here and it will
show you all sorts of security controls that you need to add along
the STLC. But if you start with
a minimal viable set of controls and iterate from that,
it seems way more likely that you will be able to succeed in improving
gradually the security of your product.
So what does it mean? Well, like a
minimal viable product or mvs security can start with
something small. In order to deliver a product with enough critical security
controls to be viable, you won't embarrass yourself in
front of your users. This is an example of
list that includes some critical controls. This envious
approach is that something that we will follow for
the rest of the talk, and I will demo a few of them that are
highlighted here in this talk.
What's their goal and how to add them in your CI CD
pipeline. So I will talk about static code analysis,
secrets detection, dependency check, API security
and MFA for GitHub.
So this is the application that I want to demonstrate
today. It's a movie applications based on a fast
API framework that mostly return
a list of movies and the name of the actor that
are playing in a specific movie. It's a containerized application
that is providing a couple of HTTP endpoints.
Now I want to
talk about how to secure this application. For that I
will show you and demonstrate how to add those different
controls. So you have bandits
that I will use for static code analysis, Gitlix for
detecting secrets, kicks for the infrastructure safety
for these dependency check zap that will be used
for API security. And finally, I will write some custom
control in order to check for MFA in GitHub.
But I want to dive a little bit more deep into
each one of these controls. So let's start first
of all, static analysis. These is used to detect vulnerabilities
in code using existing patterns. For this demo
we'll use bandits which scans Python code.
It's an open source project with more than 30 built in rules to
detect vulnerabilities. Next, for secured detection
we'll use Gitlix, which comes with almost 100
Regex expressions for the common popular
third party services like AWS, Slack,
GitHub, and so on. If you have some
infrastructure as code that is expressed as code,
then it should be also possible to detect misconfiguration
early by scanning the code instead of having to
look for misconfigurations at runtime.
One of the popular tools here are kicks.
I'll not show that specifically in this demo,
but it works in a very similar way than the bandits
that I will demonstrate. And just for the
record, kicks supports many infrastructure types from cloud formation,
terraform, kubernetes, Docker and ansible, and it
includes more than 2000 built in queries.
Next we want to check for vulnerabilities in our packages, and for
that we'll leverage the USS project called safety.
It detects publicly disclosed vulnerabilities that are contained
within the project dependencies. And you have actually two versions,
one of these open source with a monthly update or commercial with
something that is updated more frequently.
Next, I will want to talk about runtime monitoring.
So some vulnerabilities can only be detected at runtime,
for example some of the cross site scripting and some
of the SQL injections. So for this demo we'll
use the OAS project called
Zap for Z attack proxy that includes
about seventail binge and rules, and uses
these open API specification in order to pull the different endpoints
that the application is exposing.
And finally, let's talk about the SEM security. So let's say
in this case GitHub security, because with rising supplying
chain attacks it's critical to ensure that your GitHub service and the
pipeline are also proper secured.
And for that the minimum would be to start by making
sure that all your users are enables MFA in all
the services and specifically into GitHub. So for this
demo I will write a custom control that will
basically list these GitHub users that don't have MFA enables.
And this control will fail if the list is not empty.
And that will leverage a token that I will
add to the GitHub secrets in order to get access to the GitHub API.
So now we talk about that. Let's go into the demo and
just for the record, everything that I will show you here is available
in the publicly repository that
the address is mentioned here.
Okay, so the first thing that I want to show you is actually the application.
So it's a simple application.
This is the main API. And you
can see that it uses database movies Db
that includes some data from IMDb and
basically you have here a docker file in
order to build it. Okay, it uses uv
corn in order to run it.
It includes some secret for aws that will probably be detected
by my control.
And in terms of the API itself,
the first endpoint is returning the number of movies in database.
The second one is used to look for a specific movie
and then to return the list of the stars in the
movie. So let's see it in action.
Let me start by running my application. So jit,
okay, so my application is
running on port at thousand and let's now
go to the browser.
So if I'm going here in docs,
I should be able to see the different
endpoints that my application is exposing.
And now let's just make sure that it works properly.
If I'm going to movies count, I'm securing the number
of movies in the database. If I'm going to movie
title equal Titanic like
that,
then I will get the list of all the movies
with the different release dates. Let's say I want this one,
so I'm going to this and
I want the list of stores in it. This is
the list of the stores that are playing in this movie. So the
API is working correctly right now
let's go back to the code. So these are
the requirements to make it work.
Pay attention. I added a special here requirement of
a package called Alexa that has some vulnerability.
And this is for the purpose of these demo. But you can
imagine that you have any package here that may have some vulnerability.
Now I want to show you also what I will use
in order to implement all
my controls. So this is these GitHub action workflow
called security Yaml that is triggered on push.
And now I want to show you the different jobs
that are included here. So first of all you
have these SAS jobs and this is using action that
is encapsulating the bandit package
of Python. And here I'm adding a few parameters so
that the output will be in JSON and in a
file called output JSON. And then I'm using this action
called upload artifact in order to upload the
results into the GitHub artifacts. And basically if
there is any vulnerability here that bandit will find
in the current folder, then JIT will return an exit code of one.
And so this job will fail.
The second job is for secret. And here I'm also using
another built in action that was written
by the guy who
actually wrote the project. And so here
it's these same thing. If it fails, it returns an exit code
of one and then the job will also fail.
The third thing that I'm doing here is using
zap. So it's the API scanner.
And for this, what I did previously is
that I packaged my application
into a container using the docker file that was included
here. And basically I uploaded that to
the GitHub container registry. And here what
I'm doing is that I'm using the option of
service container that GitHub action is providing.
So I'm loading my container here as a
service. I'm making sure that it's working
so it's loaded properly by adding a health check command.
And I'm using the count endpoint
to make sure that I have some results.
And here I'm mapping the port
80 to port 80 89.
And then in the steps of the job I'm using the
built in action provided by zap.
And here I'm providing these fact that I'm using open API and
these is my target. As you can see I'm using localhost
with the port that I specified here with open API JSon
that is provided by fast
API in order to sca
my API and these also I'm specifying
that I won't fail action true, meaning that if there are some issues then
it will return an exit code of one and my job will fail.
Next sca I'm using here safety. So I'm
installing safety directly and I want
to scan these requirements TXT and return
a JSON format into a files called Alphabet
JSoN. And then I'm uploading that as an artifact.
And finally this is my custom control. As you'll see
it's very simple. I previously created a
token called my or
token here that I stored in the GitHub secrets. And my token
has a scope of admin read so that I can call the API for the
list of users in my organization.
And this is a simple code in JavaScript, not in Python though we could do
the same thing in Python, but here we're leveraging the GitHub script
action that is built for JavaScript. So basically
here I'm just calling an API of a list member
for a specific organization with a files
of two Fa disabled. So this will only return
results in an array if there are users that don't
have MFA enabled. And so if this is
the case then for each one I want to show
a message with the user don't have MFA enabled.
And then in that case I want to exit with one,
otherwise with zero. So that was
the main file. Let's see it in action inside
GitHub itself. So let's go back to the browser.
And this is these repository that I talked about
here. You can see the requirements, you can see the main
code of the application. These is
the main code of these application. Everything I showed you before,
these are the workflows here that
I just prescribed. And now let's see what happened.
Jit already ran once, so let's see what happened
here. So basically all
the jobs failed. And this is what I expected because this is
a goat project. So it's flowed by design.
And let's see each of the results. So let's
start with these first one. The first one is sas, so it's
running bandit for this one. It's returning
directly the results in a file and as an
artifact. So let's go back and let's see the results.
So this is the artifact, I can download it, let's download
it.
And now I want to see
the results.
So let's see the results in the terminal for example.
So here I have my output and I
want to do like that output. And what
I can see here is that I
have three issues that Bendy detected with the medium confidence.
If I'm looking at the details, I will see that it discovered
a few SQL injection, right? Possible SQL
injection vector. Okay.
And the reason for that, if I'm going back to the code,
is that in the code I
actually left this part as
part of formatting. So potentially
someone can introduce some malicious input here,
especially because these comes from the
user input. So basically there's SQL injection
here possible. So this is what Bandit found.
Let's go back to these browser and now
let's go to the secret one. So the secrets,
let's see the results here. And we can see that,
yes, basically there is two secrets
that have been found that are redacted,
but I can find exactly, this is the AWS key.
Okay. And so I can go and not only remove
the key because that won't be enough because now it's on GitHub,
so you never know what can happen. But I need probably to recycle
the key, right, so disable the key and create a new one.
The third job is the API security scanner.
So it's a zap scan. So I could read here
the results. But basically Zap
is also uploading some artifact and also
it's creating an issue here. So I can check the issue here.
This is probably these last one. Let's go to the last one.
And as you can see, it found also some SQL injection as
well as a couple of other issues that I need to
fix in my code. Okay. And as you can see,
what happened here is that Jit tried different URLs and that's basically
based on the open API specification
that the application is returning.
So if I'm coming back here, that's one of the features that
Fastapi is returning here I can see the open API specification
which returns the list of all the endpoints that
this API is returning. And that helps zap
find the exact targets that it
needs to scan. Okay. And that's how
it knows that there's a movie title equals
and this attempt to do some SQL injection.
Let's go back to these actions here and
see the next thing. So now we're going
to dependency check. Dependency check also
is returning some artifact.
So let's get here to see the artifact itself.
Okay, so that's safety. I will also download it and
let's show the results. Okay,
yeah, now let's
see what I have here. And this is the Alexa
package that I added in my requirements. So that's a package
that helps writing Alexa skills, for example.
But here the problem is that it
had some PI openssl vulnerability. So if I
want to get Jit fixed, I need to bump the version to
the latest one probably, or one of the latest one, which is at least
00:40 and
now I can also check the last of the controls.
So this is the MFA checker.
And as you can see here, it failed. And it tells me that this
specific user doesn't have MFA enabled. So also here
a very simple fix is actually to go and tell this
user to enable MFA so that the checks will pass.
Okay, so these are four different actions
that I added in my four different actions that I added
in my pipeline. Basically. By the way,
the MFA checker shouldn't be triggered on push because it doesn't change every
time you're pushing some code. It should be run on schedule, but that
was just faster to show you all the different
controls like that in one place.
Okay, so coming back to
the slides a little bit,
what I show you is that there
are a lot of securing controls that you can add to your pipelines and
there are a lot of different areas. These you should add some controls,
but basically in order to be able to secure your project from
d zero, what you can do is sast
with something minimal. And this something minimal is
an example of something minimal is what I showed in this toque,
taking as an example a couple of different controls
and how it's easy to actually implement them and add
them into your GitHub action CI pipeline.
Of course it works with other type of
CI pipeline. Jit can work with GitLab or with bucket with any
other CI pipeline the same way. These are
actually, most of them are built in actions,
but the code is available so at
the end it's just containers. So you can definitely run them any
place you want.
Here at JIT we also follow the same mvs
approach. We built a continuous security
platform for developers in order to help them secured the applications they are
building, automating these, integration of these control in
your environment and removing the code and unifying
their interface. And if you want to know more about us
then go to our website, JIT IO. If you
want to test our platform, send us a quick email.
Jitmein at JiT IO and
if like all of us, you want to help developers with these security
these, you're more than welcome to join our team because we need
you. That's it. Thank you very much for your
time. I hope it will help you increase the
security of your application from the zero. Don't wait any longer
because you can start already today. Thank you very
much and see you soon.