Skip to content

Deleted accounts leave OAuth tokens valid #19111

Closed
@kousu

Description

@kousu

Gitea Version

Gitea version 1.16.3 built with GNU Make 4.1, go1.17.7 : bindata, sqlite, sqlite_unlock_notify

Git Version

2.25.1

Operating System

Ubuntu 20.04

How are you running Gitea?

Installed with:

# mkdir 
# useradd -m -r -d /srv/gitea gitea
# curl -L https://github.com/go-gitea/gitea/releases/download/v1.16.3/gitea-1.16.3-linux-amd64 -o /srv/gitea/gitea
# chmod +x /srv/gitea/gitea

Run manually with:

# sudo -i gitea
# ./gitea

On:

# cat /etc/os-release 
NAME="Ubuntu"
VERSION="20.04.4 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.4 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal

(and I have an nginx reverse proxy for TLS in front; if you want to see it's config too I can add it)

Database

PostgreSQL

Can you reproduce the bug on the Gitea demo site?

Yes

Log Gist

https://gist.github.com/kousu/7a0adf177e50bf8387a00b4fa3fd7dd3

Description

An OAuth app created by a deleted user is left behind in the database, and tokens it handed out are still valid, and can even see private repos created after the deletion.

Reproduction

  1. Make two accounts

    Account 1

    Screenshot 2022-03-16 at 19-03-49 Gitea Git with a cup of tea

    Account 2

    Screenshot 2022-03-16 at 19-04-00 Gitea Git with a cup of tea

  2. In account 1: create an OAuth app

    Screenshot 2022-03-16 at 19-20-09 Gitea Git with a cup of tea

  3. In account 2: create a couple repositories

    Screenshot 2022-03-16 at 20-43-22 bivott82

    You can see this on the demo site at: https://try.gitea.io/bivott82

  4. Deploy DroneCI (or some other OAuth consumer), providing it the OAuth app credentials.

    Get a public IP, set up DNS and open firewall ports for :80 and :443, and install docker before running this:

    docker run \
      --volume=/var/lib/drone:/data \
      --env=DRONE_GITEA_SERVER=https://try.gitea.io \
      --env=DRONE_GITEA_CLIENT_ID=4d9b78ea-d8fc-45ed-a11a-ea684a690108 \
      --env=DRONE_GITEA_CLIENT_SECRET=gto_z5tbfeunl4g752hlj5aeoksj25jev7lxblzejdop5sxt76nmacvq \
      --env=DRONE_RPC_SECRET="$(openssl rand -hex 16)" \
      --env=DRONE_SERVER_HOST=drone1.kousu.ca \
      --env=DRONE_SERVER_PROTO=https \
      --env=DRONE_TLS_AUTOCERT=true \
      --publish=80:80 \
      --publish=443:443 \
      --restart=always \
      --detach=true \
      --name=drone \
      drone/drone:2
    
  5. In account 2: login to DroneCI; you will see the two repositories:

    Screenshot 2022-03-16 at 20-44-09 Drone CI

    Screenshot 2022-03-16 at 20-44-19 Gitea Git with a cup of tea

    Screenshot 2022-03-16 at 20-44-46 Drone CI
    Screenshot 2022-03-16 at 20-44-53 Drone CI

  6. In account 1: delete account

    Screenshot 2022-03-16 at 20-48-38 Gitea Git with a cup of tea

  7. In account 1: create a third repository

    Screenshot 2022-03-16 at 20-49-08 Gitea Git with a cup of tea

    You can see this on the demo site at: https://try.gitea.io/bivott82

  8. In DroneCI: refresh

    Screenshot 2022-03-16 at 20-49-33 Drone CI

    You will: incorrectly see the third repository.

    Screenshot 2022-03-16 at 20-49-44 Drone CI

  9. Log out of DroneCI

    Screenshot 2022-03-16 at 20-49-59 Account - Drone CI

  10. Try to login again:

    Screenshot 2022-03-16 at 20-50-13 Drone CI

    You will: get a half-correct HTTP 500 error from Gitea.

    Screenshot 2022-03-16 at 20-50-22 Gitea Git with a cup of tea

    You should be able to see this screen on the demo site at:
    https://try.gitea.io/login/oauth/authorize?client_id=4d9b78ea-d8fc-45ed-a11a-ea684a690108&redirect_uri=https%3A%2F%2Fdrone1.kousu.ca%2Flogin&response_type=code&state=30b95ff183c471d4

  11. If you can look in the database:

    You will: see the oauth2_application is still recorded.

    # sudo -u gitea psql -c 'select * from oauth2_application' | tee /dev/null
    id | uid |  name   |              client_id               |                        client_secret                         |           redirect_uris            | created_unix | updated_unix 
    ----+-----+---------+--------------------------------------+--------------------------------------------------------------+------------------------------------+--------------+--------------
      1 |   5 | DroneCI | 3cb8ec3b-5140-4875-bffa-716f9cf1cef7 | $2a$10$L6nyevnaNwKNB3cZc6rhUenodOlZ2DNFr4wIM.jPIP9BULRHRP8QW | ["http://3.98.145.180:8080/login"] |   1647449740 |   1647452962
    (1 row)
    

    even though the associated uid is gone:

    # sudo -u gitea psql -c 'select id,name from public.user where id=5;' | tee /dev/null
    id | name 
    ----+------
    (0 rows)
    

Expected Behaviour

I would expect that deleting a user would delete all access rights that user had.

So, I would expect that deleting a user would delete all OAuth apps in their name and immediately revoke all tokens that were given out to it. The tokens not being revoked means a user can leave a ghost app around, at least

Right now you apparently can't get a new OAuth token issued (:+1:), but previously issued ones are still valid (:-1:), meaning someone who phished you into opening their malicious app can hide their tracks.

The HTTP 500 should instead be the standard HTTP 400 with "Client ID not registered":

Screenshot 2022-03-16 at 22-03-51 Gitea Git with a cup of tea

and clicking "Sync" on Drone (or any similar app) should fail.

Metadata

Metadata

Assignees

No one assigned

    Labels

    topic/securitySomething leaks user information or is otherwise vulnerable. Should be fixed!

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions