mirror of
https://gitlab.com/davical-project/davical.git
synced 2026-09-23 06:39:18 +00:00
turn cherry-picked commits into a quilt patch and prepare security upload
This commit is contained in:
parent
9d12734793
commit
2ab18d802e
8
debian/changelog
vendored
8
debian/changelog
vendored
@ -1,3 +1,11 @@
|
|||||||
|
davical (1.1.8-1+deb10u1) buster-security; urgency=high
|
||||||
|
|
||||||
|
* Fix three cross-site scripting and cross-site request forgery
|
||||||
|
vulnerabilities in the web administration front-end:
|
||||||
|
CVE-2019-18345 CVE-2019-18346 CVE-2019-18347 (closes: #946343)
|
||||||
|
|
||||||
|
-- Florian Schlichting <fsfs@debian.org> Thu, 12 Dec 2019 01:08:40 +0800
|
||||||
|
|
||||||
davical (1.1.8-1) unstable; urgency=medium
|
davical (1.1.8-1) unstable; urgency=medium
|
||||||
|
|
||||||
* New upstream release
|
* New upstream release
|
||||||
|
|||||||
357
debian/patches/CVE-2019-18345_183456_183457
vendored
Normal file
357
debian/patches/CVE-2019-18345_183456_183457
vendored
Normal file
@ -0,0 +1,357 @@
|
|||||||
|
From: Florian Schlichting <fsfs@debian.org>
|
||||||
|
Subject: fix CVE-2019-18345 CVE-2019-18346 CVE-2019-18347
|
||||||
|
This combines four upstream commits contained in davical 1.1.9.2:
|
||||||
|
86a8ec530 Added CSRF to the application, Mitigated the XSS vulnerabilities reported by HackDefense
|
||||||
|
1a917b30e Addressed comments made by @puck42
|
||||||
|
c8a0ca453 Fix CSRF not being checked in collection-edit.php
|
||||||
|
e2c6b927c HTTP_REFERER will usually be unset for caldav requests, prevent "Undefined index" warnings
|
||||||
|
The fix was developed by nielsvangijzen <n.van.gijzen@gmail.com>
|
||||||
|
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=946343
|
||||||
|
|
||||||
|
diff --git a/htdocs/admin.php b/htdocs/admin.php
|
||||||
|
index b48b8558..3efe4b8a 100644
|
||||||
|
--- a/htdocs/admin.php
|
||||||
|
+++ b/htdocs/admin.php
|
||||||
|
@@ -1,4 +1,5 @@
|
||||||
|
<?php
|
||||||
|
+
|
||||||
|
require_once('./always.php');
|
||||||
|
require_once('classEditor.php');
|
||||||
|
require_once('classBrowser.php');
|
||||||
|
@@ -25,7 +26,12 @@ require_once('interactive-page.php');
|
||||||
|
$page_elements = array();
|
||||||
|
$code_file = sprintf( 'ui/%s-%s.php', $component, $action );
|
||||||
|
if ( ! @include_once( $code_file ) ) {
|
||||||
|
- $c->messages[] = sprintf('No page found to %s %s%s%s', $action, ($action == 'browse' ? '' : 'a '), $component, ($action == 'browse' ? 's' : ''));
|
||||||
|
+ $c->messages[] = sprintf(
|
||||||
|
+ 'No page found to %s %s%s%s',
|
||||||
|
+ htmlspecialchars($action),
|
||||||
|
+ ($action == 'browse' ? '' : 'a '), $component,
|
||||||
|
+ ($action == 'browse' ? 's' : '')
|
||||||
|
+ );
|
||||||
|
include('page-header.php');
|
||||||
|
include('page-footer.php');
|
||||||
|
@ob_flush(); exit(0);
|
||||||
|
diff --git a/htdocs/always.php b/htdocs/always.php
|
||||||
|
index 3e457bee..cd223e7d 100644
|
||||||
|
--- a/htdocs/always.php
|
||||||
|
+++ b/htdocs/always.php
|
||||||
|
@@ -8,6 +8,47 @@
|
||||||
|
|
||||||
|
if ( preg_match('{/always.php$}', $_SERVER['SCRIPT_NAME'] ) ) header('Location: index.php');
|
||||||
|
|
||||||
|
+// XSS Protection
|
||||||
|
+function filter_post(&$val, $index) {
|
||||||
|
+ if(in_array($index, ["newpass1", "newpass2"])) return;
|
||||||
|
+
|
||||||
|
+ switch (gettype($val)) {
|
||||||
|
+ case "string":
|
||||||
|
+ $val = htmlspecialchars($val);
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ case "array":
|
||||||
|
+ array_walk_recursive($val, function(&$v) {
|
||||||
|
+ if (gettype($v) == "string") {
|
||||||
|
+ $v = htmlspecialchars($v);
|
||||||
|
+ }
|
||||||
|
+ });
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+function clean_get() {
|
||||||
|
+ $temp = [];
|
||||||
|
+
|
||||||
|
+ foreach($_GET as $key => $value) {
|
||||||
|
+ // XSS is possible in both key and values
|
||||||
|
+ $k = htmlspecialchars($key);
|
||||||
|
+ $v = htmlspecialchars($value);
|
||||||
|
+ $temp[$k] = $v;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return $temp;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+// Before anything else is executed we filter all the user input, a lot of code in this project
|
||||||
|
+// relies on variables that are easily manipulated by the user. These lines and functions filter all those variables.
|
||||||
|
+if(isset($_POST)) array_walk($_POST, 'filter_post');
|
||||||
|
+$_GET = clean_get();
|
||||||
|
+$_SERVER['REQUEST_URI'] = str_replace("&", "&", htmlspecialchars($_SERVER['REQUEST_URI']));
|
||||||
|
+$_SERVER['HTTP_REFERER'] = htmlspecialchars(@$_SERVER['HTTP_REFERER']);
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+
|
||||||
|
// Ensure the configuration starts out as an empty object.
|
||||||
|
$c = (object) array();
|
||||||
|
$c->script_start_time = microtime(true);
|
||||||
|
diff --git a/inc/csrf_tokens.php b/inc/csrf_tokens.php
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..9d05ec4e
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/inc/csrf_tokens.php
|
||||||
|
@@ -0,0 +1,119 @@
|
||||||
|
+<?php
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * Update the CSRF token
|
||||||
|
+ */
|
||||||
|
+function updateCsrf() {
|
||||||
|
+ if(!sessionExists()) {
|
||||||
|
+ session_start();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ $_SESSION['csrf_token'] = generateCsrf();
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * Check whether a session is currently active
|
||||||
|
+ * @return bool
|
||||||
|
+ */
|
||||||
|
+function sessionExists() {
|
||||||
|
+ if (version_compare(phpversion(), '5.4.0', '>')) {
|
||||||
|
+ return session_id() !== '';
|
||||||
|
+ } else {
|
||||||
|
+ return session_status() === PHP_SESSION_ACTIVE;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * Generate a CSRF token, it chooses from 3 different functions based on PHP version and modules
|
||||||
|
+ * @return bool|string
|
||||||
|
+ */
|
||||||
|
+function generateCsrf() {
|
||||||
|
+ if (version_compare(phpversion(), '7.0.0', '>=')) {
|
||||||
|
+ $random = generateRandom();
|
||||||
|
+ if($random !== false) return $random;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (function_exists('mcrypt_create_iv')) {
|
||||||
|
+ return generateMcrypt();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return generateOpenssl();
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * Generate a random string using the PHP built in function random_bytes
|
||||||
|
+ * @version 7.0.0
|
||||||
|
+ * @return bool|string
|
||||||
|
+ */
|
||||||
|
+function generateRandom() {
|
||||||
|
+ try {
|
||||||
|
+ return bin2hex(random_bytes(32));
|
||||||
|
+ } catch (Exception $e) {
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * Generate a random string using MCRYPT
|
||||||
|
+ * @return string
|
||||||
|
+ */
|
||||||
|
+function generateMcrypt() {
|
||||||
|
+ return bin2hex(mcrypt_create_iv(32, MCRYPT_DEV_URANDOM));
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * Generate a random string using OpenSSL
|
||||||
|
+ * @return string
|
||||||
|
+ */
|
||||||
|
+function generateOpenssl() {
|
||||||
|
+ return bin2hex(openssl_random_pseudo_bytes(32));
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * Checks for session and the existence of a key
|
||||||
|
+ * after ensuring both are present it returns the
|
||||||
|
+ * current CSRF token
|
||||||
|
+ * @return string
|
||||||
|
+ */
|
||||||
|
+function getCsrf() {
|
||||||
|
+ if(!sessionExists()) {
|
||||||
|
+ session_start();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if(!array_key_exists('csrf_token', $_SESSION)) {
|
||||||
|
+ updateCsrf();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return $_SESSION['csrf_token'];
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * Get a hidden CSRF input field to be used in forms
|
||||||
|
+ * @return string
|
||||||
|
+ */
|
||||||
|
+function getCsrfField() {
|
||||||
|
+ return sprintf("<input type=\"hidden\" name=\"csrf_token\" value=\"%s\">", getCsrf());
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * Verify a given CSRF token
|
||||||
|
+ * @param $csrf_token
|
||||||
|
+ * @return bool
|
||||||
|
+ */
|
||||||
|
+function verifyCsrf($csrf_token) {
|
||||||
|
+ $current_csrf = getCsrf();
|
||||||
|
+ // Prefer hash_equals over === because the latter is vulnerable to timing attacks
|
||||||
|
+ if(function_exists('hash_equals')) {
|
||||||
|
+ return hash_equals($current_csrf, $csrf_token);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return $current_csrf === $csrf_token;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * Uses the global $_POST variable to check if the CSRF token is valid
|
||||||
|
+ * @return bool
|
||||||
|
+ */
|
||||||
|
+function verifyCsrfPost() {
|
||||||
|
+ return (isset($_POST['csrf_token']) && verifyCsrf($_POST['csrf_token']));
|
||||||
|
+}
|
||||||
|
\ No newline at end of file
|
||||||
|
diff --git a/inc/interactive-page.php b/inc/interactive-page.php
|
||||||
|
index 86c88898..c0e87389 100644
|
||||||
|
--- a/inc/interactive-page.php
|
||||||
|
+++ b/inc/interactive-page.php
|
||||||
|
@@ -20,6 +20,9 @@ if ( isset($_SERVER['SCRIPT_NAME']) ) {
|
||||||
|
if ( $wiki_help == 'admin' ) {
|
||||||
|
$wiki_help .= '/' . $_GET['t'] . '/' . $_GET['action'];
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ $wiki_help = htmlspecialchars($wiki_help);
|
||||||
|
+
|
||||||
|
$wiki_help = 'w/Help/'.$wiki_help;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/inc/ui/collection-edit.php b/inc/ui/collection-edit.php
|
||||||
|
index 4fa778c9..81bffb0b 100644
|
||||||
|
--- a/inc/ui/collection-edit.php
|
||||||
|
+++ b/inc/ui/collection-edit.php
|
||||||
|
@@ -1,4 +1,5 @@
|
||||||
|
<?php
|
||||||
|
+require_once("csrf_tokens.php");
|
||||||
|
|
||||||
|
// Editor component for collections
|
||||||
|
$editor = new Editor(translate('Collection'), 'collection');
|
||||||
|
@@ -65,6 +66,12 @@ if ( isset($privsql) ) {
|
||||||
|
$can_write_collection = ($session->AllowedTo('Admin') || (bindec($permissions->priv) & privilege_to_bits('DAV::bind')) );
|
||||||
|
}
|
||||||
|
|
||||||
|
+// Verify CSRF token
|
||||||
|
+if($_SERVER['REQUEST_METHOD'] === "POST" && !verifyCsrfPost()) {
|
||||||
|
+ $c->messages[] = i18n("A valid CSRF token must be provided");
|
||||||
|
+ $can_write_collection = false;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
dbg_error_log('collection-edit', "Can write collection: %s", ($can_write_collection? 'yes' : 'no') );
|
||||||
|
|
||||||
|
$pwstars = '@@@@@@@@@@';
|
||||||
|
@@ -273,6 +280,7 @@ EOPRIV;
|
||||||
|
$submit_row = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
+$csrf_field = getCsrfField();
|
||||||
|
$id = $editor->Value('collection_id');
|
||||||
|
$template = <<<EOTEMPLATE
|
||||||
|
##form##
|
||||||
|
@@ -384,6 +392,7 @@ label.privilege {
|
||||||
|
<tr> <th class="right">$prompt_description:</th> <td class="left">##description.textarea.78x6##</td> </tr>
|
||||||
|
$submit_row
|
||||||
|
</table>
|
||||||
|
+$csrf_field
|
||||||
|
</form>
|
||||||
|
<script language="javascript">
|
||||||
|
toggle_enabled('fld_is_calendar','=fld_timezone','=fld_schedule_transp','!fld_is_addressbook');
|
||||||
|
@@ -453,9 +462,11 @@ if ( $editor->Available() ) {
|
||||||
|
$orig_to_id = $row_data->to_principal;
|
||||||
|
$form_id = $grantrow->Id();
|
||||||
|
$form_url = preg_replace( '#&(edit|delete)_grant=\d+#', '', $_SERVER['REQUEST_URI'] );
|
||||||
|
+ $csrf_field = getCsrfField();
|
||||||
|
|
||||||
|
$template = <<<EOTEMPLATE
|
||||||
|
<form method="POST" enctype="multipart/form-data" id="form_$form_id" action="$form_url">
|
||||||
|
+ $csrf_field
|
||||||
|
<td class="left" colspan="2"><input type="hidden" name="id" value="$id"><input type="hidden" name="orig_to_id" value="$orig_to_id">##to_principal.select##</td>
|
||||||
|
<td class="left" colspan="2">
|
||||||
|
<input type="button" value="$btn_all" class="submit" title="$btn_all_title" onclick="toggle_privileges('grant_privileges', 'all', 'form_$form_id');">
|
||||||
|
diff --git a/inc/ui/principal-edit.php b/inc/ui/principal-edit.php
|
||||||
|
index 2e37cd59..6646b7c2 100644
|
||||||
|
--- a/inc/ui/principal-edit.php
|
||||||
|
+++ b/inc/ui/principal-edit.php
|
||||||
|
@@ -1,4 +1,5 @@
|
||||||
|
<?php
|
||||||
|
+require_once("csrf_tokens.php");
|
||||||
|
|
||||||
|
param_to_global('id', 'int', 'old_id', 'principal_id' );
|
||||||
|
|
||||||
|
@@ -181,6 +182,13 @@ function principal_editor() {
|
||||||
|
$editor->AddAttribute( 'email', 'title', translate("The email address identifies principals when processing invitations and freebusy lookups. It should be set to a unique value.") );
|
||||||
|
$editor->SetWhere( 'principal_id='.$id );
|
||||||
|
|
||||||
|
+ if($_SERVER['REQUEST_METHOD'] === "POST" && !verifyCsrfPost()) {
|
||||||
|
+ $c->messages[] = i18n("A valid CSRF token must be provided");
|
||||||
|
+ $can_write_principal = false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ $csrf_field = getCsrfField();
|
||||||
|
+
|
||||||
|
$editor->AddField('is_admin', 'EXISTS( SELECT 1 FROM role_member WHERE role_no = 1 AND role_member.user_no = dav_principal.user_no )' );
|
||||||
|
$editor->AddAttribute('is_admin', 'title', translate('An "Administrator" user has full rights to the whole DAViCal System'));
|
||||||
|
|
||||||
|
@@ -396,6 +404,7 @@ label.privilege {
|
||||||
|
<tr> <th class="right" style="white-space:normal;">$prompt_privileges:</th><td class="left">$privs_html</td> </tr>
|
||||||
|
$submit_row
|
||||||
|
</table>
|
||||||
|
+ $csrf_field
|
||||||
|
</form>
|
||||||
|
EOTEMPLATE;
|
||||||
|
|
||||||
|
@@ -545,9 +554,11 @@ function edit_group_row( $row_data ) {
|
||||||
|
global $id, $grouprow;
|
||||||
|
|
||||||
|
$form_url = preg_replace( '#&(edit|delete)_group=\d+#', '', $_SERVER['REQUEST_URI'] );
|
||||||
|
+ $csrf_field = getCsrfField();
|
||||||
|
|
||||||
|
$template = <<<EOTEMPLATE
|
||||||
|
<form method="POST" enctype="multipart/form-data" id="add_group" action="$form_url">
|
||||||
|
+ $csrf_field
|
||||||
|
<td class="left"><input type="hidden" name="id" value="$id"></td>
|
||||||
|
<td class="left" colspan="3">##member_id.select## ##Add.submit##</td>
|
||||||
|
<td class="center"></td>
|
||||||
|
@@ -660,8 +671,11 @@ function edit_grant_row_principal( $row_data ) {
|
||||||
|
$form_id = $grantrow->Id();
|
||||||
|
$form_url = preg_replace( '#&(edit|delete)_grant=\d+#', '', $_SERVER['REQUEST_URI'] );
|
||||||
|
|
||||||
|
+ $csrf_field = getCsrfField();
|
||||||
|
+
|
||||||
|
$template = <<<EOTEMPLATE
|
||||||
|
<form method="POST" enctype="multipart/form-data" id="form_$form_id" action="$form_url">
|
||||||
|
+ $csrf_field
|
||||||
|
<td class="left" colspan="2"><input type="hidden" name="id" value="$id"><input type="hidden" name="orig_to_id" value="$orig_to_id">##to_principal.select##</td>
|
||||||
|
<td class="left" colspan="2">$privs_html</td>
|
||||||
|
<td class="center">##submit##</td>
|
||||||
|
@@ -788,9 +802,11 @@ function edit_ticket_row( $row_data ) {
|
||||||
|
$form_id = $ticketrow->Id();
|
||||||
|
$ticket_id = $row_data->ticket_id;
|
||||||
|
$form_url = preg_replace( '#&(edit|delete)_[a-z]+=\d+#', '', $_SERVER['REQUEST_URI'] );
|
||||||
|
+ $csrf_field = getCsrfField();
|
||||||
|
|
||||||
|
$template = <<<EOTEMPLATE
|
||||||
|
<form method="POST" enctype="multipart/form-data" id="form_$form_id" action="$form_url">
|
||||||
|
+ $csrf_field
|
||||||
|
<td class="left">$ticket_id<input type="hidden" name="id" value="$id"><input type="hidden" name="ticket_id" value="$ticket_id"></td>
|
||||||
|
<td class="left"><input type="text" name="target" value="$row_data->target"></td>
|
||||||
|
<td class="left"><input type="text" name="expires" value="$row_data->expires" size="10"></td>
|
||||||
|
@@ -1011,8 +1027,11 @@ function edit_binding_row( $row_data ) {
|
||||||
|
$source_title = translate('Path to collection you wish to bind, like /user1/calendar/ or https://cal.example.com/user2/cal/');
|
||||||
|
$access_title = translate('optional');
|
||||||
|
|
||||||
|
+ $csrf_field = getCsrfField();
|
||||||
|
+
|
||||||
|
$template = <<<EOTEMPLATE
|
||||||
|
<form method="POST" enctype="multipart/form-data" id="form_$form_id" action="$form_url">
|
||||||
|
+ $csrf_field
|
||||||
|
<td class="left"> <input type="hidden" name="id" value="$id"></td>
|
||||||
|
<td class="left"><input type="text" name="dav_name" value="$row_data->dav_name" size="25"></td>
|
||||||
|
<td class="left"><input type="text" name="dav_displayname" size="20"></td>
|
||||||
1
debian/patches/series
vendored
Normal file
1
debian/patches/series
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
CVE-2019-18345_183456_183457
|
||||||
@ -1,5 +1,4 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
require_once('./always.php');
|
require_once('./always.php');
|
||||||
require_once('classEditor.php');
|
require_once('classEditor.php');
|
||||||
require_once('classBrowser.php');
|
require_once('classBrowser.php');
|
||||||
@ -26,12 +25,7 @@ require_once('interactive-page.php');
|
|||||||
$page_elements = array();
|
$page_elements = array();
|
||||||
$code_file = sprintf( 'ui/%s-%s.php', $component, $action );
|
$code_file = sprintf( 'ui/%s-%s.php', $component, $action );
|
||||||
if ( ! @include_once( $code_file ) ) {
|
if ( ! @include_once( $code_file ) ) {
|
||||||
$c->messages[] = sprintf(
|
$c->messages[] = sprintf('No page found to %s %s%s%s', $action, ($action == 'browse' ? '' : 'a '), $component, ($action == 'browse' ? 's' : ''));
|
||||||
'No page found to %s %s%s%s',
|
|
||||||
htmlspecialchars($action),
|
|
||||||
($action == 'browse' ? '' : 'a '), $component,
|
|
||||||
($action == 'browse' ? 's' : '')
|
|
||||||
);
|
|
||||||
include('page-header.php');
|
include('page-header.php');
|
||||||
include('page-footer.php');
|
include('page-footer.php');
|
||||||
@ob_flush(); exit(0);
|
@ob_flush(); exit(0);
|
||||||
|
|||||||
@ -8,47 +8,6 @@
|
|||||||
|
|
||||||
if ( preg_match('{/always.php$}', $_SERVER['SCRIPT_NAME'] ) ) header('Location: index.php');
|
if ( preg_match('{/always.php$}', $_SERVER['SCRIPT_NAME'] ) ) header('Location: index.php');
|
||||||
|
|
||||||
// XSS Protection
|
|
||||||
function filter_post(&$val, $index) {
|
|
||||||
if(in_array($index, ["newpass1", "newpass2"])) return;
|
|
||||||
|
|
||||||
switch (gettype($val)) {
|
|
||||||
case "string":
|
|
||||||
$val = htmlspecialchars($val);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "array":
|
|
||||||
array_walk_recursive($val, function(&$v) {
|
|
||||||
if (gettype($v) == "string") {
|
|
||||||
$v = htmlspecialchars($v);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function clean_get() {
|
|
||||||
$temp = [];
|
|
||||||
|
|
||||||
foreach($_GET as $key => $value) {
|
|
||||||
// XSS is possible in both key and values
|
|
||||||
$k = htmlspecialchars($key);
|
|
||||||
$v = htmlspecialchars($value);
|
|
||||||
$temp[$k] = $v;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Before anything else is executed we filter all the user input, a lot of code in this project
|
|
||||||
// relies on variables that are easily manipulated by the user. These lines and functions filter all those variables.
|
|
||||||
if(isset($_POST)) array_walk($_POST, 'filter_post');
|
|
||||||
$_GET = clean_get();
|
|
||||||
$_SERVER['REQUEST_URI'] = str_replace("&", "&", htmlspecialchars($_SERVER['REQUEST_URI']));
|
|
||||||
$_SERVER['HTTP_REFERER'] = htmlspecialchars(@$_SERVER['HTTP_REFERER']);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Ensure the configuration starts out as an empty object.
|
// Ensure the configuration starts out as an empty object.
|
||||||
$c = (object) array();
|
$c = (object) array();
|
||||||
$c->script_start_time = microtime(true);
|
$c->script_start_time = microtime(true);
|
||||||
|
|||||||
@ -1,119 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the CSRF token
|
|
||||||
*/
|
|
||||||
function updateCsrf() {
|
|
||||||
if(!sessionExists()) {
|
|
||||||
session_start();
|
|
||||||
}
|
|
||||||
|
|
||||||
$_SESSION['csrf_token'] = generateCsrf();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check whether a session is currently active
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
function sessionExists() {
|
|
||||||
if (version_compare(phpversion(), '5.4.0', '>')) {
|
|
||||||
return session_id() !== '';
|
|
||||||
} else {
|
|
||||||
return session_status() === PHP_SESSION_ACTIVE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate a CSRF token, it chooses from 3 different functions based on PHP version and modules
|
|
||||||
* @return bool|string
|
|
||||||
*/
|
|
||||||
function generateCsrf() {
|
|
||||||
if (version_compare(phpversion(), '7.0.0', '>=')) {
|
|
||||||
$random = generateRandom();
|
|
||||||
if($random !== false) return $random;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (function_exists('mcrypt_create_iv')) {
|
|
||||||
return generateMcrypt();
|
|
||||||
}
|
|
||||||
|
|
||||||
return generateOpenssl();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate a random string using the PHP built in function random_bytes
|
|
||||||
* @version 7.0.0
|
|
||||||
* @return bool|string
|
|
||||||
*/
|
|
||||||
function generateRandom() {
|
|
||||||
try {
|
|
||||||
return bin2hex(random_bytes(32));
|
|
||||||
} catch (Exception $e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate a random string using MCRYPT
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
function generateMcrypt() {
|
|
||||||
return bin2hex(mcrypt_create_iv(32, MCRYPT_DEV_URANDOM));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate a random string using OpenSSL
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
function generateOpenssl() {
|
|
||||||
return bin2hex(openssl_random_pseudo_bytes(32));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks for session and the existence of a key
|
|
||||||
* after ensuring both are present it returns the
|
|
||||||
* current CSRF token
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
function getCsrf() {
|
|
||||||
if(!sessionExists()) {
|
|
||||||
session_start();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!array_key_exists('csrf_token', $_SESSION)) {
|
|
||||||
updateCsrf();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $_SESSION['csrf_token'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a hidden CSRF input field to be used in forms
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
function getCsrfField() {
|
|
||||||
return sprintf("<input type=\"hidden\" name=\"csrf_token\" value=\"%s\">", getCsrf());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Verify a given CSRF token
|
|
||||||
* @param $csrf_token
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
function verifyCsrf($csrf_token) {
|
|
||||||
$current_csrf = getCsrf();
|
|
||||||
// Prefer hash_equals over === because the latter is vulnerable to timing attacks
|
|
||||||
if(function_exists('hash_equals')) {
|
|
||||||
return hash_equals($current_csrf, $csrf_token);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $current_csrf === $csrf_token;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Uses the global $_POST variable to check if the CSRF token is valid
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
function verifyCsrfPost() {
|
|
||||||
return (isset($_POST['csrf_token']) && verifyCsrf($_POST['csrf_token']));
|
|
||||||
}
|
|
||||||
@ -20,9 +20,6 @@ if ( isset($_SERVER['SCRIPT_NAME']) ) {
|
|||||||
if ( $wiki_help == 'admin' ) {
|
if ( $wiki_help == 'admin' ) {
|
||||||
$wiki_help .= '/' . $_GET['t'] . '/' . $_GET['action'];
|
$wiki_help .= '/' . $_GET['t'] . '/' . $_GET['action'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$wiki_help = htmlspecialchars($wiki_help);
|
|
||||||
|
|
||||||
$wiki_help = 'w/Help/'.$wiki_help;
|
$wiki_help = 'w/Help/'.$wiki_help;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once("csrf_tokens.php");
|
|
||||||
|
|
||||||
// Editor component for collections
|
// Editor component for collections
|
||||||
$editor = new Editor(translate('Collection'), 'collection');
|
$editor = new Editor(translate('Collection'), 'collection');
|
||||||
@ -66,12 +65,6 @@ if ( isset($privsql) ) {
|
|||||||
$can_write_collection = ($session->AllowedTo('Admin') || (bindec($permissions->priv) & privilege_to_bits('DAV::bind')) );
|
$can_write_collection = ($session->AllowedTo('Admin') || (bindec($permissions->priv) & privilege_to_bits('DAV::bind')) );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify CSRF token
|
|
||||||
if($_SERVER['REQUEST_METHOD'] === "POST" && !verifyCsrfPost()) {
|
|
||||||
$c->messages[] = i18n("A valid CSRF token must be provided");
|
|
||||||
$can_write_collection = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
dbg_error_log('collection-edit', "Can write collection: %s", ($can_write_collection? 'yes' : 'no') );
|
dbg_error_log('collection-edit', "Can write collection: %s", ($can_write_collection? 'yes' : 'no') );
|
||||||
|
|
||||||
$pwstars = '@@@@@@@@@@';
|
$pwstars = '@@@@@@@@@@';
|
||||||
@ -280,7 +273,6 @@ EOPRIV;
|
|||||||
$submit_row = '';
|
$submit_row = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
$csrf_field = getCsrfField();
|
|
||||||
$id = $editor->Value('collection_id');
|
$id = $editor->Value('collection_id');
|
||||||
$template = <<<EOTEMPLATE
|
$template = <<<EOTEMPLATE
|
||||||
##form##
|
##form##
|
||||||
@ -392,7 +384,6 @@ label.privilege {
|
|||||||
<tr> <th class="right">$prompt_description:</th> <td class="left">##description.textarea.78x6##</td> </tr>
|
<tr> <th class="right">$prompt_description:</th> <td class="left">##description.textarea.78x6##</td> </tr>
|
||||||
$submit_row
|
$submit_row
|
||||||
</table>
|
</table>
|
||||||
$csrf_field
|
|
||||||
</form>
|
</form>
|
||||||
<script language="javascript">
|
<script language="javascript">
|
||||||
toggle_enabled('fld_is_calendar','=fld_timezone','=fld_schedule_transp','!fld_is_addressbook');
|
toggle_enabled('fld_is_calendar','=fld_timezone','=fld_schedule_transp','!fld_is_addressbook');
|
||||||
@ -462,11 +453,9 @@ if ( $editor->Available() ) {
|
|||||||
$orig_to_id = $row_data->to_principal;
|
$orig_to_id = $row_data->to_principal;
|
||||||
$form_id = $grantrow->Id();
|
$form_id = $grantrow->Id();
|
||||||
$form_url = preg_replace( '#&(edit|delete)_grant=\d+#', '', $_SERVER['REQUEST_URI'] );
|
$form_url = preg_replace( '#&(edit|delete)_grant=\d+#', '', $_SERVER['REQUEST_URI'] );
|
||||||
$csrf_field = getCsrfField();
|
|
||||||
|
|
||||||
$template = <<<EOTEMPLATE
|
$template = <<<EOTEMPLATE
|
||||||
<form method="POST" enctype="multipart/form-data" id="form_$form_id" action="$form_url">
|
<form method="POST" enctype="multipart/form-data" id="form_$form_id" action="$form_url">
|
||||||
$csrf_field
|
|
||||||
<td class="left" colspan="2"><input type="hidden" name="id" value="$id"><input type="hidden" name="orig_to_id" value="$orig_to_id">##to_principal.select##</td>
|
<td class="left" colspan="2"><input type="hidden" name="id" value="$id"><input type="hidden" name="orig_to_id" value="$orig_to_id">##to_principal.select##</td>
|
||||||
<td class="left" colspan="2">
|
<td class="left" colspan="2">
|
||||||
<input type="button" value="$btn_all" class="submit" title="$btn_all_title" onclick="toggle_privileges('grant_privileges', 'all', 'form_$form_id');">
|
<input type="button" value="$btn_all" class="submit" title="$btn_all_title" onclick="toggle_privileges('grant_privileges', 'all', 'form_$form_id');">
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once("csrf_tokens.php");
|
|
||||||
|
|
||||||
param_to_global('id', 'int', 'old_id', 'principal_id' );
|
param_to_global('id', 'int', 'old_id', 'principal_id' );
|
||||||
|
|
||||||
@ -182,13 +181,6 @@ function principal_editor() {
|
|||||||
$editor->AddAttribute( 'email', 'title', translate("The email address identifies principals when processing invitations and freebusy lookups. It should be set to a unique value.") );
|
$editor->AddAttribute( 'email', 'title', translate("The email address identifies principals when processing invitations and freebusy lookups. It should be set to a unique value.") );
|
||||||
$editor->SetWhere( 'principal_id='.$id );
|
$editor->SetWhere( 'principal_id='.$id );
|
||||||
|
|
||||||
if($_SERVER['REQUEST_METHOD'] === "POST" && !verifyCsrfPost()) {
|
|
||||||
$c->messages[] = i18n("A valid CSRF token must be provided");
|
|
||||||
$can_write_principal = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$csrf_field = getCsrfField();
|
|
||||||
|
|
||||||
$editor->AddField('is_admin', 'EXISTS( SELECT 1 FROM role_member WHERE role_no = 1 AND role_member.user_no = dav_principal.user_no )' );
|
$editor->AddField('is_admin', 'EXISTS( SELECT 1 FROM role_member WHERE role_no = 1 AND role_member.user_no = dav_principal.user_no )' );
|
||||||
$editor->AddAttribute('is_admin', 'title', translate('An "Administrator" user has full rights to the whole DAViCal System'));
|
$editor->AddAttribute('is_admin', 'title', translate('An "Administrator" user has full rights to the whole DAViCal System'));
|
||||||
|
|
||||||
@ -404,7 +396,6 @@ label.privilege {
|
|||||||
<tr> <th class="right" style="white-space:normal;">$prompt_privileges:</th><td class="left">$privs_html</td> </tr>
|
<tr> <th class="right" style="white-space:normal;">$prompt_privileges:</th><td class="left">$privs_html</td> </tr>
|
||||||
$submit_row
|
$submit_row
|
||||||
</table>
|
</table>
|
||||||
$csrf_field
|
|
||||||
</form>
|
</form>
|
||||||
EOTEMPLATE;
|
EOTEMPLATE;
|
||||||
|
|
||||||
@ -554,11 +545,9 @@ function edit_group_row( $row_data ) {
|
|||||||
global $id, $grouprow;
|
global $id, $grouprow;
|
||||||
|
|
||||||
$form_url = preg_replace( '#&(edit|delete)_group=\d+#', '', $_SERVER['REQUEST_URI'] );
|
$form_url = preg_replace( '#&(edit|delete)_group=\d+#', '', $_SERVER['REQUEST_URI'] );
|
||||||
$csrf_field = getCsrfField();
|
|
||||||
|
|
||||||
$template = <<<EOTEMPLATE
|
$template = <<<EOTEMPLATE
|
||||||
<form method="POST" enctype="multipart/form-data" id="add_group" action="$form_url">
|
<form method="POST" enctype="multipart/form-data" id="add_group" action="$form_url">
|
||||||
$csrf_field
|
|
||||||
<td class="left"><input type="hidden" name="id" value="$id"></td>
|
<td class="left"><input type="hidden" name="id" value="$id"></td>
|
||||||
<td class="left" colspan="3">##member_id.select## ##Add.submit##</td>
|
<td class="left" colspan="3">##member_id.select## ##Add.submit##</td>
|
||||||
<td class="center"></td>
|
<td class="center"></td>
|
||||||
@ -671,11 +660,8 @@ function edit_grant_row_principal( $row_data ) {
|
|||||||
$form_id = $grantrow->Id();
|
$form_id = $grantrow->Id();
|
||||||
$form_url = preg_replace( '#&(edit|delete)_grant=\d+#', '', $_SERVER['REQUEST_URI'] );
|
$form_url = preg_replace( '#&(edit|delete)_grant=\d+#', '', $_SERVER['REQUEST_URI'] );
|
||||||
|
|
||||||
$csrf_field = getCsrfField();
|
|
||||||
|
|
||||||
$template = <<<EOTEMPLATE
|
$template = <<<EOTEMPLATE
|
||||||
<form method="POST" enctype="multipart/form-data" id="form_$form_id" action="$form_url">
|
<form method="POST" enctype="multipart/form-data" id="form_$form_id" action="$form_url">
|
||||||
$csrf_field
|
|
||||||
<td class="left" colspan="2"><input type="hidden" name="id" value="$id"><input type="hidden" name="orig_to_id" value="$orig_to_id">##to_principal.select##</td>
|
<td class="left" colspan="2"><input type="hidden" name="id" value="$id"><input type="hidden" name="orig_to_id" value="$orig_to_id">##to_principal.select##</td>
|
||||||
<td class="left" colspan="2">$privs_html</td>
|
<td class="left" colspan="2">$privs_html</td>
|
||||||
<td class="center">##submit##</td>
|
<td class="center">##submit##</td>
|
||||||
@ -802,11 +788,9 @@ function edit_ticket_row( $row_data ) {
|
|||||||
$form_id = $ticketrow->Id();
|
$form_id = $ticketrow->Id();
|
||||||
$ticket_id = $row_data->ticket_id;
|
$ticket_id = $row_data->ticket_id;
|
||||||
$form_url = preg_replace( '#&(edit|delete)_[a-z]+=\d+#', '', $_SERVER['REQUEST_URI'] );
|
$form_url = preg_replace( '#&(edit|delete)_[a-z]+=\d+#', '', $_SERVER['REQUEST_URI'] );
|
||||||
$csrf_field = getCsrfField();
|
|
||||||
|
|
||||||
$template = <<<EOTEMPLATE
|
$template = <<<EOTEMPLATE
|
||||||
<form method="POST" enctype="multipart/form-data" id="form_$form_id" action="$form_url">
|
<form method="POST" enctype="multipart/form-data" id="form_$form_id" action="$form_url">
|
||||||
$csrf_field
|
|
||||||
<td class="left">$ticket_id<input type="hidden" name="id" value="$id"><input type="hidden" name="ticket_id" value="$ticket_id"></td>
|
<td class="left">$ticket_id<input type="hidden" name="id" value="$id"><input type="hidden" name="ticket_id" value="$ticket_id"></td>
|
||||||
<td class="left"><input type="text" name="target" value="$row_data->target"></td>
|
<td class="left"><input type="text" name="target" value="$row_data->target"></td>
|
||||||
<td class="left"><input type="text" name="expires" value="$row_data->expires" size="10"></td>
|
<td class="left"><input type="text" name="expires" value="$row_data->expires" size="10"></td>
|
||||||
@ -1027,11 +1011,8 @@ function edit_binding_row( $row_data ) {
|
|||||||
$source_title = translate('Path to collection you wish to bind, like /user1/calendar/ or https://cal.example.com/user2/cal/');
|
$source_title = translate('Path to collection you wish to bind, like /user1/calendar/ or https://cal.example.com/user2/cal/');
|
||||||
$access_title = translate('optional');
|
$access_title = translate('optional');
|
||||||
|
|
||||||
$csrf_field = getCsrfField();
|
|
||||||
|
|
||||||
$template = <<<EOTEMPLATE
|
$template = <<<EOTEMPLATE
|
||||||
<form method="POST" enctype="multipart/form-data" id="form_$form_id" action="$form_url">
|
<form method="POST" enctype="multipart/form-data" id="form_$form_id" action="$form_url">
|
||||||
$csrf_field
|
|
||||||
<td class="left"> <input type="hidden" name="id" value="$id"></td>
|
<td class="left"> <input type="hidden" name="id" value="$id"></td>
|
||||||
<td class="left"><input type="text" name="dav_name" value="$row_data->dav_name" size="25"></td>
|
<td class="left"><input type="text" name="dav_name" value="$row_data->dav_name" size="25"></td>
|
||||||
<td class="left"><input type="text" name="dav_displayname" size="20"></td>
|
<td class="left"><input type="text" name="dav_displayname" size="20"></td>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user