Insufficient Type Check on GraphQL leading to Maintainer delete repository
High
G
GitLab
Submitted None
Actions:
Reported by
ledz1996
Vulnerability Details
Technical details and impact analysis
### Summary
As you have know, Maintainer cannot delete/archive repository. But via GraphQL, they can do as there exists an sufficient check on GraphQL API
***app/graphql/mutations/snippets/destroy.rb***
```ruby
def resolve(id:)
snippet = authorized_find!(id: id)
response = ::Snippets::DestroyService.new(current_user, snippet).execute
```
The function `authorized_find` lead to `object_from_id!`
***app/graphql/mutations/snippets/base.rb***
```ruby
def find_object(id:)
GitlabSchema.object_from_id(id)
end
def authorized_resource?(snippet)
Ability.allowed?(context[:current_user], ability_for(snippet), snippet)
end
def ability_for(snippet)
"#{ability_name}_#{snippet.to_ability_name}".to_sym
end
```
Here there is no check for whether the Object returned from `find_object` is a Snippet. I could specify any object which the user have permission of
` "#{ability_name}_#{snippet.to_ability_name}".to_sym` to.
For example: A DiffNote that is created by a Maintainer in the Project as the function.
If I have such a ID:
```
mutation test{
destroySnippet(input: {id: "gid://gitlab/DiffNote/116"}){
errors
}
}
```
It refer to an DiffNote with id `116`
Perfectly, a Maintainer have an `admin_note` and `admin_snippet` on a DiffNote (!!!)
In the mutation Destroy the call to `` ::Snippets::DestroyService.new(current_user, snippet)`` but the Object of `snippet` is actually a `DiffNote`
***app/services/snippets/destroy_service.rb***
```ruby
def attempt_destroy!
result = Repositories::DestroyService.new(snippet.repository).execute
raise DestroyError if result[:status] == :error
snippet.destroy!
end
```
and in
***app/models/diff_note.rb***
```ruby
def repository
noteable.respond_to?(:repository) ? noteable.repository : project.repository
end
```
It return the `project.repository` which in turn the Project that the `DestroyService` gonna delete
### Steps to reproduce
1. Create 2 User: User A, User B
2. User A create a project set User B as Maintainer.
F802288
3. User B create 2 branch with the same file but different content
F802287
F802289
4. Create a merge request for those 2 Branch
F802290
5. Create a diff note for the file by clicking at the comment on a line of the file then Submit it
F802291
6. To know the ID of diff note, delete this one, the ID will show up in burp then you will know the ID of the next one
F802292
7. Use the `/-/graphiql-explorer` to execute the following the query
```
mutation test{
destroySnippet(input: {id: "gid://gitlab/DiffNote/118"}){
errors
}
}
```
F802293
8. Enjoy no repository
F802294
9. If you click on `Create empty repository` It will actually make the Project 404 but It still show up on the User's project feed
F802295
F802296
### Impact
Unauthorized deleting of repository/project by maintainers
### Output of checks
This bug happens on GitLab.com
## Impact
Unauthorized deleting of repository/project by maintainers
Report Details
Additional information and metadata
State
Closed
Substate
Resolved
Submitted
Weakness
Improper Access Control - Generic