mysql плъгини, които да не използваме

Въпроси и проблеми свързани с AMXModX.
Отговори
Потребителски аватар

Автор на темата
sianbg gta5-bg
Модератор
Модератор
Мнения: 230
Регистриран: 13 ное 2017, 12:18
Контакти:

mysql плъгини, които да не използваме

Мнение от sianbg gta5-bg » 11 фев 2018, 17:18

Здравейте. Не знам къде да сложа темата, но искам да съобщя нещо на всички сървър администратор. В момента имам възможност да хакна много сървъри, но вместо това ще споделя с вас. Много от авторите на плъгини са направили фундаментални грешки при използване на mysql. Не се ползва нищо за да се подсигурят входните данни. Просто 60% от sql плъгините, които съм проверил са с тази грешка. Няма да влизам в технически детайли. Всичко е тествано, а не е само теоретично. Искам да се извиня публично на insane-cs. Да, аз ви изтрих базата 2 пъти. Дори не исках да ви правя поразии, но все пак трябваше да се тества в напълно реална обстановка. Просто вашето безхаберие ... Това, че ограничихте правата на mysql потребителя не означава, че не мога да ви хакна отново. Мога да ви направя много по-големи поразии от това да ви изтрия базата ... Връща се за 30 секунди. Бъгавият плъгин все още е във всичките ви сървъри, а вас не ви интересува. Просто това е ... Надявам се да си оправите нещата и да се консултирате на тема сигурност. 20 години гледаме този филм в тази игра... Започнете да правите нещата сигурни.


Бъгави плъгини:
https://forums.alliedmods.net/showthread.php?t=146705
https://forums.alliedmods.net/showthread.php?t=221935
https://forums.alliedmods.net/showthread.php?t=222866
https://forums.alliedmods.net/showthread.php?t=294858
https://forums.alliedmods.net/showthread.php?t=191708
https://forums.alliedmods.net/showthread.php?t=201869
https://forums.alliedmods.net/showthread.php?t=220383
https://forums.alliedmods.net/showthread.php?t=176850

Има много други плъгини, но нямам време да седя и да разглеждам. Просто нека всеки, който използва плъгин свързан с mysql да пише в темата и да се консултира.


Защитени:
AMXBANS
Psychostats
HLSTATS
GAG System KOSTOV
War3FT
Veco Basebuilder
ProKreedz Ultimativ v2.4

Потребителски аватар

wrath .sma
Потребител
Потребител
Мнения: 167
Регистриран: 21 яну 2018, 10:30
Местоположение: /changerace
Години: 16
Контакти:

mysql плъгини, които да не използваме

Мнение от wrath .sma » 11 фев 2018, 19:46

Ето за какво си говорил.. Някакви дупки ли има в плъгините ,все още не разбирам..? :coffee:
I am not big on sermons ,broken bones teach better lessons. Изображение Изображение

Потребителски аватар

JustyleR
Модератор
Модератор
Мнения: 358
Регистриран: 24 фев 2017, 18:59
Местоположение: Русе
Се отблагодари: 5 пъти
Получена благодарност: 20 пъти
Години: 19
Контакти:

mysql плъгини, които да не използваме

Мнение от JustyleR » 11 фев 2018, 19:51

Можеш да го наречеш така, няма нужда да се споделя начина как става за да не се злоупотреби с това.
Браво за темата.
Steam | Github
Вече не ползвам Skype, ако има нещо ми пишете на лично или в Discord сървъра.

Потребителски аватар

Nikolow
AMXX Скриптър
AMXX Скриптър
Мнения: 172
Регистриран: 27 ное 2016, 13:02
Местоположение: Варна
Се отблагодари: 3 пъти
Получена благодарност: 47 пъти
Контакти:

mysql плъгини, които да не използваме

Мнение от Nikolow » 11 фев 2018, 22:35


Въведение

Понеже с колегата се занимавахме известно време да тестваме някакви неща относно "тема сигурност" в плъгините, ще е хубаво да прегледате всички ваши плъгини, които използват mysql. Най-масово използваните плъгините, които събрахме с колегата са вече изложени.
Понеже на повечето от вас не ви е много ясно какво да гледаме и как да се справим с това, ще дам един прост пример с един от най-разпространените плъгини с тази дупка в сигурността.
Пример

Става дума за Call Admin (MYSQL)
За примера ще използвам моята редактирана версия (в която има добавен IP адрес на нарушителя, когото репортвате).
Оригинален код:

Код: Избери всички

#include <amxmodx>
#include <amxmisc>
#include <cromchat>
#include <sqlx>


new bool:iUserCalled[33]; 
new iCacheUserName[34]
new iCacheReporter[34], iCacheUserIp[18]; 

#define CREATE_DB	"CREATE TABLE IF NOT EXISTS `call_admin` (`id` INT(12) NOT NULL AUTO_INCREMENT PRIMARY KEY ,`nick` VARCHAR(30) NOT NULL ,`report` VARCHAR(255) NOT NULL ,`date` VARCHAR(10) NOT NULL ,`time` VARCHAR(10) NOT NULL ,`ip` VARCHAR(22) NOT NULL ,`server` VARCHAR(30) NOT NULL ,`ip2` VARCHAR(16) NOT NULL ,`reporter_name` VARCHAR(30) NOT NULL)"
#define IMPORRT_DB	"INSERT INTO `call_admin` (nick,ip,report,date,time,server,ip2,reporter_name) VALUES ('%s','%s','%s','%s','%s','%s','%s','%s')"



#define szHost  "192.168.1.101"
#define szUser  "root" 
#define szPass  "test1337"
#define szDb    "test"

new Handle:SqlConnection

public plugin_init() 
{
	register_plugin("CallAdmin Mysql","0.1","Nikolow")
	
	register_clcmd("say /call", "cmdCallMenu", ADMIN_ALL); 
	register_clcmd("say /calladmin", "cmdCallMenu", ADMIN_ALL); 
	register_concmd("amx_callreason", "cmdCallReason", ADMIN_ALL); 
}

public plugin_cfg() 
{ 
	SqlConnection = SQL_MakeDbTuple(szHost,szUser,szPass,szDb)
	new QueryCache[1024]
	formatex(QueryCache,1023,CREATE_DB) 
	SQL_ThreadQuery(SqlConnection,"QueryCreateTable",QueryCache)
}

public plugin_end() { SQL_FreeHandle(SqlConnection); } 

public QueryCreateTable(iFailState,Handle:hQuery,szError[],iError,iData[],iDataSize,Float:flQueueTime) 
{
	switch(iFailState) 
	{
		case TQUERY_CONNECT_FAILED: log_amx("Failed to connect to database (%i): %s", iError, szError); 
		case TQUERY_QUERY_FAILED: log_amx("Error on query for QueryCreateTable() (%i): %s", iError, szError);
		default: { /*successfully created tables*/ }
	}
}

public cmdCallMenu(id, level, cid) 
{ 
   if(!cmd_access(id, level, cid, 1)) 
      return PLUGIN_HANDLED; 
    
   new iMenu = menu_create("\rCall Admin Menu:", "cmdCallMenuFunc"); 
   new iPlayers[32], iNum, iTarget; 
   new UserName[34], szTempID[10]; 
   get_players(iPlayers, iNum); 
   for(new i; i < iNum; i++) 
   { 
      iTarget = iPlayers[i]; 
      get_user_name(iTarget, UserName, sizeof UserName - 1); 
      num_to_str(iTarget, szTempID, charsmax(szTempID)); 
      menu_additem(iMenu, UserName, szTempID, _, menu_makecallback("CallMenuPlayers")); 
   } 

   menu_display(id, iMenu, 0); 
   return PLUGIN_HANDLED; 
} 

public CallMenuPlayers(iClient, iMenu, Item) 
{ 
   new iAccess, Info[3], iCallback; 
   menu_item_getinfo(iMenu, Item, iAccess, Info, sizeof Info - 1, _, _, iCallback); 
     
   new iGetID = str_to_num(Info); 
    
   if(access(iGetID, ADMIN_IMMUNITY)) // админи с имунитед не се показват
   { 
      return ITEM_DISABLED; 
   }  
    
   if(iUserCalled[iGetID]) // вече репортнати хора не се показват
   { 
      return ITEM_DISABLED; 
   } 
    
   return ITEM_ENABLED; 
} 

public cmdCallMenuFunc(id, iMenu, Item) 
{ 
   if(Item == MENU_EXIT) 
   { 
      menu_destroy(iMenu); 
      return PLUGIN_HANDLED; 
   } 

   new iData[6], iName[64]; 
   new access, callback; 
   menu_item_getinfo(iMenu, Item, access, iData, charsmax(iData), iName, charsmax(iName), callback); 

   new iTarget = str_to_num(iData); 
   get_user_name(iTarget, iCacheUserName, sizeof iCacheUserName - 1); 
   get_user_name(id, iCacheReporter, sizeof iCacheReporter - 1); 
   get_user_ip(iTarget, iCacheUserIp, sizeof iCacheUserIp - 1, 1); 

   ColorChat(id, "[ AMXX ]^1 Please type^4 Reason^1 for this^3 Call^1 !"); 
   client_cmd(id, "messagemode amx_callreason"); 
   
   menu_destroy(iMenu); 
   return PLUGIN_HANDLED; 
} 

public cmdCallReason(id, level, cid) 
{ 
   if(!cmd_access(id, level, cid, 1)) 
      return PLUGIN_HANDLED; 
    
   new iReason[64]; 
   read_argv(1, iReason, sizeof iReason - 1); 
   
   
   CallFunction(id, iCacheUserName, iCacheUserIp, iReason, iCacheReporter); 
   
   
   return PLUGIN_HANDLED; 
} 

stock CallFunction(id, const iPlayer[], const PlayerIp[], const iReason[], const iReporter[]) 
{
	new plID = find_player("bl", iPlayer)

	// server ip address
	new ip[22], szPort[6];
	//get_user_ip(id,ip,15,1) 
	get_user_ip(0,ip,15,1) 
	get_cvar_string("port", szPort, 5);
	format(ip, 21, "%s:%s", ip, szPort);
   
	// server host name
	new srvname[32];
	get_cvar_string("hostname",srvname,31)
   
	// date ?
	new datestr[11];
	get_time("%d.%m.%Y",datestr,10) 
	//get_time("%Y.%m.%d",datestr,10) 
   
	// current time ?
	new timestr[9];
	get_time("%H:%M:%S",timestr,8)
	


   
	new query[1001] 
	format(query,1000,IMPORRT_DB,iPlayer,ip,iReason,datestr,timestr,srvname,PlayerIp, iReporter)  
	SQL_ThreadQuery(SqlConnection,"QueryCreateTable",query) 
	
	//ColorChat(id, "^4[ AMXX ]^3 %s^4[^3 %s^4 ]^1 has been^4 Reported^1 for^3 %s^1 by^4 %s", iPlayer, PlayerIp, iReason, iReporter)
	ColorChat(id, "^4[ AMXX ]^3 %s^1 has been^4 Reported^1 for^3 %s^1 by^4 %s", iPlayer, iReason, iReporter)
	iUserCalled[plID] = true;
} 

public client_connect(id) 
{ 
   iUserCalled[id] = false; 
}

public client_disconnected(id) 
{ 
   iUserCalled[id] = false; 
}    


Редакция по Примера

Стар код:

Код: Избери всички

public plugin_cfg() 
{ 
	SqlConnection = SQL_MakeDbTuple(szHost,szUser,szPass,szDb)
	new QueryCache[1024]
	formatex(QueryCache,1023,CREATE_DB) 
	SQL_ThreadQuery(SqlConnection,"QueryCreateTable",QueryCache)
}
Става на:

Код: Избери всички

new Handle:g_iSqlX
new iError[512]
public plugin_cfg() 
{ 
	new iErrorCode;
	g_iSqlX    = SQL_MakeDbTuple(szHost,szUser,szPass,szDb);
	SqlConnection = SQL_Connect(g_iSqlX, iErrorCode, iError, sizeof iError - 1);
	
	if(!SqlConnection)
	{
		server_cmd("Could not connect to SQL database!");
		SQL_FreeHandle(SqlConnection);
		SQL_FreeHandle(g_iSqlX);
	}
	
	new Handle:tables;
	tables = SQL_PrepareQuery(SqlConnection, CREATE_DB);
	if(!SQL_Execute(tables)) set_fail_state("Could not create the tables. Probably syntax error.")
	SQL_FreeHandle(tables);
}

Стар код:

Код: Избери всички

public plugin_end() { SQL_FreeHandle(SqlConnection); } 
Става на:

Код: Избери всички

public plugin_end()
{
	if(SqlConnection)
	{
		SQL_FreeHandle(SqlConnection);
		SQL_FreeHandle(g_iSqlX);
	}
}

Стар код:

Код: Избери всички

	new query[1001] 
	format(query,1000,IMPORRT_DB,iPlayer,ip,iReason,datestr,timestr,srvname,PlayerIp, iReporter)  
	SQL_ThreadQuery(SqlConnection,"QueryCreateTable",query) 
Става на:

Код: Избери всички

	new Handle:report;
	report = SQL_PrepareQuery(SqlConnection,IMPORRT_DB,iPlayer,ip,iReason,datestr,timestr,srvname,PlayerIp, iReporter);
	SQL_Execute(report);
	SQL_FreeHandle(report);

Не забравяме да изтрием и функцията, която не ползваме -> QueryCreateTable

Пълен преработен код

Код: Избери всички

#include <amxmodx>
#include <amxmisc>
#include <cromchat>
#include <sqlx>


new bool:iUserCalled[33]; 
new iCacheUserName[34]
new iCacheReporter[34], iCacheUserIp[18]; 

#define CREATE_DB	"CREATE TABLE IF NOT EXISTS `call_admin` (`id` INT(12) NOT NULL AUTO_INCREMENT PRIMARY KEY ,`nick` VARCHAR(30) NOT NULL ,`report` VARCHAR(255) NOT NULL ,`date` VARCHAR(10) NOT NULL ,`time` VARCHAR(10) NOT NULL ,`ip` VARCHAR(22) NOT NULL ,`server` VARCHAR(30) NOT NULL ,`ip2` VARCHAR(16) NOT NULL ,`reporter_name` VARCHAR(30) NOT NULL)"
#define IMPORRT_DB	"INSERT INTO `call_admin` (nick,ip,report,date,time,server,ip2,reporter_name) VALUES ('%s','%s','%s','%s','%s','%s','%s','%s')"



#define szHost  "192.168.1.100"
#define szUser  "root" 
#define szPass  "test1337"
#define szDb    "test"

new Handle:SqlConnection, Handle:g_iSqlX
new iError[512]

public plugin_init() 
{
	register_plugin("CallAdmin Mysql","0.1","Nikolow")
	
	register_clcmd("say /call", "cmdCallMenu", ADMIN_ALL); 
	register_clcmd("say /calladmin", "cmdCallMenu", ADMIN_ALL); 
	register_concmd("amx_callreason", "cmdCallReason", ADMIN_ALL); 
}

public plugin_cfg() 
{ 
	new iErrorCode;
	g_iSqlX    = SQL_MakeDbTuple(szHost,szUser,szPass,szDb);
	SqlConnection = SQL_Connect(g_iSqlX, iErrorCode, iError, sizeof iError - 1);
	
	if(!SqlConnection)
	{
		SQL_FreeHandle(SqlConnection);
		SQL_FreeHandle(g_iSqlX);
		set_fail_state("Could not connect to SQL database!")
	}
	else
	{
		new Handle:tables;
		tables = SQL_PrepareQuery(SqlConnection, CREATE_DB);
		if(!SQL_Execute(tables)) set_fail_state("Could not create the tables. Probably syntax error.")
		SQL_FreeHandle(tables);
	}

	/*SqlConnection = SQL_MakeDbTuple(szHost,szUser,szPass,szDb)
	new QueryCache[1024]
	formatex(QueryCache,1023,CREATE_DB) 
	SQL_ThreadQuery(SqlConnection,"QueryCreateTable",QueryCache)*/
}

public plugin_end()
{
	if(SqlConnection)
	{
		SQL_FreeHandle(SqlConnection);
		SQL_FreeHandle(g_iSqlX);
	}
}

public cmdCallMenu(id, level, cid) 
{ 
   if(!cmd_access(id, level, cid, 1)) 
      return PLUGIN_HANDLED; 
    
   new iMenu = menu_create("\rCall Admin Menu:", "cmdCallMenuFunc"); 
   new iPlayers[32], iNum, iTarget; 
   new UserName[34], szTempID[10]; 
   get_players(iPlayers, iNum); 
   for(new i; i < iNum; i++) 
   { 
      iTarget = iPlayers[i]; 
      get_user_name(iTarget, UserName, sizeof UserName - 1); 
      num_to_str(iTarget, szTempID, charsmax(szTempID)); 
      menu_additem(iMenu, UserName, szTempID, _, menu_makecallback("CallMenuPlayers")); 
   } 

   menu_display(id, iMenu, 0); 
   return PLUGIN_HANDLED; 
} 

public CallMenuPlayers(iClient, iMenu, Item) 
{ 
   new iAccess, Info[3], iCallback; 
   menu_item_getinfo(iMenu, Item, iAccess, Info, sizeof Info - 1, _, _, iCallback); 
     
   new iGetID = str_to_num(Info); 
    
   if(access(iGetID, ADMIN_IMMUNITY)) // админи с имунитед не се показват
   { 
      return ITEM_DISABLED; 
   }  
    
   if(iUserCalled[iGetID]) // вече репортнати хора не се показват
   { 
      return ITEM_DISABLED; 
   } 
    
   return ITEM_ENABLED; 
} 

public cmdCallMenuFunc(id, iMenu, Item) 
{ 
   if(Item == MENU_EXIT) 
   { 
      menu_destroy(iMenu); 
      return PLUGIN_HANDLED; 
   } 

   new iData[6], iName[64]; 
   new access, callback; 
   menu_item_getinfo(iMenu, Item, access, iData, charsmax(iData), iName, charsmax(iName), callback); 

   new iTarget = str_to_num(iData); 
   get_user_name(iTarget, iCacheUserName, sizeof iCacheUserName - 1); 
   get_user_name(id, iCacheReporter, sizeof iCacheReporter - 1); 
   get_user_ip(iTarget, iCacheUserIp, sizeof iCacheUserIp - 1, 1); 

   ColorChat(id, "[ AMXX ]^1 Please type^4 Reason^1 for this^3 Call^1 !"); 
   client_cmd(id, "messagemode amx_callreason"); 
   
   menu_destroy(iMenu); 
   return PLUGIN_HANDLED; 
} 

public cmdCallReason(id, level, cid) 
{ 
   if(!cmd_access(id, level, cid, 1)) 
      return PLUGIN_HANDLED; 
    
   new iReason[64]; 
   read_argv(1, iReason, sizeof iReason - 1); 
   
   
   CallFunction(id, iCacheUserName, iCacheUserIp, iReason, iCacheReporter); 
   
   
   return PLUGIN_HANDLED; 
} 

stock CallFunction(id, const iPlayer[], const PlayerIp[], const iReason[], const iReporter[]) 
{
	new plID = find_player("bl", iPlayer)

	// server ip address
	new ip[22], szPort[6];
	//get_user_ip(id,ip,15,1) 
	get_user_ip(0,ip,15,1) 
	get_cvar_string("port", szPort, 5);
	format(ip, 21, "%s:%s", ip, szPort);
   
	// server host name
	new srvname[32];
	get_cvar_string("hostname",srvname,31)
   
	// date ?
	new datestr[11];
	get_time("%d.%m.%Y",datestr,10) 
	//get_time("%Y.%m.%d",datestr,10) 
   
	// current time ?
	new timestr[9];
	get_time("%H:%M:%S",timestr,8)
	

	
	new Handle:report;
	report = SQL_PrepareQuery(SqlConnection,IMPORRT_DB,iPlayer,ip,iReason,datestr,timestr,srvname,PlayerIp, iReporter);
	SQL_Execute(report);
	SQL_FreeHandle(report);
   
	//new query[1001] 
	//format(query,1000,IMPORRT_DB,iPlayer,ip,iReason,datestr,timestr,srvname,PlayerIp, iReporter)  
	//SQL_ThreadQuery(SqlConnection,"QueryCreateTable",query) 
	
	//ColorChat(id, "^4[ AMXX ]^3 %s^4[^3 %s^4 ]^1 has been^4 Reported^1 for^3 %s^1 by^4 %s", iPlayer, PlayerIp, iReason, iReporter)
	ColorChat(id, "^4[ AMXX ]^3 %s^1 has been^4 Reported^1 for^3 %s^1 by^4 %s", iPlayer, iReason, iReporter)
	iUserCalled[plID] = true;
} 

public client_connect(id) 
{ 
   iUserCalled[id] = false; 
}

public client_disconnected(id) 
{ 
   iUserCalled[id] = false; 
}  

Процес на обработка (редакция)

  1. При свързването на плъгина трябва да променим няколко основни неща
    • Създаваме 2 глобални Handle (един за SQL_MakeDbTuple и един за SQL_Connect)
    • В plugin_cfg (най-често) правим самата връзка.
    • След това правим предпазна една проверка, в която проверяваме дали имаме връзка.
      - Ако НЯМАМЕ връзка, освобождаваме и спираме плъгина
      - Ако ИМАМЕ връзка, създаваме таблицата/таблиците.
    • КОД - Пример (до момента)

      Код: Избери всички

      public plugin_cfg() 
      { 
      	new iErrorCode;
      	g_iSqlX    = SQL_MakeDbTuple(szHost,szUser,szPass,szDb); // първият HANDLE
      	SqlConnection = SQL_Connect(g_iSqlX, iErrorCode, iError, sizeof iError - 1); // вторият HANDLE
      
      	// проверката дали имаме връзка
      	if(!SqlConnection) // нямаме връзка
      	{
      		SQL_FreeHandle(SqlConnection); // освобождаваме HANDLE 1
      		SQL_FreeHandle(g_iSqlX); // освобождаваме HANDLE 2
      		set_fail_state("Could not connect to SQL database!") // спираме плъгина с грешка
      	}
      	else // имаме връзка
      	{
      		new Handle:tables; // създаваме нов HANDLE (локален)
      		tables = SQL_PrepareQuery(SqlConnection, CREATE_DB); // правим SQL_PrepareQuery, където ни е кода за таблиците
      		if(!SQL_Execute(tables)) set_fail_state("Could not create the tables. Probably syntax error.") // ако не можем да изпълним кода ни дава грешка
      		SQL_FreeHandle(tables); // освобождаваме
      	}
      }	
      
  2. След което Задължително в plugin_end() освобождаваме

    Код: Избери всички

    public plugin_end()
    {
    	if(SqlConnection)
    	{
    		SQL_FreeHandle(SqlConnection);
    		SQL_FreeHandle(g_iSqlX);
    	}
    }
    
  3. След което отиваме и търсим къде имаме заявка и правим следното:
    • Трием сегашният код, който е ~3 реда.
    • Променяме го по този същият начин както със създаването на таблиците:
    • КОД - Пример

      Код: Избери всички

      	new Handle:report; // създаваме нов HANDLE (локален)
      	report = SQL_PrepareQuery(SqlConnection,IMPORRT_DB,iPlayer,ip,iReason,datestr,timestr,srvname,PlayerIp, iReporter); // правим SQL_PrepareQuery с данните на заявката
      	SQL_Execute(report); // изпълняваме я
      	SQL_FreeHandle(report); // освобождаваме
      

Заключение

Хубаво е ако сте собственик на сървър, който притежава плъгини, с които се свързвате с база данни, да отделите време, да защитите плъгините по подобен начин, както по-горе. Всеки малко повече разбиращ, може да ви навреди до такава степен, че дори може да не разберете и да се чудите после от къде ви е дошло.
Ако успея да намеря излишно време ще се опитам да редактирам най-разпространените плъгини по българските сървъри, с цел защита по кода им, както на този с примера за Call Admin.
Tired and retired...

Отговори

Върни се в “Поддръжка / Помощ”

Кой е на линия

Потребители, разглеждащи този форум: Няма регистрирани потребители и 2 госта