
Criando um painel de administração de trading em MQL5 (Parte VII): Usuário confiável, recuperação e criptografia
Conteúdo
- Introdução
- Implementação do usuário confiável no painel administrativo
- Criptografia e exemplos de aplicação no painel administrativo
- Testes
- Considerações finais
Introdução
O Mercado do MQL5 ilustra a importância da identificação do dispositivo para garantir a segurança dos produtos distribuídos. Nossas pesquisas atuais foram motivadas por problemas enfrentados ao trabalhar com nosso painel administrativo seguro. Após a implementação de medidas de segurança reforçadas, o processo de desenvolvimento e testes passou a sofrer atrasos devido às constantes solicitações de login e autenticação, que surgiam a cada compilação do arquivo ou teste de funções no terminal. Esse nível adicional de segurança, embora necessário, trouxe dificuldades ao nosso fluxo de trabalho.
O aviso mostrado abaixo aparece na primeira página do Mercado ao publicar um novo produto. Ele destaca como o MQL5 prioriza e aplica medidas de segurança robustas para proteger tanto desenvolvedores quanto usuários.Cada programa vendido no Mercado é criptografado com uma chave especial que protege o produto contra uso ilegal. A chave de criptografia é exclusiva para cada comprador e vinculada ao seu computador, garantindo assim que todos os produtos no Mercado tenham proteção automática contra cópia.
Um Produto adquirido pode ser ativado no mínimo cinco vezes. Isso garante um equilíbrio entre os interesses de compradores e vendedores. A quantidade de ativações disponíveis é definida pelo vendedor.
Muitos aplicativos e sites implementam a proteção de segundo nível de forma seletiva, ativando-a apenas quando detectam atividade suspeita, como o uso de um IP anônimo, tentativas de login a partir de novos dispositivos ou várias falhas consecutivas de login. Essa abordagem minimiza interrupções no uso, ao mesmo tempo em que mantém a segurança.
No nosso caso, o atraso nos testes durante o desenvolvimento é causado pela repetida digitação de senhas e pela verificação do aplicativo Telegram em busca dos códigos de 6 dígitos gerados. Alertas frequentes podem se tornar cansativos, especialmente quando são provocados por mudanças na atividade do terminal. Abaixo estão algumas ações que levam à reinicialização do dispositivo e, consequentemente, a novas solicitações de senha:
- Troca de par
- Troca de timeframe
- Reinicialização do terminal e similares
Em alguns cenários, nossos programas são reinicializados repetidamente devido a diferentes ações, um processo inevitável por motivos técnicos ou de utilização prática. O algoritmo de verificação de usuário está incorporado no início da função de inicialização, tornando impossível continuar a execução do programa sem passar por essa etapa. No entanto, podemos introduzir um mecanismo alternativo na função de inicialização para otimizar o processo. Esse algoritmo de bypass rastreia o número de tentativas de login, garantindo uma execução mais contínua durante sessões válidas.
Se o número de tentativas incorretas de senha ultrapassar o limite definido, isso sinaliza um comportamento suspeito ou indica que o usuário original pode ter perdido ou esquecido sua senha. Por outro lado, se a senha correta for digitada em até três tentativas, o sistema contorna o 2FA, o que economiza bastante tempo ao evitar a reautenticação via Telegram. Essa abordagem aumenta tanto a segurança quanto a eficiência, especialmente nas fases intensas de desenvolvimento e testes.
Na imagem abaixo é mostrado o problema do envio de múltiplas mensagens de verificação no Telegram durante o desenvolvimento do aplicativo, o que demonstra a necessidade prática desse algoritmo aprimorado.
Painel administrativo: Bot pessoal para entrega de códigos 2FA no Telegram
Anteriormente, as repetidas solicitações de senha e de autenticação de dois fatores a cada inicialização do programa tornavam o processo extremamente trabalhoso. Para economizar tempo no desenvolvimento, adicionei uma linha de código que exibia o código de verificação de 6 dígitos, enviado pelo Telegram, diretamente no log do Expert do terminal. Isso me permitiu extrair rapidamente o código do log durante os testes do aplicativo, sem precisar alternar para o Telegram, o que simplificou consideravelmente o processo.
O fragmento de código em questão faz parte da função responsável pelo envio de mensagens ao Telegram. Para conveniência, incluí nele a função de registrar a mensagem no log. Contudo, nesta fase de desenvolvimento pretendo remover essa função para aumentar a segurança em versões futuras. Colocar informações confidenciais, por exemplo códigos de verificação, no log pode representar uma ameaça à segurança em caso de acesso não autorizado. Esta medida reflete o equilíbrio entre otimizar o processo de desenvolvimento e seguir as melhores práticas de proteção de dados confidenciais.
O trecho de código abaixo mostra a linha que exibe a mensagem enviada.
//+------------------------------------------------------------------+ //| Send the message to Telegram | //+------------------------------------------------------------------+ bool SendMessageToTelegram(string message, string chatId, string botToken) { string url = "https://api.telegram.org/bot" + botToken + "/sendMessage"; string jsonMessage = "{\"chat_id\":\"" + chatId + "\", \"text\":\"" + message + "\"}"; char postData[]; ArrayResize(postData, StringToCharArray(jsonMessage, postData) - 1); int timeout = 5000; char result[]; string responseHeaders; int responseCode = WebRequest("POST", url, "Content-Type: application/json\r\n", timeout, postData, result, responseHeaders); if (responseCode == 200) { Print("Message sent successfully: ", message); //This line prints the message in journal,thus a security leak that I used to bypass telegram during app tests. return true; } else { Print("Failed to send message. HTTP code: ", responseCode, " Error code: ", GetLastError()); Print("Response: ", CharArrayToString(result)); return false; } }
Abaixo está a mensagem enviada ao Telegram, contendo o código de confirmação. Essa abordagem provou ser um modo conveniente de contornar a verificação do código do Telegram durante o desenvolvimento. Porém, o código cria uma séria ameaça à segurança, já que pessoas não autorizadas podem obter o código diretamente do terminal, sem acesso ao Telegram. O texto normalmente é exibido na aba "Experts" do terminal:
Objetivo da discussão:2024.11.22 08:44:47.980 Admin Panel V1.22 (Volatility 75 (1s) Index,M1) Message sent successfully: A login attempt was made on the Admin Panel. Please use this code to verify your identity: 028901 2024.11.22 08:44:48.040 Admin Panel V1.22 (Volatility 75 (1s) Index,M1) Password authentication successful. A 2FA code has been sent to your Telegram.
O objetivo desta discussão é integrar um sistema confiável de reconhecimento de usuários, que otimize os processos de login e autenticação de dois fatores (2FA). Usuários que inserirem a senha correta em até três tentativas poderão contornar o 2FA, enquanto o exceder do limite ativará o 2FA, exigindo o código enviado via Telegram e uma senha rígida programada para recuperação. Esse sistema combina conveniência com segurança, limitando o número de tentativas repetidas para evitar ataques por força bruta, ao mesmo tempo em que garante um processo de autenticação contínuo. A confiança depende da sessão e requer revalidação a cada novo login. Na seção seguinte serão apresentadas informações adicionais sobre medidas de combate a ataques por força bruta.
O que é força bruta (ataque por tentativa e erro)?
Um ataque por tentativa e erro é um método usado por agentes maliciosos para obter acesso não autorizado a contas, sistemas ou dados criptografados, por meio da tentativa sistemática de todas as combinações possíveis de senhas, chaves de criptografia ou credenciais, até encontrar a correta. Essa abordagem se baseia em poder computacional e persistência, não na exploração de uma vulnerabilidade específica do sistema.
Principais características de um ataque por tentativa e erro:
- Método de tentativa e erro: O invasor tenta repetidamente usar diferentes combinações de caracteres até obter acesso.
- Automatização: Para acelerar o processo, frequentemente são usados scripts ou ferramentas especializadas que permitem realizar milhares ou até milhões de tentativas em um curto período de tempo.
- Grande consumo de tempo: O tempo necessário depende da complexidade da senha ou chave alvo. Senhas mais seguras, com maior número de caracteres e combinações variadas, exigem muito mais tempo para serem quebradas.
Tipos de ataques por tentativa e erro:
- Força bruta simples – tentativa de todas as combinações possíveis de caracteres.
- Ataque de dicionário – uso de listas de senhas comuns (por exemplo, "123456", "password" ou "qwerty") para tentar obter acesso.
- Substituição de credenciais – utilização de pares "usuário-senha" obtidos em outros vazamentos para acessar contas em diferentes plataformas.
Prevenção:
- Limitação do número de tentativas de login.
- Uso de senhas fortes (longas, contendo letras maiúsculas e minúsculas, números e símbolos).
- Implementação da autenticação de dois fatores (2FA) para adicionar uma camada extra de segurança.
O sistema atual de segurança de acesso ao painel é vulnerável a esse tipo de ataque e, embora a limitação de tentativas de login seja um passo importante, também buscamos evitar autenticações frequentes via Telegram, a fim de economizar tempo. O envio do código de verificação serve tanto para proteger contra acessos não autorizados quanto para alertar o administrador sobre qualquer atividade potencialmente maliciosa.
Implementação do usuário confiável no painel administrativo
Para implementar a nova função no painel administrativo, alteramos apenas algumas partes do nosso código-fonte relacionadas à segurança e à inicialização do EA. Essa abordagem garante que o restante do programa permaneça inalterado, minimizando o risco de erros ao lidar com um código extenso. O foco principal aqui está na função de tratamento do login, e introduzimos novas variáveis que são declaradas no seguinte trecho de código.
int failedAttempts = 0; // Counter for failed login attempts bool isTrustedUser = false; // Flag for trusted users
As variáveis globais failedAttempts e isTrustedUser são fundamentais para a implementação das novas funções. failedAttempts rastreia o número de entradas de senha incorretas e ajuda a determinar quando aplicar medidas adicionais. A flag isTrustedUser reconhece usuários que conseguiram realizar login dentro do número permitido de tentativas, permitindo que eles pulem o processo de 2FA. Reajustando essas variáveis na função OnLoginButtonClick, o sistema exerce controle dinâmico sobre o fluxo de autenticação, garantindo flexibilidade e segurança.
Aprimoramento da função de login para as novas funcionalidades
A função OnLoginButtonClick integra as novas funcionalidades, rastreando as tentativas de login por meio do contador failedAttempts e identificando usuários confiáveis através da flag isTrustedUser. Quando a senha correta é inserida, o sistema verifica se o usuário pode ser considerado confiável, desde que o número de tentativas incorretas não ultrapasse três. Usuários confiáveis pulam a etapa de 2FA e são direcionados diretamente para o painel principal do administrador. Caso o número de tentativas malsucedidas ultrapasse o limite, a função gera um código 2FA, envia-o ao usuário via Telegram junto com uma senha rígida de recuperação e exibe a solicitação de autenticação em 2FA. Isso garante o equilíbrio entre conveniência para usuários confiáveis e segurança reforçada após falhas de login.
//+------------------------------------------------------------------+ //| Handle login button click | //+------------------------------------------------------------------+ void OnLoginButtonClick() { string enteredPassword = passwordInputBox.Text(); if (enteredPassword == Password) { failedAttempts = 0; // Reset attempts on successful login isTrustedUser = true; if (failedAttempts <= 3) // Skip 2FA for trusted users { authentication.Destroy(); adminHomePanel.Show(); Print("Login successful. 2FA skipped for trusted user."); } else { } } else { failedAttempts++; feedbackLabel.Text("Wrong password. Try again."); passwordInputBox.Text(""); if (failedAttempts >= 3) { Print("Too many failed attempts. 2FA will be required."); twoFACode = GenerateRandom6DigitCode(); SendMessageToTelegram( "A login attempt was made on the Admin Panel.\n" + "Use this code to verify your identity: " + twoFACode + "\n" + "Reminder: Your admin password is: " + Password, Hardcoded2FAChatId, Hardcoded2FABotToken ); authentication.Destroy(); ShowTwoFactorAuthPrompt(); Print("Password authentication successful. A 2FA code has been sent to your Telegram."); failedAttempts = 0; // Reset attempts after requiring 2FA } } }
Cinco etapas durante a inicialização do programa
O processo de autenticação, incluindo as novas funcionalidades de bypass do 2FA, entra em ação durante a inicialização, pois a função ShowAuthenticationPrompt() exibe a interface de login, onde o handler OnLoginButtonClick está vinculado ao botão Login. O funcionamento passo a passo é o seguinte:
- Início da solicitação de autenticação: Na função OnInit(), a primeira chamada é ShowAuthenticationPrompt(). Essa função cria e exibe a janela de diálogo de autenticação, contendo o campo de senha e o botão Login. O programa pausa a execução até que o usuário interaja com a janela de diálogo.
- Tratamento das tentativas de login: Quando o usuário pressiona o botão Login, a função OnLoginButtonClick é executada. Ela verifica a senha inserida, atualiza o contador failedAttempts e decide se deve conceder o acesso diretamente ou aplicar o 2FA, com base no número de falhas.
- Continuação após autenticação bem-sucedida: Se o login for realizado com sucesso e o usuário atender aos critérios de confiabilidade (menos de três tentativas incorretas), a janela de autenticação é fechada e o painel principal do administrador é exibido imediatamente. Isso permite pular o 2FA para usuários confiáveis.
- Exigência de 2FA quando necessário: Se o usuário ultrapassar o limite de tentativas incorretas, o programa ativa o 2FA. Um código de 6 dígitos é gerado, e enviado via Telegram, e a janela de autenticação 2FA é exibida pela função ShowTwoFactorAuthPrompt(). Lembre-se da função de geração do nosso código numérico, destacada em vermelho.
//+------------------------------------------------------------------+ //| Generate a random 6-digit code for 2FA | //+------------------------------------------------------------------+ string GenerateRandom6DigitCode() { int code = MathRand() % 1000000; // Generate a 6-digit number return StringFormat("%06d", code); // Ensure leading zeros }
5. Continuação da inicialização: Após a autenticação do usuário (seja por login confiável ou por autenticação de dois fatores bem-sucedida), os demais painéis (painel principal do administrador, painel de comunicações, painel de controle de trading) são inicializados em segundo plano, mas permanecem ocultos até serem explicitamente exibidos durante a navegação.
Aqui está um trecho do código da função de inicialização:
//+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { if (!ShowAuthenticationPrompt()) { Print("Authorization failed. Exiting..."); return INIT_FAILED; } if (!adminHomePanel.Create(ChartID(), "Admin Home Panel", 0, 30, 30, 500, 500)) { Print("Failed to create Admin Home Panel"); return INIT_FAILED; } if (!CreateAdminHomeControls()) { Print("Home panel control creation failed"); return INIT_FAILED; } if (!communicationsPanel.Create(ChartID(), "Communications Panel", 0, 30, 30, 500, 500)) { Print("Failed to create Communications panel dialog"); return INIT_FAILED; } if (!tradeManagementPanel.Create(ChartID(), "Trade Management Panel", 0,260, 30, 1040, 170)) { Print("Failed to create Trade Management panel dialog"); return INIT_FAILED; } if (!CreateControls()) { Print("Control creation failed"); return INIT_FAILED; } if (!CreateTradeManagementControls()) { Print("Trade management control creation failed"); return INIT_FAILED; } adminHomePanel.Hide(); // Hide home panel by default on initialization communicationsPanel.Hide(); // Hide the Communications Panel tradeManagementPanel.Hide(); // Hide the Trade Management Panel return INIT_SUCCEEDED; }
Criptografia e exemplos de aplicação no painel administrativo
Criptografia no MQL5 envolve o uso de algoritmos e métodos para proteger dados confidenciais, como senhas, mensagens ou códigos de autenticação.
A seguir, são apresentados quatro modos de aplicar esse conceito no painel administrativo.
1. Hashing de senhas
- A função HashPassword utiliza a função CryptEncode com o algoritmo CRYPT_HASH_SHA256 para realizar o hashing da senha inserida. O resultado do hash é convertido em uma string hexadecimal com CharArrayToHex para armazenamento ou comparação. Na função VerifyPassword, a senha digitada é hasheada e comparada com o hash salvo, garantindo que nenhuma senha em texto puro seja armazenada ou processada.
- Armazenar senhas hasheadas assegura que, mesmo em caso de acesso não autorizado aos dados salvos, as próprias senhas permaneçam protegidas. O hashing é unidirecional, ou seja, não é possível recuperar a senha original a partir do hash, o que adiciona uma camada essencial de segurança à autenticação.
// Example for storing our hard-coded password string HashPassword(string password) { uchar hash[]; CryptEncode(CRYPT_HASH_SHA256, password, hash); return CharArrayToHex(hash); } // Usage string PasswordHash = HashPassword("2024"); // Store this instead of plaintext bool VerifyPassword(string enteredPassword) { return HashPassword(enteredPassword) == PasswordHash; }
2. Criptografia de dados confidenciais
- A função EncryptData utiliza o algoritmo AES-256 (CRYPT_AES256) para criptografar informações confidenciais, como códigos 2FA, usando uma chave de criptografia segura. A função DecryptData realiza o processo inverso, descriptografando os dados para restaurá-los ao formato original. A chave é um elemento crítico nesse processo, pois deve coincidir tanto na criptografia quanto na descriptografia.
- A criptografia protege dados confidenciais durante o armazenamento ou a transmissão. Por exemplo, se um código 2FA for interceptado durante a comunicação, a versão criptografada garante que usuários não autorizados não consigam interpretá-lo sem a chave correta.
//Example for encryption of our 2FA verification code string EncryptData(string data, string key) { uchar encrypted[]; CryptEncode(CRYPT_AES256, data, encrypted, StringToCharArray(key)); return CharArrayToHex(encrypted); } string DecryptData(string encryptedData, string key) { uchar decrypted[]; uchar input[]; StringToCharArray(encryptedData, input); CryptDecode(CRYPT_AES256, input, decrypted, StringToCharArray(key)); return CharArrayToString(decrypted); } // Usage string key = "StrongEncryptionKey123"; // Use a secure key string encrypted2FA = EncryptData(twoFACode, key); Print("Encrypted 2FA code: ", encrypted2FA);
3. Geração segura de números aleatórios para 2FA
- A função GenerateSecureRandom6DigitCode utiliza a função CryptEncode com o algoritmo CRYPT_HASH_SHA256 para gerar uma sequência aleatória criptograficamente segura. O resultado é convertido em um número de 6 dígitos usando aritmética modular e formatação.
- Funções aleatórias padrão, como MathRand, são apenas pseudorrandômicas e previsíveis. O uso de aleatoriedade criptográfica garante que os códigos 2FA sejam robustos e resistentes a previsões ou ataques por força bruta, aumentando a segurança do processo de autenticação.
// Example for generating a secure verification code string GenerateSecureRandom6DigitCode() { uchar randomBytes[3]; CryptEncode(CRYPT_HASH_SHA256, MathRand(), randomBytes); // Use CryptEncode for randomness int randomValue = (randomBytes[0] << 16) | (randomBytes[1] << 8) | randomBytes[2]; randomValue = MathAbs(randomValue % 1000000); // Ensure 6 digits return StringFormat("%06d", randomValue); }
4. Comunicação segura com o Telegram
- A função SendEncryptedMessageToTelegram criptografa a mensagem utilizando a função EncryptData antes de enviá-la ao servidor do Telegram através da função SendMessageToTelegram. Apenas quem possui a chave correta de descriptografia pode decodificar a mensagem criptografada.
- A criptografia da comunicação garante a confidencialidade de informações, como códigos 2FA, mesmo que a transmissão seja interceptada. Isso é especialmente importante ao usar plataformas de comunicação de terceiros, onde os dados podem não estar totalmente protegidos.
//Example of the securely sending to Telegram bool SendEncryptedMessageToTelegram(string message, string chatId, string botToken, string key) { string encryptedMessage = EncryptData(message, key); return SendMessageToTelegram(encryptedMessage, chatId, botToken); } // Usage string key = "StrongEncryptionKey123"; SendEncryptedMessageToTelegram("Your 2FA code is: " + twoFACode, Hardcoded2FAChatId, Hardcoded2FABotToken, key);
Testes
Nesta etapa, apresentamos os resultados das melhorias de segurança no painel administrativo. A atualização simplifica o processo de login para usuários confiáveis, permitindo que acessem rapidamente o painel, enquanto usuários não confiáveis precisam passar por uma verificação adicional para confirmar sua autenticidade. Caso o usuário esqueça sua senha, é possível recuperá-la por meio da autenticação.
No log do Experts abaixo, mostramos tentativas de login malsucedidas, assim como o processo de autenticação.
2024.11.22 03:53:59.675 Admin Panel V1.23 (Volatility 75 (1s) Index,M2) Too many failed attempts. 2FA will be required. 2024.11.22 03:54:00.643 Admin Panel V1.23 (Volatility 75 (1s) Index,M2) Message sent successfully: Check your telegram for verification code and Password 2024.11.22 03:54:00.646 Admin Panel V1.23 (Volatility 75 (1s) Index,M2) Password authentication successful. A 2FA code has been sent to your Telegram. 2024.11.22 03:54:22.946 Admin Panel V1.23 (Volatility 75 (1s) Index,M2) 2FA authentication successful. Access granted to Admin Home Panel.
Mensagem do Telegram enviada para verificação
Painel administrativo: tentativas malsucedidas de login
Para usuários confiáveis, o processo de login é simples. Eles podem pular a etapa de verificação secundária, facilitando o acesso ao painel administrativo. Abaixo está um log do Experts mostrando um login bem-sucedido de usuários confiáveis, assim como o fluxo para aqueles que inseriram a senha correta.2024.11.22 03:57:41.563 Admin Panel V1.23 (Volatility 75 (1s) Index,M2) Login successful. 2FA skipped for trusted user.
Painel administrativo: Login bem-sucedido de usuário confiável com senha
Considerações finais
Durante a melhoria do painel administrativo, alcançamos avanços significativos tanto em funcionalidade quanto em segurança. A introdução da função de usuário confiável proporciona um processo de login mais fluido e eficiente para usuários conhecidos, ao limitar o número de tentativas a três e permitir o bypass do 2FA para autenticações bem-sucedidas dentro desse limite. Essa abordagem equilibra segurança e usabilidade, reduzindo obstáculos para os usuários e, ao mesmo tempo, mantendo controles de acesso rigorosos.
Também exploramos o potencial da criptografia para reforçar a segurança do painel. Com o uso de hashing de senhas, criptografia de dados confidenciais e geração segura de números aleatórios para códigos 2FA, garantimos a integridade e a confidencialidade das informações críticas. O hashing protege senhas armazenadas contra acessos não autorizados, enquanto a criptografia assegura a proteção de dados durante transmissão ou armazenamento. Além disso, a aleatoriedade criptograficamente segura garante a imprevisibilidade dos códigos gerados, adicionando uma camada extra de proteção contra ataques de força bruta.
Essas melhorias nos ajudam a garantir uma ferramenta prática e segura para o gerenciamento das comunicações e operações de trading. Ao dar atenção tanto à funcionalidade quanto à segurança, estabelecemos a base para futuras evoluções que podem otimizar ainda mais os fluxos de trabalho, mantendo ao mesmo tempo os mais altos padrões de proteção de dados.
Traduzido do Inglês pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/en/articles/16339
Aviso: Todos os direitos sobre esses materiais pertencem à MetaQuotes Ltd. É proibida a reimpressão total ou parcial.
Esse artigo foi escrito por um usuário do site e reflete seu ponto de vista pessoal. A MetaQuotes Ltd. não se responsabiliza pela precisão das informações apresentadas nem pelas possíveis consequências decorrentes do uso das soluções, estratégias ou recomendações descritas.





- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Você concorda com a política do site e com os termos de uso