mirror of
https://github.com/vrana/adminer.git
synced 2026-07-08 09:33:07 +02:00
Avoid denial-of-service via version check (GHSA-q4f2-39gr-45jh, regression from 4.6.2)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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'",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -11,13 +11,12 @@ class AdminerVersionGithub extends Adminer\Plugin {
|
||||
function head($dark = null) {
|
||||
?>
|
||||
<script <?php echo Adminer\nonce(); ?>>
|
||||
verifyVersion = (current, url, token) => {
|
||||
verifyVersion = current => {
|
||||
// dummy value to prevent repeated verifications after AJAX failure
|
||||
cookie('adminer_version=0', 1);
|
||||
ajax('https://api.github.com/repos/vrana/adminer/releases/latest', request => {
|
||||
const response = JSON.parse(request.responseText);
|
||||
const version = response.tag_name.replace(/^v/, '');
|
||||
// we don't save to adminer.version because the response is not signed; also GitHub can handle our volume of requests
|
||||
// we don't display the version here because we don't have version_compare(); design.inc.php will display it on the next load
|
||||
cookie('adminer_version=' + version, 1);
|
||||
}, null, null);
|
||||
|
||||
Reference in New Issue
Block a user