Add CSRF protection to admin forms
This commit is contained in:
parent
45afdb4bba
commit
d25dec3563
|
@ -31,10 +31,14 @@ function ajaxFunc() {
|
|||
|
||||
if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'get') {
|
||||
jsonQuery();
|
||||
} else if ($_REQUEST['type'] == 'settings') {
|
||||
updateSettings();
|
||||
} else {
|
||||
addEdit();
|
||||
checkCsrfToken();
|
||||
|
||||
if ($_REQUEST['type'] == 'settings') {
|
||||
updateSettings();
|
||||
} else {
|
||||
addEdit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,6 +104,9 @@ function jsonQuery() {
|
|||
|
||||
function jsonError($error) {
|
||||
jsonForAjax(Array('error' => $error));
|
||||
|
||||
// Die even if not an AJAX request, should this call error_log() ?
|
||||
die();
|
||||
}
|
||||
|
||||
function jsonForAjax($arr) {
|
||||
|
@ -213,6 +220,28 @@ function pickFilename($arr=Array(), $ext='.jpg') {
|
|||
return $filename;
|
||||
}
|
||||
|
||||
function checkCsrfToken() {
|
||||
if(!constant_time_compare(CSRF_TOKEN, $_POST['csrf_token'])) {
|
||||
jsonError('Invalid CSRF token');
|
||||
}
|
||||
}
|
||||
|
||||
// based on version from utils.py
|
||||
function constant_time_compare($expected, $actual)
|
||||
{
|
||||
$actual_len = strlen($actual);
|
||||
$expected_len = strlen($expected);
|
||||
$res = $actual_len ^ $expected_len;
|
||||
|
||||
if ($expected_len > 0) {
|
||||
for ($i = 0; $i < $actual_len; ++$i) {
|
||||
$res |= ord($expected[$i % $expected_len]) ^ ord($actual[$i]);
|
||||
}
|
||||
}
|
||||
|
||||
return $res === 0;
|
||||
}
|
||||
|
||||
function sanitize_file_name( $filename ) {
|
||||
$special_chars = array("?", "[", "]", "/", "\\", "=", "<", ">", ":", ";", ",", "'", "\"", "&", "$", "#", "*", "(", ")", "|", "~", "`", "!", "{", "}");
|
||||
$filename = str_replace($special_chars, '', $filename);
|
||||
|
|
|
@ -17,6 +17,9 @@
|
|||
<link rel="stylesheet" href="./style.css" type="text/css" />
|
||||
<link href='http://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,700,300italic' rel='stylesheet' type='text/css'>
|
||||
|
||||
<script type="text/javascript">
|
||||
window.CSRF_TOKEN = <?= json_encode(CSRF_TOKEN, JSON_HEX_TAG) ?>;
|
||||
</script>
|
||||
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js" type="text/javascript"></script>
|
||||
<script src="js/bootstrap.min.js" type="text/javascript"></script>
|
||||
<script src="js/jquery-ui.min.js" type="text/javascript"></script>
|
||||
|
@ -53,6 +56,7 @@
|
|||
|
||||
<form action="" enctype="multipart/form-data" method="post" class="well form-horizontal" role="form">
|
||||
<input type="hidden" name="type" value="videos" />
|
||||
<input type="hidden" name="csrf_token" value="<?= htmlentities(CSRF_TOKEN) ?>" />
|
||||
<div class="form-group row">
|
||||
<div class="col-lg-5">
|
||||
<div class="row">
|
||||
|
@ -190,6 +194,7 @@
|
|||
|
||||
<form action="" enctype="multipart/form-data" method="post" class="well form-horizontal" role="form">
|
||||
<input type="hidden" name="type" value="skins" />
|
||||
<input type="hidden" name="csrf_token" value="<?= htmlentities(CSRF_TOKEN) ?>" />
|
||||
<div class="form-group row">
|
||||
<div class="col-lg-5">
|
||||
<div class="row">
|
||||
|
@ -338,6 +343,7 @@
|
|||
|
||||
<form action="" enctype="multipart/form-data" method="post" class="well form-horizontal" role="form">
|
||||
<input type="hidden" name="type" value="channels" />
|
||||
<input type="hidden" name="csrf_token" value="<?= htmlentities(CSRF_TOKEN) ?>" />
|
||||
<div class="form-group row">
|
||||
<div class="col-lg-5">
|
||||
<div class="row">
|
||||
|
@ -528,6 +534,7 @@
|
|||
<hr />
|
||||
<form id="general-settings" action="" enctype="multipart/form-data" method="post" class="well form-horizontal" role="form">
|
||||
<input type="hidden" name="type" value="settings" />
|
||||
<input type="hidden" name="csrf_token" value="<?= htmlentities(CSRF_TOKEN) ?>" />
|
||||
<div class="form-group row">
|
||||
<div class="col-lg-4">
|
||||
<div class="input-group">
|
||||
|
@ -578,6 +585,7 @@
|
|||
<h3>Default Channels</h3>
|
||||
<form id="default-channels" action="" enctype="multipart/form-data" method="post" class="well form-horizontal" role="form">
|
||||
<input type="hidden" name="type" value="default-channels" />
|
||||
<input type="hidden" name="csrf_token" value="<?= htmlentities(CSRF_TOKEN) ?>" />
|
||||
<div class="form-group row control-group">
|
||||
<div class="col-lg-6">
|
||||
<div class="input-group">
|
||||
|
@ -632,6 +640,7 @@
|
|||
<h3>Recommended Channels</h3>
|
||||
<form id="recommended-channels" action="" enctype="multipart/form-data" method="post" class="well form-horizontal" role="form">
|
||||
<input type="hidden" name="type" value="recommended-channels" />
|
||||
<input type="hidden" name="csrf_token" value="<?= htmlentities(CSRF_TOKEN) ?>" />
|
||||
<div class="form-group row control-group">
|
||||
<div class="col-lg-6">
|
||||
<div class="input-group">
|
||||
|
|
|
@ -411,6 +411,7 @@ $.each(channelTypes, function(i, channelType) {
|
|||
feed = JSON.stringify(feed);
|
||||
|
||||
postData = {
|
||||
'csrf_token': window.CSRF_TOKEN,
|
||||
'ajax' : true,
|
||||
'type' : 'settings',
|
||||
};
|
||||
|
|
|
@ -6,6 +6,10 @@ define('UPLOAD_URL', 'uploads/');
|
|||
define('AWS_BUCKET', 'reddittv');
|
||||
define('USE_SQLITE', false);
|
||||
|
||||
// Since user auth is done via .htpasswd, there's no need to support per-user
|
||||
// CSRF tokens. Replace this when / if user auth gets added to admin panel.
|
||||
define('CSRF_TOKEN', 'REPLACE_ME');
|
||||
|
||||
// Include RedbeanPHP
|
||||
require_once(dirname(__FILE__).'/rb.php');
|
||||
|
||||
|
|
Loading…
Reference in New Issue