From 9f5f8958c5881c0bf858f81a7efae01f22fc2f26 Mon Sep 17 00:00:00 2001 From: Miraty Date: Fri, 28 Apr 2023 15:39:05 +0200 Subject: [PATCH] Rate-limit most form processings --- pages.php | 20 ++++++++++++++++++++ pg-act/auth/approval.php | 2 ++ pg-act/auth/password.php | 2 ++ pg-act/auth/username.php | 2 ++ pg-act/ns/caa.php | 2 ++ pg-act/ns/cname.php | 2 ++ pg-act/ns/dname.php | 2 ++ pg-act/ns/ip.php | 2 ++ pg-act/ns/loc.php | 2 ++ pg-act/ns/mx.php | 2 ++ pg-act/ns/ns.php | 2 ++ pg-act/ns/print.php | 2 ++ pg-act/ns/srv.php | 2 ++ pg-act/ns/sshfp.php | 2 ++ pg-act/ns/tlsa.php | 2 ++ pg-act/ns/txt.php | 2 ++ pg-act/reg/ds.php | 2 ++ pg-act/reg/glue.php | 2 ++ pg-act/reg/ns.php | 2 ++ pg-act/reg/print.php | 2 ++ pg-act/reg/transfer.php | 2 ++ 21 files changed, 60 insertions(+) diff --git a/pages.php b/pages.php index 3aa4aee..79d1dd0 100644 --- a/pages.php +++ b/pages.php @@ -31,14 +31,17 @@ define('PAGES', [ 'approval' => [ 'title' => _('Switch to an approved account'), 'description' => _('Switch to an approved account using an approval key'), + 'tokens_account_cost' => 300, ], 'password' => [ 'title' => _('Change password'), 'description' => _('Change the character string used to authenticate yourself'), + 'tokens_account_cost' => 300, ], 'username' => [ 'title' => _('Change username'), 'description' => _('Change the name used to identify your account when logging in and displayed at the start of every page'), + 'tokens_account_cost' => 300, ], ], 'reg' => [ @@ -58,22 +61,27 @@ define('PAGES', [ 'print' => [ 'title' => _('Display domain records'), 'description' => _('Print every record related to a domain and served by the registry'), + 'tokens_account_cost' => 60, ], 'ns' => [ 'title' => sprintf(_('%s records'), 'NS'), 'description' => sprintf(_('Indicate the name servers of a %s subdomain'), '' . key(CONF['reg']['suffixes']) . ''), + 'tokens_account_cost' => 300, ], 'ds' => [ 'title' => sprintf(_('%s records'), 'DS'), 'description' => _('Delegate DNSSEC trust'), + 'tokens_account_cost' => 300, ], 'transfer' => [ 'title' => _('Receive a domain transfer'), 'description' => _('Transfer a domain owned by another account to the current account'), + 'tokens_account_cost' => 300, ], 'glue' => [ 'title' => _('Glue records'), 'description' => _('Advanced: store the IP address of a name server whose domain is inside the domain it serves'), + 'tokens_account_cost' => 300, ], ], 'ns' => [ @@ -93,6 +101,7 @@ define('PAGES', [ 'print' => [ 'title' => _('Display zone'), 'description' => _('Print zonefile content'), + 'tokens_account_cost' => 60, ], 'edit' => [ 'title' => _('Edit zone'), @@ -102,46 +111,57 @@ define('PAGES', [ 'ip' => [ 'title' => _('AAAA and A records'), 'description' => _('Store domain\'s IP address'), + 'tokens_account_cost' => 120, ], 'ns' => [ 'title' => sprintf(_('%s records'), 'NS'), 'description' => _('Store zone\'s name server'), + 'tokens_account_cost' => 120, ], 'txt' => [ 'title' => sprintf(_('%s records'), 'TXT'), 'description' => _('Associate text to domain'), + 'tokens_account_cost' => 120, ], 'caa' => [ 'title' => sprintf(_('%s records'), 'CAA'), 'description' => _('Limit the certificate authorities allowed to certify the domain'), + 'tokens_account_cost' => 120, ], 'srv' => [ 'title' => sprintf(_('%s records'), 'SRV'), 'description' => _('Store the location of a domain\'s service'), + 'tokens_account_cost' => 120, ], 'mx' => [ 'title' => sprintf(_('%s records'), 'MX'), 'description' => _('Store the email server\'s address'), + 'tokens_account_cost' => 120, ], 'sshfp' => [ 'title' => sprintf(_('%s records'), 'SSHFP'), 'description' => _('Store SSH public keys fingerprints'), + 'tokens_account_cost' => 120, ], 'tlsa' => [ 'title' => sprintf(_('%s records'), 'TLSA'), 'description' => _('Setup DANE by publishing the TLS certificate fingerprint'), + 'tokens_account_cost' => 120, ], 'cname' => [ 'title' => sprintf(_('%s records'), 'CNAME'), 'description' => _('Define a domain as an alias of another'), + 'tokens_account_cost' => 120, ], 'dname' => [ 'title' => sprintf(_('%s records'), 'DNAME'), 'description' => _('Define all subdomains of a domain as aliases of subdomains of another domain'), + 'tokens_account_cost' => 120, ], 'loc' => [ 'title' => sprintf(_('%s records'), 'LOC'), 'description' => _('Store geographic coordinates'), + 'tokens_account_cost' => 120, ], ], 'ht' => [ diff --git a/pg-act/auth/approval.php b/pg-act/auth/approval.php index 091c3e1..9a8a046 100644 --- a/pg-act/auth/approval.php +++ b/pg-act/auth/approval.php @@ -3,6 +3,8 @@ if ($_SESSION['type'] !== 'testing') output(403, _('This account is already approved.')); +rateLimit(); + if (isset(query('select', 'approval-keys', ['key' => $_POST['key']], 'key')[0]) !== true) output(403, _('This approval key is not available. It has been mistyped, used for another account, or has expired.')); diff --git a/pg-act/auth/password.php b/pg-act/auth/password.php index 413bcab..6da1be9 100644 --- a/pg-act/auth/password.php +++ b/pg-act/auth/password.php @@ -5,6 +5,8 @@ checkPasswordFormat($_POST['new-password']); if (checkPassword($_SESSION['id'], $_POST['current-password']) !== true) output(403, _('Wrong current password.')); +rateLimit(); + changePassword($_SESSION['id'], $_POST['new-password']); output(200, _('Password updated.')); diff --git a/pg-act/auth/username.php b/pg-act/auth/username.php index 2a9062e..274e818 100644 --- a/pg-act/auth/username.php +++ b/pg-act/auth/username.php @@ -10,6 +10,8 @@ $username = hashUsername($_POST['new-username']); if (usernameExists($username) !== false) output(403, _('This username is already taken.')); +rateLimit(); + DB->prepare('UPDATE users SET username = :username WHERE id = :id') ->execute([':username' => $username, ':id' => $_SESSION['id']]); diff --git a/pg-act/ns/caa.php b/pg-act/ns/caa.php index 83e20ce..53095d6 100644 --- a/pg-act/ns/caa.php +++ b/pg-act/ns/caa.php @@ -11,6 +11,8 @@ if (!(preg_match('/^[a-z]{1,127}$/D', $_POST['tag']))) if (!(preg_match('/^[a-z0-9.-]{1,255}$/D', $_POST['value']))) output(403, 'Wrong value for value.'); +rateLimit(); + knotcZoneExec($_POST['zone'], [ $values['domain'], $values['ttl'], diff --git a/pg-act/ns/cname.php b/pg-act/ns/cname.php index 3daeadf..f870b05 100644 --- a/pg-act/ns/cname.php +++ b/pg-act/ns/cname.php @@ -4,6 +4,8 @@ $values = nsParseCommonRequirements(); $_POST['cname'] = formatAbsoluteDomain($_POST['cname']); +rateLimit(); + knotcZoneExec($_POST['zone'], [ $values['domain'], $values['ttl'], diff --git a/pg-act/ns/dname.php b/pg-act/ns/dname.php index ff2e5a7..155fae3 100644 --- a/pg-act/ns/dname.php +++ b/pg-act/ns/dname.php @@ -4,6 +4,8 @@ $values = nsParseCommonRequirements(); $_POST['dname'] = formatAbsoluteDomain($_POST['dname']); +rateLimit(); + knotcZoneExec($_POST['zone'], [ $values['domain'], $values['ttl'], diff --git a/pg-act/ns/ip.php b/pg-act/ns/ip.php index 5fa0da1..4c6b9b9 100644 --- a/pg-act/ns/ip.php +++ b/pg-act/ns/ip.php @@ -4,6 +4,8 @@ $values = nsParseCommonRequirements(); $record = checkIpFormat($_POST['ip']); +rateLimit(); + knotcZoneExec($_POST['zone'], [ $values['domain'], $values['ttl'], diff --git a/pg-act/ns/loc.php b/pg-act/ns/loc.php index 23ed875..a3a50de 100644 --- a/pg-act/ns/loc.php +++ b/pg-act/ns/loc.php @@ -49,6 +49,8 @@ if (!($_POST['hp'] >= 0 AND $_POST['hp'] <= 90000000)) if (!($_POST['vp'] >= 0 AND $_POST['vp'] <= 90000000)) output(403, 'Wrong value for vp.'); +rateLimit(); + knotcZoneExec($_POST['zone'], [ $values['domain'], $values['ttl'], diff --git a/pg-act/ns/mx.php b/pg-act/ns/mx.php index 370151f..c534816 100644 --- a/pg-act/ns/mx.php +++ b/pg-act/ns/mx.php @@ -7,6 +7,8 @@ if (!($_POST['priority'] >= 0 AND $_POST['priority'] <= 255)) $_POST['host'] = formatAbsoluteDomain($_POST['host']); +rateLimit(); + knotcZoneExec($_POST['zone'], [ $values['domain'], $values['ttl'], diff --git a/pg-act/ns/ns.php b/pg-act/ns/ns.php index 8dcf92c..c064131 100644 --- a/pg-act/ns/ns.php +++ b/pg-act/ns/ns.php @@ -4,6 +4,8 @@ $values = nsParseCommonRequirements(); $_POST['ns'] = formatAbsoluteDomain($_POST['ns']); +rateLimit(); + knotcZoneExec($_POST['zone'], [ $values['domain'], $values['ttl'], diff --git a/pg-act/ns/print.php b/pg-act/ns/print.php index 67096e2..c415d15 100644 --- a/pg-act/ns/print.php +++ b/pg-act/ns/print.php @@ -4,6 +4,8 @@ nsCheckZonePossession($_POST['zone']); $data['zone_name'] = $_POST['zone']; +rateLimit(); + $zone_content = file_get_contents(CONF['ns']['knot_zones_path'] . '/' . $data['zone_name'] . 'zone'); if ($zone_content === false) output(500, 'Unable to read zone file.'); diff --git a/pg-act/ns/srv.php b/pg-act/ns/srv.php index 02f329c..7c5af6b 100644 --- a/pg-act/ns/srv.php +++ b/pg-act/ns/srv.php @@ -13,6 +13,8 @@ if (!($_POST['port'] >= 0 AND $_POST['port'] <= 65535)) $_POST['target'] = formatAbsoluteDomain($_POST['target']); +rateLimit(); + knotcZoneExec($_POST['zone'], [ $values['domain'], $values['ttl'], diff --git a/pg-act/ns/sshfp.php b/pg-act/ns/sshfp.php index b131cc3..b3b40a1 100644 --- a/pg-act/ns/sshfp.php +++ b/pg-act/ns/sshfp.php @@ -11,6 +11,8 @@ if (!($_POST['type'] === '2')) if (!(preg_match('/^[a-z0-9]{64}$/D', $_POST['fp']))) output(403, 'Wrong value for fp.'); +rateLimit(); + knotcZoneExec($_POST['zone'], [ $values['domain'], $values['ttl'], diff --git a/pg-act/ns/tlsa.php b/pg-act/ns/tlsa.php index c9ded9f..de5241e 100644 --- a/pg-act/ns/tlsa.php +++ b/pg-act/ns/tlsa.php @@ -14,6 +14,8 @@ if (!($_POST['type'] >= 0 AND $_POST['type'] <= 2)) if (!(preg_match('/^[a-zA-Z0-9.-]{1,1024}$/D', $_POST['content']))) output(403, 'Wrong value for content.'); +rateLimit(); + knotcZoneExec($_POST['zone'], [ $values['domain'], $values['ttl'], diff --git a/pg-act/ns/txt.php b/pg-act/ns/txt.php index ebabc5c..959ef49 100644 --- a/pg-act/ns/txt.php +++ b/pg-act/ns/txt.php @@ -5,6 +5,8 @@ $values = nsParseCommonRequirements(); if (!(preg_match('/^[a-zA-Z0-9 .@=:!%$+\/\()[\]_-]{5,8192}$/D', $_POST['txt']))) output(403, 'Wrong value for txt.'); +rateLimit(); + knotcZoneExec($_POST['zone'], [ $values['domain'], $values['ttl'], diff --git a/pg-act/reg/ds.php b/pg-act/reg/ds.php index 0b6710e..a656165 100644 --- a/pg-act/reg/ds.php +++ b/pg-act/reg/ds.php @@ -17,6 +17,8 @@ if ($_POST['dt'] !== '2' AND $_POST['dt'] !== '4') regCheckDomainPossession($_POST['zone']); +rateLimit(); + knotcZoneExec(regParseDomain($_POST['zone'])['suffix'], [ $_POST['zone'], CONF['reg']['ttl'], diff --git a/pg-act/reg/glue.php b/pg-act/reg/glue.php index 2b4e7c7..3ceecf9 100644 --- a/pg-act/reg/glue.php +++ b/pg-act/reg/glue.php @@ -2,6 +2,8 @@ regCheckDomainPossession($_POST['suffix']); +rateLimit(); + knotcZoneExec(regParseDomain($_POST['suffix'])['suffix'], [ formatAbsoluteDomain(formatEndWithDot($_POST['subdomain']) . $_POST['suffix']), CONF['reg']['ttl'], diff --git a/pg-act/reg/ns.php b/pg-act/reg/ns.php index 3da9608..487c27e 100644 --- a/pg-act/reg/ns.php +++ b/pg-act/reg/ns.php @@ -2,6 +2,8 @@ regCheckDomainPossession($_POST['domain']); +rateLimit(); + knotcZoneExec(regParseDomain($_POST['domain'])['suffix'], [ $_POST['domain'], CONF['reg']['ttl'], diff --git a/pg-act/reg/print.php b/pg-act/reg/print.php index d00a99e..b639a52 100644 --- a/pg-act/reg/print.php +++ b/pg-act/reg/print.php @@ -2,6 +2,8 @@ regCheckDomainPossession($_POST['domain']); +rateLimit(); + $zone_content = file_get_contents(CONF['reg']['suffixes_path'] . '/' . regParseDomain($_POST['domain'])['suffix'] . 'zone'); if ($zone_content === false) output(500, 'Unable to read registry file.'); diff --git a/pg-act/reg/transfer.php b/pg-act/reg/transfer.php index 8af8fa5..6a44150 100644 --- a/pg-act/reg/transfer.php +++ b/pg-act/reg/transfer.php @@ -19,6 +19,8 @@ if (preg_match('/^' . preg_quote($domain, '/') . '[\t ]+[0-9]{1,8}[\t ]+IN[\t ]+ checkAuthToken($matches['salt'], $matches['hash']); +rateLimit(); + DB->prepare('UPDATE registry SET username = :username WHERE domain = :domain') ->execute([':username' => $_SESSION['id'], ':domain' => $domain]);