•  
      request #37545 Deleting or moving an artifact can delete values from unrelated artifacts
    Infos
    #37545
    Thomas Gerbet (tgerbet)
    2024-05-07 11:10
    2024-03-28 16:09
    39165
    Details
    Deleting or moving an artifact can delete values from unrelated artifacts

    Moving or deleting an artifact can lead to the removal of information on other unrelated artifacts on the instance.

    Impact

    A malicious user could exploit this issue on purpose to delete information on the instance. It is however not possible to control exactly which information is deleted.

    Information from the following fields can be impacted:

    • Date
    • File
    • Float
    • Int
    • List (checkbox, selectbox, radio button, multi-selectbox)
    • OpenList
    • Text
    • String
    • Permissions on artifact (for the history visualization, actual permissions are not affected, see details below)

    Issue is present since Tuleap 14.11.99.34 (git #tuleap/stable/7f2e5e974596196bd96c2146c533353ecbcc592f)

    CVSSv3.1 score: 7.1 (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:L)

    Details on the "Permissions on artifact" field

    Data stored in the tracker_changeset_value_permissionsonartifact database table can be affected by this issue. This affects features such as the diff of values in changeset history, CSV export, REST API and webhooks data, etc.
    However, the set of permissions that are currently enforced for a given artifact are stored in another database table named permissions which is not affected by this issue. As a result, there are two possible cases for an artifact where the "Permissions on artifact" value has been affected by this issue:

    1. If the "Permissions on artifact" value has never changed since the affected value, the permissions that had been set are still in effect. User groups that had permission to see the artifact can still see it, user groups that did not have permission are still rejected. Confidentiality is preserved, but changeset history, CSV export, REST API will have a gap for this field.
    2. If the "Permissions on artifact" value has changed (or will change) since the affected value, the new permissions will apply as usual. Confidentiality is preserved.

    References

    CWE-440
    CVE-2024-30246

    Acknowledgements

    This issue was identified and reported by Guilhem Bonnefille from CS Group.

    Trackers
    All
    Empty
    • [ ] enhancement
    • [ ] internal improvement
    Empty
    Stage
    Thomas Gerbet (tgerbet)
    Closed
    2024-03-29
    Attachments
    Tool to identify and possibly repair corrupted data
    References

    Follow-ups

    User avatar
    Thomas Gerbet (tgerbet)2024-04-19 14:41
    last edited by: Thomas Gerbet (tgerbet) 2024-05-07 11:11

    Attaching a tool (git #tuleap/stable/8881e29531b0d65f9b70562af10178df83206d59) to help identify and retrieve corrupted data from a backup. The tool works in 2 steps.
    The first step is expected to be executed against the current production DB of a Tuleap instance. It will try to identify changeset values that might have been affected by the issue. It will output something looking like that:

    $> /opt/remi/php82/root/usr/bin/php ./CVE-2024-30246_14490449103aee2.phar identify --dbhost=127.0.0.1 --dbname=tuleap --dbusername=tuleapadm --output-file=/path/to/write/suspected_changeset_values_document.json
    Password for DB user 'tuleapadm':
    Searching...
    Maximum changeset_id = '20415'
    Submission date of the last affected changeset: '2018-04-16T15:52:00+00:00'
    Estimated date of update to Tuleap higher than 14.11 = '2023-09-07 07:13:50'
    Submission date of the last affected changeset for complex fields: '2018-06-01T08:26:33+00:00'
    Estimated date of update to Tuleap higher than 14.11 = '2023-09-07 07:13:50'
    End of report
    

    The second part of the tool will use the document that has been generated by the first one to generate SQL queries to fix the corrupted values. The second part of the tool must be executed against a restored backup of the DB. You will want to restore a backup around the indicated date of the 14.11 upgrade to restore corrupted values created before this date.

    $> /opt/remi/php82/root/usr/bin/php ./CVE-2024-30246_0ab35aa8b09.phar retrieve --dbhost=127.0.0.1 --dbname=tuleap_backup --dbusername=tuleapadm --input-file=/path/to/suspected_changeset_values_document.json --output-file=/path/to/write/sql_queries.sql
    Password for DB user 'tuleapadm':
    Checking text fields...
    Checking list fields...
    Checking computed fields...
    Checking float fields...
    Checking int fields...
    Checking date fields...
    Checking file fields...
    Checking openlist fields...
    Checking artifact link fields...
    Checking permissions on artifact fields...
    

    The generated SQL file can then be applied on your current production DB.


    • Attachments CVE-2024-30246_0ab35aa8b09.phar added
    User avatar
    Thomas Gerbet (tgerbet)2024-04-19 10:46

    Adjusting the CVSS score with the additional details on the "permissions on artifact" field


    • Original Submission
      Something went wrong, the follow up content couldn't be loaded
      Only formatting have been changed, you should switch to markup to see the changes
    User avatar

    As a reminder, here is the script I imagined to retrieve lost data from a live MySQL backup, providing the missing Artifact Changeset as argument:

    #!/bin/sh
    
    #
    # For authentication, set $MYSQL_PWD
    #
    
    CHANGESETS=`echo $* | tr ' ' ','`
    
    IDS=`mysql -u tuleapadm -B -N -e "SELECT id FROM tracker_changeset_value WHERE changeset_id IN ($CHANGESETS)" tuleap | tr '\n' ',' | sed 's/,$//'`
    
    for table in tracker_changeset_value_artifactlink tracker_changeset_value_computedfield_manual_value tracker_changeset_value_date tracker_changeset_value_file tracker_changeset_value_float tracker_changeset_value_int tracker_changeset_value_list tracker_changeset_value_openlist tracker_changeset_value_permissionsonartifact tracker_changeset_value_text
    do
      mysqldump -u tuleapadm -y -n -t tuleap $table --where "changeset_value_id in ($IDS)"
    done
    
    User avatar
    Joris MASSON (jmasson)2024-04-02 15:36

    Added details on the impacts for the "Permissions on artifact" field.


    • Original Submission
      Something went wrong, the follow up content couldn't be loaded
      Only formatting have been changed, you should switch to markup to see the changes
    User avatar
    Joris MASSON (jmasson)2024-03-29 17:38

    Added "String" field type and added details for List field types


    • Original Submission
      Something went wrong, the follow up content couldn't be loaded
      Only formatting have been changed, you should switch to markup to see the changes
    User avatar
    Thomas Gerbet (tgerbet)2024-03-29 17:37
    • Original Submission
      Something went wrong, the follow up content couldn't be loaded
      Only formatting have been changed, you should switch to markup to see the changes
    User avatar
    Thomas Gerbet (tgerbet)2024-03-29 15:25

    CVE-2024-30246 has been assigned to this issue.


    • Original Submission
      Something went wrong, the follow up content couldn't be loaded
      Only formatting have been changed, you should switch to markup to see the changes
    User avatar
    Thomas Gerbet (tgerbet)2024-03-29 12:26
    • Original Submission
      Something went wrong, the follow up content couldn't be loaded
      Only formatting have been changed, you should switch to markup to see the changes
    User avatar
    Thomas Gerbet (tgerbet)2024-03-29 08:35

    Flagging this as an security issue since it impacts data integrity and there is at least one offensive scenario where a bad actor can exploit it to wreak havoc on purpose.

    @gbonnefille Is it fine if we credit you and CS Group in the advisory?

    User avatar
    Thomas Gerbet (tgerbet)2024-03-28 16:42

    • Summary
      -Deleting an artifact can delete values from unrelated artifact 
      +Deleting or moving an artifact can delete values from unrelated artifacts 
    • Original Submission
      Something went wrong, the follow up content couldn't be loaded
      Only formatting have been changed, you should switch to markup to see the changes
    • Status changed from Under implementation to Under review
    User avatar

    Furthermore, as the deletion did not select the right elements, the database also contains orphans 'values'. We can find them with:

    SELECT * FROM tracker_changeset_value_all vv
    WHERE NOT EXISTS (SELECT id FROM tracker_changeset_value v WHERE v.id = vv.changeset_value_id);
    
    User avatar
    last edited by: Guilhem Bonnefille (CS) (gbonnefille) 2024-03-28 16:24

    It is possible to identify the affected changesets with the following SQL requests:

    CREATE TEMPORARY TABLE tracker_changeset_value_all (PRIMARY KEY my_pkey (changeset_value_id)) SELECT * FROM (
    SELECT changeset_value_id FROM
    tracker_changeset_value_artifactlink
    UNION
    SELECT changeset_value_id FROM tracker_changeset_value_computedfield_manual_value
    UNION
    SELECT changeset_value_id FROM tracker_changeset_value_date UNION   SELECT changeset_value_id FROM tracker_changeset_value_file UNION   SELECT changeset_value_id FROM tracker_changeset_value_float
    UNION
    SELECT changeset_value_id FROM tracker_changeset_value_int UNION   SELECT changeset_value_id FROM tracker_changeset_value_list
    UNION
    SELECT changeset_value_id FROM tracker_changeset_value_openlist UNION   SELECT changeset_value_id FROM tracker_changeset_value_permissionsonartifact
    UNION
    SELECT changeset_value_id FROM tracker_changeset_value_text ) AS foo;
    
    SELECT c.id, FROM_UNIXTIME(c.submitted_on), c.artifact_id, a.id, a.tracker_id, t.name, g.group_name FROM tracker_changeset c
    LEFT JOIN tracker_artifact a ON c.artifact_id = a.id
    LEFT JOIN tracker t ON t.id = a.tracker_id
    LEFT JOIN groups g ON g.group_id = t.group_id
    WHERE NOT EXISTS (SELECT cv.id FROM tracker_changeset_value cv WHERE c.id = cv.changeset_id AND EXISTS (SELECT * FROM tracker_changeset_value_all WHERE changeset_value_id = cv.id)) AND NOT EXISTS (SELECT * FROM tracker_changeset_comment cm WHERE c.id = cm.changeset_id) ;