> a .git directory on the VPS hosting this site was exposed to the internet by a configuration mistake, providing enough information to allow an attacker to access the site's database.
I had trouble figuring out how they got from point A to point B. My best guess is that a file containing database configuration settings had been committed to the Git repo at some point.
Lessons:
- Don't commit secrets to your Git repo. Store them in config files which are listed in .gitignore. Yes, this means you have to manually copy or write config files when you set up different servers, but those servers are likely to have different database credentials and the like anyway, right? If you've found that you've committed secrets by accident but haven't pushed anywhere yet, revert your branch to before the commit and redo or cherry-pick any subsequent commits safely. If it is too late, change the credentials to access the database or whatever other secrets you've revealed.
- Don't put web-accessible files in the root level of a Git repository. Instead, have a subdirectory contain the web-accessible files, and configure your web server to serve from that. That ensures that the .git directory won't be right next to web-accessible files, and has other benefits as well - you can also easily have subdirectories for docs, CLI scripts, and other things that shouldn't be web-accessible right there in the same repo. But if that isn't an option (or even if it is), configure your web daemon to not serve files from .git, or probably any other file or directory that starts with a dot.
- Edit to add one more: As much as possible, lock down access to your database server. An attacker having your database credentials is bad, but they still won't get far if the database server is configured to only listen to connections from the IP address that the web application server is hosted at, or, if they're on the same server, only over local sockets.
Of course, the same applies to other VCSes besides Git.
> have a subdirectory contain the web-accessible files
You can also separate your git repository from the working directory. I have my git repositories at ~/repositories, with a post-receive hook that checks out the working directories at ~/projects and then _actively_ copies only relevant files to ~/html. Basically a "poor man's CI/CD", with the bonus of having to opt-in to publish any files.
You can also tell git that the .git dir is completely separated from the working dir:
alias dogit='GIT_WORK_TREE=/path/to/src/dir GIT_DIR=/path/to/dotgit/dir git'
dogit pull remote treeish
---
I set this up as a "poor man's version control" on a large client's server back in 2016-ish. I was lost for words when last year I saw my colleagues still using Ctrl-R to rerun that alias line.
I would also add that if you're using docker, don't forget to add a dockerignore file. I often see people miss this step and end up with exposed secrets and git folder (and poor build times).
> Yes, this means you have to manually copy or write config files when you set up different servers, but those servers are likely to have different database credentials and the like anyway, right?
No, you can use GitHub Secrets, AWS Secrets Manager, etc ... or encrypt your config files and add a decrypt step to your build. [1]
I had trouble figuring out how they got from point A to point B. My best guess is that a file containing database configuration settings had been committed to the Git repo at some point.
Lessons:
- Don't commit secrets to your Git repo. Store them in config files which are listed in .gitignore. Yes, this means you have to manually copy or write config files when you set up different servers, but those servers are likely to have different database credentials and the like anyway, right? If you've found that you've committed secrets by accident but haven't pushed anywhere yet, revert your branch to before the commit and redo or cherry-pick any subsequent commits safely. If it is too late, change the credentials to access the database or whatever other secrets you've revealed.
- Don't put web-accessible files in the root level of a Git repository. Instead, have a subdirectory contain the web-accessible files, and configure your web server to serve from that. That ensures that the .git directory won't be right next to web-accessible files, and has other benefits as well - you can also easily have subdirectories for docs, CLI scripts, and other things that shouldn't be web-accessible right there in the same repo. But if that isn't an option (or even if it is), configure your web daemon to not serve files from .git, or probably any other file or directory that starts with a dot.
- Edit to add one more: As much as possible, lock down access to your database server. An attacker having your database credentials is bad, but they still won't get far if the database server is configured to only listen to connections from the IP address that the web application server is hosted at, or, if they're on the same server, only over local sockets.
Of course, the same applies to other VCSes besides Git.