diff --git a/application/controllers/Qso.php b/application/controllers/Qso.php index b38b62057..43b41be25 100644 --- a/application/controllers/Qso.php +++ b/application/controllers/Qso.php @@ -217,6 +217,14 @@ class QSO extends CI_Controller { * Returns JSON */ public function saveqso() { + // CSRF mitigation: this endpoint is AJAX-only; reject plain form submissions + if ($this->input->server('HTTP_X_REQUESTED_WITH') !== 'XMLHttpRequest') { + $this->output->set_status_header(403) + ->set_content_type('application/json') + ->set_output(json_encode(['error' => 'Forbidden'])); + return; + } + $this->load->model('logbook_model'); $qso_data = [ @@ -563,7 +571,20 @@ class QSO extends CI_Controller { } /* Delete QSO */ - function delete($id) { + function delete() { + // CSRF mitigation: reject non-POST requests + if ($this->input->method() !== 'post') { + $this->session->set_flashdata('error', __("Invalid request method")); + redirect('dashboard'); + return; + } + + $id = $this->input->post('id', TRUE); + if (empty($id)) { + redirect('dashboard'); + return; + } + $this->load->model('logbook_model'); if ($this->logbook_model->check_qso_is_accessible($id)) { diff --git a/application/controllers/Station.php b/application/controllers/Station.php index e65d47387..8ef8e3e46 100644 --- a/application/controllers/Station.php +++ b/application/controllers/Station.php @@ -66,10 +66,21 @@ class Station extends CI_Controller $data['oqrs'] = $this->input->post('oqrs'); $data['oqrsemail'] = $this->input->post('oqrsemail'); $data['oqrstext'] = $this->input->post('oqrstext'); + $csrf_token = bin2hex(random_bytes(32)); + $this->session->set_userdata('csrf_station_create', $csrf_token); + $data['csrf_token'] = $csrf_token; $this->load->view('interface_assets/header', $data); $this->load->view('station_profile/create', $data); $this->load->view('interface_assets/footer'); } else { + $submitted = $this->input->post('csrf_token', TRUE); + $stored = $this->session->userdata('csrf_station_create'); + if (empty($submitted) || empty($stored) || !hash_equals($stored, $submitted)) { + $this->session->set_flashdata('error', __("Invalid security token")); + redirect('station/create'); + return; + } + $this->session->set_userdata('csrf_station_create', bin2hex(random_bytes(32))); $this->stations->add(); redirect('stationsetup'); } @@ -85,10 +96,22 @@ class Station extends CI_Controller $this->form_validation->set_rules('dxcc', 'DXCC', 'required'); $this->form_validation->set_rules('gridsquare', 'Locator', 'callback_check_locator'); if ($this->form_validation->run() == FALSE) { + $csrf_token = bin2hex(random_bytes(32)); + $this->session->set_userdata('csrf_station_edit', $csrf_token); + $data['csrf_token'] = $csrf_token; $this->load->view('interface_assets/header', $data); - $this->load->view('station_profile/edit'); + $this->load->view('station_profile/edit', $data); $this->load->view('interface_assets/footer'); } else { + $submitted = $this->input->post('csrf_token', TRUE); + $stored = $this->session->userdata('csrf_station_edit'); + if (empty($submitted) || empty($stored) || !hash_equals($stored, $submitted)) { + $this->session->set_flashdata('error', __("Invalid security token")); + redirect('station/edit/' . $id); + return; + } + $this->session->set_userdata('csrf_station_edit', bin2hex(random_bytes(32))); + if ($this->stations->edit()) { $data['notice'] = __("Station Location") . $this->security->xss_clean($this->input->post('station_profile_name', true)) . " Updated"; } diff --git a/application/controllers/User.php b/application/controllers/User.php index d166dd10a..19dd7e356 100644 --- a/application/controllers/User.php +++ b/application/controllers/User.php @@ -1088,6 +1088,9 @@ class User extends CI_Controller { if ($this->form_validation->run() == FALSE) { + $csrf_token = bin2hex(random_bytes(32)); + $this->session->set_userdata('csrf_user_delete', $csrf_token); + $data->csrf_token = $csrf_token; $this->load->view('interface_assets/header', $data); $this->load->view('user/delete'); @@ -1095,6 +1098,15 @@ class User extends CI_Controller { } else { + $submitted = $this->input->post('csrf_token', TRUE); + $stored = $this->session->userdata('csrf_user_delete'); + if (empty($submitted) || empty($stored) || !hash_equals($stored, $submitted)) { + $this->session->set_flashdata('error', __("Invalid security token")); + redirect('user'); + return; + } + $this->session->set_userdata('csrf_user_delete', bin2hex(random_bytes(32))); + if($this->user_model->delete($data->user_id)) { $this->session->set_flashdata('notice', __("User deleted")); diff --git a/application/views/station_profile/create.php b/application/views/station_profile/create.php index bbcea74a1..6ba49d5c3 100644 --- a/application/views/station_profile/create.php +++ b/application/views/station_profile/create.php @@ -43,6 +43,7 @@ if ($dxcc_list->result() > 0) {