Skip to content
Snippets Groups Projects
Commit 4f7c4dcb authored by JediKev's avatar JediKev
Browse files

iframe: Allow Multiple iFrame Domains

Previously, we added a security header to prevent click-jacking called
"X-Frame-Options". This introduced an issue with people using osTicket in
iFrames on their websites. To mitigate the issue, this updates the security
header to allow the site to be framed from specified domains, if none
provided we default to 'self'. This adds a new field to General System
Settings called "Allow iFrames" where you may enter a comma separated list
of domains that the site can be framed on. This also adds a validator for
the field to validate the domains and ensure they fit the <host-source>
syntax from [Mozilla Developer
Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/frame-ancestors#Sources).
parent 43a5900e
No related branches found
No related tags found
No related merge requests found
......@@ -429,6 +429,10 @@ class OsticketConfig extends Config {
return $this->get('enable_richtext');
}
function getAllowIframes() {
return str_replace(array(', ', ','), array(' ', ' '), $this->get('allow_iframes')) ?: 'self';
}
function isAvatarsEnabled() {
return $this->get('enable_avatars');
}
......@@ -1121,6 +1125,7 @@ class OsticketConfig extends Config {
$f['helpdesk_title']=array('type'=>'string', 'required'=>1, 'error'=>__('Helpdesk title is required'));
$f['default_dept_id']=array('type'=>'int', 'required'=>1, 'error'=>__('Default Department is required'));
$f['autolock_minutes']=array('type'=>'int', 'required'=>1, 'error'=>__('Enter lock time in minutes'));
$f['allow_iframes']=array('type'=>'cs-domain', 'required'=>0, 'error'=>__('Enter comma separated list of domains'));
//Date & Time Options
$f['time_format']=array('type'=>'string', 'required'=>1, 'error'=>__('Time format is required'));
$f['date_format']=array('type'=>'string', 'required'=>1, 'error'=>__('Date format is required'));
......@@ -1179,6 +1184,7 @@ class OsticketConfig extends Config {
'enable_avatars' => isset($vars['enable_avatars']) ? 1 : 0,
'enable_richtext' => isset($vars['enable_richtext']) ? 1 : 0,
'files_req_auth' => isset($vars['files_req_auth']) ? 1 : 0,
'allow_iframes' => Format::sanitize($vars['allow_iframes']),
));
}
......
......@@ -123,6 +123,14 @@ class Validator {
if(!is_numeric($this->input[$k]) || (strlen($this->input[$k])!=5))
$this->errors[$k]=$field['error'];
break;
case 'cs-domain': // Comma separated list of domains
if($values=explode(',', $this->input[$k]))
foreach($values as $v)
if(!preg_match_all(
'/^(https?:\/\/)?((\*\.|\w+\.)?[\w-]+(\.[a-zA-Z]+)?(:([0-9]+|\*))?)+$/',
ltrim($v)))
$this->errors[$k]=$field['error'];
break;
default://If param type is not set...or handle..error out...
$this->errors[$k]=$field['error'].' '.__('(type not set)');
endswitch;
......
......@@ -6,7 +6,7 @@ $signin_url = ROOT_PATH . "login.php"
$signout_url = ROOT_PATH . "logout.php?auth=".$ost->getLinkToken();
header("Content-Type: text/html; charset=UTF-8");
header("X-Frame-Options: SAMEORIGIN");
header("Content-Security-Policy: frame-ancestors '".$cfg->getAllowIframes()."';");
if (($lang = Internationalization::getCurrentLanguage())) {
$langs = array_unique(array($lang, $cfg->getPrimaryLanguage()));
$langs = Internationalization::rfc1766($langs);
......
......@@ -93,6 +93,20 @@ collision_avoidance:
<br><br>
Enter <span class="doc-desc-opt">0</span> to disable the lockout feature.
allow_iframes:
title: Allow iFrames
content: >
Enter comma separated list of domains for the system to be framed
in. If left empty, the system will default to 'self'. This accepts
domain wildcards, HTTP/HTTPS URL scheme, and port numbers.
<br><br>
<b>Example:</b>
<br>
https://domain.tld, sub.domain.tld:443, http://*.domain.tld
links:
- title: Syntax Information (host-source)
href: "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/frame-ancestors#Sources"
# Date and time options
date_time_options:
title: Date &amp; Time Options
......
<?php
header("Content-Type: text/html; charset=UTF-8");
header("X-Frame-Options: SAMEORIGIN");
header("Content-Security-Policy: frame-ancestors '".$cfg->getAllowIframes()."';");
$title = ($ost && ($title=$ost->getPageTitle()))
? $title : ('osTicket :: '.__('Staff Control Panel'));
......
<?php
defined('OSTSCPINC') or die('Invalid path');
header("X-Frame-Options: SAMEORIGIN");
header("Content-Security-Policy: frame-ancestors '".$cfg->getAllowIframes()."';");
?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
......
......@@ -131,6 +131,13 @@ $gmtime = Misc::gmtime();
<i class="help-tip icon-question-sign" href="#enable_richtext"></i>
</td>
</tr>
<tr>
<td><?php echo __('Allow iFrames'); ?>:</td>
<td><input type="text" size="40" name="allow_iframes" value="<?php echo $config['allow_iframes']; ?>">
&nbsp;<font class="error">&nbsp;<?php echo $errors['allow_iframes']; ?></font>
<i class="help-tip icon-question-sign" href="#allow_iframes"></i>
</td>
</tr>
<tr>
<th colspan="2">
<em><b><?php echo __('Date and Time Options'); ?></b>&nbsp;
......
<?php header("X-Frame-Options: SAMEORIGIN"); ?>
<?php
header("Content-Security-Policy: frame-ancestors '".$cfg->getAllowIframes()."';");
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html <?php
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment