Threats of leaked Github Personal Access Tokens : Private Github Enumeration, Backdooring Apps and Stealing Secrets from CICD systems

We have seen scenarios and real world impacts of secrets / api keys in public version control systems like github , gitlab. They have contributed to serious breaches, leaked personal information and so on. The risks of a leaked token is already serious but it is even worse incase it is a Github Personal Access Token. I will demonstrate in this post about the impacts of a leaked github personal access token.  As leaked Github Personal Access Tokens are on rise in public repos in github, this post is to educate about the threats and risks it poses if they are leaked. 

Personal access tokens are an alternative to using passwords for authentication via commandline or github API. Github personal access tokens are popularly found in configuration files where a developer may need to clone some private repositories. Private repositories are not visible to users who don't have right authorization to view. Take for example this url https://github.com/hellctflife/myapp . It will throw a 404. 


Hence it is not necessary in github if any repo url throws 404 is an indication that repo might not exist. A private repository will also not appear in the profile of the user's repositories.

We will start the scenario with two assumptions. From a public repository :

  • We found a leaked personal access token
  • We found an app running on a public url for our demo  http://myapp2-env.eba-axbm9z3d.us-east-1.elasticbeanstalk.com/


Github Enumeration

First let us try to check if the token is actually working or not

curl -H "Authorization: token LEAKED_TOKEN" https://api.github.com


If the token is wrong or it has expired it will throw an error

{

"message": "Bad credentials",

"documentation_url": "https://docs.github.com/rest"

}

Now that we could validate that the token works, we can now start user enumeration phase. We will start with finding their username, the repos he/she created, etc. Lets find who issued the token. 

curl -H "Authorization: token LEAKED_TOKEN" https://api.github.com/user



The juicy information uncovered is the username(login) : hellctflife 

Next we will try to find all the repositories created by the user. Please note as I am creating this demo and I already know where I have kept the target application. Hence I am going directly for the repo owned by the user. However in real world scenario it is good to look into other orgs/repos etc which the user has access to. It is always possible he/she might be a contributor to some private repo and may or may not be repo owner. 

curl -H "Authorization: token LEAKED_TOKEN" https://api.github.com/search/repositories?q=user:hellctflife -s | jq '.items[].html_url'


The juicy information uncovered so far is the username(login) : hellctflife , the private_repository of the application: https://github.com/hellctflife/myapp . As discussed earlier this private repo is not visible when you will access the profile of the user. 

Backdooring Applications

The myapp  repository is our main target. We already had the token and now we need to verify if the token has enough privileges to clone the repository. We will clone the repository and as it is private we need to provide the username we found and the access token (as password) which we had since beginning.  

We can also look for various branches , tags , etc and see which one could be our main point of attack. Here our interest is the master branch. 

As the application is running on python, we tried to insert some backdoor code. Here we are trying a simple system command to list the contents in the current path. Of course we could try some reverse shell and other cool things but this is just a small proof of concept and not a real pentest. 

Now we just need to commit the code and we also need to be lucky if the token has write / modify capabilities. A successful operation will push the code to master branch.

As for the demo there is a CICD automation in place, the new changes are pulled and deployed. If our attack is successful we can see the result of the command execution of the backdoor.


Attacking CICD System 

Another interesting point of attack is the CICD systems. The CICD build systems can be within the infrastructure and can be used for pivoting and other other possible attacks. The CICD systems also stores various configuration values and secrets which are injected into the environment during runtime.

As for travis, the configuration file is stored in .travis.yml 



We can see in the travis.yml file that there are no hardcoded values for aws access key and secret. Instead we find variable placeholder. This means that the values are configured and set in the Travis web application and its injected into the build containers as environment variables in build phase. 

 access_key_id:
    secure: $AWS_ACCESS_KEY_ID
 secret_access_key:
    secure: $AWS_ACCESS_KEY_SECRET

The attack we can try here is exfiltrating the environment variables from the build system. We try to encode the data as base64 and exfiltrate over http post request. To do this we will add another backdoor and this time to travis.yml file. Line 7 is our backdoored code. 



At the same time we should have a listener ready to accept the incoming http post request from the build server.



From the huge base64 payload we can find out the aws access key and the secrets

"base64payload" | base64 -d 

<SNIP>
APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=1
PWD=/home/travis/build/hellctflife/myapp
JAVA_HOME=/usr/local/lib/jvm/openjdk11
CONTINUOUS_INTEGRATION=true
LANG=en_US.UTF-8
TRAVIS_PRE_CHEF_BOOTSTRAP_TIME=2020-06-24T13:13:03
MERB_ENV=test
TZ=UTC
PERLBREW_HOME=/home/travis/.perlbrew
...
...
....
<SNIP>

Once we have the AWS Access Key and Secret, we can use them to authenticate to get access to AWS resources. We can dig further into it and maybe uncover and pwn more things. 



So we have seen how reusing a leaked Github Token , we found private repositories, we ended up backdooring running applications , exfiltrated secrets out of CICD system also got access to AWS infrastructure. 

Well that's it for this post. Hope you had fun reading it. 


Reference :
Sample Beanstalk app : https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/tutorials.html