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 .