diff --git a/adminer/include/auth.inc.php b/adminer/include/auth.inc.php index c53e1ca7..b64b3ac2 100644 --- a/adminer/include/auth.inc.php +++ b/adminer/include/auth.inc.php @@ -1,10 +1,11 @@ login($_GET["username"], get_password() $driver = new Min_Driver($connection); -$token = $_SESSION["token"]; ///< @var string CSRF protection if ($auth && $_POST["token"]) { $_POST["token"] = $token; // reset token after explicit login } $error = ''; ///< @var string if ($_POST) { - if ($_POST["token"] != $token) { + if (!verify_token()) { $ini = "max_input_vars"; $max_vars = ini_get($ini); if (extension_loaded("suhosin")) { diff --git a/adminer/include/bootstrap.inc.php b/adminer/include/bootstrap.inc.php index 3a1bc35e..eaaab5a7 100644 --- a/adminer/include/bootstrap.inc.php +++ b/adminer/include/bootstrap.inc.php @@ -25,7 +25,7 @@ if (isset($_GET["file"])) { 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 $_SERVER["REQUEST_URI"] = $_SERVER["ORIG_PATH_INFO"]; diff --git a/adminer/include/functions.inc.php b/adminer/include/functions.inc.php index 08e42dae..6d1cd287 100644 --- a/adminer/include/functions.inc.php +++ b/adminer/include/functions.inc.php @@ -1124,6 +1124,22 @@ var timeout = setTimeout(function () { 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 function lzw_decompress($binary) { // convert binary string to codes diff --git a/adminer/include/lang.inc.php b/adminer/include/lang.inc.php index 86f1244b..bf430d18 100644 --- a/adminer/include/lang.inc.php +++ b/adminer/include/lang.inc.php @@ -76,11 +76,11 @@ function switch_lang() { echo "
\n
"; echo lang('Language') . ": " . html_select("lang", $langs, $LANG, "this.form.submit();"); echo " \n"; - echo "\n"; // $token may be empty in auth.inc.php + echo "\n"; // $token may be empty in auth.inc.php echo "
\n
\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"]); $_SESSION["lang"] = $_POST["lang"]; // cookies may be disabled $_SESSION["translations"] = array(); // used in compiled version diff --git a/adminer/sql.inc.php b/adminer/sql.inc.php index 72afbea7..eb4fa1c7 100644 --- a/adminer/sql.inc.php +++ b/adminer/sql.inc.php @@ -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("only_errors", 1, $_POST["only_errors"], lang('Show only errors')) . "\n"; +echo "\n"; if (!isset($_GET["import"]) && $history) { print_fieldset("history", lang('History'), $_GET["history"] != ""); @@ -231,5 +232,4 @@ if (!isset($_GET["import"]) && $history) { echo "\n"; } ?> - diff --git a/changes.txt b/changes.txt index b891168d..277ea3b9 100644 --- a/changes.txt +++ b/changes.txt @@ -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 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 +Protect CSRF token against BREACH SQLite: Allow editing primary key SQLite: Allow editing foreign keys PostgreSQL: Fix handling of nextval() default values