Ignore request values that are not strings.

An array action or username no longer causes a PHP error.
This commit is contained in:
tim
2026-09-26 15:27:51 +02:00
parent be814a3ba5
commit 52f4855850
6 changed files with 27 additions and 4 deletions
+1 -1
View File
@@ -64,7 +64,7 @@ Ordinary web users can: write article
$action = NULL;
if (isset($_POST['action'])) {
$action = strtolower($_POST['action']);
$action = is_string($_POST['action']) ? strtolower($_POST['action']) : NULL;
// We can trigger only choose and edit via GET variables.
} else if (isset($_GET['action'])) {
if ($_GET['action'] == 'choose') {
+1 -1
View File
@@ -58,7 +58,7 @@ Ordinary web users can: write article
*/
if (isset($_POST['action']))
$action = strtolower($_POST['action']);
$action = is_string($_POST['action']) ? strtolower($_POST['action']) : NULL;
else
$action = NULL;
+3 -2
View File
@@ -6,13 +6,14 @@ $denied = NULL;
$wait_minutes = 0;
$captcha_failed = FALSE;
$is_admin = NULL;
$login_name = is_string($_POST['username'] ?? NULL) ? $_POST['username'] : '';
if (isset($_SESSION['editor'])) {
session_write_close();
header("Location: /publish/edit");
return;
} else if (isset($_POST['login']) && !csrf_valid()) {
$denied = TRUE;
} else if (isset($_POST['login']) && ($wait = login_blocked_for((string)($_POST['username'] ?? ''))) > 0) {
} else if (isset($_POST['login']) && ($wait = login_blocked_for($login_name)) > 0) {
$denied = TRUE;
$wait_minutes = (int)ceil($wait / 60);
} else if (isset($_POST['login']) && !captcha_verify_response()) {
@@ -23,7 +24,7 @@ if (isset($_SESSION['editor'])) {
$table = "editors";
open_db('open');
$username = (string)($_POST['username'] ?? '');
$username = $login_name;
$query = "SELECT * FROM $table WHERE username = ? LIMIT 1";
$getid = $db->execute_query($query, array($username)) or db_fail();
$row = $getid->fetch_assoc();
+7
View File
@@ -72,6 +72,13 @@ class EditTest extends PageTestCase {
$this->assertSame(array('5', 'Changed', 'Needs work'), array($row['id'], $row['title'], $row['comments']));
}
public function testAnArrayActionIsIgnored(): void {
$this->loginAs();
$page = $this->post('/publish/edit', array('action' => array('delete'), 'id' => '1'));
$this->assertSame(200, $page['status']);
$this->assertSame(array(), $this->queries('/^(DELETE|INSERT|UPDATE)/'));
}
public function testDeletingNeedsTheToken(): void {
$page = $this->post('/publish/edit', array('action' => 'delete', 'id' => '1', 'queue' => '0', 'csrf_token' => 'wrong'));
$this->assertStringContainsString('Your session has expired.', $page['body']);
+8
View File
@@ -39,6 +39,14 @@ class LoginTest extends PageTestCase {
$this->get('/publish/login', array('X-Test-Plain' => '1', 'Host' => 'evil.example')));
}
public function testAnArrayUsernameIsRefused(): void {
$token = $this->csrfToken($this->get('/publish/login')['body']);
$answer = $this->post('/publish/login', array('login' => '1', 'username' => array('ed'), 'password' => 'secret',
'csrf_token' => $token, 'g-recaptcha-response' => 'pass'));
$this->assertSame(200, $answer['status']);
$this->assertStringContainsString('Access denied.', $answer['body']);
}
public function testTheFormHasATokenAndTheCaptcha(): void {
$body = $this->get('/publish/login')['body'];
$this->assertSame($this->session()['csrf_token'], $this->csrfToken($body));
+7
View File
@@ -111,6 +111,13 @@ class SubmitTest extends PageTestCase {
$this->assertSame(array(), $this->queries('/^INSERT/'));
}
public function testAnArrayActionIsIgnored(): void {
$page = $this->post('/publish', array('action' => array('post')));
$this->assertSame(200, $page['status']);
$this->assertStringNotContainsString('Please review your submission.', $page['body']);
$this->assertSame(array(), $this->queries('/^INSERT/'));
}
public function testFieldsAreEscapedInTheForm(): void {
$token = $this->csrfToken($this->get('/publish')['body']);
$page = $this->post('/publish', $this->story(array('action' => 'preview', 'csrf_token' => $token, 'g-recaptcha-response' => 'pass',