CVE-2017-15278 (PHP, published 2017-10-12T08:29Z)
Description: value: Cross-Site Scripting (XSS) was discovered in TeamPass before 2.1.27.9. The vulnerability exists due to insufficient filtration of data (in /sources/folders.queries.php). An attacker could execute arbitrary HTML and script code in a browser in the context of the vulnerable website.
Severity: LOW (CVSS v3 base score: 5.4)
Weakness: CWE-79 \u2014 Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
Repository: https://github.com/nilsteampassnet/TeamPass
Files changed:
changelog.md
folders.load.php
folders.php
includes/language/arabic.php
includes/language/bulgarian.php
includes/language/catalan.php
includes/language/chinese.php
includes/language/czech.php
includes/language/dutch.php
includes/language/english.php
includes/language/estonian.php
includes/language/french.php
includes/language/german.php
includes/language/greek.php
includes/language/hungarian.php
includes/language/italian.php
includes/language/japanese.php
includes/language/norwegian.php
includes/language/polish.php
includes/language/portuguese.php
includes/language/portuguese_br.php
includes/language/romanian.php
includes/language/russian.php
includes/language/spanish.php
includes/language/swedish.php
includes/language/turkish.php
includes/language/ukrainian.php
includes/language/vietnamese.php
items.load.php
profile.php
sources/folders.queries.php
sources/items.queries.php
sources/main.functions.php
Commit message: 2.1.27

Fixed "PW copy to clipboard" log unconsistency in specific case
Improved the possibility to define the access level on Roles when creating new folder


Vulnerable code:
            $("#div_add_group input, #div_add_group select").val("");
                            "block_modif": $("#folder_block_modif").val()
    <label for="ajouter_groupe_titre" class="label_cpm">'.$LANG['group_title'].'</label>
    <label for="new_rep_complexite" class="label_cpm">'.$LANG['complex_asked'].'</label>
    <label for="add_node_renewal_period" class="label_cpm">'.$LANG['group_pw_duration'].'</label>
    <label for="folder_block_creation" class="">'.$LANG['auth_creation_without_complexity'].'</label>
        <label for="folder_block_modif">'.$LANG['auth_modification_without_complexity'].'</label>
<?php 
function itemLog(log_case)
            id_item     : $('#id_item').val(),
        hid_label   : $('#hid_label').val(),
            itemLog("item_password_copied");
                    if ($isPersonal !== 1
                        && isset($SETTINGS['subfolder_rights_as_parent'])
                        && $SETTINGS['subfolder_rights_as_parent'] === 1
                        || ($isPersonal !== 1 && $parentId === "0")
                    ) {
                            array_push($_SESSION['groupes_visibles'], $newId),
                            $_SESSION['fonction_id']
                            if (!empty($role)) {
                                        'type' => "W"
                    //If it is a subfolder, then give access to it for all roles that allows the parent folder
                    $rows = DB::query("SELECT role_id, type FROM ".prefix_table("roles_values")." WHERE folder_id = %i", $parentId);
                    foreach ($rows as $record) {
                        //add access to this subfolder
                        DB::insert(
                            prefix_table("roles_values"),
                            array(
                                'role_id' => $record['role_id'],
                                'folder_id' => $newId,
                                'type' => $record['type']
                            )
                        );
                                    $new_line .= '<i class="fa fa-sm fa-lock mi-black mini_pw" data-clipboard-text="'.strtr($pw, '"', "&quot;").'" title="'.$LANG['item_menu_copy_pw'].'"></i>&nbsp;';
        if (!is_array($groupesInterditsUser)) {

Fixed code:
 Fixed "PW copy to clipboard" log unconsistency in specific case
 Improved the possibility to define the access level on Roles when creating new folder
    $("#span_new_rep_roles").hide();
            $("#div_add_group input, #div_add_group select, #new_rep_roles").val("");
                            "block_modif": $("#folder_block_modif").val(),
                            "access_level": $("#new_rep_roles").val()

    $("#parent_id").change(function() {
        if ($(this).val() === "0") {
            $("#span_new_rep_roles").show();
        } else {
            $("#span_new_rep_roles").hide();
        }
    })
    <label for="ajouter_groupe_titre" class="label_cpm">'.addslashes($LANG['group_title']).'</label>
    <label for="new_rep_complexite" class="label_cpm">'.addslashes($LANG['complex_asked']).'</label>
    <span id="span_new_rep_roles">
    <label for="new_rep_roles" class="label_cpm">'.addslashes($LANG['access_level_for_roles']).'</label>
    <select id="new_rep_roles" class="input_text text ui-widget-content ui-corner-all">
        <option value="">'.$LANG['no_access'].'</option>
        <option value="R">'.$LANG['read'].'</option>
        <option value="W">'.$LANG['write'].'</option>
    </select>
    </span>

    <label for="add_node_renewal_period" class="label_cpm">'.addslashes($LANG['group_pw_duration']).'</label>
    <label for="folder_block_creation" class="">'.addslashes($LANG['auth_creation_without_complexity']).'</label>
        <label for="folder_block_modif">'.addslashes($LANG['auth_modification_without_complexity']).'</label>
    'access_level_for_roles' => 'Associated access for Roles',
    'access_level_for_roles' => 'Associated access for Roles',
    'access_level_for_roles' => 'Associated access for Roles',
    'access_level_for_roles' => 'Associated access for Roles',
    'access_level_for_roles' => 'Associated access for Roles',
    'access_level_for_roles' => 'Associated access for Roles',
<?php
    'access_level_for_roles' => 'Associated access for Roles',
    'access_level_for_roles' => 'Associated access for Roles',
    'access_level_for_roles' => 'Droit associé des Roles',
    'access_level_for_roles' => 'Associated access for Roles',
    'access_level_for_roles' => 'Associated access for Roles',
    'access_level_for_roles' => 'Associated access for Roles',
    'access_level_for_roles' => 'Associated access for Roles',
    'access_level_for_roles' => 'Associated access for Roles',
    'access_level_for_roles' => 'Associated access for Roles',
    'access_level_for_roles' => 'Associated access for Roles',
    'access_level_for_roles' => 'Associated access for Roles',
    'access_level_for_roles' => 'Associated access for Roles',
    'access_level_for_roles' => 'Associated access for Roles',
    'access_level_for_roles' => 'Associated access for Roles',
    'access_level_for_roles' => 'Associated access for Roles',
    'access_level_for_roles' => 'Associated access for Roles',
    'access_level_for_roles' => 'Associated access for Roles',
    'access_level_for_roles' => 'Associated access for Roles',
    'access_level_for_roles' => 'Associated access for Roles',
function itemLog(log_case, item_id)
    console.log("> "+item_id);
    item_id = item_id || $('#id_item').val();
            id_item     : item_id,
            hid_label   : $('#hid_label').val(),
            itemLog("item_password_copied", e.trigger.dataset.clipboardId);
// Prepare Headers
header('Access-Control-Allow-Origin: *');
echo '
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
    <head>
        <title>User Profile</title>
    </head>
<body>';

</body>
</html>
            if ($parentId === "0") {
                if (isset($dataReceived['access_level']) === true) {
                    $access_level_by_role = filter_var(htmlspecialchars_decode($dataReceived['access_level']), FILTER_SANITIZE_STRING);
                } else {
                    if ($_SESSION['user_manager'] === "1") {
                        $access_level_by_role = "W";
                    } else {
                        $access_level_by_role = "";
                    }
                }
            } else {
                $access_level_by_role = "";
            }
                    // Add right to see this folder
                    if ($_SESSION['is_admin'] === "1" || $_SESSION['user_manager'] === "1") {
                            $_SESSION['groupes_visibles'],
                            is_array($_SESSION['fonction_id']) === true ? implode(";", $_SESSION['fonction_id']) : $_SESSION['fonction_id']
                    }
                    if ($isPersonal !== 1
                        && $parentId === "0"
                    ) {
                            if (empty($role) === false && empty($access_level_by_role) === false) {
                                        'type' => $access_level_by_role

                    if (isset($SETTINGS['subfolder_rights_as_parent']) === true
                        && $SETTINGS['subfolder_rights_as_parent'] === "1"
                    ) {
                        //If it is a subfolder, then give access to it for all roles that allows the parent folder
                        $rows = DB::query("SELECT role_id, type FROM ".prefix_table("roles_values")." WHERE folder_id = %i", $parentId);
                        foreach ($rows as $record) {
                            //add access to this subfolder
                            DB::insert(
                                prefix_table("roles_values"),
                                array(
                                    'role_id' => $record['role_id'],
                                    'folder_id' => $newId,
                                    'type' => $record['type']
                                )
                            );
                        }
                                    $new_line .= '<i class="fa fa-sm fa-lock mi-black mini_pw" data-clipboard-text="'.strtr($pw, '"', "&quot;").'" title="'.$LANG['item_menu_copy_pw'].'" data-clipboard-id="'.$record['id'].'"></i>&nbsp;';
        if (is_array($chaine) === true) {
            $chaine = implode(";", $chaine);
        }
        if (is_array($groupesInterditsUser) === false) {