From f6cc9a2f9fbba6930c590ba229b0a8185116ea65 Mon Sep 17 00:00:00 2001 From: Zankaria Date: Tue, 30 Apr 2024 11:34:53 +0200 Subject: [PATCH 1/4] auth.php: trim --- inc/mod/auth.php | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/inc/mod/auth.php b/inc/mod/auth.php index 5705c8a2..d9d393cf 100644 --- a/inc/mod/auth.php +++ b/inc/mod/auth.php @@ -9,14 +9,14 @@ defined('TINYBOARD') or exit; // create a hash/salt pair for validate logins function mkhash($username, $password, $salt = false) { global $config; - + if (!$salt) { // create some sort of salt for the hash $salt = substr(base64_encode(sha1(rand() . time(), true) . $config['cookies']['salt']), 0, 15); - + $generated_salt = true; } - + // generate hash (method is not important as long as it's strong) $hash = substr( base64_encode( @@ -30,7 +30,7 @@ function mkhash($username, $password, $salt = false) { ) ), 0, 20 ); - + if (isset($generated_salt)) return array($hash, $salt); else @@ -80,11 +80,11 @@ function generate_salt() { function login($username, $password) { global $mod, $config; - + $query = prepare("SELECT `id`, `type`, `boards`, `password`, `version` FROM ``mods`` WHERE BINARY `username` = :username"); $query->bindValue(':username', $username); $query->execute() or error(db_error($query)); - + if ($user = $query->fetch(PDO::FETCH_ASSOC)) { list($version, $ok) = test_password($user['password'], $user['version'], $password); @@ -108,7 +108,7 @@ function login($username, $password) { ); } } - + return false; } @@ -116,10 +116,10 @@ function setCookies() { global $mod, $config; if (!$mod) error('setCookies() was called for a non-moderator!'); - + setcookie($config['cookies']['mod'], $mod['username'] . // username - ':' . + ':' . $mod['hash'][0] . // password ':' . $mod['hash'][1], // salt @@ -146,36 +146,36 @@ function modLog($action, $_board=null) { else $query->bindValue(':board', null, PDO::PARAM_NULL); $query->execute() or error(db_error($query)); - + if ($config['syslog']) _syslog(LOG_INFO, '[mod/' . $mod['username'] . ']: ' . $action); } function create_pm_header() { global $mod, $config; - + if ($config['cache']['enabled'] && ($header = cache::get('pm_unread_' . $mod['id'])) != false) { if ($header === true) return false; - + return $header; } - + $query = prepare("SELECT `id` FROM ``pms`` WHERE `to` = :id AND `unread` = 1"); $query->bindValue(':id', $mod['id'], PDO::PARAM_INT); $query->execute() or error(db_error($query)); - + if ($pm = $query->fetch(PDO::FETCH_ASSOC)) $header = array('id' => $pm['id'], 'waiting' => $query->rowCount() - 1); else $header = true; - + if ($config['cache']['enabled']) cache::set('pm_unread_' . $mod['id'], $header); - + if ($header === true) return false; - + return $header; } @@ -196,12 +196,12 @@ function check_login($prompt = false) { if ($prompt) mod_login(); exit; } - + $query = prepare("SELECT `id`, `type`, `boards`, `password` FROM ``mods`` WHERE `username` = :username"); $query->bindValue(':username', $cookie[0]); $query->execute() or error(db_error($query)); $user = $query->fetch(PDO::FETCH_ASSOC); - + // validate password hash if ($cookie[1] !== mkhash($cookie[0], $user['password'], $cookie[2])) { // Malformed cookies @@ -209,7 +209,7 @@ function check_login($prompt = false) { if ($prompt) mod_login(); exit; } - + $mod = array( 'id' => (int)$user['id'], 'type' => (int)$user['type'], From 940ea3f4b583c681231d98406510f9d08224ef45 Mon Sep 17 00:00:00 2001 From: Zankaria Date: Mon, 29 Apr 2024 16:46:51 +0200 Subject: [PATCH 2/4] config.php: reduce default login cookie expire timeout --- inc/config.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/config.php b/inc/config.php index 10d7a1e3..a37a2d51 100644 --- a/inc/config.php +++ b/inc/config.php @@ -172,7 +172,7 @@ // How long should the cookies last (in seconds). Defines how long should moderators should remain logged // in (0 = browser session). - $config['cookies']['expire'] = 60 * 60 * 24 * 30 * 6; // ~6 months + $config['cookies']['expire'] = 60 * 60 * 24 * 7; // 1 week. // Make this something long and random for security. $config['cookies']['salt'] = 'abcdefghijklmnopqrstuvwxyz09123456789!@#$%^&*()'; From 003152095a1ecad834180a7e70715843c1ef3ead Mon Sep 17 00:00:00 2001 From: Zankaria Date: Tue, 30 Apr 2024 11:41:19 +0200 Subject: [PATCH 3/4] auth.php: remove obsolete code --- inc/mod/auth.php | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/inc/mod/auth.php b/inc/mod/auth.php index d9d393cf..3b62559e 100644 --- a/inc/mod/auth.php +++ b/inc/mod/auth.php @@ -37,12 +37,6 @@ function mkhash($username, $password, $salt = false) { return $hash; } -function crypt_password_old($password) { - $salt = generate_salt(); - $password = hash('sha256', $salt . sha1($password)); - return array($salt, $password); -} - function crypt_password($password) { global $config; // `salt` database field is reused as a version value. We don't want it to be 0. @@ -69,12 +63,6 @@ function test_password($password, $salt, $test) { } function generate_salt() { - // mcrypt_create_iv() was deprecated in PHP 7.1.0, only use it if we're below that version number. - if (PHP_VERSION_ID < 70100) { - // 128 bits of entropy - return strtr(base64_encode(mcrypt_create_iv(16, MCRYPT_DEV_URANDOM)), '+', '.'); - } - // Otherwise, use random_bytes() return strtr(base64_encode(random_bytes(16)), '+', '.'); } From aa99d10f1a41b1d738c8d4e01fec9749b158e458 Mon Sep 17 00:00:00 2001 From: Zankaria Date: Tue, 30 Apr 2024 11:31:06 +0200 Subject: [PATCH 4/4] auth.php: disallow unencrypted logins by default --- composer.json | 3 ++- inc/config.php | 5 +++++ inc/functions/net.php | 10 ++++++++++ inc/mod/auth.php | 10 ++++++++-- inc/mod/pages.php | 9 +++++++-- 5 files changed, 32 insertions(+), 5 deletions(-) create mode 100644 inc/functions/net.php diff --git a/composer.json b/composer.json index 5f574aa6..e9ceac19 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,8 @@ "inc/queue.php", "inc/polyfill.php", "inc/error.php", - "inc/functions.php" + "inc/functions.php", + "inc/functions/net.php" ] }, "license": "Tinyboard + vichan", diff --git a/inc/config.php b/inc/config.php index a37a2d51..d8ae7584 100644 --- a/inc/config.php +++ b/inc/config.php @@ -180,6 +180,10 @@ // Whether or not you can access the mod cookie in JavaScript. Most users should not need to change this. $config['cookies']['httponly'] = true; + // Do not allow logins via unencrypted HTTP. Should only be changed in testing environments or if you connect to a + // load-balancer without encryption. + $config['cookies']['secure_login_only'] = true; + // Used to salt secure tripcodes ("##trip") and poster IDs (if enabled). $config['secure_trip_salt'] = ')(*&^%$#@!98765432190zyxwvutsrqponmlkjihgfedcba'; @@ -1216,6 +1220,7 @@ // Moderator errors $config['error']['toomanyunban'] = _('You are only allowed to unban %s users at a time. You tried to unban %u users.'); $config['error']['invalid'] = _('Invalid username and/or password.'); + $config['error']['insecure'] = _('Login on insecure connections is disabled.'); $config['error']['notamod'] = _('You are not a mod…'); $config['error']['invalidafter'] = _('Invalid username and/or password. Your user may have been deleted or changed.'); $config['error']['malformed'] = _('Invalid/malformed cookies.'); diff --git a/inc/functions/net.php b/inc/functions/net.php new file mode 100644 index 00000000..ab08c3cb --- /dev/null +++ b/inc/functions/net.php @@ -0,0 +1,10 @@ +