Pages Unique domain overwrite risk

Problem

Currently it's possible to hijack pages with unique domain URLs. This is permitted because the current format of pages unique domains is namespace-subgroup-...-project-<RANDOM STRING>. Once this value is known, one can create a namespace (User or Group) with that random string and then a Gitlab Pages for that namespace (https://docs.gitlab.com/ee/user/project/pages/getting_started_part_one.html#gitlab-pages-default-domain-names), which will have priority on the URL lookup, hijacking the traffic. Example:

Screen_Recording_2023-06-21_at_17.49.15

Proposed solution

  • Instead of using - as the separator on the unique URL, use *.
    • * are valid URL chars, but are not valid as project/group name/path, preventing malicious users to create projects that could end-up with the same URL as a Pages Unique Domain URL.

Notes

Update: 2023-06-26
ProjectSetting.joins(:project)
.where(project_settings: { pages_unique_domain_enabled: true })
.group('projects.visibility_level')
.count
.transform_keys { Gitlab::VisibilityLevel.string_options.key(_1) }

=> {"private"=>241, "public"=>76}

Public projects have higher risk of being attacked.

Update: 2023-06-27
  • Hijacking projects
Project.where(path: ProjectSetting.select("project_settings.pages_unique_domain || '.gitlab.io'"))

=> []
  • Hijacked projects
ProjectSetting
.joins(:project)
.where(projects: { path: "project_settings.pages_unique_domain || '.gitlab.io'" })
.select(:project_id)

=> []
Edited by Kassio Borges