Concurrent SSH and HTTPS
Enabling HTTPS (e.g. DavSVN or Git Smart HTTP) write access to repository (or read access to private repositories).
Solving the source issue
Usually you want to use HTTPS for bad reasons, that is, because some of your users are block behind a fascist^Wrestrictive firewall. You can, instead, talk the system administrator into opening outgoing SSH access.
Solving the issue without HTTPS
If talking to the sysadmin administrators proved fruitless, you can also open a SSH server on port 443, and add a small stanza in your ~/.ssh/config: https://savannah.gnu.org/maintenance/CvsFromBehindFirewall/
You could even use Tor, although that may be less practical.
sslh, a ssh+https multiplexer, can help implement this solution seemlessly.
We can argue at length that using HTTPS is wrong, but in the end we don't have enough communication coverage to change people's mind.
An approach to:
- strongly disrecommend webdav
- still implement with decent isolation
sounds good (e.g. ).
Common attack vector
Well that goes without saying, but if your web server gets compromised while it's root, as usual, you're doomed.
You could mitigate this by properly un-privileging the web server, e.g. if it's only used to browse public repositories - but we're talking about write access here.
I guess the security impact is fine for small forges (< 30 projects), but is quite a hazard for 4000 projects.
Adding www-data to all groups
'www-data' is made a member of all groups through a small cron that adds it to a local /etc/group file (that is used in addition to the libnss-pgsql2 user/group mapping).
(Alternatively this could be done through ACLs, or through libnss-pgsql2 configuration, but that doesn't change the fundamental model.)
The main issue is security: if users have access to the SVN hooks, they can run arbitrary commands under the 'www-data' user through WebDAV commits, over any other repository. This leads to information disclosure and potential loss of repository integrity. A work-around is to disable user access to the hooks.
Also this setup is open to the 'single-user' setup attack vectors (see below). It is slightly mitigated by the fact Apache is group member and not owner of all files.
Running everything as a single user
This appears to be the solution of choice by recent forges.
GitHub/Gitorious/Gitlab: All repositories are also available through WebDav and/or git-http-backend. SSH access is limited to user 'git', whose shell checks repository access, identifying the user through the SSH key (s)he used. Consequently all repositories are owned by a single Unix user.
Mercurial: http(s) access is done through the hgweb webapp (or a similar tool), and can be read/write if the repos belong to the web server. Similarly mercurial-server can be used to share all repositories through a single SSH user.
Hooks are not directly accessible by users.
This setup is secure but fragile. Any vulnerability in the forge webapp, commit hooks, or the VCS will expose direct write access to all hosted repositories. Additional external security measures must be implemented to protect Apache and the webapps it runs, such as using a web application firewall (mod_security or proprietary appliances). To mitigate the attack, read-only parts of the forge web app should be run by an unprivileges user. Since we have no information on the internals of GitHub, it's difficult to know what kind of mitigation they use.
Performance note: SSH patching might be necessary to optimize keys lookup in a single 'authorized_keys' file or command referencing thousands of users.
Allura is shipping a basic Fuse filesystem called 'accessfs', which mirrors an existing directory under a new mount point. Permissions are checked through a web API.
All the files are created under the user running the Fuse script (normally member of the 'fuse' group). It's not really meant to add WebDAV access - everything is already under the same user in Allura. It's just meant to provide SSH access using an all_squash-like mechanism. This also means hooks are not accessible by users.
While security is maintained when using SSH, this is equivalent to a 'single-user' setup when using WebDAV (direct access to all projects), so security is fragile.
SSH and HTTPS mutually exclusive access
With appropriate permissions, project could be configured either use exclusively HTTPS, or exclusively SSH.
However, HTTPS-accessed repositories still need to be protected against custom hooks. Also projects configured to use WebDAV are open to the 'single-user' setup attack vectors.
mod-itk http://mpm-itk.sesse.net/ adds the ability to setuid/setgid per request. This could make Apache run each HTTPS request using the FusionForge user's id, with complete isolation.
The scope appears to be limited to vhosts in the configuration, but this limitation is lifted in Apache 2.4.
However, Apache becomes less secure: as it knows what user it will run on quite late, it runs as root for longer, in particular in mod_ssl.
This also has a performance penalty (to be compared more precisely):
- that's because processes can't be reused across requests so new processes have to be forked more often than with standard mpm-prefork.
- comparing to mpm-thread is relevant since some FusionForge instances run SVN separately from the main web interface, without PHP.
- comparing to mpm-prefork is relevant because perfork can reuse an existing fork several times, while mpm-itk doesn't.
User:Lolando made some tests to run git-http-backend over CGI: http://lists.fusionforge.org/pipermail/fusionforge-general/2014-April/002654.html
SourceForge uses a more complex Fuse filesytem called 'fuse-projauth', that perserves file ownership. It is coupled with an Apache module called 'mod_spy_pidpath' that requests project permissions to Fuse for the current Apache PID, by looking at the user credentials and the current URL.
The communication between Apache and Fuse is performed using shared-memory, initiated when the parent Apache process is running as root.
This allows direct access to the repository hooks by users, while maintaining per-project isolation during hooks execution under www-data. SSH access could be done directly, although it's still done through Fuse at SourceForge to ease permissions in the hooks directory.
A 2010 version of those tools was released at: http://sourceforge.net/projects/sourceforge/files/project-perms/ As of 2014 SourceForge appears to run updated versions of them.
The setup is pretty secure but still adds two additional attack vectors when compared to SSH-only write access:
- If the Apache process, when running as www-data, is compromised, it gets access to the shared-memory block used by Fuse and can request new permissions. The compromision could happen through a vulnerability in mod_dav or any other module.
- Note 1: a PHP script normally cannot get access the shared memory block, even if run through mod_php: the language does not allow arbitrary adresses in shmop_open(), and loading arbitrary executable code through dl() is normally disabled in mod_php. Still, one should keep an eye on PHP and other in-process modules configuration, to avoid access to the shared memory block and hence escalate privileges.
- Note 2: commands forked from the Apache process are properly isolated as their access to the shared-memory block was revoked during the fork&exec (see execve(2)). Vulnerable or custom hooks cannot harm projects if the authenticated user isn't a member.
- If the Apache user (not process) is compromised, it won't be able to communicate with Fuse, but it may be able to write to the original mount point (not managed by Fuse) where a lot of files will be owned by Apache. To mitigate this attack vector it may make sense keep the files created by apache owned by root in the Fuse mount point, so that Apache still doesn't have any direct (non-Fuse) privilege on the repositories.
A similar system is used to per-project isolate PHP-originating file accesses on their web hosting service, though process-level isolation is not handled by this technique (nor at all).
This setup also has the added benefit of revoking any user access when it's removed from a group - even if (s)he owns some of the group repository files.
All in all, this seems the most secure setup besides disabling HTTPS access.
- Change ownership:
- user www-data -> root
- group www-data -> project group (repo top-level directory), scm_project group (below)