Parent directory

privilege-escalation-regression.txtar

4215 bytes
  1# vi: set ft=conf
  2# Regression test for privilege escalation via repository-scoped auth checks
  3#
  4# VULNERABILITY DESCRIPTION:
  5# Global admin commands (`user`, `settings`) were gated by a helper written
  6# for repository-scoped commands. That helper granted access when the caller
  7# had admin access to a repository *named by the command's first argument*.
  8# Since any authenticated user can create a repository, and the owner of a
  9# repository has admin access to it, a regular user could satisfy the check
 10# for a global command simply by creating a repository with the right name.
 11#
 12# ATTACK SCENARIO:
 13# 1. Attacker registers an SSH key (or is given any normal account)
 14# 2. Attacker runs `repo create victim`, becoming owner and therefore
 15#    repo-admin of "victim"
 16# 3. Attacker runs `user set-admin victim true`. The auth check reads the
 17#    first argument "victim" as a repository name, sees repo-admin, allows it
 18# 4. The account "victim" is now a global server administrator
 19#
 20# A related issue let a read-write collaborator grant admin-access to any
 21# account, and remove collaborators ranked above themselves.
 22#
 23# THIS TEST VERIFIES:
 24# - A non-admin cannot reach `user` or `settings` commands by creating a
 25#   repository named after the command argument
 26# - A read-write collaborator cannot grant access above their own level
 27# - A read-write collaborator cannot remove or demote a higher-ranked
 28#   collaborator
 29# - Webhook deliveries cannot be read across repositories
 30
 31# start soft serve
 32exec soft serve &
 33# wait for SSH server to start
 34ensureserverrunning SSH_PORT
 35
 36# create regular, non-admin users
 37soft user create user1 --key "$USER1_AUTHORIZED_KEY"
 38soft user create boss --key "$ATTACKER_AUTHORIZED_KEY"
 39soft user info user1
 40stdout 'Admin: false'
 41
 42# The attacker creates repositories named after the arguments they intend to
 43# pass to the global commands. They own these, so they are repo-admin of them.
 44usoft repo create user1
 45usoft repo create victim
 46usoft repo create true
 47usoft repo create admin-access
 48usoft repo create admin
 49
 50# Repo-admin access must not authorize global user commands.
 51! usoft user set-admin user1 true
 52! usoft user set-admin victim true
 53! usoft user create victim
 54! usoft user delete admin
 55! usoft user list
 56! usoft user info admin
 57! usoft user set-username admin victim
 58! usoft user add-pubkey admin "$ADMIN2_AUTHORIZED_KEY"
 59! usoft user remove-pubkey admin "$ADMIN1_AUTHORIZED_KEY"
 60
 61# Repo-admin access must not authorize global settings commands.
 62! usoft settings anon-access admin-access
 63! usoft settings anon-access read-write
 64! usoft settings allow-keyless true
 65
 66# a placeholder to reset stderr
 67soft help
 68
 69# The attacker is still not an admin, and settings are unchanged.
 70soft user info user1
 71stdout 'Admin: false'
 72soft settings anon-access
 73stdout 'read-only.*'
 74
 75# Collaborator grants are bounded by the caller's own access level.
 76soft repo create shared
 77soft repo collab add shared user1 read-write
 78soft repo collab add shared boss admin-access
 79
 80# user1 is read-write on "shared" and must not be able to grant admin-access.
 81! usoft repo collab add shared user1 admin-access
 82# ...nor remove a collaborator ranked above them.
 83! usoft repo collab remove shared boss
 84# ...nor demote one by overwriting the grant.
 85! usoft repo collab add shared boss read-only
 86
 87# a placeholder to reset stderr
 88soft help
 89
 90# boss is still an admin-access collaborator, and user1 did not escalate.
 91soft repo collab list shared
 92stdout 'boss'
 93
 94# Granting at or below the caller's own level still works.
 95soft user create peer
 96usoft repo collab add shared peer read-only
 97soft repo collab list shared
 98stdout 'peer'
 99
100# Webhook deliveries must be scoped to the named repository. The attacker has
101# admin access to their own repo "user1", which must not expose the webhook
102# deliveries of "shared" (these include full request URLs, headers, bodies).
103new-webhook WH_SHARED
104soft repo webhook create shared $WH_SHARED -e push
105soft repo webhook list shared
106stdout '1.*'
107! usoft repo webhook deliveries list user1 1
108! usoft repo webhook deliveries get user1 1 00000000-0000-0000-0000-000000000000
109
110# a placeholder to reset stderr
111soft help
112
113# stop the server
114[windows] stopserver
115[windows] ! stderr .