O mysql_samp foi desenvolvido com seguranca como prioridade. Este documento descreve as protecoes implementadas e boas praticas de uso.
O plugin protege contra SQL injection em multiplas camadas:
mysql_format com %s — Escapa automaticamente a string (aspas, barras, null bytes, etc.)mysql_escape_string — Funcao pura para escape manualescape_identifier// SEGURO: %s escapa automaticamente
new query[256];
mysql_format(gMysql, query, sizeof(query),
"SELECT * FROM players WHERE name = '%s'", playerName);
// INSEGURO: concatenacao direta — NUNCA faca isso
new query[256];
format(query, sizeof(query),
"SELECT * FROM players WHERE name = '%s'", playerName);
// Se playerName = "'; DROP TABLE players; --" → SQL injection!
| Especificador | Escape | Quando usar |
|---|---|---|
%s |
Sim | Input do usuario, dados nao confiaveis |
%r |
Nao | Valores internos confiaveis (nomes de tabela, constantes) |
Regra: Use
%spara tudo. Use%rapenas quando voce tem certeza absoluta de que o valor e seguro.
O plugin forca SET NAMES utf8mb4 em todas as conexoes do pool via init() do OptsBuilder. Isso previne:
Voce pode alterar o charset com mysql_set_charset, mas o padrao UTF-8 e o mais seguro.
O plugin implementa limites para prevenir esgotamento de memoria e threads:
| Recurso | Limite | Protecao |
|---|---|---|
| Caches salvos | 1024 | Previne memory exhaustion (CWE-770) |
| Rows por resultado | 100.000 | Previne alocacao massiva de memoria (CWE-770) |
| ORM string max_len | 4096 | Previne escrita fora dos limites (CWE-787) |
Quando um limite e atingido:
logs/mysql.logTodos os contadores de ID internos (conexoes, options, ORM, cache) usam wrapping_add com validacao de minimo 1. Isso previne:
O dispatch de callbacks verifica erros em cada operacao:
push de parametro na stack AMX falhar, o callback e abortado| Destino | Conteudo |
|---|---|
| Console | Mensagens genericas com codigos de erro |
logs/mysql.log |
Detalhes completos com timestamp |
O console nunca exibe:
mysql_format com %s// Correto
mysql_format(gMysql, query, sizeof(query),
"SELECT * FROM users WHERE name = '%s'", input);
// Errado — vulneravel a SQL injection
format(query, sizeof(query),
"SELECT * FROM users WHERE name = '%s'", input);
public OnQueryError(errorid, const error[], const callback[], const query[], connId) {
printf("[MySQL] Error %d: %s", errorid, error);
return 1;
}
forward OnData();
public OnData() {
if (cache_get_row_count() <= 0) return;
// Agora e seguro ler dados
new val = cache_get_value_name_int(0, "id");
}
// Destrua ORMs quando nao precisar mais
orm_destroy(ormId);
// Delete caches salvos quando nao precisar mais
cache_delete(cacheId);
// Feche conexoes ao descarregar
mysql_close(connId);
// NUNCA faca isso com input do usuario
mysql_format(gMysql, query, sizeof(query),
"SELECT * FROM %r WHERE id = %d", userInput, id);
// userInput poderia ser "players; DROP TABLE users; --"
| CWE | Severidade | Mitigacao |
|---|---|---|
| CWE-89 | Alta | Escape automatico em %s, %e, ORM strings e identificadores |
| CWE-787 | Alta | Limite de max_len a 4096 no ORM |
| CWE-770 | Media | Limites em caches salvos e rows por resultado |
| CWE-252 | Media | Verificacao de erros no push de parametros AMX |
| CWE-190 | Baixa | wrapping_add em todos os contadores de ID |