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"
}
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.
At the same time we should have a listener ready to accept the incoming http post request from the build server.