diff --git a/CHANGELOG.md b/CHANGELOG.md index c5029b7b..621e86d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,5 @@ ## Adminer dev +- Avoid denial-of-service via version check (GHSA-q4f2-39gr-45jh, regression from 4.6.2) - Pretty print JSON in edit - Support multiline generated values in alter table - Link //domain.tld values diff --git a/adminer/include/bootstrap.inc.php b/adminer/include/bootstrap.inc.php index bea89f2d..c9a59990 100644 --- a/adminer/include/bootstrap.inc.php +++ b/adminer/include/bootstrap.inc.php @@ -29,16 +29,6 @@ if (isset($_GET["file"])) { include "../adminer/file.inc.php"; } -if ($_GET["script"] == "version") { - $filename = get_temp_dir() . "/adminer.version"; - @unlink($filename); // it may not be writable by us, @ - it may not exist - $fp = file_open_lock($filename); - if ($fp) { - file_write_unlock($fp, serialize(array("signature" => $_POST["signature"], "version" => $_POST["version"]))); - } - exit; -} - // Adminer doesn't use any global variables; they used to be declared here if (!$_SERVER["REQUEST_URI"]) { // IIS 5 compatibility diff --git a/adminer/include/design.inc.php b/adminer/include/design.inc.php index d32e75e4..70862446 100644 --- a/adminer/include/design.inc.php +++ b/adminer/include/design.inc.php @@ -62,24 +62,8 @@ function page_header(string $title, string $error = "", $breadcrumb = array(), s adminer()->bodyClass(); echo "'>\n"; $filename = get_temp_dir() . "/adminer.version"; - if (!$_COOKIE["adminer_version"] && function_exists('openssl_verify') && file_exists($filename) && filemtime($filename) + 86400 > time()) { // 86400 - 1 day in seconds - $version = unserialize(file_get_contents($filename)); - $public = "-----BEGIN PUBLIC KEY----- -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwqWOVuF5uw7/+Z70djoK -RlHIZFZPO0uYRezq90+7Amk+FDNd7KkL5eDve+vHRJBLAszF/7XKXe11xwliIsFs -DFWQlsABVZB3oisKCBEuI71J4kPH8dKGEWR9jDHFw3cWmoH3PmqImX6FISWbG3B8 -h7FIx3jEaw5ckVPVTeo5JRm/1DZzJxjyDenXvBQ/6o9DgZKeNDgxwKzH+sw9/YCO -jHnq1cFpOIISzARlrHMa/43YfeNRAm/tsBXjSxembBPo7aQZLAWHmaj5+K19H10B -nCpz9Y++cipkVEiKRGih4ZEvjoFysEOdRLj6WiD/uUNky4xGeA6LaJqh5XpkFkcQ -fQIDAQAB ------END PUBLIC KEY----- -"; - if (openssl_verify($version["version"], base64_decode($version["signature"]), $public) == 1) { - $_COOKIE["adminer_version"] = $version["version"]; // doesn't need to send to the browser - } - } echo script("mixin(document.body, {onkeydown: bodyKeydown, onclick: bodyClick" - . (isset($_COOKIE["adminer_version"]) ? "" : ", onload: partial(verifyVersion, '" . VERSION . "', '" . js_escape(ME) . "', '" . get_token() . "')") + . (isset($_COOKIE["adminer_version"]) ? "" : ", onload: partial(verifyVersion, '" . VERSION . "')") . "}); document.body.classList.replace('nojs', 'js'); const offlineMessage = '" . js_escape(lang('You are offline.')) . "'; @@ -153,8 +137,8 @@ function csp(): array { return array( array( "script-src" => "'self' 'unsafe-inline' 'nonce-" . get_nonce() . "' 'strict-dynamic'", // 'self' is a fallback for browsers not supporting 'strict-dynamic', 'unsafe-inline' is a fallback for browsers not supporting 'nonce-' - "connect-src" => "'self'", - "frame-src" => "https://www.adminer.org", + "connect-src" => "'self' https://www.adminer.org", + "frame-src" => "'none'", "object-src" => "'none'", "base-uri" => "'none'", "form-action" => "'self'", diff --git a/adminer/static/functions.js b/adminer/static/functions.js index aee44b64..4cc95650 100644 --- a/adminer/static/functions.js +++ b/adminer/static/functions.js @@ -96,29 +96,15 @@ function cookie(assign, days) { /** Verify current Adminer version * @param string -* @param string own URL base -* @param string */ -function verifyVersion(current, url, token) { +function verifyVersion(current) { cookie('adminer_version=0', 1); - const iframe = document.createElement('iframe'); - iframe.src = 'https://www.adminer.org/version/?current=' + current; - iframe.frameBorder = 0; - iframe.marginHeight = 0; - iframe.scrolling = 'no'; - iframe.style.width = '7ex'; - iframe.style.height = '1.25em'; - iframe.style.display = 'none'; - addEventListener('message', event => { - if (event.origin == 'https://www.adminer.org') { - const match = /version=(.+)/.exec(event.data); - if (match) { - cookie('adminer_version=' + match[1], 1); - ajax(url + 'script=version', () => { }, event.data + '&token=' + token); - } - } - }, false); - qs('#version').appendChild(iframe); + // do not send X-Requested-With to avoid preflight + fetch('https://www.adminer.org/version/?current=' + current).then(async response => { + const json = await response.json(); + cookie('adminer_version=' + (json.version || current), 7); // empty if there's no newer version + qs('#version').textContent = json.version; + }); } /** Get value of select diff --git a/plugins/version-github.php b/plugins/version-github.php index 1f2984ff..30944693 100644 --- a/plugins/version-github.php +++ b/plugins/version-github.php @@ -11,13 +11,12 @@ class AdminerVersionGithub extends Adminer\Plugin { function head($dark = null) { ?>