Protect CSRF token against BREACH
This commit is contained in:
parent
31abc08df8
commit
a564bba261
|
@ -1,10 +1,11 @@
|
||||||
<?php
|
<?php
|
||||||
$connection = '';
|
$connection = '';
|
||||||
|
|
||||||
$token = $_SESSION["token"];
|
$has_token = $_SESSION["token"];
|
||||||
if (!$_SESSION["token"]) {
|
if (!$has_token) {
|
||||||
$_SESSION["token"] = rand(1, 1e6); // defense against cross-site request forgery
|
$_SESSION["token"] = rand(1, 1e6); // defense against cross-site request forgery
|
||||||
}
|
}
|
||||||
|
$token = get_token(); ///< @var string CSRF protection
|
||||||
|
|
||||||
$permanent = array();
|
$permanent = array();
|
||||||
if ($_COOKIE["adminer_permanent"]) {
|
if ($_COOKIE["adminer_permanent"]) {
|
||||||
|
@ -40,7 +41,7 @@ if ($auth) {
|
||||||
}
|
}
|
||||||
|
|
||||||
} elseif ($_POST["logout"]) {
|
} elseif ($_POST["logout"]) {
|
||||||
if ($token && $_POST["token"] != $token) {
|
if ($has_token && !verify_token()) {
|
||||||
page_header(lang('Logout'), lang('Invalid CSRF token. Send the form again.'));
|
page_header(lang('Logout'), lang('Invalid CSRF token. Send the form again.'));
|
||||||
page_footer("db");
|
page_footer("db");
|
||||||
exit;
|
exit;
|
||||||
|
@ -75,13 +76,13 @@ function unset_permanent() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function auth_error($exception = null) {
|
function auth_error($exception = null) {
|
||||||
global $connection, $adminer, $token;
|
global $connection, $adminer, $has_token;
|
||||||
$session_name = session_name();
|
$session_name = session_name();
|
||||||
$error = "";
|
$error = "";
|
||||||
if (!$_COOKIE[$session_name] && $_GET[$session_name] && ini_bool("session.use_only_cookies")) {
|
if (!$_COOKIE[$session_name] && $_GET[$session_name] && ini_bool("session.use_only_cookies")) {
|
||||||
$error = lang('Session support must be enabled.');
|
$error = lang('Session support must be enabled.');
|
||||||
} elseif (isset($_GET["username"])) {
|
} elseif (isset($_GET["username"])) {
|
||||||
if (($_COOKIE[$session_name] || $_GET[$session_name]) && !$token) {
|
if (($_COOKIE[$session_name] || $_GET[$session_name]) && !$has_token) {
|
||||||
$error = lang('Session expired, please login again.');
|
$error = lang('Session expired, please login again.');
|
||||||
} else {
|
} else {
|
||||||
$password = get_password();
|
$password = get_password();
|
||||||
|
@ -143,14 +144,13 @@ if (is_string($connection) || !$adminer->login($_GET["username"], get_password()
|
||||||
|
|
||||||
$driver = new Min_Driver($connection);
|
$driver = new Min_Driver($connection);
|
||||||
|
|
||||||
$token = $_SESSION["token"]; ///< @var string CSRF protection
|
|
||||||
if ($auth && $_POST["token"]) {
|
if ($auth && $_POST["token"]) {
|
||||||
$_POST["token"] = $token; // reset token after explicit login
|
$_POST["token"] = $token; // reset token after explicit login
|
||||||
}
|
}
|
||||||
|
|
||||||
$error = ''; ///< @var string
|
$error = ''; ///< @var string
|
||||||
if ($_POST) {
|
if ($_POST) {
|
||||||
if ($_POST["token"] != $token) {
|
if (!verify_token()) {
|
||||||
$ini = "max_input_vars";
|
$ini = "max_input_vars";
|
||||||
$max_vars = ini_get($ini);
|
$max_vars = ini_get($ini);
|
||||||
if (extension_loaded("suhosin")) {
|
if (extension_loaded("suhosin")) {
|
||||||
|
|
|
@ -25,7 +25,7 @@ if (isset($_GET["file"])) {
|
||||||
|
|
||||||
include "../adminer/include/functions.inc.php";
|
include "../adminer/include/functions.inc.php";
|
||||||
|
|
||||||
global $adminer, $connection, $drivers, $edit_functions, $enum_length, $error, $functions, $grouping, $HTTPS, $inout, $jush, $LANG, $langs, $on_actions, $permanent, $structured_types, $token, $translations, $types, $unsigned, $VERSION; // allows including Adminer inside a function
|
global $adminer, $connection, $drivers, $edit_functions, $enum_length, $error, $functions, $grouping, $HTTPS, $inout, $jush, $LANG, $langs, $on_actions, $permanent, $structured_types, $has_token, $token, $translations, $types, $unsigned, $VERSION; // allows including Adminer inside a function
|
||||||
|
|
||||||
if (!$_SERVER["REQUEST_URI"]) { // IIS 5 compatibility
|
if (!$_SERVER["REQUEST_URI"]) { // IIS 5 compatibility
|
||||||
$_SERVER["REQUEST_URI"] = $_SERVER["ORIG_PATH_INFO"];
|
$_SERVER["REQUEST_URI"] = $_SERVER["ORIG_PATH_INFO"];
|
||||||
|
|
|
@ -1124,6 +1124,22 @@ var timeout = setTimeout(function () {
|
||||||
return array_keys($return);
|
return array_keys($return);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Generate BREACH resistant CSRF token
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function get_token() {
|
||||||
|
$rand = rand(1, 1e6);
|
||||||
|
return ($rand ^ $_SESSION["token"]) . ":$rand";
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Verify if supplied CSRF token is valid
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
function verify_token() {
|
||||||
|
list($token, $rand) = explode(":", $_POST["token"]);
|
||||||
|
return ($rand ^ $_SESSION["token"]) == $token;
|
||||||
|
}
|
||||||
|
|
||||||
// used in compiled version
|
// used in compiled version
|
||||||
function lzw_decompress($binary) {
|
function lzw_decompress($binary) {
|
||||||
// convert binary string to codes
|
// convert binary string to codes
|
||||||
|
|
|
@ -76,11 +76,11 @@ function switch_lang() {
|
||||||
echo "<form action='' method='post'>\n<div id='lang'>";
|
echo "<form action='' method='post'>\n<div id='lang'>";
|
||||||
echo lang('Language') . ": " . html_select("lang", $langs, $LANG, "this.form.submit();");
|
echo lang('Language') . ": " . html_select("lang", $langs, $LANG, "this.form.submit();");
|
||||||
echo " <input type='submit' value='" . lang('Use') . "' class='hidden'>\n";
|
echo " <input type='submit' value='" . lang('Use') . "' class='hidden'>\n";
|
||||||
echo "<input type='hidden' name='token' value='$_SESSION[token]'>\n"; // $token may be empty in auth.inc.php
|
echo "<input type='hidden' name='token' value='" . get_token() . "'>\n"; // $token may be empty in auth.inc.php
|
||||||
echo "</div>\n</form>\n";
|
echo "</div>\n</form>\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($_POST["lang"]) && $_SESSION["token"] == $_POST["token"]) { // $token and $error not yet available
|
if (isset($_POST["lang"]) && verify_token()) { // $error not yet available
|
||||||
cookie("adminer_lang", $_POST["lang"]);
|
cookie("adminer_lang", $_POST["lang"]);
|
||||||
$_SESSION["lang"] = $_POST["lang"]; // cookies may be disabled
|
$_SESSION["lang"] = $_POST["lang"]; // cookies may be disabled
|
||||||
$_SESSION["translations"] = array(); // used in compiled version
|
$_SESSION["translations"] = array(); // used in compiled version
|
||||||
|
|
|
@ -218,6 +218,7 @@ if (!isset($_GET["import"])) {
|
||||||
|
|
||||||
echo checkbox("error_stops", 1, ($_POST ? $_POST["error_stops"] : isset($_GET["import"])), lang('Stop on error')) . "\n";
|
echo checkbox("error_stops", 1, ($_POST ? $_POST["error_stops"] : isset($_GET["import"])), lang('Stop on error')) . "\n";
|
||||||
echo checkbox("only_errors", 1, $_POST["only_errors"], lang('Show only errors')) . "\n";
|
echo checkbox("only_errors", 1, $_POST["only_errors"], lang('Show only errors')) . "\n";
|
||||||
|
echo "<input type='hidden' name='token' value='$token'>\n";
|
||||||
|
|
||||||
if (!isset($_GET["import"]) && $history) {
|
if (!isset($_GET["import"]) && $history) {
|
||||||
print_fieldset("history", lang('History'), $_GET["history"] != "");
|
print_fieldset("history", lang('History'), $_GET["history"] != "");
|
||||||
|
@ -231,5 +232,4 @@ if (!isset($_GET["import"]) && $history) {
|
||||||
echo "</div></fieldset>\n";
|
echo "</div></fieldset>\n";
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
<input type="hidden" name="token" value="<?php echo $token; ?>">
|
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -15,6 +15,7 @@ Encrypt passwords stored in session by a key stored in cookie
|
||||||
Don't append newlines to uploaded files, bug since Adminer 3.7.0
|
Don't append newlines to uploaded files, bug since Adminer 3.7.0
|
||||||
Don't display SQL edit form on Ctrl+click on the select query, introduced in Adminer 3.6.4
|
Don't display SQL edit form on Ctrl+click on the select query, introduced in Adminer 3.6.4
|
||||||
Use MD5 for editing long keys only in supported drivers, bug since Adminer 3.6.4
|
Use MD5 for editing long keys only in supported drivers, bug since Adminer 3.6.4
|
||||||
|
Protect CSRF token against BREACH
|
||||||
SQLite: Allow editing primary key
|
SQLite: Allow editing primary key
|
||||||
SQLite: Allow editing foreign keys
|
SQLite: Allow editing foreign keys
|
||||||
PostgreSQL: Fix handling of nextval() default values
|
PostgreSQL: Fix handling of nextval() default values
|
||||||
|
|
Loading…
Reference in a new issue