Medium severity4.9NVD Advisory· Published Nov 27, 2017· Updated May 13, 2026
CVE-2017-15053
CVE-2017-15053
Description
TeamPass before 2.1.27.9 does not properly enforce manager access control when requesting roles.queries.php. It is then possible for a manager user to modify any arbitrary roles within the application, or delete any arbitrary role. To exploit the vulnerability, an authenticated attacker must have the manager rights on the application, then tamper with the requests sent directly, for example by changing the "id" parameter when invoking "delete_role" on roles.queries.php.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
nilsteampassnet/teampassPackagist | < 2.1.27.9 | 2.1.27.9 |
Patches
111 files changed · +135 −58
changelog.md+1 −0 modified@@ -11,6 +11,7 @@ Fixed issue while restoring DB from administration page Improved / Fixed administration task for encrypting/decrypting files Improved security regarding item history display + Added filter in Roles #1947 Dependency & array update in install checks #1945 Cannot delete items #1944 File upload results in error
includes/css/passman.css+11 −1 modified@@ -165,7 +165,7 @@ float:left; .td_title{ font-weight:bold; -min-width: 150px; +min-width: 120px; } ul{ @@ -181,6 +181,11 @@ list-style-type:none; padding: 10px; } +.normal { + font: normal; "Lucida Grande"; + color: #464646; +} + .readme{ font-family: sans-serif; font-size: 9px; @@ -392,4 +397,9 @@ div.dataTables_processing { z-index: 1; } .hidden { display: none; +} + +.no-border { + border: none; + border-collapse: collapse; } \ No newline at end of file
index.php+2 −1 modified@@ -117,6 +117,7 @@ $session_hide_maintenance = $superGlobal->get("hide_maintenance", "SESSION"); $session_initial_url = $superGlobal->get("initial_url", "SESSION"); $server_request_uri = $superGlobal->get("REQUEST_URI", "SERVER"); +$session_nb_users_online = $superGlobal->get("nb_users_online", "SESSION"); /* DEFINE WHAT LANGUAGE TO USE */ @@ -783,7 +784,7 @@ class="ui-state-error ui-corner-all"> <a href="https://www.reddit.com/r/TeamPass/" target="_blank" style="color:#F0F0F0;" class="tip" title="'.addslashes($LANG['admin_help']).'"><i class="fa fa-reddit-alien"></i></a> </div> <div style="float:left;width:32%;text-align:center;"> - ', ($session_user_id !== null && empty($session_user_id) === false) ? '<i class="fa fa-users"></i> '.$_SESSION['nb_users_online'].' '.$LANG['users_online'].' | <i class="fa fa-hourglass-end"></i> '.$LANG['index_expiration_in'].' <div style="display:inline;" id="countdown"></div>' : '', ' + ', ($session_user_id !== null && empty($session_user_id) === false) ? '<i class="fa fa-users"></i> '.$session_nb_users_online.' '.$LANG['users_online'].' | <i class="fa fa-hourglass-end"></i> '.$LANG['index_expiration_in'].' <div style="display:inline;" id="countdown"></div>' : '', ' </div><div id="countdown2"></div> <div style="float:right;text-align:right;"> <i class="fa fa-clock-o"></i> '. $LANG['server_time']." : ".@date($SETTINGS['date_format'], (string) $_SERVER['REQUEST_TIME'])." - ".@date($SETTINGS['time_format'], (string) $_SERVER['REQUEST_TIME']).'
install/install.queries.php+1 −1 modified@@ -364,7 +364,7 @@ function encryptFollowingDefuse($message, $ascii_key) $mysqli_result = mysqli_query( $dbTmp, "CREATE TABLE IF NOT EXISTS `".$var['tbl_prefix']."misc` ( - `id` int(12) NOT null AUTO_INCREMENT, + `increment_id` int(12) NOT null AUTO_INCREMENT, `type` varchar(50) NOT NULL, `intitule` varchar(100) NOT NULL, `valeur` varchar(500) NOT NULL,
install/upgrade_run_2.1.27.php+14 −6 modified@@ -188,11 +188,19 @@ function cleanFields($txt) // alter table Items mysqli_query($db_link, "ALTER TABLE `".$pre."items` MODIFY pw_len INT(5) NOT NULL DEFAULT '0'"); -// alter table misc to add an index -mysqli_query( - $db_link, - "ALTER TABLE `".$pre."misc` ADD `id` INT(12) NOT NULL AUTO_INCREMENT FIRST, ADD PRIMARY KEY (`id`)" -); +// alter table MISC - rename ID is exists +$result = mysqli_query("SHOW COLUMNS FROM `misc` LIKE 'id'"); +if (mysqli_num_rows($result) !== 0) { + // Change name of field + mysqli_query($db_link, "ALTER TABLE `".$pre."misc` CHANGE `id` `increment_id` INT(12) NOT NULL"); +} else { + // alter table misc to add an index + $res = addColumnIfNotExist( + $pre."misc", + "increment_id", + "INT(12) NOT NULL AUTO_INCREMENT FIRST, ADD PRIMARY KEY (`id`)" + ); +} // alter table misc to add an index mysqli_query( @@ -703,7 +711,7 @@ function replace_a_line($data) utf8_encode( "<?php global \$SETTINGS; -\$SETTINGS = array (" . $config_text . " +\$SETTINGS = array (" . $config_text . " );" ) );
items.load.php+21 −6 modified@@ -792,7 +792,9 @@ function(data) { function EditerItem() { - $("#div_formulaire_edition_item_info").html("<?php echo "<i class='fa fa-cog fa-spin fa-lg'></i> ".addslashes($LANG['please_wait'])."..."; ?>").show(); + $("#div_formulaire_edition_item_info") + .html("<?php echo "<i class='fa fa-cog fa-spin fa-lg'></i> ".addslashes($LANG['please_wait'])."..."; ?>") + .removeClass("hidden"); $("#item_detail_zone_loader").addClass("hidden"); var erreur = ""; var reg=new RegExp("[.|,|;|:|!|=|+|-|*|/|#|\"|'|&]"); @@ -965,7 +967,7 @@ function(data) { LoadingPage(); } else { //refresh item in list - $("#fileclass"+data.id).text($('#edit_label').val()); + $("#fileclass"+data.id).html('<div class="truncate">' + $('#edit_label').val() + '</div>'); //Refresh form $("#id_label").text($('#edit_label').val()); @@ -1088,16 +1090,24 @@ function(data) { );*/ } else { - $('#edit_show_error').html("<?php echo addslashes($LANG['error_complex_not_enought']); ?>").show(); + $('#edit_show_error') + .html("<?php echo addslashes($LANG['error_complex_not_enought']); ?>") + .show(); $("#div_formulaire_edition_item ~ .ui-dialog-buttonpane").find("button:contains('<?php echo addslashes($LANG['save_button']); ?>')").prop("disabled", false); - $("#div_formulaire_edition_item_info").addClass("hidden").html(""); + $("#div_formulaire_edition_item_info") + .addClass("hidden") + .html(""); } } if (erreur != "") { $('#edit_show_error').html(erreur).show(); - $("#div_formulaire_edition_item_info").addClass("hidden").html(""); - $("#div_formulaire_edition_item ~ .ui-dialog-buttonpane").find("button:contains('<?php echo addslashes($LANG['save_button']); ?>')").prop("disabled", false); + $("#div_formulaire_edition_item_info") + .addClass("hidden") + .html(""); + $("#div_formulaire_edition_item ~ .ui-dialog-buttonpane") + .find("button:contains('<?php echo addslashes($LANG['save_button']); ?>')") + .prop("disabled", false); } } @@ -3293,6 +3303,11 @@ function(data) { function(data) { if (data[0].error === "") { $("#div_suggest_change_wait").html("<?php echo addslashes($LANG['suggestion_done']); ?>").show(1).delay(1500).fadeOut(1000); + + // set indicator if item has change proposal + $("#item_extra_info").prepend('<i class="fa fa-lightbulb-o fa-sm mi-yellow tip" title="<?php echo addslashes($LANG['item_has_change_proposal']); ?>" onclick=""></i> '); + $(".tip").tooltipster({multiple: true}); + setTimeout( function() { $("#div_suggest_change").dialog("close");
items.php+27 −23 modified@@ -226,11 +226,11 @@ <i class="fa fa-warning"></i> <b>'.$LANG['pw_is_expired_-_update_it'].'</b> </div> </div> - <table width="100%" id="item_details_table">'; + <table width="100%" class="no-border" id="item_details_table">'; // Line for LABEL echo ' <tr> - <td valign="top" class="td_title" colspan="2"> + <td valign="top" class="td_title" width="120px" style="background-color:rgba(178, 178, 178, 0.13);"> <div class="quick_menu2" style="float:left; margin-right: 5px;"> <ul class="quick_menu ui-menu"> <li><i class="fa fa-bars"></i> @@ -252,7 +252,11 @@ </li> </ul> </div> - <div id="id_label" style="display:inline; margin:4px 0px 0px 120px; "></div> + </td> + <td valign="middle" style="background-color:rgba(178, 178, 178, 0.13);"> + <span id="id_label" style="font-weight:bold;"></span> + </td> + <td style="background-color:rgba(178, 178, 178, 0.13);"> <input type="hidden" id="hid_label" value="', isset($dataItem) ? htmlspecialchars($dataItem['label']) : '', '" /> <div style="float:right; font-family:arial; margin-right:5px;" id="item_viewed_x_times"></div> @@ -266,15 +270,15 @@ echo ' <tr> <td valign="top" class="td_title" width="180px"> <i class="fa fa-angle-right"></i> '.$LANG['description'].' :</td> - <td> + <td colspan="2"> <div id="id_desc" style="font-style:italic;display:inline;"></div><input type="hidden" id="hid_desc" value="', isset($dataItem) ? htmlspecialchars($dataItem['description']) : '', '" /> </td> </tr>'; // Line for PW echo ' <tr> <td valign="top" class="td_title"> <i class="fa fa-angle-right"></i> '.$LANG['pw'].' :<span id="button_quick_pw_copy" class="fa fa-paste fa-border fa-sm tip" style="cursor:pointer;display:none;float:right;margin-right:2px;" title="'.$LANG['item_menu_copy_pw'].'"></i></td> - <td> + <td colspan="2"> <div id="id_pw" class="unhide_masked_data" style="float:left; cursor:pointer; width:300px;"></div> <input type="hidden" id="hid_pw" value="" /> @@ -285,7 +289,7 @@ echo ' <tr> <td valign="top" class="td_title"> <i class="fa fa-angle-right"></i> '.$LANG['index_login'].' :<span id="button_quick_login_copy" class="fa fa-paste fa-border fa-sm tip" style="cursor:pointer;display:none;float:right;margin-right:2px;" title="'.$LANG['item_menu_copy_login'].'"></span></td> - <td> + <td colspan="2"> <div id="id_login" style="float:left;"></div> <input type="hidden" id="hid_login" value="" /> </td> @@ -294,23 +298,23 @@ echo ' <tr> <td valign="top" class="td_title"> <i class="fa fa-angle-right"></i> '.$LANG['email'].' :</td> - <td> + <td colspan="2"> <div id="id_email" style="display:inline;"></div><input type="hidden" id="hid_email" value="" /> </td> </tr>'; // Line for URL echo ' <tr> <td valign="top" class="td_title"> <i class="fa fa-angle-right"></i> '.$LANG['url'].' :</td> - <td> + <td colspan="2"> <div id="id_url" style="display:inline;"></div><input type="hidden" id="hid_url" value="" /> </td> </tr>'; // Line for FILES echo ' <tr> <td valign="top" class="td_title"> <i class="fa fa-angle-right"></i> '.$LANG['files_&_images'].' :</td> - <td> + <td colspan="2"> <div id="id_files" style="display:inline;font-size:11px;"></div><input type="hidden" id="hid_files" /> <div id="dialog_files" style="display: none;"> @@ -321,42 +325,42 @@ echo ' <tr> <td valign="top" class="td_title"> <i class="fa fa-angle-right"></i> '.$LANG['restricted_to'].' :</td> - <td> + <td colspan="2"> <div id="id_restricted_to" style="display:inline;"></div><input type="hidden" id="hid_restricted_to" /><input type="hidden" id="hid_restricted_to_roles" /> </td> </tr>'; // Line for TAGS echo ' <tr> <td valign="top" class="td_title"> <i class="fa fa-angle-right"></i> '.$LANG['tags'].' :</td> - <td> + <td colspan="2"> <div id="id_tags" style="display:inline;"></div><input type="hidden" id="hid_tags" /> </td> </tr>'; // Line for KBs if (isset($SETTINGS['enable_kb']) && $SETTINGS['enable_kb'] == 1) { echo ' - <tr> - <td valign="top" class="td_title"> <i class="fa fa-angle-right"></i> '.$LANG['kbs'].' :</td> - <td> - <div id="id_kbs" style="display:inline;"></div><input type="hidden" id="hid_kbs" /> - </td> - </tr>'; + <tr> + <td valign="top" class="td_title"> <i class="fa fa-angle-right"></i> '.$LANG['kbs'].' :</td> + <td colspan="2"> + <div id="id_kbs" style="display:inline;"></div><input type="hidden" id="hid_kbs" /> + </td> + </tr>'; } // lines for FIELDS if (isset($SETTINGS['item_extra_fields']) && $SETTINGS['item_extra_fields'] == 1) { foreach ($_SESSION['item_fields'] as $elem) { $itemCatName = $elem[0]; echo ' - <tr class="tr_fields hidden" id="tr_catfield_'.$elem[0].'"> - <td valign="top" class="td_title"> <i class="fa fa-angle-right"></i> '.$elem[1].' :</td> - <td></td> - </tr>'; + <tr class="tr_fields hidden" id="tr_catfield_'.$elem[0].'"> + <td valign="top" class="td_title"> <i class="fa fa-angle-right"></i> '.$elem[1].' :</td> + <td colspan="2"></td> + </tr>'; foreach ($elem[2] as $field) { echo ' <tr class="tr_cf tr_fields hidden" id="cf_tr_'.$field[0].'"> <td valign="top" class="td_title"> <i class="fa fa-caret-right"></i> <i>'.$field[1].'</i> :</td> - <td>'; + <td colspan="2">'; if ($field[3] === "masked") { echo ' <div id="id_field_'.htmlspecialchars($field[0]).'_'.$elem[0].'" style="float:left; cursor:pointer; width:300px;" class="fields_div unhide_masked_data pointer"></div><input type="hidden" id="hid_field_'.htmlspecialchars($field[0]).'_'.$elem[0].'" class="fields" />'; @@ -778,7 +782,7 @@ </div>'; } echo ' - <div style="display:none; padding:5px;" id="div_formulaire_edition_item_info" class="ui-state-default ui-corner-all"></div> + <div style="padding:5px;" id="div_formulaire_edition_item_info" class="ui-state-default ui-corner-all hidden"></div> </div> </form> </div>';
roles.load.php+22 −8 modified@@ -205,8 +205,6 @@ function(data) { } }); - - refresh_roles_matrix(); }); @@ -280,7 +278,7 @@ function refresh_roles_matrix(order) $("#div_loading").show(); //clean up - $("#roles_next, #roles_previous").hide(); + $(".roles_next, .roles_previous").hide(); //manage start query if (order == "next") { @@ -299,26 +297,42 @@ function refresh_roles_matrix(order) "sources/roles.queries.php", { type : "refresh_roles_matrix", - start : start + start : start, + filter : $("#filter_roles").val() }, function(data) { //decrypt data data = $.parseJSON(data); $("#matrice_droits").html(""); - if (data.new_table != "") { + if (data.new_table !== "") { $("#matrice_droits").html(data.new_table); - if (data.next < data.all) { - $("#roles_next").show(); + if (data.next < data.all && data.next >= 9) { + $(".roles_next").show(); } if (data.next >= 9 && data.previous >= 0) { - $("#roles_previous").show(); + $(".roles_previous").show(); } //manage next & previous arrows $('#next_role').val(data.next); $('#previous_role').val(data.previous); + + $("#filter_roles").val(""); } else { $("#matrice_droits").html(data.error); } + + // Prepare autocomplete for filterbox + //Prepare autocomplete for filter + $("#filter_roles") + .autocomplete({ + source: data.list_of_roles, + focus: function() { + // prevent value inserted on focus + return false; + } + } + ); + $("#div_loading").hide(); } );
roles.php+17 −4 modified@@ -50,17 +50,30 @@ <div class="title ui-widget-content ui-corner-all"> '.$LANG['admin_functions'].' <button title="'.htmlentities(strip_tags($LANG['add_role_tip']), ENT_QUOTES).'" onclick="OpenDialog(\'add_new_role\')" class="button" style="font-size:16px;"> - <i class="fa fa-plus"></i> + <span class="fa fa-plus"></span> </button> + + <span class="normal"><input id="filter_roles" class="ui-widget ui-corner-all" type="text" value="" placeholder="No filter" /></span> <button title="'.htmlentities(strip_tags($LANG['refresh_matrix']), ENT_QUOTES).'" onclick="refresh_roles_matrix()" class="button" style="font-size:16px;"> - <i class="fa fa-refresh"></i> + <span class="fa fa-refresh"></span> + </button> + + <button onclick="refresh_roles_matrix(\'previous\')" class="button roles_previous" style="font-size:16px;"> + <span class="fa fa-arrow-left"></span> + </button> + <button onclick="refresh_roles_matrix(\'next\')" class="button roles_next" style="font-size:16px;"> + <span class="fa fa-arrow-right"></span> </button> </div> <div style="line-height:20px;" align="center"> <div id="matrice_droits"></div> <div style=""> - <span class="fa fa-arrow-left" style="display:none;cursor:pointer" id="roles_previous" onclick="refresh_roles_matrix(\'previous\')"></span> - <span class="fa fa-arrow-right" style="display:none;cursor:pointer" id="roles_next" onclick="refresh_roles_matrix(\'next\')"></span> + <button onclick="refresh_roles_matrix(\'previous\')" class="button roles_previous" style="font-size:16px;"> + <span class="fa fa-arrow-left"></span> + </button> + <button onclick="refresh_roles_matrix(\'next\')" class="button roles_next" style="font-size:16px;"> + <span class="fa fa-arrow-right"></span> + </button> </div> </div> <input type="hidden" id="selected_function" />
sources/import.queries.php+1 −1 modified@@ -251,7 +251,7 @@ function sanitiseString($str, $crLFReplacement) // Show results to user. echo '[{"error":"no" , "output" : "'.$display.'"}]'; } - + //delete file unlink($file);
sources/roles.queries.php+18 −7 modified@@ -288,24 +288,33 @@ // Prepare POST variables $post_start = filter_input(INPUT_POST, 'start', FILTER_SANITIZE_NUMBER_INT); + $post_filter = filter_input(INPUT_POST, 'filter', FILTER_SANITIZE_STRING); $tree = $tree->getDescendants(); $texte = '<table><thead><tr><th>'.$LANG['groups'].'</th>'; $gpes_ok = array(); $gpes_nok = array(); - $tab_fonctions = array(); + $arrRolesTitle = array(); $arrRoles = array(); $display_nb = 8; $sql_limit = ""; $next = 1; $previous = 1; + $where = ""; + + // Should we filter on role names + if (empty($post_filter) === false) { + $where = " WHERE title LIKE '".$post_filter."%'"; + } //count nb of roles $arrUserRoles = array_filter($_SESSION['user_roles']); - if (count($arrUserRoles) == 0 || $_SESSION['is_admin'] == 1) { - $where = ""; - } else { - $where = " WHERE id IN (".implode(',', $arrUserRoles).")"; + if (count($arrUserRoles) >= 0 && $_SESSION['is_admin'] !== "1") { + if (empty($where) === false) { + $where = " WHERE id IN (".implode(',', $arrUserRoles).")"; + } else { + $where .= " AND id IN (".implode(',', $arrUserRoles).")"; + } } DB::query("SELECT * FROM ".prefix_table("roles_title").$where); $roles_count = DB::count(); @@ -318,7 +327,7 @@ $previous = $start - $display_nb; } $sql_limit = " LIMIT ".mysqli_real_escape_string($link, filter_var($start, FILTER_SANITIZE_NUMBER_INT)).", ".mysqli_real_escape_string($link, filter_var($display_nb, FILTER_SANITIZE_NUMBER_INT)); - $next = $start + $display_nb; + $next = $start + $display_nb + 1; } // array of roles for actual user @@ -348,6 +357,7 @@ '<div style=\'margin-top:-8px;\'>[ '.$SETTINGS_EXT['pwComplexity'][$record['complexity']][1].' ]</div></th>'; array_push($arrRoles, $record['id']); + array_push($arrRolesTitle, $record['title']); } } $texte .= '</tr></thead><tbody>'; @@ -419,7 +429,8 @@ "new_table" => $texte, "all" => $roles_count, "next" => $next, - "previous" => $previous + "previous" => $previous, + "list_of_roles" => $arrRolesTitle ); $return_values = json_encode($return_values, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP);
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
4- github.com/nilsteampassnet/TeamPass/commit/ef32e9c28b6ddc33cee8a25255bc8da54434af3envdPatchWEB
- blog.amossys.fr/teampass-multiple-cve-01.htmlnvdExploitTechnical DescriptionThird Party AdvisoryWEB
- github.com/advisories/GHSA-xvjf-394g-phrrghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2017-15053ghsaADVISORY
News mentions
0No linked articles in our index yet.