Backlog Unificado
Projeto: RioNoTeatro. Fonte principal: /www/wwwroot/rionoteatro.com.br/docs/BACKLOG.md.
Modo read-only: ações de escrita ficam disponíveis apenas para o Cérebro.
Sem itens pendentes em /www/wwwroot/rionoteatro.com.br/docs/BACKLOG.md.
Especificações Disponíveis (fora da fila pendente)
- BK-136
- BK-137
- BK-138
- BK-147
- BK-148
- BK-149
- BK-150
- BK-151
- BK-156
- BK-158
- BK-159
- BK-160
- BK-161
- BK-162
- BK-163
- BK-164
- BK-165
- BK-166
- BK-170
- BK-171
- BK-172
- BK-177
- BK-183
- BK-186
- BK-187
- BK-189
- BK-190
- BK-191
- BK-192
- BK-193
- BK-195
- BK-196
- BK-197
- BK-198
- BK-199
- BK-201
- BK-205
- BK-207
- BK-208
- BK-209
- BK-210
- BK-211
- BK-212
- BK-213
- BK-214
- BK-215
- BK-216
- BK-217
- BK-218
- BK-219
- BK-220
- BK-221
- BK-229
- BK-230
- BK-231
- BK-232
- BK-233
- BK-234
- BK-235
- BK-236
- BK-239
- BK-240
- BK-241
- BK-242
- BK-243
- BK-244
- BK-245
- BK-246
- BK-248
- BK-249
- BK-250
- BK-251
- BK-252
- BK-253
- BK-254
- BK-255
- BK-256
- BK-257
- BK-258
- BK-259
- BK-260
- BK-261
- BK-262
- BK-263
- BK-264
- BK-265
- BK-266
- BK-267
- BK-268
- BK-269
- BK-270
- BK-271
- BK-272
- BK-275
- BK-276
- BK-277
- BK-278
- BK-279
- BK-280
- BK-295
- BK-313
Detalhe do BK Selecionado
BK-254 - Hardening do cadastro público e PalcoFan contra abuso automatizado
Contexto
Em 2026-04-11, o site recebeu automação hostil a partir do IP 148.113.214.92, com payloads clássicos de SQLi (DBMS_PIPE, PG_SLEEP, waitfor delay) espalhados por formulários e URLs.
Achado operacional confirmado:
- conta falsa criada em
clientes.id = 50981 - nome:
MmzHrrdb - e-mail:
sample@email.tst cpf:g00dPa$$w0rDrg:1- status:
A - essa conta foi usada para enviar avaliações pendentes no PalcoFan, inclusive para:
teatro id 118evento id 1460peca id 1493
Leitura atual:
- até aqui, não há prova de webshell nem de comprometimento confirmado do servidor
- há prova forte de abuso da aplicação por falta de barreiras no cadastro público e no formulário AJAX do PalcoFan
Evidências
Conta falsa no banco
```sql
SELECT id,nome,email,created,telefone,celular,cpf,rg,status
FROM clientes
WHERE id = 50981;
```
Retorno observado:
```json
{"id":"50981","nome":"MmzHrrdb","email":"sample@email.tst","created":"2026-04-11 02:08:36","telefone":null,"celular":"(1","cpf":"g00dPa$$w0rD","rg":"1","status":"A"}
```
Comentários maliciosos armazenados como texto
```sql
SELECT id,id_cliente,tipo_item,id_item,estrelas,comentario,status,data_criacao
FROM tb_avaliacoes
WHERE comentario LIKE '%DBMS_PIPE.RECEIVE_MESSAGE%';
```
Retornos observados:
id=5,id_cliente=50981,tipo_item=teatro,id_item=118id=4,id_cliente=50981,tipo_item=evento,id_item=1460id=2,id_cliente=50981,tipo_item=peca,id_item=1493
Logs web
O access log mostrou rajadas do mesmo IP atacando:
painel/modulos/profile/index.php?act=editarprodutor/modulos/profile/?act=editarprodutor/modulos/eventos/incluir.php?act=cadastrar
com payloads de:
DBMS_PIPE.RECEIVE_MESSAGE(...)PG_SLEEP(...)waitfor delay- variantes
OR 1=1
Causa raiz confirmada
Cadastro público frouxo
Em action.php, o case "cadastro" aceitava qualquer valor não vazio como “passaporte” quando o campo cpf não tinha 11 dígitos:
```php
$cpf_valido = (strlen($CPF) == 11) ? valida_cpf($CPF) : (strlen($CPF) > 0);
```
Isso permitiu criar conta com cpf = g00dPa$$w0rD.
PalcoFan sem barreiras reais
Em includes/ajax_palcofan.php, o endpoint:
- exigia login
- mas não tinha
CSRF - não tinha
honeypot - não tinha
rate limit - não tinha bloqueio mínimo de conteúdo abusivo
Objetivo do hotfix
- endurecer cadastro público
- endurecer o PalcoFan
- reduzir abuso automatizado sem quebrar o fluxo legítimo
- registrar que o incidente atual é de abuso do app, não de RCE comprovado
Escopo de código desta rodada
config/security_request_helper.phpaction.phpcadastre-se.phpincludes/inc_palcofan.phpincludes/ajax_palcofan.php
Correções mínimas planejadas
Cadastro público
- validar e-mail no servidor
- validar confirmação de e-mail no servidor
- exigir senha mínima
- validar CPF brasileiro real quando vier com 11 dígitos
- validar “passaporte/documento alternativo” com regex mínima segura
- validar
rg/documento com fotocom regex mínima segura - adicionar
CSRF - adicionar
honeypot - adicionar
rate limitpor IP
PalcoFan
- adicionar
CSRF - adicionar
honeypot - adicionar
rate limit - limitar tamanho de comentário
- rejeitar payloads abusivos típicos de SQLi no campo de comentário
Implementado nesta rodada
Helper novo
config/security_request_helper.php- token CSRF por escopo
- honeypot
- detecção simples de IP
- rate limit em arquivo temporário
- validação mínima de CPF/passaporte
- validação mínima de documento com foto
- assinatura simples de payloads clássicos de SQLi
Cadastro público endurecido
action.php- passou a validar
csrf_token - passou a validar honeypot
website - ganhou rate limit por IP
- passou a validar e-mail e confirmação de e-mail no servidor
- passou a exigir senha mínima
- deixou de aceitar qualquer string arbitrária como “passaporte”
- passou a validar o campo de documento com foto antes de inserir em
clientes
cadastre-se.php- formulário agora envia
csrf_token - formulário agora inclui honeypot invisível
PalcoFan endurecido
includes/inc_palcofan.php- formulário agora envia
csrf_token - formulário agora inclui honeypot invisível
includes/ajax_palcofan.php- valida
csrf_token - valida honeypot
- aplica rate limit por cliente/IP
- limita comentário a
1000caracteres - bloqueia payloads com assinatura clássica de SQLi antes de gravar
Validação local executada
php -l config/security_request_helper.phpphp -l action.phpphp -l cadastre-se.phpphp -l includes/inc_palcofan.phpphp -l includes/ajax_palcofan.php
Validação funcional auxiliar:
- regex de passaporte aceitou
A1234567 - regex de passaporte rejeitou
g00dPa$$w0rD - regex de documento rejeitou
1'||DBMS_PIPE - filtro de assinatura abusiva detectou
DBMS_PIPE.RECEIVE_MESSAGE(...)
Próximos passos fora deste hotfix
- endurecer endpoints que ainda aceitam mutação por
GET - revisar páginas de perfil cliente/produtor que apareceram nos logs de abuso
- avaliar bloqueio temporário do IP
148.113.214.92na borda - revisar política de ativação automática de conta pública
- decidir o tratamento da conta
50981e das avaliações pendentes já gravadas
Revisão das recomendações externas recebidas em 2026-04-11
1. Desabilitar display_errors e manter log_errors
Status:
- válido
- já aplicado no projeto
Leitura:
- o relatório acertou ao apontar o vazamento de path real do servidor
- isso foi mitigado em duas camadas:
- hotfix funcional do
urlbaseemincludes/inc_peca.php display_errors=Offnophp.inilocal e no.user.ini
Observação:
- o follow-up de
error_logdedicado eexpose_phpfica documentado emBK-255
2. includes/security.php com PDO + prepared statements + CSRF + rate limit
Status:
- válido como direção
- não válido como drop-in literal
Leitura:
- a parte conceitual está correta:
- prepared statements
- CSRF
- rate limit
- mas o snippet proposto é genérico demais para o RNT:
- o projeto hoje é legado em
mysqli/helpers próprios - trocar para PDO em massa no meio do incidente aumentaria risco
Input::text()comhtmlspecialchars()no momento da entrada não deve virar padrão global do banco; o correto continua sendo escapar na saída
Decisão desta rodada:
- em vez de importar esse arquivo cru, foi criado
config/security_request_helper.php - ele cobre o recorte urgente do incidente sem refatoração transversal do banco inteiro
3. Snippet de Nginx com fastcgi_pass e rate limit
Status:
- parcialmente válido
- perigoso se aplicado cru
Leitura:
- válido:
- headers HTTP de segurança
limit_req_zone- bloqueio de arquivos sensíveis
- perigoso/incorreto para o ambiente real:
- o snippet usa
php-cgi-74.sock, mas o RNT hoje mostraphp-cgi-56.socknos logs - sobrescrever
fastcgi_passmanualmente no vhost do aaPanel sem reconciliar com o include atual pode quebrar o site - as rotas listadas não cobrem o vetor confirmado do incidente (
/includes/ajax_palcofan.php,/action.php,painel/action.php,produtor/.../action.php) - bloquear
curl/7.como user-agent é agressivo demais e pode derrubar integrações legítimas X-XSS-Protectioné legado/obsoleto e não deve ser tratado como defesa principal
Decisão:
- esse tema foi separado para
BK-255
4. reCAPTCHA v3
Status:
- válido como camada adicional
- não substitui validação, CSRF e rate limit
Leitura:
- bom candidato para:
- cadastro público
- login
- comentário/avaliação
- precisa:
- chave em local seguro
- score ajustado com teste real
- fallback para falsos positivos
Decisão:
- manter como follow-up prioritário de segurança de aplicação
5. Cloudflare / WAF
Status:
- válido
Leitura:
- útil para filtrar scanners óbvios e dar rate limit na borda
- não elimina a necessidade de corrigir o app
Decisão:
- manter como follow-up de borda em
BK-255
6. Ideia de usar “Conta WhatsApp Ativa” como sinal de usuário real
Status:
- válido como sinal de confiança
- não válido como único fator de autenticação/autorização
Leitura:
- isso pode ajudar muito como antifraude para áreas de abuso, por exemplo:
- comentar no PalcoFan
- abrir certas funções de produtor
- reduzir spam de conta recém-criada
- mas não deve virar bloqueio bruto de “acessar a área” inteira, porque:
- depende de um serviço externo
- pode excluir usuário legítimo sem WhatsApp ativo
- não substitui sessão, senha, CSRF e rate limit
Recomendação prática:
- usar como trust score
- melhor ainda: combinar com evidência de compra real
Sugestão de regra futura para o PalcoFan:
- permitir avaliação se o cliente cumprir ao menos um dos critérios:
- tem pedido pago/consumido relacionado
- tem telefone com sinal forte de conta WhatsApp ativa
- foi liberado manualmente pelo admin
Isso é mais coerente com o produto do que deixar qualquer conta recém-criada comentar só por estar logada.
7. Hipótese de IDOR em checkout_pix.php?id=...
Status:
- não confirmado como IDOR explorável no código atual
- válido como preocupação de enumeração/tokenização futura
Leitura:
- o
checkout_pix.phphoje ainda usa ID sequencial na URL - porém o código já faz ownership guard por sessão:
pedidos.cliente_id == $_SESSION['CMS_X_Cliente']['id']orders.user_id == $_SESSION['CMS_X_Cliente']['id']- os endpoints críticos de PIX/carteira/cartão em
action.phptambém filtram pelocliente_idda sessão
Conclusão:
- a crítica “URL sequencial” é válida
- a crítica “IDOR confirmado do pedido de outro cliente” não ficou confirmada no código atual
- isso virou follow-up próprio no
BK-257