Skip to content

Commit

Permalink
Several security improvements
Browse files Browse the repository at this point in the history
New feature: one time item view for anonymous user
  • Loading branch information
nilsteampassnet committed Apr 26, 2014
1 parent 8e70cd0 commit fd549b2
Show file tree
Hide file tree
Showing 10 changed files with 241 additions and 32 deletions.
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#544 - DataTables warning: JSON data from server could not be parsed
Fork from slimm609 - Encrypted Sessions and CSRFGuard enabled
Issues with folder creation in "personal folder"
New: one time view page for anonymous user

2.1.19
#413 - fix for PHP Parse error: syntax error, unexpected '['
Expand Down
Binary file added includes/images/globe-share.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions includes/include.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,14 @@
$k['admin_full_right'] = true;
$k['admin_no_info'] = false;
$k['copyright'] = " © 2009 - 2014";
$k['otv_expiration_period'] = 604800; // 1 week
$k['allowedTags'] = "<b><i><sup><sub><em><strong><u><br><br /><a><strike><ul><blockquote><blockquote><img><li><h1><h2><h3><h4><h5><ol><small><font>";

@define('ERR_NOT_ALLOWED', "1000");
@define('ERR_NOT_EXIST', "1001");
@define('ERR_SESS_EXPIRED', "1002");
@define('ERR_NO_MCRYPT', "1003");
@define('ERR_VALID_SESSION', "1004");

// Management Pages
$mngPages = array(
Expand Down
2 changes: 2 additions & 0 deletions includes/language/english.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
$TeamPass_url = $_SESSION['settings']['cpassman_url'];
}

$txt['one_time_item_view'] = "One time view link";
$txt['one_time_view_item_url_box'] = "Share the One-Time URL with a person of Trust <br><br>#URL#<br><br>Remember that this link will only be visible one time until the #DAY#";
$txt['url_copied_clipboard'] = "URL copied in clipboard";
$txt['url_copy'] = "Copy URL in clipboard";

Expand Down
45 changes: 28 additions & 17 deletions index.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
*
* @file index.php
* @author Nils Laumaillé
* @version 2.1.19
* @version 2.1.20
* @copyright (c) 2009-2014 Nils Laumaillé
* @licensing GNU AFFERO GPL 3.0
* @link http://www.teampass.net
Expand Down Expand Up @@ -51,15 +51,12 @@

//load main functions needed
require_once 'sources/main.functions.php';
// Load CORE
require_once $_SESSION['settings']['cpassman_dir'].'/sources/core.php';

/* DEFINE WHAT LANGUAGE TO USE */
if (!isset($_SESSION['user_id']) && !isset($_POST['language'])) {
//get default language
/*$dataLanguage =
$db->fetchRow(
"SELECT valeur FROM ".$pre."misc
WHERE type = 'admin' AND intitule = 'default_language'"
);*/
$dataLanguage = $db->queryGetRow(
"misc",
array(
Expand Down Expand Up @@ -91,12 +88,16 @@
}
}
// Load user languages files
require_once $_SESSION['settings']['cpassman_dir'].'/includes/language/'.$_SESSION['user_language'].'.php';
if (isset($_GET['page']) && $_GET['page'] == "kb") {
require_once $_SESSION['settings']['cpassman_dir'].'/includes/language/'.$_SESSION['user_language'].'_kb.php';
if (in_array($_SESSION['user_language'], $languagesList)) {
require_once $_SESSION['settings']['cpassman_dir'].'/includes/language/'.$_SESSION['user_language'].'.php';
if (isset($_GET['page']) && $_GET['page'] == "kb") {
require_once $_SESSION['settings']['cpassman_dir'].'/includes/language/'.$_SESSION['user_language'].'_kb.php';
}
} else {
$_SESSION['error']['code'] = ERR_NOT_ALLOWED; //not allowed page
include 'error.php';
}
// Load CORE
require_once $_SESSION['settings']['cpassman_dir'].'/sources/core.php';

// Load links, css and javascripts
@require_once $_SESSION['settings']['cpassman_dir'].'/load.php';
?>
Expand Down Expand Up @@ -208,7 +209,8 @@
</div>';
}
// Display language menu
echo '
if (!isset($_GET['otv'])) {
echo '
<div style="float:right;">
<dl id="flags" class="dropdown">
<dt><img src="includes/images/flags/'.$_SESSION['user_language_flag'].'" alt="" /></dt>
Expand All @@ -218,7 +220,9 @@
</ul>
</dd>
</dl>
</div>
</div>';
}
echo '
</div>';

/* LAST SEEN */
Expand Down Expand Up @@ -299,7 +303,9 @@
<br />
<button title="'.$txt['history'].'" id="menu_button_history" class="" onclick="OpenDialog(\'div_item_history\', \'false\')"><img src="includes/images/report.png" id="div_history" alt="" /></button>
<br />
<button title="'.$txt['share'].'" id="menu_button_share" class="" onclick="OpenDialog(\'div_item_share\', \'false\')"><img src="includes/images/share.png" id="div_share" alt="" /></button>';
<button title="'.$txt['share'].'" id="menu_button_share" class="" onclick="OpenDialog(\'div_item_share\', \'false\')"><img src="includes/images/share.png" id="div_share" alt="" /></button>
<br />
<button title="'.$txt['one_time_item_view'].'" id="menu_button_otv" class="" onclick="prepareOneTimeView()"><img src="includes/images/globe-share.png" id="div_otv" alt="" /></button>';
if (isset($_SESSION['settings']['enable_email_notification_on_item_shown']) && $_SESSION['settings']['enable_email_notification_on_item_shown'] == 1) {
echo '
<br />
Expand Down Expand Up @@ -458,9 +464,14 @@ class="ui-state-highlight ui-corner-all" id="div_maintenance">
include 'error.php';
} elseif ((!isset($_SESSION['validite_pw']) || empty($_SESSION['validite_pw']) || empty($_SESSION['user_id'])) && isset($_GET['otv']) && $_GET['otv'] == "true") {
// case where one-shot viewer
if (isset($_GET['session']) && !empty($_GET['session'])) {
include 'otv.php?session='.$_GET['session'];
} else {
if (
isset($_GET['code']) && !empty($_GET['code'])
&& isset($_GET['item_id']) && !empty($_GET['item_id'])
&& isset($_GET['stamp']) && !empty($_GET['stamp'])
&& isset($_GET['otv_id'])
) {
include 'otv.php';
} else {
$_SESSION['error']['code'] = ERR_VALID_SESSION;
$_SESSION['initial_url'] = substr($_SERVER["REQUEST_URI"], strpos($_SERVER["REQUEST_URI"], "index.php?"));
include 'error.php';
Expand Down
34 changes: 30 additions & 4 deletions items.load.php
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ function ListerItems(groupe_id, restricted, start)
if ($(".tr_fields") != undefined) $(".tr_fields, .newItemCat, .editItemCat").hide();

//Disable menu buttons
$('#menu_button_edit_item,#menu_button_del_item,#menu_button_add_fav,#menu_button_del_fav,#menu_button_show_pw,#menu_button_copy_pw,#menu_button_copy_login,#menu_button_copy_link,#menu_button_copy_item,#menu_button_notify,#menu_button_history,#menu_button_share').attr('disabled', 'disabled');
$('#menu_button_edit_item,#menu_button_del_item,#menu_button_add_fav,#menu_button_del_fav,#menu_button_show_pw,#menu_button_copy_pw,#menu_button_copy_login,#menu_button_copy_link,#menu_button_copy_item,#menu_button_notify,#menu_button_history,#menu_button_share,#menu_button_otv').attr('disabled', 'disabled');

// clear existing clips
//ZeroClipboard.destroy();
Expand Down Expand Up @@ -197,7 +197,7 @@ function(data) {
} else if (data.error == "not_authorized") {
//warn user
$("#hid_cat").val("");
$("#menu_button_copy_item, #menu_button_add_group, #menu_button_edit_group, #menu_button_del_group, #menu_button_add_item, #menu_button_edit_item, #menu_button_del_item, #menu_button_history, #menu_button_share").attr('disabled', 'disabled');
$("#menu_button_copy_item, #menu_button_add_group, #menu_button_edit_group, #menu_button_del_group, #menu_button_add_item, #menu_button_edit_item, #menu_button_del_item, #menu_button_history, #menu_button_share, #menu_button_otv").attr('disabled', 'disabled');
$("#item_details_nok").show();
$("#item_details_ok, #item_details_no_personal_saltkey").hide();
$("#items_list_loader").hide();
Expand Down Expand Up @@ -1115,9 +1115,9 @@ function(data) {

// disable share button for personal folder
if ($("#recherche_group_pf").val() == 1) {
$("#menu_button_share").attr('disabled', 'disabled');
$("#menu_button_share, #menu_button_otv").attr('disabled', 'disabled');
} else {
$("#menu_button_share").prop("disabled", false);
$("#menu_button_share, #menu_button_otv").prop("disabled", false);
}

//Manage to deleted information
Expand Down Expand Up @@ -2600,4 +2600,30 @@ function aes_decrypt(text)
{
return Aes.Ctr.decrypt(text, "<?php echo $_SESSION['key'];?>", 256);
}

/*
* Launch the redirection to OTV page
*/
function prepareOneTimeView()
{
//Send query
$.post(
"sources/items.queries.php",
{
type : "generate_OTV_url",
id : $("#id_item").val(),
key : "<?php echo $_SESSION['key'];?>"
},
function(data) {
//check if format error
if (data[0].error == "") {
$("#div_dialog_message").dialog('open');
$("#div_dialog_message_text").html(data[0].url);
} else {
$("#item_history_log_error").html(data[0].error).show();
}
},
"json"
);
}
</script>
14 changes: 7 additions & 7 deletions items.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
*/

if (
!isset($_SESSION['CPM']) || $_SESSION['CPM'] != 1 ||
!isset($_SESSION['user_id']) || empty($_SESSION['user_id']) ||
!isset($_SESSION['key']) || empty($_SESSION['key']))
!isset($_SESSION['CPM']) || $_SESSION['CPM'] != 1 ||
!isset($_SESSION['user_id']) || empty($_SESSION['user_id']) ||
!isset($_SESSION['key']) || empty($_SESSION['key']))
{
die('Hacking attempt...');
}
Expand Down Expand Up @@ -74,11 +74,11 @@
$selectVisibleFoldersOptions = $selectVisibleNonPersonalFoldersOptions = "";
// Hidden things
echo '
<input type="hidden" name="hid_cat" id="hid_cat" value="', isset($_GET['group']) ? $_GET['group'] : "", '" />
<input type="hidden" name="hid_cat" id="hid_cat" value="', isset($_GET['group']) ? htmlspecialchars($_GET['group']) : "", '" />
<input type="hidden" id="complexite_groupe" />
<input type="hidden" name="selected_items" id="selected_items" />
<input type="hidden" name="input_liste_utilisateurs" id="input_liste_utilisateurs" value="'.$usersString.'" />
<input type="hidden" name="input_list_roles" id="input_list_roles" value="'.htmlentities($listRoles, ENT_QUOTES, 'UTF-8').'" />
<input type="hidden" name="input_list_roles" id="input_list_roles" value="'.htmlspecialchars(htmlentities($listRoles, ENT_QUOTES, 'UTF-8')).'" />
<input type="hidden" id="bloquer_creation_complexite" />
<input type="hidden" id="bloquer_modification_complexite" />
<input type="hidden" id="error_detected" />
Expand All @@ -87,7 +87,7 @@
<input type="hidden" id="richtext_on" value="1" />
<input type="hidden" id="query_next_start" value="0" />
<input type="hidden" id="display_categories" value="0" />
<input type="hidden" id="nb_items_to_display_once" value="', isset($_SESSION['settings']['nb_items_by_query']) ? $_SESSION['settings']['nb_items_by_query'] : 'auto', '" />
<input type="hidden" id="nb_items_to_display_once" value="', isset($_SESSION['settings']['nb_items_by_query']) ? htmlspecialchars($_SESSION['settings']['nb_items_by_query']) : 'auto', '" />
<input type="hidden" id="user_is_read_only" value="', isset($_SESSION['user_read_only']) && $_SESSION['user_read_only'] == 1 ? '1' : '', '" />
<input type="hidden" id="request_ongoing" />
<input type="hidden" id="request_lastItem" />
Expand Down Expand Up @@ -118,7 +118,7 @@
$firstGroup = "";
}
echo '
<input type="hidden" name="jstree_group_selected" id="jstree_group_selected" value="'.$firstGroup.'" />';
<input type="hidden" name="jstree_group_selected" id="jstree_group_selected" value="'.htmlspecialchars($firstGroup).'" />';

echo '
<div id="div_items">';
Expand Down
103 changes: 103 additions & 0 deletions otv.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
<?php
/**
* @file otv.php
* @author Nils Laumaillé
* @version 2.1.20
* @copyright (c) 2009-2014 Nils Laumaillé
* @licensing GNU AFFERO GPL 3.0
* @link http://www.teampass.net
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/

require_once('sources/sessions.php');
@session_start();
if (!isset($_SESSION['CPM']) || $_SESSION['CPM'] != 1) {
die('Hacking attempt...');
}

$html = "";
if (
filter_var($_GET['code'], FILTER_SANITIZE_STRING) != ""
&& filter_var($_GET['item_id'], FILTER_SANITIZE_STRING) >= 0
&& filter_var($_GET['stamp'], FILTER_SANITIZE_STRING) >= 0
&& filter_var($_GET['otv_id'], FILTER_SANITIZE_STRING) >= 0
) {
//Include files
require_once $_SESSION['settings']['cpassman_dir'].'/includes/settings.php';
require_once $_SESSION['settings']['cpassman_dir'].'/includes/include.php';
require_once $_SESSION['settings']['cpassman_dir'].'/sources/SplClassLoader.php';

// connect to DB
$db = new SplClassLoader('Database\Core', '../includes/libraries');
$db->register();
$db = new Database\Core\DbCore($server, $user, $pass, $database, $pre);
$db->connect();

// Include main functions used by TeamPass
require_once 'sources/main.functions.php';

// check session validity
$data = $db->queryGetRow(
"otv",
array(
"timestamp",
"code",
"item_id"
),
array(
"id" => intval($_GET['otv_id'])
)
);
if (
$data[0] == $_GET['stamp']
&& $data[1] == $_GET['code']
&& $data[2] == $_GET['item_id']
) {
// otv is too old
if ($data[0] < (time() - $k['otv_expiration_period']) ) {
$html = "Link is too old!";
} else {
$dataItem = $db->queryFirst(
"SELECT *
FROM ".$pre."items as i
INNER JOIN ".$pre."log_items as l ON (l.id_item = i.id)
WHERE i.id=".intval($_GET['item_id'])."
AND l.action = 'at_creation'"
);

// get data
$pw = decrypt($dataItem['pw']);
$label = $dataItem['label'];
$email = $dataItem['email'];
$url = $dataItem['url'];
$description = preg_replace('/(?<!\\r)\\n+(?!\\r)/', '', strip_tags($dataItem['description'], $k['allowedTags']));
$login = str_replace('"', '&quot;', $dataItem['login']);

// display data
$html = "<div style='margin:30px;'>".
"<div style='font-size:20px;font-weight:bold;'>Welcome to One-Time item view page.</div>".
"<div style='font-style:italic;'>Here are the details of the Item that has been shared to you</div>".
"<div style='margin-top:10px;'><table>".
"<tr><td>Label:</td><td>" . $label . "</td</tr>".
"<tr><td>Password:</td><td>" . $pw . "</td</tr>".
"<tr><td>Description:</td><td>" . $description . "</td</tr>".
"<tr><td>login:</td><td>" . $login . "</td</tr>".
"<tr><td>URL:</td><td>" . $url ."</td</tr>".
"</table></div>".
"<div style='margin-top:30px;'>Copy carefully the data you need. This page is only visible once.</div>".
"</div>";

// delete entry
//$db->query("DELETE FROM ".$pre."otv WHERE id = '".intval($_GET['item_id'])."'");
}
} else {
$html = "Not a valid page!";
}
} else {
$html = "Not a valid page!";
}

echo $html;
9 changes: 7 additions & 2 deletions sources/find.queries.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

//Columns name
$aColumns = array('id', 'label', 'description', 'tags', 'id_tree', 'folder', 'login');
$aSortTypes = array('ASC', 'DESC');

//init SQL variables
$sOrder = $sLimit = "";
Expand Down Expand Up @@ -80,9 +81,10 @@
}

//Ordering
if (isset($_GET['iSortCol_0'])) {
if (isset($_GET['iSortCol_0']) && in_array($_GET['iSortCol_0'], $aSortTypes)) {
$sOrder = "ORDER BY ";
for ($i=0; $i<intval($_GET['iSortingCols']); $i++) {

if (
$_GET[ 'bSortable_'.filter_var($_GET['iSortCol_'.$i], FILTER_SANITIZE_NUMBER_INT)] == "true" &&
preg_match("#^(asc|desc)\$#i", $_GET['sSortDir_'.$i])
Expand All @@ -96,8 +98,11 @@
if ($sOrder == "ORDER BY") {
$sOrder = "";
}
} else if (!in_array($_GET['iSortCol_0'], $aSortTypes)) {
// possible attack - stop
echo '[{}]';
}
//echo $sOrder;

/*
* Filtering
* NOTE this does not match the built-in DataTables filtering which does it
Expand Down

0 comments on commit fd549b2

Please sign in to comment.