post.php: add turnstile server side checks

This commit is contained in:
Zankaria 2024-07-27 16:54:18 +02:00
parent 12f0fd1cb4
commit 67de8df246

View file

@ -92,6 +92,43 @@ function check_recaptcha($secret, $response, $remote_ip)
return !!$resp['success'];
}
function check_turnstile($secret, $response, $remote_ip, $expected_action)
{
$data = [
'secret' => $secret,
'response' => $response,
];
if ($remote_ip !== null) {
$data['remoteip'] = $remote_ip;
}
$c = curl_init();
curl_setopt_array($c, [
CURLOPT_URL => 'https://challenges.cloudflare.com/turnstile/v0/siteverify',
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => $data,
CURLOPT_RETURNTRANSFER => true,
]);
$c_ret = curl_exec($c);
if ($c_ret === false) {
$err_no = curl_errno($c);
$err_str = curl_error($c);
curl_close($c);
error_log("Turnstide call failed. Curl returned: $err_no ($err_str)");
return false;
}
curl_close($c);
$json_ret = json_decode($c_ret, true);
if ($json_ret === null) {
error_log("Turnstide call failed. Malformed json: $c_ret");
return false;
}
return $json_ret['success'] === true && $json_ret['action'] === $expected_action;
}
/**
* Deletes the (single) captcha associated with the ip and code.
*
@ -690,22 +727,42 @@ function handle_post()
if (!$dropped_post) {
if ($config['dynamic_captcha'] && $_SERVER['REMOTE_ADDR'] === '127.0.0.1' && $config['recaptcha']) {
if (!isset($_POST['g-recaptcha-response'])) {
error($config['error']['bot']);
}
if (!check_recaptcha($config['recaptcha_private'], $_POST['g-recaptcha-response'], null)) {
error($config['error']['captcha']);
if ($config['dynamic_captcha'] && $_SERVER['REMOTE_ADDR'] === '127.0.0.1') {
if ($config['recaptcha']) {
if (!isset($_POST['g-recaptcha-response'])) {
error($config['error']['bot']);
}
if (!check_recaptcha($config['recaptcha_private'], $_POST['g-recaptcha-response'], null)) {
error($config['error']['captcha']);
}
} elseif ($config['turnstile']) {
if (!isset($_POST['cf-turnstile-response'])) {
error($config['error']['bot']);
}
$expected_action = $post['op'] ? 'post-thread' : 'post-reply';
if (!check_turnstile($config['turnstile_private'], $_POST['cf-turnstile-response'], null, $expected_action)) {
error($config['error']['captcha']);
}
}
}
// Check for CAPTCHA right after opening the board so the "return" link is in there.
if (!$config['dynamic_captcha'] && $config['recaptcha']) {
if (!isset($_POST['g-recaptcha-response'])) {
error($config['error']['bot']);
}
if (!check_recaptcha($config['recaptcha_private'], $_POST['g-recaptcha-response'], $_SERVER['REMOTE_ADDR'])) {
error($config['error']['captcha']);
if (!$config['dynamic_captcha']) {
if ($config['recaptcha']) {
if (!isset($_POST['g-recaptcha-response'])) {
error($config['error']['bot']);
}
if (!check_recaptcha($config['recaptcha_private'], $_POST['g-recaptcha-response'], $_SERVER['REMOTE_ADDR'])) {
error($config['error']['captcha']);
}
} elseif ($config['turnstile']) {
if (!isset($_POST['cf-turnstile-response'])) {
error($config['error']['bot']);
}
$expected_action = $post['op'] ? 'post-thread' : 'post-reply';
if (!check_turnstile($config['turnstile_private'], $_POST['cf-turnstile-response'], null, $expected_action)) {
error($config['error']['captcha']);
}
}
}