Skip to content
Securing an API - From basics to beyond
TypeScript Java HTML JavaScript Makefile Dockerfile CSS
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.dependabot
back
docker
docs
front
.gitignore
LICENSE
Makefile
README.md
code-of-conduct.md
contributing.md
pom.xml

README.md

Securing an API - From basics to beyond

This repository is used to accompany and illustrate some security vulnerabilities highlighted during the Securing an API - From basics to beyond talk.

Table of Contents

Requirements

  • GIT - Seems obvious right... - 2.20.1+

  • Docker - Docker Engine release - 17.12.0+

  • Docker-compose - compose - 1.23+

  • Maven - Dependency Management / Back - 3.3.9+

  • Java - Compilation & runtime / Back - Java 8+

  • Npm - Dependency Management / Front - 6.8.0+

  • NodeJs - Javascript runtime / Front - v10.7.0+

Architecture

We have four stacks for this demo :

Alt text

Important settings

If you run the full stack (gravitee api management & access management) in addition to the initial spring boot api & angular website, then please make sure to follow these two below recommendations :

#1: Declare two domains into your /etc/hosts by running sudo vi /etc/hosts and add following value:
127.0.0.1 apim.gravitee.io am.gravitee.io

#2: Upgrade default memory allocation to Docker For Mac (default 2, use at least 4 as described below)

Alt text

Install & Run

For the first time run cmd make init else run cmd make start or have a look to command lines inside the Makefile.

Usefull links

Play with API & login page

You can import this into your postman (collection v2.1) : (click on below link)
Postman collection

SQL injection

Target here is only to show an example of injection which is currently the number 1 in the OWASP top 10. (latest owasp report was 2017)

We will inject some sql in the form field (password field). A common injection is to input something' or 1=1 --, in our case, for the demo effect, we will use instead something' or username='admin' --

JWT Brute force

By exploring the browser console, we can see that a JWT token is saved on the local storage.
By decoding (BASE64) the token or do it thanks to https://www.jwt.io, we see that the token use HS256 encryption.
HS256 is symetric encryption, i will then use a tool to try to get the shared secret. I use here brendan rius jwt-cracker, this tool can find secret when they are too small, which is our case.
You can find others tool with different way of finding the shared secret, like trying all password included in a file instead of doing brut force

Alt text

Once we have the secret we can generate by ourself a token, use it to replace the current local storage token.
Just need to refresh and see what happens...

Play with Oauth2

Current webapp is using implicit or code flow oauth2 flow.
There's plenty of oauth2 hacks that happens in past years (facebook, google, github...), i will focus on redirect_uri.

redirect_uri control

My expectations here is only to show that we must always do exact matching on redirect, avoiding regex, wildcard & so on.
The client settings has a https://localhost:8888/login* redirect_uri, you can then change the redirect_uri with http://localhost:8888/login/../hack

Play with API Management

By restoring current mongo settings, the above API will be exposed through the API Management gateway on port 8082 and path /confoo

  • Call API through Gateway :
    curl -X GET http://localhost:8082/confoo/users -H 'X-Gravitee-Api-Key: 4d58b5f6-88dc-4253-8f80-a70aca9d2989'

  • Call API through Gateway :
    curl -X GET http://localhost:8082/confoo/users/f90df750-3069-48e6-8df7-50306988e691 -H 'X-Gravitee-Api-Key: 4d58b5f6-88dc-4253-8f80-a70aca9d2989'

Security

I used a white list on the API endpoint to allow only /users and /users/ endpoint access and GET http verb only and forbid all others paths.
If you try to access to confoo/authenticate/basic, you'll get a 403 with api key, and 401 without api key.

  • Path not white listed API endpoint :
    curl -X POST http://localhost:8082/confoo/authenticate/basic -H 'X-Gravitee-Api-Key: 4d58b5f6-88dc-4253-8f80-a70aca9d2989' -H 'Authorization: Basic bHVzb2FsZXg6bHVzb2FsZXg='

  • Path ok but not the http verb : curl -X DELETE http://localhost:8082/confoo/users/f90df750-3069-48e6-8df7-50306988e691 -H 'X-Gravitee-Api-Key: 4d58b5f6-88dc-4253-8f80-a70aca9d2989'

Rate limiting & quota

Target here is to see what happens if we exceed the number of allowed api calls.
We'll run a wrk command to trigger many request in a short time and see what happens.
this is not a benchmark...

Install wrk command

Run wrk command

Generate many requests for 10 seconds, using 12 threads, and keeping 400 HTTP connections open.

wrk -t12 -c400 -d10s http://localhost:8082/confoo/users -H 'X-Gravitee-Api-Key: 4d58b5f6-88dc-4253-8f80-a70aca9d2989'
Alt text

Most of the request will fall in 429 due to Rate limit exceeded ! You reach the limit of 10 requests per 1 seconds", we have 6791 requests for 6692 failures, mean 100 request succeed.
I select an asynchronous rate limit to reduce the latency overhead, but we can enable it in synchronous...

Circuit breaker

We will stop the API container to see what happens when we try to access to the api through the api management gateway.
Run cmd docker stop TALK_SECURITY_BACK_DEMO
As a consequence, the health check of the API will show an unavailability.
Alt text
By doing the curl, you'll get a 503 (Service Unavailable) response. The gateway will not send the request to the API until the healh check is healthy.
That means it let the API try to reboot and reply to the request immediately (better than a timeout).

Contributing

Any contributions are more than welcome. But before please pay attention to :

Talk sessions

You can’t perform that action at this time.